/* $OpenBSD: interplayer.c,v 1.4 2000/06/29 07:39:44 pjanzen Exp $ */ /* $NetBSD: interplayer.c,v 1.2 1995/03/24 03:58:47 cgd Exp $ */ /* * interplayer.c - player to player routines for Phantasia */ #include "include.h" /************************************************************************ / / FUNCTION NAME: checkbattle() / / FUNCTION: check to see if current player should battle another / / AUTHOR: E. A. Estes, 12/4/85 / / ARGUMENTS: none / / RETURN VALUE: none / / MODULES CALLED: battleplayer(), fread(), fseek() / / GLOBAL INPUTS: Other, Users, Player, Fileloc, *Playersfp / / GLOBAL OUTPUTS: Users / / DESCRIPTION: / Seach player file for a foe at the same coordinates as the / current player. / Also update user count. / *************************************************************************/ void checkbattle() { long foeloc = 0L; /* location in file of person to fight */ Users = 0; fseek(Playersfp, 0L, SEEK_SET); while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) { if (Other.p_status != S_OFF && Other.p_status != S_NOTUSED && Other.p_status != S_HUNGUP && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR)) /* player is on and not a cloaked valar */ { ++Users; if (Player.p_x == Other.p_x && Player.p_y == Other.p_y /* same coordinates */ && foeloc != Fileloc /* not self */ && Player.p_status == S_PLAYING && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE) /* both are playing */ && Other.p_specialtype != SC_VALAR && Player.p_specialtype != SC_VALAR) /* neither is valar */ { battleplayer(foeloc); return; } } foeloc += SZ_PLAYERSTRUCT; } } /**/ /************************************************************************ / / FUNCTION NAME: battleplayer() / / FUNCTION: inter-terminal battle with another player / / AUTHOR: E. A. Estes, 2/15/86 / / ARGUMENTS: / long foeplace - location in player file of person to battle / / RETURN VALUE: none / / MODULES CALLED: readrecord(), readmessage(), writerecord(), collecttaxes(), / displaystats(), fabs(), more(), death(), sleep(), wmove(), waddch(), printw(), / myturn(), altercoordinates(), waddstr(), wrefresh(), mvprintw(), / getanswer(), wclrtoeol(), wclrtobot() / / GLOBAL INPUTS: Foestrikes, LINES, Lines, Other, Shield, Player, *stdscr, / Fileloc, *Enemyname / / GLOBAL OUTPUTS: Foestrikes, Lines, Shield, Player, Luckout, *Enemyname / / DESCRIPTION: / Inter-terminal battle is a very fragile and slightly klugy thing. / At any time, one player is master and the other is slave. / We pick who is master first by speed and level. After that, / the slave waits for the master to relinquish its turn, and / the slave becomes master, and so on. / / The items in the player structure which control the handshake are: / p_tampered: / master increments this to relinquish control / p_istat: / master sets this to specify particular action / p_1scratch: / set to total damage inflicted so far; changes to indicate action / *************************************************************************/ void battleplayer(foeplace) long foeplace; { double dtemp; /* for temporary calculations */ double oldhits = 0.0; /* previous damage inflicted by foe */ int loop; /* for timing out */ int ch; /* input */ short oldtampered; /* old value of foe's p_tampered */ Lines = 8; Luckout = FALSE; mvaddstr(4, 0, "Preparing for battle!\n"); refresh(); #ifdef SYS5 flushinp(); #endif /* set up variables, file, etc. */ Player.p_status = S_INBATTLE; Shield = Player.p_energy; /* if p_tampered is not 0, someone else may try to change it (king, * etc.) */ Player.p_tampered = oldtampered = 1; Player.p_1scratch = 0.0; Player.p_istat = I_OFF; readrecord(&Other, foeplace); if (fabs(Player.p_level - Other.p_level) > 20.0) /* see if players are greatly mismatched */ { dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level); if (dtemp < -0.5) /* foe outweighs this one */ Player.p_speed *= 2.0; } writerecord(&Player, Fileloc); /* write out all our info */ if (Player.p_blindness) Enemyname = "someone"; else Enemyname = Other.p_name; mvprintw(6, 0, "You have encountered %s Level: %.0f\n", Enemyname, Other.p_level); refresh(); for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop) /* wait for foe to respond */ { readrecord(&Other, foeplace); sleep(1); } if (Other.p_status != S_INBATTLE) /* foe did not respond */ { mvprintw(5, 0, "%s is not responding.\n", Enemyname); goto LEAVE; } /* else, we are ready to battle */ move(4, 0); clrtoeol(); /* * determine who is first master * if neither player is faster, check level * if neither level is greater, battle is not allowed * (this should never happen, but we have to handle it) */ if (Player.p_speed > Other.p_speed) Foestrikes = FALSE; else if (Other.p_speed > Player.p_speed) Foestrikes = TRUE; else if (Player.p_level > Other.p_level) Foestrikes = FALSE; else if (Other.p_level > Player.p_level) Foestrikes = TRUE; else { /* no one is faster */ printw("You can't fight %s yet.", Enemyname); goto LEAVE; } for (;;) { displaystats(); readmessage(); mvprintw(1, 26, "%20.0f", Shield); /* overprint energy */ if (!Foestrikes) /* take action against foe */ myturn(); else /* wait for foe to take action */ { mvaddstr(4, 0, "Waiting...\n"); clrtoeol(); refresh(); for (loop = 0; loop < 20; ++loop) /* wait for foe to act */ { readrecord(&Other, foeplace); if (Other.p_1scratch != oldhits) /* p_1scratch changes to indicate * action */ break; else /* wait and try again */ { sleep(1); addch('.'); refresh(); } } if (Other.p_1scratch == oldhits) { /* timeout */ mvaddstr(22, 0, "Timeout: waiting for response. Do you want to wait ? "); ch = getanswer("NY", FALSE); move(22, 0); clrtobot(); if (ch == 'Y') continue; else break; } else /* foe took action */ { switch (Other.p_istat) { case I_RAN: /* foe ran away */ mvprintw(Lines++, 0, "%s ran away!", Enemyname); break; case I_STUCK: /* foe tried to run, but * couldn't */ mvprintw(Lines++, 0, "%s tried to run away.", Enemyname); break; case I_BLEWIT: /* foe tried to luckout, but * didn't */ mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname); break; default: dtemp = Other.p_1scratch - oldhits; mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp); Shield -= dtemp; break; } oldhits = Other.p_1scratch; /* keep track of old * hits */ if (Other.p_tampered != oldtampered) /* p_tampered changes to relinquish * turn */ { oldtampered = Other.p_tampered; Foestrikes = FALSE; } } } /* decide what happens next */ refresh(); if (Lines > LINES - 2) { more(Lines); move(Lines = 8, 0); clrtobot(); } if (Other.p_istat == I_KILLED || Shield < 0.0) /* we died */ { Shield = -2.0; /* insure this value is negative */ break; } if (Player.p_istat == I_KILLED) /* we killed foe; award treasre */ { mvprintw(Lines++, 0, "You killed %s!", Enemyname); Player.p_experience += Other.p_experience; Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0; Player.p_amulets += Other.p_amulets; Player.p_charms += Other.p_charms; collecttaxes(Other.p_gold, Other.p_gems); Player.p_sword = MAX(Player.p_sword, Other.p_sword); Player.p_shield = MAX(Player.p_shield, Other.p_shield); Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver); if (Other.p_virgin && !Player.p_virgin) { mvaddstr(Lines++, 0, "You have rescued a virgin. Will you be honorable ? "); if ((ch = getanswer("YN", FALSE)) == 'Y') Player.p_virgin = TRUE; else { ++Player.p_sin; Player.p_experience += 8000.0; } } sleep(3); /* give other person time to die */ break; } else if (Player.p_istat == I_RAN || Other.p_istat == I_RAN) /* either player ran away */ break; } LEAVE: /* clean up things and leave */ writerecord(&Player, Fileloc); /* update a final time */ altercoordinates(0.0, 0.0, A_NEAR); /* move away from battle site */ Player.p_energy = Shield; /* set energy to actual value */ Player.p_tampered = T_OFF; /* clear p_tampered */ more(Lines); /* pause */ move(4, 0); clrtobot(); /* clear bottom area of screen */ if (Player.p_energy < 0.0) /* we are dead */ death("Interterminal battle"); } /**/ /************************************************************************ / / FUNCTION NAME: myturn() / / FUNCTION: process players action against foe in battle / / AUTHOR: E. A. Estes, 2/7/86 / / ARGUMENTS: none / / RETURN VALUE: none / / MODULES CALLED: writerecord(), inputoption(), floor(), wmove(), drandom(), / waddstr(), wrefresh(), mvprintw(), wclrtoeol(), wclrtobot() / / GLOBAL INPUTS: Lines, Other, Player, *stdscr, Fileloc, Luckout, / *Enemyname / / GLOBAL OUTPUTS: Foestrikes, Lines, Player, Luckout / / DESCRIPTION: / Take action action against foe, and decide who is master / for next iteration. / *************************************************************************/ void myturn() { double dtemp; /* for temporary calculations */ int ch; /* input */ mvaddstr(7, 0, "1:Fight 2:Run Away! 3:Power Blast "); if (Luckout) clrtoeol(); else addstr("4:Luckout "); ch = inputoption(); move(Lines = 8, 0); clrtobot(); switch (ch) { default: /* fight */ dtemp = ROLL(2.0, Player.p_might); HIT: mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp); Player.p_sin += 0.5; Player.p_1scratch += dtemp; Player.p_istat = I_OFF; break; case '2': /* run away */ Player.p_1scratch -= 1.0; /* change this to indicate * action */ if (drandom() > 0.25) { mvaddstr(Lines++, 0, "You got away!"); Player.p_istat = I_RAN; } else { mvprintw(Lines++, 0, "%s is still after you!", Enemyname); Player.p_istat = I_STUCK; } break; case '3': /* power blast */ dtemp = MIN(Player.p_mana, Player.p_level * 5.0); Player.p_mana -= dtemp; dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0; mvprintw(Lines++, 0, "You blasted %s !", Enemyname); goto HIT; case '4': /* luckout */ if (Luckout || drandom() > 0.1) { if (Luckout) mvaddstr(Lines++, 0, "You already tried that!"); else { mvaddstr(Lines++, 0, "Not this time . . ."); Luckout = TRUE; } Player.p_1scratch -= 1.0; Player.p_istat = I_BLEWIT; } else { mvaddstr(Lines++, 0, "You just lucked out!"); Player.p_1scratch = Other.p_energy * 1.1; } break; } refresh(); Player.p_1scratch = floor(Player.p_1scratch); /* clean up any mess */ if (Player.p_1scratch > Other.p_energy) Player.p_istat = I_KILLED; else if (drandom() * Player.p_speed < drandom() * Other.p_speed) /* relinquish control */ { ++Player.p_tampered; Foestrikes = TRUE; } writerecord(&Player, Fileloc); /* let foe know what we did */ } /**/ /************************************************************************ / / FUNCTION NAME: checktampered() / / FUNCTION: check if current player has been tampered with / / AUTHOR: E. A. Estes, 12/4/85 / / ARGUMENTS: none / / RETURN VALUE: none / / MODULES CALLED: readrecord(), fread(), fseek(), tampered(), writevoid() / / GLOBAL INPUTS: *Energyvoidfp, Other, Player, Fileloc, Enrgyvoid / / GLOBAL OUTPUTS: Enrgyvoid / / DESCRIPTION: / Check for energy voids, holy grail, and tampering by other / players. / *************************************************************************/ void checktampered() { long loc = 0L; /* location in energy void file */ /* first check for energy voids */ fseek(Energyvoidfp, 0L, SEEK_SET); while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1) if (Enrgyvoid.ev_active && Enrgyvoid.ev_x == Player.p_x && Enrgyvoid.ev_y == Player.p_y) /* sitting on one */ { if (loc > 0L) /* not the holy grail; inactivate energy void */ { Enrgyvoid.ev_active = FALSE; writevoid(&Enrgyvoid, loc); tampered(T_NRGVOID, 0.0, 0.0); } else if (Player.p_status != S_CLOAKED) /* holy grail */ tampered(T_GRAIL, 0.0, 0.0); break; } else loc += SZ_VOIDSTRUCT; /* now check for other things */ readrecord(&Other, Fileloc); if (Other.p_tampered != T_OFF) tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch); } /**/ /************************************************************************ / / FUNCTION NAME: tampered() / / FUNCTION: take care of tampering by other players / / AUTHOR: E. A. Estes, 12/4/85 / / ARGUMENTS: / int what - what type of tampering / double arg1, arg2 - rest of tampering info / / RETURN VALUE: none / / MODULES CALLED: writerecord(), more(), fread(), death(), fseek(), sleep(), / floor(), wmove(), waddch(), drandom(), printw(), altercoordinates(), / waddstr(), wrefresh(), encounter(), writevoid() / / GLOBAL INPUTS: Other, Player, *stdscr, Enrgyvoid, *Playersfp / / GLOBAL OUTPUTS: Other, Player, Changed, Enrgyvoid / / DESCRIPTION: / Take care of energy voids, holy grail, decree and intervention / action on current player. / *************************************************************************/ void tampered(what, arg1, arg2) int what; double arg1; double arg2; { long loc; /* location in file of other players */ Changed = TRUE; move(4, 0); Player.p_tampered = T_OFF; /* no longer tampered with */ switch (what) { case T_NRGVOID: addstr("You've hit an energy void !\n"); Player.p_mana /= 3.0; Player.p_energy /= 2.0; Player.p_gold = floor(Player.p_gold / 1.25) + 0.1; altercoordinates(0.0, 0.0, A_NEAR); break; case T_TRANSPORT: addstr("The king transported you ! "); if (Player.p_charms > 0) { addstr("But your charm saved you. . .\n"); --Player.p_charms; } else { altercoordinates(0.0, 0.0, A_FAR); addch('\n'); } break; case T_BESTOW: printw("The king has bestowed %.0f gold pieces on you !\n", arg1); Player.p_gold += arg1; break; case T_CURSED: addstr("You've been cursed ! "); if (Player.p_blessing) { addstr("But your blessing saved you. . .\n"); Player.p_blessing = FALSE; } else { addch('\n'); Player.p_poison += 2.0; Player.p_energy = 10.0; Player.p_maxenergy *= 0.95; Player.p_status = S_PLAYING; /* no longer cloaked */ } break; case T_VAPORIZED: addstr("You have been vaporized!\n"); more(7); death("Vaporization"); break; case T_MONSTER: addstr("The Valar zapped you with a monster!\n"); more(7); encounter((int) arg1); return; case T_BLESSED: addstr("The Valar has blessed you!\n"); Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield; Player.p_mana += 500.0; Player.p_strength += 0.5; Player.p_brains += 0.5; Player.p_magiclvl += 0.5; Player.p_poison = MIN(0.5, Player.p_poison); break; case T_RELOCATE: addstr("You've been relocated. . .\n"); altercoordinates(arg1, arg2, A_FORCED); break; case T_HEAL: addstr("You've been healed!\n"); Player.p_poison -= 0.25; Player.p_energy = Player.p_maxenergy + Player.p_shield; break; case T_EXVALAR: addstr("You are no longer Valar!\n"); Player.p_specialtype = SC_COUNCIL; break; case T_GRAIL: addstr("You have found The Holy Grail!!\n"); if (Player.p_specialtype < SC_COUNCIL) /* must be council of wise to behold grail */ { addstr("However, you are not experienced enough to behold it.\n"); Player.p_sin *= Player.p_sin; Player.p_mana += 1000; } else if (Player.p_specialtype == SC_VALAR || Player.p_specialtype == SC_EXVALAR) { addstr("You have made it to the position of Valar once already.\n"); addstr("The Grail is of no more use to you now.\n"); } else { addstr("It is now time to see if you are worthy to behold it. . .\n"); refresh(); sleep(4); if (drandom() / 2.0 < Player.p_sin) { addstr("You have failed!\n"); Player.p_strength = Player.p_mana = Player.p_energy = Player.p_maxenergy = Player.p_magiclvl = Player.p_brains = Player.p_experience = Player.p_quickness = 1.0; altercoordinates(1.0, 1.0, A_FORCED); Player.p_level = 0.0; } else { addstr("You made to position of Valar!\n"); Player.p_specialtype = SC_VALAR; Player.p_lives = 5; fseek(Playersfp, 0L, SEEK_SET); loc = 0L; while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) /* search for existing valar */ if (Other.p_specialtype == SC_VALAR && Other.p_status != S_NOTUSED) /* found old valar */ { Other.p_tampered = T_EXVALAR; writerecord(&Other, loc); break; } else loc += SZ_PLAYERSTRUCT; } } /* move grail to new location */ Enrgyvoid.ev_active = TRUE; Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6); Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6); writevoid(&Enrgyvoid, 0L); break; } refresh(); sleep(2); } /**/ /************************************************************************ / / FUNCTION NAME: userlist() / / FUNCTION: print list of players and locations / / AUTHOR: E. A. Estes, 2/28/86 / / ARGUMENTS: / bool ingameflag - set if called while playing / / RETURN VALUE: none / / MODULES CALLED: descrstatus(), descrlocation(), more(), fread(), fseek(), / floor(), wmove(), printw(), waddstr(), distance(), wrefresh(), / descrtype(), wclrtobot() / / GLOBAL INPUTS: LINES, Other, Circle, Wizard, Player, *stdscr, *Playersfp / / GLOBAL OUTPUTS: none / / DESCRIPTION: / We can only see the coordinate of those closer to the origin / from us. / Kings and council of the wise can see and can be seen by everyone. / Palantirs are good for seeing everyone; and the valar can use / one to see through a 'cloak' spell. / The valar has no coordinates, and is completely invisible if / cloaked. / *************************************************************************/ void userlist(ingameflag) bool ingameflag; { int numusers = 0; /* number of users on file */ if (ingameflag && Player.p_blindness) { mvaddstr(8, 0, "You cannot see anyone.\n"); return; } fseek(Playersfp, 0L, SEEK_SET); mvaddstr(8, 0, "Name X Y Lvl Type Login Status\n"); while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) { if (Other.p_status == S_NOTUSED /* record is unused */ || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED)) /* cloaked valar */ { if (!Wizard) /* wizard can see everything on file */ continue; } ++numusers; if (ingameflag && /* must be playing for the rest of these conditions */ (Player.p_specialtype >= SC_KING /* kings and higher can see others */ || Other.p_specialtype >= SC_KING /* kings and higher can be seen by others */ || Circle >= CIRCLE(Other.p_x, Other.p_y) /* those nearer the origin can be seen */ || Player.p_palantir) /* palantir enables one to see others */ && (Other.p_status != S_CLOAKED || (Player.p_specialtype == SC_VALAR && Player.p_palantir)) /* not cloaked; valar can see through cloak with a palantir */ && Other.p_specialtype != SC_VALAR) /* not a valar */ /* coordinates should be printed */ printw("%-20s %8.0f %8.0f ", Other.p_name, Other.p_x, Other.p_y); else /* cannot see player's coordinates */ printw("%-20s %19.19s ", Other.p_name, descrlocation(&Other, TRUE)); printw("%6.0f %s %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE), Other.p_login, descrstatus(&Other)); if ((numusers % (LINES - 10)) == 0) { more(LINES - 1); move(9, 0); clrtobot(); } } printw("Total players on file = %d\n", numusers); refresh(); } /**/ /************************************************************************ / / FUNCTION NAME: throneroom() / / FUNCTION: king stuff upon entering throne / / AUTHOR: E. A. Estes, 12/16/85 / / ARGUMENTS: none / / RETURN VALUE: none / / MODULES CALLED: writerecord(), fread(), fseek(), fopen(), wmove(), fclose(), / fwrite(), altercoordinates(), waddstr(), fprintf() / / GLOBAL INPUTS: *Energyvoidfp, Other, Player, *stdscr, / Enrgyvoid, *Playersfp / / GLOBAL OUTPUTS: Other, Player, Changed / / DESCRIPTION: / If player is not already king, make him/her so if the old king / is not playing. / Clear energy voids with new king. / Print 'decree' prompt. / *************************************************************************/ void throneroom() { FILE *fp; /* to clear energy voids */ long loc = 0L; /* location of old king in player file */ if (Player.p_specialtype < SC_KING) /* not already king -- assumes crown */ { fseek(Playersfp, 0L, SEEK_SET); while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED) /* found old king */ { if (Other.p_status != S_OFF) /* old king is playing */ { mvaddstr(4, 0, "The king is playing, so you cannot steal his throne\n"); altercoordinates(0.0, 0.0, A_NEAR); move(6, 0); return; } else /* old king is not playing - remove * him/her */ { Other.p_specialtype = SC_NONE; if (Other.p_crowns) --Other.p_crowns; writerecord(&Other, loc); break; } } else loc += SZ_PLAYERSTRUCT; /* make player new king */ Changed = TRUE; Player.p_specialtype = SC_KING; mvaddstr(4, 0, "You have become king!\n"); /* let everyone else know */ fp = fopen(_PATH_MESS, "w"); fprintf(fp, "All hail the new king!"); fclose(fp); /* clear all energy voids; retain location of holy grail */ fseek(Energyvoidfp, 0L, SEEK_SET); fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp); fp = fopen(_PATH_VOID, "w"); fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp); fclose(fp); } mvaddstr(6, 0, "0:Decree "); } /**/ /************************************************************************ / / FUNCTION NAME: dotampered() / / FUNCTION: king and valar special options / / AUTHOR: E. A. Estes, 2/28/86 / / ARGUMENTS: none / / RETURN VALUE: none / / MODULES CALLED: writerecord(), truncstring(), fread(), fseek(), fopen(), / floor(), wmove(), drandom(), fclose(), fwrite(), sscanf(), strcmp(), / infloat(), waddstr(), findname(), distance(), userlist(), mvprintw(), / allocvoid(), getanswer(), getstring(), wclrtoeol(), writevoid() / / GLOBAL INPUTS: *Energyvoidfp, Other, Illcmd[], Wizard, Player, *stdscr, / Databuf[], Enrgyvoid / / GLOBAL OUTPUTS: Other, Player, Enrgyvoid / / DESCRIPTION: / Tamper with other players. Handle king/valar specific options. / *************************************************************************/ void dotampered() { short tamper; /* value for tampering with other players */ char *option; /* pointer to option description */ double temp1 = 0.0, temp2 = 0.0; /* other tampering values */ int ch; /* input */ long loc; /* location in energy void file */ FILE *fp; /* for opening gold file */ move(6, 0); clrtoeol(); if (Player.p_specialtype < SC_COUNCIL && !Wizard) /* king options */ { addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes "); ch = getanswer(" ", TRUE); move(6, 0); clrtoeol(); move(4, 0); switch (ch) { case '1': /* transport someone */ tamper = T_TRANSPORT; option = "transport"; break; case '2': /* curse another */ tamper = T_CURSED; option = "curse"; break; case '3': /* create energy void */ if ((loc = allocvoid()) > 20L * SZ_VOIDSTRUCT) /* can only have 20 void active at once */ mvaddstr(5, 0, "Sorry, void creation limit reached.\n"); else { addstr("Enter the X Y coordinates of void ? "); getstring(Databuf, SZ_DATABUF); sscanf(Databuf, "%lf %lf", &temp1, &temp2); Enrgyvoid.ev_x = floor(temp1); Enrgyvoid.ev_y = floor(temp2); Enrgyvoid.ev_active = TRUE; writevoid(&Enrgyvoid, loc); mvaddstr(5, 0, "It is done.\n"); } return; case '4': /* bestow gold to subject */ tamper = T_BESTOW; addstr("How much gold to bestow ? "); temp1 = infloat(); if (temp1 > Player.p_gold || temp1 < 0) { mvaddstr(5, 0, "You don't have that !\n"); return; } /* adjust gold after we are sure it will be given to * someone */ option = "give gold to"; break; case '5': /* collect accumulated taxes */ if ((fp = fopen(_PATH_GOLD, "r+")) != NULL) /* collect taxes */ { fread((char *) &temp1, sizeof(double), 1, fp); fseek(fp, 0L, SEEK_SET); /* clear out value */ temp2 = 0.0; fwrite((char *) &temp2, sizeof(double), 1, fp); fclose(fp); } mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1); Player.p_gold += floor(temp1); return; default: return; } /* end of king options */ } else /* council of wise, valar, wizard options */ { addstr("1:Heal "); if (Player.p_palantir || Wizard) addstr("2:Seek Grail "); if (Player.p_specialtype == SC_VALAR || Wizard) addstr("3:Throw Monster 4:Relocate 5:Bless "); if (Wizard) addstr("6:Vaporize "); ch = getanswer(" ", TRUE); if (!Wizard) { if (ch > '2' && Player.p_specialtype != SC_VALAR) { ILLCMD(); return; } if (Player.p_mana < MM_INTERVENE) { mvaddstr(5, 0, "No mana left.\n"); return; } else Player.p_mana -= MM_INTERVENE; } switch (ch) { case '1': /* heal another */ tamper = T_HEAL; option = "heal"; break; case '2': /* seek grail */ if (Player.p_palantir) /* need a palantir to seek */ { fseek(Energyvoidfp, 0L, SEEK_SET); fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp); temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y); temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0); /* add some error */ mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1); } else /* no palantir */ mvaddstr(5, 0, "You need a palantir to seek the Grail.\n"); return; case '3': /* lob monster at someone */ mvaddstr(4, 0, "Which monster [0-99] ? "); temp1 = infloat(); temp1 = MAX(0.0, MIN(99.0, temp1)); tamper = T_MONSTER; option = "throw a monster at"; break; case '4': /* move another player */ mvaddstr(4, 0, "New X Y coordinates ? "); getstring(Databuf, SZ_DATABUF); sscanf(Databuf, "%lf %lf", &temp1, &temp2); tamper = T_RELOCATE; option = "relocate"; break; case '5': /* bless a player */ tamper = T_BLESSED; option = "bless"; break; case '6': /* kill off a player */ if (Wizard) { tamper = T_VAPORIZED; option = "vaporize"; break; } else return; default: return; } /* adjust age after we are sure intervention will be done */ /* end of valar, etc. options */ } for (;;) /* prompt for player to affect */ { mvprintw(4, 0, "Who do you want to %s ? ", option); getstring(Databuf, SZ_DATABUF); truncstring(Databuf); if (Databuf[0] == '\0') userlist(TRUE); else break; } if (strcmp(Player.p_name, Databuf) != 0) /* name other than self */ { if ((loc = findname(Databuf, &Other)) >= 0L) { if (Other.p_tampered != T_OFF) { mvaddstr(5, 0, "That person has something pending already.\n"); return; } else { if (tamper == T_RELOCATE && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y) && !Wizard) mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n"); else { if (tamper == T_BESTOW) Player.p_gold -= floor(temp1); if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER || tamper == T_RELOCATE || tamper == T_BLESSED)) Player.p_age += N_AGE; /* age penalty */ Other.p_tampered = tamper; Other.p_1scratch = floor(temp1); Other.p_2scratch = floor(temp2); writerecord(&Other, loc); mvaddstr(5, 0, "It is done.\n"); } return; } } else /* player not found */ mvaddstr(5, 0, "There is no one by that name.\n"); } else /* self */ mvaddstr(5, 0, "You may not do it to yourself!\n"); } /**/ /************************************************************************ / / FUNCTION NAME: writevoid() / / FUNCTION: update energy void entry in energy void file / / AUTHOR: E. A. Estes, 12/4/85 / / ARGUMENTS: / struct energyvoid *vp - pointer to structure to write to file / long loc - location in file to update / / RETURN VALUE: none / / MODULES CALLED: fseek(), fwrite(), fflush() / / GLOBAL INPUTS: *Energyvoidfp / / GLOBAL OUTPUTS: none / / DESCRIPTION: / Write out energy void structure at specified location. / *************************************************************************/ void writevoid(vp, loc) struct energyvoid *vp; long loc; { fseek(Energyvoidfp, loc, SEEK_SET); fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp); fflush(Energyvoidfp); fseek(Energyvoidfp, 0L, SEEK_SET); } /**/ /************************************************************************ / / FUNCTION NAME: allocvoid() / / FUNCTION: allocate space for a new energy void / / AUTHOR: E. A. Estes, 12/4/85 / / ARGUMENTS: none / / RETURN VALUE: location of new energy void space / / MODULES CALLED: fread(), fseek() / / GLOBAL INPUTS: *Energyvoidfp, Enrgyvoid / / GLOBAL OUTPUTS: none / / DESCRIPTION: / Search energy void file for an inactive entry and return its / location. / If no inactive ones are found, return one more than last location. / *************************************************************************/ long allocvoid() { long loc = 0L; /* location of new energy void */ fseek(Energyvoidfp, 0L, SEEK_SET); while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1) if (Enrgyvoid.ev_active) loc += SZ_VOIDSTRUCT; else break; return (loc); }