2 * interplayer.c - player to player routines for Phantasia
4 * $FreeBSD: src/games/phantasia/interplayer.c,v 1.6 1999/11/16 02:57:33 billf Exp $
5 * $DragonFly: src/games/phantasia/interplayer.c,v 1.3 2005/05/31 00:06:26 swildner Exp $
11 /* functions which we need to know about */
13 extern void encounter(int);
15 extern int getanswer(const char *, bool);
16 extern void getstring(char *, int);
17 extern double infloat(void);
18 extern int inputoption(void);
19 extern void more(int);
21 extern void altercoordinates(double, double, int);
22 extern void collecttaxes(double, double);
23 extern void death(const char *);
24 extern const char *descrlocation(struct player
*, bool);
25 extern const char *descrstatus(struct player
*);
26 extern const char *descrtype(struct player
*, bool);
27 extern void displaystats(void);
28 extern double distance(double, double, double, double);
29 extern long findname(char *, struct player
*);
30 extern void readmessage(void);
31 extern void readrecord(struct player
*, long);
32 extern void truncstring(char *);
33 extern void writerecord(struct player
*, long);
35 extern double drandom(void);
37 size_t allocvoid(void);
38 void battleplayer(long);
39 void checkbattle(void);
40 void checktampered(void);
41 void dotampered(void);
43 void tampered(int, double, double);
44 void throneroom(void);
46 void writevoid(struct energyvoid
*, long);
49 * FUNCTION: check to see if current player should battle another
51 * GLOBAL INPUTS: Other, Users, Player, Fileloc, *Playersfp
53 * GLOBAL OUTPUTS: Users
56 * Seach player file for a foe at the same coordinates as the
58 * Also update user count.
64 long foeloc
= 0L; /* location in file of person to fight */
67 fseek(Playersfp
, 0L, SEEK_SET
);
69 while (fread((char *)&Other
, SZ_PLAYERSTRUCT
, 1, Playersfp
) == 1) {
70 if (Other
.p_status
!= S_OFF
71 && Other
.p_status
!= S_NOTUSED
72 && Other
.p_status
!= S_HUNGUP
73 && (Other
.p_status
!= S_CLOAKED
|| Other
.p_specialtype
!= SC_VALAR
)) {
74 /* player is on and not a cloaked valar */
77 if (Player
.p_x
== Other
.p_x
78 && Player
.p_y
== Other
.p_y
79 /* same coordinates */
82 && Player
.p_status
== S_PLAYING
83 && (Other
.p_status
== S_PLAYING
|| Other
.p_status
== S_INBATTLE
)
84 /* both are playing */
85 && Other
.p_specialtype
!= SC_VALAR
86 && Player
.p_specialtype
!= SC_VALAR
) {
87 /* neither is valar */
92 foeloc
+= SZ_PLAYERSTRUCT
;
97 * FUNCTION: inter-terminal battle with another player
100 * long foeplace - location in player file of person to battle
102 * GLOBAL INPUTS: Foestrikes, LINES, Lines, Other, Shield, Player, *stdscr,
103 * Fileloc, *Enemyname
105 * GLOBAL OUTPUTS: Foestrikes, Lines, Shield, Player, Luckout, *Enemyname
108 * Inter-terminal battle is a very fragile and slightly klugy thing.
109 * At any time, one player is master and the other is slave.
110 * We pick who is master first by speed and level. After that,
111 * the slave waits for the master to relinquish its turn, and
112 * the slave becomes master, and so on.
114 * The items in the player structure which control the handshake are:
116 * master increments this to relinquish control
118 * master sets this to specify particular action
120 * set to total damage inflicted so far; changes to indicate action
124 battleplayer(long foeplace
)
126 double dtemp
; /* for temporary calculations */
127 double oldhits
= 0.0; /* previous damage inflicted by foe */
128 int loop
; /* for timing out */
130 short oldtampered
; /* old value of foe's p_tampered */
134 mvaddstr(4, 0, "Preparing for battle!\n");
141 /* set up variables, file, etc. */
142 Player
.p_status
= S_INBATTLE
;
143 Shield
= Player
.p_energy
;
145 /* if p_tampered is not 0, someone else may try to change it (king, etc.) */
146 Player
.p_tampered
= oldtampered
= 1;
147 Player
.p_1scratch
= 0.0;
148 Player
.p_istat
= I_OFF
;
150 readrecord(&Other
, foeplace
);
151 if (fabs(Player
.p_level
- Other
.p_level
) > 20.0) {
152 /* see if players are greatly mismatched */
153 dtemp
= (Player
.p_level
- Other
.p_level
) / MAX(Player
.p_level
, Other
.p_level
);
155 /* foe outweighs this one */
156 Player
.p_speed
*= 2.0;
158 writerecord(&Player
, Fileloc
); /* write out all our info */
160 if (Player
.p_blindness
)
161 Enemyname
= "someone";
163 Enemyname
= Other
.p_name
;
165 mvprintw(6, 0, "You have encountered %s Level: %.0f\n", Enemyname
, Other
.p_level
);
168 for (loop
= 0; Other
.p_status
!= S_INBATTLE
&& loop
< 30; ++loop
) {
169 /* wait for foe to respond */
170 readrecord(&Other
, foeplace
);
174 if (Other
.p_status
!= S_INBATTLE
) {
175 /* foe did not respond */
176 mvprintw(5, 0, "%s is not responding.\n", Enemyname
);
179 /* else, we are ready to battle */
185 * determine who is first master
186 * if neither player is faster, check level
187 * if neither level is greater, battle is not allowed
188 * (this should never happen, but we have to handle it)
190 if (Player
.p_speed
> Other
.p_speed
)
192 else if (Other
.p_speed
> Player
.p_speed
)
194 else if (Player
.p_level
> Other
.p_level
)
196 else if (Other
.p_level
> Player
.p_level
)
199 /* no one is faster */
200 printw("You can't fight %s yet.", Enemyname
);
207 mvprintw(1, 26, "%20.0f", Shield
); /* overprint energy */
210 /* take action against foe */
213 /* wait for foe to take action */
214 mvaddstr(4, 0, "Waiting...\n");
218 for (loop
= 0; loop
< 20; ++loop
) {
219 /* wait for foe to act */
220 readrecord(&Other
, foeplace
);
221 if (Other
.p_1scratch
!= oldhits
)
222 /* p_1scratch changes to indicate action */
225 /* wait and try again */
232 if (Other
.p_1scratch
== oldhits
) {
234 mvaddstr(22, 0, "Timeout: waiting for response. Do you want to wait ? ");
235 ch
= getanswer("NY", FALSE
);
243 /* foe took action */
244 switch (Other
.p_istat
) {
245 case I_RAN
: /* foe ran away */
246 mvprintw(Lines
++, 0, "%s ran away!", Enemyname
);
249 case I_STUCK
: /* foe tried to run, but couldn't */
250 mvprintw(Lines
++, 0, "%s tried to run away.", Enemyname
);
253 case I_BLEWIT
: /* foe tried to luckout, but didn't */
254 mvprintw(Lines
++, 0, "%s tried to luckout!", Enemyname
);
258 dtemp
= Other
.p_1scratch
- oldhits
;
259 mvprintw(Lines
++, 0, "%s hit you %.0f times!", Enemyname
, dtemp
);
264 oldhits
= Other
.p_1scratch
; /* keep track of old hits */
266 if (Other
.p_tampered
!= oldtampered
) {
267 /* p_tampered changes to relinquish turn */
268 oldtampered
= Other
.p_tampered
;
274 /* decide what happens next */
276 if (Lines
> LINES
- 2) {
282 if (Other
.p_istat
== I_KILLED
|| Shield
< 0.0) {
284 Shield
= -2.0; /* insure this value is negative */
288 if (Player
.p_istat
== I_KILLED
) {
289 /* we killed foe; award treasre */
290 mvprintw(Lines
++, 0, "You killed %s!", Enemyname
);
291 Player
.p_experience
+= Other
.p_experience
;
292 Player
.p_crowns
+= (Player
.p_level
< 1000.0) ? Other
.p_crowns
: 0;
293 Player
.p_amulets
+= Other
.p_amulets
;
294 Player
.p_charms
+= Other
.p_charms
;
295 collecttaxes(Other
.p_gold
, Other
.p_gems
);
296 Player
.p_sword
= MAX(Player
.p_sword
, Other
.p_sword
);
297 Player
.p_shield
= MAX(Player
.p_shield
, Other
.p_shield
);
298 Player
.p_quksilver
= MAX(Player
.p_quksilver
, Other
.p_quksilver
);
299 if (Other
.p_virgin
&& !Player
.p_virgin
) {
300 mvaddstr(Lines
++, 0, "You have rescued a virgin. Will you be honorable ? ");
301 if ((ch
= getanswer("YN", FALSE
)) == 'Y')
302 Player
.p_virgin
= TRUE
;
305 Player
.p_experience
+= 8000.0;
308 sleep(3); /* give other person time to die */
310 } else if (Player
.p_istat
== I_RAN
|| Other
.p_istat
== I_RAN
)
311 /* either player ran away */
316 /* clean up things and leave */
317 writerecord(&Player
, Fileloc
); /* update a final time */
318 altercoordinates(0.0, 0.0, A_NEAR
); /* move away from battle site */
319 Player
.p_energy
= Shield
; /* set energy to actual value */
320 Player
.p_tampered
= T_OFF
; /* clear p_tampered */
322 more(Lines
); /* pause */
325 clrtobot(); /* clear bottom area of screen */
327 if (Player
.p_energy
< 0.0)
329 death("Interterminal battle");
333 * FUNCTION: process players action against foe in battle
335 * GLOBAL INPUTS: Lines, Other, Player, *stdscr, Fileloc, Luckout,
338 * GLOBAL OUTPUTS: Foestrikes, Lines, Player, Luckout
341 * Take action action against foe, and decide who is master
342 * for next iteration.
348 double dtemp
; /* for temporary calculations */
351 mvaddstr(7, 0, "1:Fight 2:Run Away! 3:Power Blast ");
355 addstr("4:Luckout ");
363 dtemp
= ROLL(2.0, Player
.p_might
);
365 mvprintw(Lines
++, 0, "You hit %s %.0f times!", Enemyname
, dtemp
);
367 Player
.p_1scratch
+= dtemp
;
368 Player
.p_istat
= I_OFF
;
371 case '2': /* run away */
372 /* change this to indicate action */
373 Player
.p_1scratch
-= 1.0;
374 if (drandom() > 0.25) {
375 mvaddstr(Lines
++, 0, "You got away!");
376 Player
.p_istat
= I_RAN
;
378 mvprintw(Lines
++, 0, "%s is still after you!", Enemyname
);
379 Player
.p_istat
= I_STUCK
;
383 case '3': /* power blast */
384 dtemp
= MIN(Player
.p_mana
, Player
.p_level
* 5.0);
385 Player
.p_mana
-= dtemp
;
386 dtemp
*= (drandom() + 0.5) * Player
.p_magiclvl
* 0.2 + 2.0;
387 mvprintw(Lines
++, 0, "You blasted %s !", Enemyname
);
390 case '4': /* luckout */
391 if (Luckout
|| drandom() > 0.1) {
393 mvaddstr(Lines
++, 0, "You already tried that!");
395 mvaddstr(Lines
++, 0, "Not this time . . .");
399 Player
.p_1scratch
-= 1.0;
400 Player
.p_istat
= I_BLEWIT
;
402 mvaddstr(Lines
++, 0, "You just lucked out!");
403 Player
.p_1scratch
= Other
.p_energy
* 1.1;
409 Player
.p_1scratch
= floor(Player
.p_1scratch
); /* clean up any mess */
411 if (Player
.p_1scratch
> Other
.p_energy
)
412 Player
.p_istat
= I_KILLED
;
413 else if (drandom() * Player
.p_speed
< drandom() * Other
.p_speed
) {
414 /* relinquish control */
419 writerecord(&Player
, Fileloc
); /* let foe know what we did */
423 * FUNCTION: check if current player has been tampered with
425 * GLOBAL INPUTS: *Energyvoidfp, Other, Player, Fileloc, Enrgyvoid
427 * GLOBAL OUTPUTS: Enrgyvoid
430 * Check for energy voids, holy grail, and tampering by other
437 long loc
= 0L; /* location in energy void file */
439 /* first check for energy voids */
440 fseek(Energyvoidfp
, 0L, SEEK_SET
);
441 while (fread((char *)&Enrgyvoid
, SZ_VOIDSTRUCT
, 1, Energyvoidfp
) == 1)
442 if (Enrgyvoid
.ev_active
443 && Enrgyvoid
.ev_x
== Player
.p_x
444 && Enrgyvoid
.ev_y
== Player
.p_y
) {
447 /* not the holy grail; inactivate energy void */
448 Enrgyvoid
.ev_active
= FALSE
;
449 writevoid(&Enrgyvoid
, loc
);
450 tampered(T_NRGVOID
, 0.0, 0.0);
451 } else if (Player
.p_status
!= S_CLOAKED
)
453 tampered(T_GRAIL
, 0.0, 0.0);
456 loc
+= SZ_VOIDSTRUCT
;
458 /* now check for other things */
459 readrecord(&Other
, Fileloc
);
460 if (Other
.p_tampered
!= T_OFF
)
461 tampered(Other
.p_tampered
, Other
.p_1scratch
, Other
.p_2scratch
);
465 * FUNCTION: take care of tampering by other players
468 * int what - what type of tampering
469 * double arg1, arg2 - rest of tampering info
471 * GLOBAL INPUTS: Other, Player, *stdscr, Enrgyvoid, *Playersfp
473 * GLOBAL OUTPUTS: Other, Player, Changed, Enrgyvoid
476 * Take care of energy voids, holy grail, decree and intervention
477 * action on current player.
481 tampered(int what
, double arg1
, double arg2
)
483 long loc
; /* location in file of other players */
488 Player
.p_tampered
= T_OFF
; /* no longer tampered with */
492 addstr("You've hit an energy void !\n");
493 Player
.p_mana
/= 3.0;
494 Player
.p_energy
/= 2.0;
495 Player
.p_gold
= floor(Player
.p_gold
/ 1.25) + 0.1;
496 altercoordinates(0.0, 0.0, A_NEAR
);
500 addstr("The king transported you ! ");
501 if (Player
.p_charms
> 0) {
502 addstr("But your charm saved you. . .\n");
505 altercoordinates(0.0, 0.0, A_FAR
);
511 printw("The king has bestowed %.0f gold pieces on you !\n", arg1
);
512 Player
.p_gold
+= arg1
;
516 addstr("You've been cursed ! ");
517 if (Player
.p_blessing
) {
518 addstr("But your blessing saved you. . .\n");
519 Player
.p_blessing
= FALSE
;
522 Player
.p_poison
+= 2.0;
523 Player
.p_energy
= 10.0;
524 Player
.p_maxenergy
*= 0.95;
525 Player
.p_status
= S_PLAYING
; /* no longer cloaked */
530 addstr("You have been vaporized!\n");
532 death("Vaporization");
536 addstr("The Valar zapped you with a monster!\n");
538 encounter((int)arg1
);
542 addstr("The Valar has blessed you!\n");
543 Player
.p_energy
= (Player
.p_maxenergy
*= 1.05) + Player
.p_shield
;
544 Player
.p_mana
+= 500.0;
545 Player
.p_strength
+= 0.5;
546 Player
.p_brains
+= 0.5;
547 Player
.p_magiclvl
+= 0.5;
548 Player
.p_poison
= MIN(0.5, Player
.p_poison
);
552 addstr("You've been relocated. . .\n");
553 altercoordinates(arg1
, arg2
, A_FORCED
);
557 addstr("You've been healed!\n");
558 Player
.p_poison
-= 0.25;
559 Player
.p_energy
= Player
.p_maxenergy
+ Player
.p_shield
;
563 addstr("You are no longer Valar!\n");
564 Player
.p_specialtype
= SC_COUNCIL
;
568 addstr("You have found The Holy Grail!!\n");
569 if (Player
.p_specialtype
< SC_COUNCIL
) {
570 /* must be council of wise to behold grail */
571 addstr("However, you are not experienced enough to behold it.\n");
572 Player
.p_sin
*= Player
.p_sin
;
573 Player
.p_mana
+= 1000;
574 } else if (Player
.p_specialtype
== SC_VALAR
||
575 Player
.p_specialtype
== SC_EXVALAR
) {
576 addstr("You have made it to the position of Valar once already.\n");
577 addstr("The Grail is of no more use to you now.\n");
579 addstr("It is now time to see if you are worthy to behold it. . .\n");
583 if (drandom() / 2.0 < Player
.p_sin
) {
584 addstr("You have failed!\n");
591 Player
.p_experience
=
592 Player
.p_quickness
= 1.0;
594 altercoordinates(1.0, 1.0, A_FORCED
);
595 Player
.p_level
= 0.0;
597 addstr("You made to position of Valar!\n");
598 Player
.p_specialtype
= SC_VALAR
;
600 fseek(Playersfp
, 0L, SEEK_SET
);
602 while (fread((char *)&Other
, SZ_PLAYERSTRUCT
, 1, Playersfp
) == 1)
603 /* search for existing valar */
604 if (Other
.p_specialtype
== SC_VALAR
&&
605 Other
.p_status
!= S_NOTUSED
) {
606 /* found old valar */
607 Other
.p_tampered
= T_EXVALAR
;
608 writerecord(&Other
, loc
);
611 loc
+= SZ_PLAYERSTRUCT
;
615 /* move grail to new location */
616 Enrgyvoid
.ev_active
= TRUE
;
617 Enrgyvoid
.ev_x
= ROLL(-1.0e6
, 2.0e6
);
618 Enrgyvoid
.ev_y
= ROLL(-1.0e6
, 2.0e6
);
619 writevoid(&Enrgyvoid
, 0L);
627 * FUNCTION: print list of players and locations
630 * bool ingameflag - set if called while playing
632 * GLOBAL INPUTS: LINES, Other, Circle, Wizard, Player, *stdscr, *Playersfp
635 * We can only see the coordinate of those closer to the origin
637 * Kings and council of the wise can see and can be seen by everyone.
638 * Palantirs are good for seeing everyone; and the valar can use
639 * one to see through a 'cloak' spell.
640 * The valar has no coordinates, and is completely invisible if
645 userlist(bool ingameflag
)
647 int numusers
= 0; /* number of users on file */
649 if (ingameflag
&& Player
.p_blindness
) {
650 mvaddstr(8, 0, "You cannot see anyone.\n");
654 fseek(Playersfp
, 0L, SEEK_SET
);
656 "Name X Y Lvl Type Login Status\n");
658 while (fread((char *)&Other
, SZ_PLAYERSTRUCT
, 1, Playersfp
) == 1) {
659 if (Other
.p_status
== S_NOTUSED
660 /* record is unused */
661 || (Other
.p_specialtype
== SC_VALAR
&& Other
.p_status
== S_CLOAKED
)) {
664 /* wizard can see everything on file */
671 /* must be playing for the rest of these conditions */
672 (Player
.p_specialtype
>= SC_KING
673 /* kings and higher can see others */
674 || Other
.p_specialtype
>= SC_KING
675 /* kings and higher can be seen by others */
676 || Circle
>= CIRCLE(Other
.p_x
, Other
.p_y
)
677 /* those nearer the origin can be seen */
678 || Player
.p_palantir
)
679 /* palantir enables one to see others */
680 && (Other
.p_status
!= S_CLOAKED
681 || (Player
.p_specialtype
== SC_VALAR
&& Player
.p_palantir
))
682 /* not cloaked; valar can see through cloak with a palantir */
683 && Other
.p_specialtype
!= SC_VALAR
)
685 /* coordinates should be printed */
686 printw("%-20s %8.0f %8.0f ",
687 Other
.p_name
, Other
.p_x
, Other
.p_y
);
689 /* cannot see player's coordinates */
690 printw("%-20s %19.19s ",
691 Other
.p_name
, descrlocation(&Other
, TRUE
));
693 printw("%6.0f %s %-9.9s%s\n", Other
.p_level
, descrtype(&Other
, TRUE
),
694 Other
.p_login
, descrstatus(&Other
));
696 if ((numusers
% (LINES
- 10)) == 0) {
703 printw("Total players on file = %d\n", numusers
);
708 * FUNCTION: king stuff upon entering throne
710 * GLOBAL INPUTS: *Energyvoidfp, Other, Player, *stdscr,
711 * Enrgyvoid, *Playersfp
713 * GLOBAL OUTPUTS: Other, Player, Changed
716 * If player is not already king, make him/her so if the old king
718 * Clear energy voids with new king.
719 * Print 'decree' prompt.
725 FILE *fp
; /* to clear energy voids */
726 long loc
= 0L; /* location of old king in player file */
728 if (Player
.p_specialtype
< SC_KING
) {
729 /* not already king -- assumes crown */
730 fseek(Playersfp
, 0L, SEEK_SET
);
731 while (fread((char *)&Other
, SZ_PLAYERSTRUCT
, 1, Playersfp
) == 1)
732 if (Other
.p_specialtype
== SC_KING
&& Other
.p_status
!= S_NOTUSED
) {
734 if (Other
.p_status
!= S_OFF
) {
735 /* old king is playing */
736 mvaddstr(4, 0, "The king is playing, so you cannot steal his throne\n");
737 altercoordinates(0.0, 0.0, A_NEAR
);
741 /* old king is not playing - remove him/her */
742 Other
.p_specialtype
= SC_NONE
;
745 writerecord(&Other
, loc
);
749 loc
+= SZ_PLAYERSTRUCT
;
751 /* make player new king */
753 Player
.p_specialtype
= SC_KING
;
754 mvaddstr(4, 0, "You have become king!\n");
756 /* let everyone else know */
757 fp
= fopen(_PATH_MESS
, "w");
758 fprintf(fp
, "All hail the new king!");
761 /* clear all energy voids; retain location of holy grail */
762 fseek(Energyvoidfp
, 0L, SEEK_SET
);
763 fread((char *)&Enrgyvoid
, SZ_VOIDSTRUCT
, 1, Energyvoidfp
);
764 fp
= fopen(_PATH_VOID
, "w");
765 fwrite((char *)&Enrgyvoid
, SZ_VOIDSTRUCT
, 1, fp
);
769 mvaddstr(6, 0, "0:Decree ");
773 * FUNCTION: king and valar special options
775 * GLOBAL INPUTS: *Energyvoidfp, Other, Illcmd[], Wizard, Player, *stdscr,
776 * Databuf[], Enrgyvoid
778 * GLOBAL OUTPUTS: Other, Player, Enrgyvoid
781 * Tamper with other players. Handle king/valar specific options.
787 short tamper
; /* value for tampering with other players */
788 const char *option
; /* pointer to option description */
789 double temp1
= 0.0, temp2
= 0.0; /* other tampering values */
791 long loc
; /* location in energy void file */
792 FILE *fp
; /* for opening gold file */
796 if (Player
.p_specialtype
< SC_COUNCIL
&& !Wizard
) {
798 addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes ");
800 ch
= getanswer(" ", TRUE
);
805 case '1': /* transport someone */
806 tamper
= T_TRANSPORT
;
807 option
= "transport";
810 case '2': /* curse another */
815 case '3': /* create energy void */
816 if ((loc
= allocvoid()) > 20L * (long)SZ_VOIDSTRUCT
)
817 /* can only have 20 void active at once */
818 mvaddstr(5, 0, "Sorry, void creation limit reached.\n");
820 addstr("Enter the X Y coordinates of void ? ");
821 getstring(Databuf
, SZ_DATABUF
);
822 sscanf(Databuf
, "%lf %lf", &temp1
, &temp2
);
823 Enrgyvoid
.ev_x
= floor(temp1
);
824 Enrgyvoid
.ev_y
= floor(temp2
);
825 Enrgyvoid
.ev_active
= TRUE
;
826 writevoid(&Enrgyvoid
, loc
);
827 mvaddstr(5, 0, "It is done.\n");
831 case '4': /* bestow gold to subject */
833 addstr("How much gold to bestow ? ");
835 if (temp1
> Player
.p_gold
|| temp1
< 0) {
836 mvaddstr(5, 0, "You don't have that !\n");
840 /* adjust gold after we are sure it will be given to someone */
841 option
= "give gold to";
844 case '5': /* collect accumulated taxes */
845 if ((fp
= fopen(_PATH_GOLD
, "r+")) != NULL
) {
847 fread((char *)&temp1
, sizeof(double), 1, fp
);
848 fseek(fp
, 0L, SEEK_SET
);
849 /* clear out value */
851 fwrite((char *)&temp2
, sizeof(double), 1, fp
);
855 mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1
);
856 Player
.p_gold
+= floor(temp1
);
862 /* end of king options */
864 /* council of wise, valar, wizard options */
866 if (Player
.p_palantir
|| Wizard
)
867 addstr("2:Seek Grail ");
868 if (Player
.p_specialtype
== SC_VALAR
|| Wizard
)
869 addstr("3:Throw Monster 4:Relocate 5:Bless ");
871 addstr("6:Vaporize ");
873 ch
= getanswer(" ", TRUE
);
875 if (ch
> '2' && Player
.p_specialtype
!= SC_VALAR
) {
880 if (Player
.p_mana
< MM_INTERVENE
) {
881 mvaddstr(5, 0, "No mana left.\n");
884 Player
.p_mana
-= MM_INTERVENE
;
888 case '1': /* heal another */
893 case '2': /* seek grail */
894 if (Player
.p_palantir
) {
895 /* need a palantir to seek */
896 fseek(Energyvoidfp
, 0L, SEEK_SET
);
897 fread((char *)&Enrgyvoid
, SZ_VOIDSTRUCT
, 1, Energyvoidfp
);
898 temp1
= distance(Player
.p_x
, Enrgyvoid
.ev_x
, Player
.p_y
, Enrgyvoid
.ev_y
);
899 temp1
+= ROLL(-temp1
/ 10.0, temp1
/ 5.0); /* add some error */
900 mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1
);
903 mvaddstr(5, 0, "You need a palantir to seek the Grail.\n");
906 case '3': /* lob monster at someone */
907 mvaddstr(4, 0, "Which monster [0-99] ? ");
909 temp1
= MAX(0.0, MIN(99.0, temp1
));
911 option
= "throw a monster at";
914 case '4': /* move another player */
915 mvaddstr(4, 0, "New X Y coordinates ? ");
916 getstring(Databuf
, SZ_DATABUF
);
917 sscanf(Databuf
, "%lf %lf", &temp1
, &temp2
);
922 case '5': /* bless a player */
927 case '6': /* kill off a player */
929 tamper
= T_VAPORIZED
;
939 /* adjust age after we are sure intervention will be done */
940 /* end of valar, etc. options */
944 /* prompt for player to affect */
945 mvprintw(4, 0, "Who do you want to %s ? ", option
);
946 getstring(Databuf
, SZ_DATABUF
);
947 truncstring(Databuf
);
949 if (Databuf
[0] == '\0')
955 if (strcmp(Player
.p_name
, Databuf
) != 0) {
956 /* name other than self */
957 if ((loc
= findname(Databuf
, &Other
)) >= 0L) {
958 if (Other
.p_tampered
!= T_OFF
) {
959 mvaddstr(5, 0, "That person has something pending already.\n");
962 if (tamper
== T_RELOCATE
963 && CIRCLE(temp1
, temp2
) < CIRCLE(Other
.p_x
, Other
.p_y
)
965 mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n");
967 if (tamper
== T_BESTOW
)
968 Player
.p_gold
-= floor(temp1
);
969 if (!Wizard
&& (tamper
== T_HEAL
|| tamper
== T_MONSTER
||
970 tamper
== T_RELOCATE
|| tamper
== T_BLESSED
))
971 Player
.p_age
+= N_AGE
; /* age penalty */
972 Other
.p_tampered
= tamper
;
973 Other
.p_1scratch
= floor(temp1
);
974 Other
.p_2scratch
= floor(temp2
);
975 writerecord(&Other
, loc
);
976 mvaddstr(5, 0, "It is done.\n");
981 /* player not found */
982 mvaddstr(5, 0, "There is no one by that name.\n");
985 mvaddstr(5, 0, "You may not do it to yourself!\n");
989 * FUNCTION: update energy void entry in energy void file
992 * struct energyvoid *vp - pointer to structure to write to file
993 * long loc - location in file to update
995 * GLOBAL INPUTS: *Energyvoidfp
998 * Write out energy void structure at specified location.
1002 writevoid(struct energyvoid
*vp
, long loc
)
1004 fseek(Energyvoidfp
, loc
, SEEK_SET
);
1005 fwrite((char *)vp
, SZ_VOIDSTRUCT
, 1, Energyvoidfp
);
1006 fflush(Energyvoidfp
);
1007 fseek(Energyvoidfp
, 0L, SEEK_SET
);
1011 * FUNCTION: allocate space for a new energy void
1013 * RETURN VALUE: location of new energy void space
1015 * GLOBAL INPUTS: *Energyvoidfp, Enrgyvoid
1018 * Search energy void file for an inactive entry and return its
1020 * If no inactive ones are found, return one more than last location.
1026 size_t loc
= 0; /* location of new energy void */
1028 fseek(Energyvoidfp
, 0L, SEEK_SET
);
1029 while (fread((char *)&Enrgyvoid
, SZ_VOIDSTRUCT
, 1, Energyvoidfp
) == 1)
1030 if (Enrgyvoid
.ev_active
)
1031 loc
+= SZ_VOIDSTRUCT
;