* fight.c Phantasia monster fighting routines
/************************************************************************
/ FUNCTION NAME: encounter()
/ FUNCTION: monster battle routine
/ AUTHOR: E. A. Estes, 2/20/86
/ int particular - particular monster to fight if >= 0
/ MODULES CALLED: monsthits(), playerhits(), readmessage(), callmonster(),
/ writerecord(), pickmonster(), displaystats(), pow(), cancelmonster(),
/ awardtreasure(), more(), death(), wmove(), setjmp(), drandom(), printw(),
/ longjmp(), wrefresh(), mvprintw(), wclrtobot()
/ GLOBAL INPUTS: Curmonster, Whichmonster, LINES, Lines, Circle, Shield,
/ Player, *stdscr, Fileloc, Fightenv[], *Enemyname
/ GLOBAL OUTPUTS: Curmonster, Whichmonster, Lines, Shield, Player, Luckout
/ Choose a monster and check against some special types.
/ Arbitrate between monster and player. Watch for either
/************************************************************************/
bool firsthit
= Player
.p_blessing
; /* set if player gets the first hit */
int flockcnt
= 1; /* how many time flocked */
/* let others know what we are doing */
Player
.p_status
= S_MONSTER
;
writerecord(&Player
, Fileloc
);
Shield
= 0.0; /* no shield up yet */
/* monster is specified */
Whichmonster
= particular
;
/* pick random monster */
Whichmonster
= pickmonster();
setjmp(Fightenv
); /* this is to enable changing fight state */
clrtobot(); /* clear bottom area of screen */
callmonster(Whichmonster
); /* set up monster to fight */
Luckout
= FALSE
; /* haven't tried to luckout yet */
if (Curmonster
.m_type
== SM_MORGOTH
)
mvprintw(4, 0, "You've encountered %s, Bane of the Council and Valar.\n",
if (Curmonster
.m_type
== SM_UNICORN
)
printw("You just subdued %s, thanks to the virgin.\n", Enemyname
);
printw("You just saw %s running away!\n", Enemyname
);
Curmonster
.m_experience
= 0.0;
Curmonster
.m_treasuretype
= 0;
/* not a special monster */
/* print header, and arbitrate between player and monster */
mvprintw(6, 0, "You are being attacked by %s, EXP: %.0f (Size: %.0f)\n",
Enemyname
, Curmonster
.m_experience
, Circle
);
mvprintw(1, 26, "%20.0f", Player
.p_energy
+ Shield
); /* overprint energy */
if (Curmonster
.m_type
== SM_DARKLORD
/* overpower Dark Lord with blessing and charm */
mvprintw(7, 0, "You just overpowered %s!", Enemyname
);
Player
.p_blessing
= FALSE
;
/* allow paralyzed monster to wake up */
Curmonster
.m_speed
= MIN(Curmonster
.m_speed
+ 1.0, Curmonster
.m_maxspeed
);
if (drandom() * Curmonster
.m_speed
> drandom() * Player
.p_speed
&& Curmonster
.m_type
!= SM_DARKLORD
&& Curmonster
.m_type
!= SM_SHRIEKER
/* near bottom of screen - pause */
if (Player
.p_energy
<= 0.0)
break; /* fight ends if the player is saved from death */
if (Curmonster
.m_energy
<= 0.0)
/* give player credit for killing monster */
Player
.p_experience
+= Curmonster
.m_experience
;
if (drandom() < Curmonster
.m_flock
/ 100.0)
&& Curmonster
.m_treasuretype
> 0
&& drandom() > 0.2 + pow(0.4, (double) (flockcnt
/ 3 + Circle
/ 3.0)))
/* monster has treasure; this takes # of flocks and size into account */
/* pause before returning */
getyx(stdscr
, Lines
, flockcnt
);
Player
.p_ring
.ring_inuse
= FALSE
; /* not using ring */
/* clean up the screen */
/************************************************************************
/ FUNCTION NAME: pickmonster()
/ FUNCTION: choose a monster based upon where we are
/ AUTHOR: E. A. Estes, 2/20/86
/ RETURN VALUE: monster number to call
/ MODULES CALLED: floor(), drandom()
/ GLOBAL INPUTS: Marsh, Circle, Player
/ Certain monsters can be found in certain areas of the grid.
/ We take care of rolling them here.
/ Unfortunately, this routine assumes that the monster data
/ base is arranged in a particular order. If the data base
/ is altered (to add monsters, or make them tougher), this
/ routine may also need to be changed.
/************************************************************************/
if (Player
.p_specialtype
== SC_VALAR
)
/* even chance of any monster */
return((int) ROLL(0.0, 100.0));
return((int) ROLL(0.0, 15.0));
/* even chance of all non-water monsters */
return((int) ROLL(14.0, 86.0));
/* chance of all non-water monsters, weighted toward middle */
return((int) (ROLL(0.0, 50.0) + ROLL(14.0, 37.0)));
/* not all non-water monsters, weighted toward middle */
return((int) (ROLL(0.0, 50.0) + ROLL(14.0, 26.0)));
/* even chance of some tamer non-water monsters */
return((int) ROLL(14.0, 50.0));
/* even chance of some of the tamest non-water monsters */
return((int) ROLL(14.0, 25.0));
/************************************************************************
/ FUNCTION NAME: playerhits()
/ FUNCTION: prompt player for action in monster battle, and process
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: hitmonster(), throwspell(), inputoption(), cancelmonster(),
/ floor(), wmove(), drandom(), altercoordinates(), waddstr(), mvprintw(),
/ wclrtoeol(), wclrtobot()
/ GLOBAL INPUTS: Curmonster, Lines, Player, *stdscr, Luckout, *Enemyname
/ GLOBAL OUTPUTS: Curmonster, Lines, Player, Luckout
/ Process all monster battle options.
/************************************************************************/
double inflict
; /* damage inflicted */
mvaddstr(7, 0, "1:Melee 2:Skirmish 3:Evade 4:Spell 5:Nick ");
/* haven't tried to luckout yet */
if (Curmonster
.m_type
== SM_MORGOTH
)
/* cannot luckout against Morgoth */
if (Player
.p_ring
.ring_type
!= R_NONE
)
clrtobot(); /* clear any messages from before */
mvaddstr(4, 0, "\n\n"); /* clear status area */
case 'T': /* timeout; lose turn */
/* melee affects monster's energy and strength */
inflict
= ROLL(Player
.p_might
/ 2.0 + 5.0, 1.3 * Player
.p_might
)
+ (Player
.p_ring
.ring_inuse
? Player
.p_might
: 0.0);
Curmonster
.m_melee
+= inflict
;
Curmonster
.m_strength
= Curmonster
.m_o_strength
- Curmonster
.m_melee
/ Curmonster
.m_o_energy
* Curmonster
.m_o_strength
/ 4.0;
/* skirmish affects monter's energy and speed */
inflict
= ROLL(Player
.p_might
/ 3.0 + 3.0, 1.1 * Player
.p_might
)
+ (Player
.p_ring
.ring_inuse
? Player
.p_might
: 0.0);
Curmonster
.m_skirmish
+= inflict
;
Curmonster
.m_maxspeed
= Curmonster
.m_o_speed
- Curmonster
.m_skirmish
/ Curmonster
.m_o_energy
* Curmonster
.m_o_speed
/ 4.0;
/* use brains and speed to try to evade */
if ((Curmonster
.m_type
== SM_DARKLORD
|| Curmonster
.m_type
== SM_SHRIEKER
/* can always run from D. L. and shrieker */
|| drandom() * Player
.p_speed
* Player
.p_brains
> drandom() * Curmonster
.m_speed
* Curmonster
.m_brains
)
&& (Curmonster
.m_type
!= SM_MIMIC
))
/* cannot run from mimic */
mvaddstr(Lines
++, 0, "You got away!");
altercoordinates(0.0, 0.0, A_NEAR
);
mvprintw(Lines
++, 0, "%s is still after you!", Enemyname
);
case '4': /* magic spell */
/* hit 1 plus sword; give some experience */
inflict
= 1.0 + Player
.p_sword
;
Player
.p_experience
+= floor(Curmonster
.m_experience
/ 10.0);
Curmonster
.m_experience
*= 0.92;
/* monster gets meaner */
Curmonster
.m_maxspeed
+= 2.0;
Curmonster
.m_speed
= (Curmonster
.m_speed
< 0.0) ? 0.0 : Curmonster
.m_speed
+ 2.0;
if (Curmonster
.m_type
== SM_DARKLORD
)
/* Dark Lord; doesn't like to be nicked */
"You hit %s %.0f times, and made him mad!", Enemyname
, inflict
);
Player
.p_quickness
/= 2.0;
altercoordinates(0.0, 0.0, A_FAR
);
mvaddstr(Lines
++, 0, "You already tried that.");
if (Curmonster
.m_type
== SM_MORGOTH
)
if (drandom() < Player
.p_sin
/ 100.0)
mvprintw(Lines
++, 0, "%s accepted!", Enemyname
);
mvaddstr(Lines
++, 0, "Nope, he's not interested.");
/* normal monster; use brains for success */
if ((drandom() + 0.333) * Player
.p_brains
< (drandom() + 0.333) * Curmonster
.m_brains
)
mvprintw(Lines
++, 0, "You blew it, %s.", Player
.p_name
);
mvaddstr(Lines
++, 0, "You made it!");
Curmonster
.m_energy
= 0.0;
if (Player
.p_ring
.ring_type
!= R_NONE
)
mvaddstr(Lines
++, 0, "Now using ring.");
Player
.p_ring
.ring_inuse
= TRUE
;
if (Player
.p_ring
.ring_type
!= R_DLREG
)
--Player
.p_ring
.ring_duration
;
/************************************************************************
/ FUNCTION NAME: monsthits()
/ FUNCTION: process a monster hitting the player
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: cancelmonster(), scramblestats(), more(), floor(), wmove(),
/ drandom(), altercoordinates(), longjmp(), waddstr(), mvprintw(),
/ GLOBAL INPUTS: Curmonster, Lines, Circle, Shield, Player, *stdscr,
/ GLOBAL OUTPUTS: Curmonster, Whichmonster, Lines, Shield, Player,
/ Handle all special monsters here. If the monster is not a special
/ one, simply roll a hit against the player.
/************************************************************************/
double inflict
; /* damage inflicted */
switch (Curmonster
.m_type
)
/* may be a special monster */
/* hits just enough to kill player */
inflict
= (Player
.p_energy
+ Shield
) * 1.02;
"Shrieeeek!! You scared it, and it called one of its friends.");
Whichmonster
= (int) ROLL(70.0, 30.0);
/* take experience away */
inflict
= ROLL(10.0, Curmonster
.m_strength
);
inflict
= MIN(Player
.p_experience
, inflict
);
"%s took away %.0f experience points.", Enemyname
, inflict
);
Player
.p_experience
-= inflict
;
if (Player
.p_holywater
> 0)
/* holy water kills when monster tries to hit */
mvprintw(Lines
++, 0, "Your holy water killed it!");
Curmonster
.m_energy
= 0.0;
/* else special things */
switch (Curmonster
.m_type
)
/* takes some of the player's strength */
inflict
= ROLL(1.0, (Circle
- 1.0) / 2.0);
inflict
= MIN(Player
.p_strength
, inflict
);
mvprintw(Lines
++, 0, "%s sapped %0.f of your strength!",
Player
.p_strength
-= inflict
;
Player
.p_might
-= inflict
;
mvprintw(Lines
++, 0, "Wormtongue stole your palantir!");
Player
.p_palantir
= FALSE
;
else if (drandom() > 0.5)
"%s transformed your gems into gold!", Enemyname
);
Player
.p_gold
+= Player
.p_gems
;
/* scramble some stats */
mvprintw(Lines
++, 0, "%s scrambled your stats!", Enemyname
);
mvprintw(Lines
++, 0, "%s transported you!", Enemyname
);
altercoordinates(0.0, 0.0, A_FAR
);
inflict
= ROLL(0, 7.5 * Circle
);
inflict
= MIN(Player
.p_mana
, floor(inflict
));
"%s sucked up %.0f of your mana!", Enemyname
, inflict
);
Player
.p_mana
-= inflict
;
/* try to take ring if player has one */
if (Player
.p_ring
.ring_type
!= R_NONE
)
mvaddstr(Lines
++, 0, "Will you relinguish your ring ? ");
ch
= getanswer("YN", FALSE
);
Player
.p_ring
.ring_type
= R_NONE
;
Player
.p_ring
.ring_inuse
= FALSE
;
/* otherwise, take some brains */
"%s neutralized 1/5 of your brain!", Enemyname
);
/* take some gold and gems */
"%s took half your gold and gems and flew off.", Enemyname
);
/* steal a gold piece and run */
"%s stole one gold piece and ran away.", Enemyname
);
Player
.p_gold
= MAX(0.0, Player
.p_gold
- 1.0);
/* bite and (medium) poison */
"%s has bitten and poisoned you!", Enemyname
);
/* bite and (small) poison */
mvprintw(Lines
++, 0, "%s bit and poisoned you!", Enemyname
);
mvprintw(Lines
++, 0, "%s farted and scampered off.", Enemyname
);
Player
.p_energy
/= 2.0; /* damage from fumes */
if (Player
.p_ring
.ring_type
!= R_NONE
)
"%s tried to steal your ring, ", Enemyname
);
addstr("but was unsuccessful.");
addstr("and ran away with it!");
Player
.p_ring
.ring_type
= R_NONE
;
/* inflict damage through shield */
inflict
= ROLL(15.0, Circle
* 10.0);
inflict
= MIN(inflict
, Player
.p_energy
);
mvprintw(Lines
++, 0, "%s sapped %.0f of your energy.",
Player
.p_energy
-= inflict
;
/* take all metal treasures */
"%s took all your metal treasures!", Enemyname
);
/* (large) poison and take a quickness */
"%s poisoned you, and took one quik.", Enemyname
);
Player
.p_quickness
-= 1.0;
/* fly away, and leave either a Jubjub bird or Bonnacon */
"%s flew away, and left you to contend with one of its friends.",
Whichmonster
= 55 + (drandom() > 0.5) ? 22 : 0;
/* partially regenerate monster */
"%s partially regenerated his energy.!", Enemyname
);
floor((Curmonster
.m_o_energy
- Curmonster
.m_energy
) / 2.0);
Curmonster
.m_strength
= Curmonster
.m_o_strength
;
Curmonster
.m_melee
= Curmonster
.m_skirmish
= 0.0;
Curmonster
.m_maxspeed
= Curmonster
.m_o_speed
;
mvprintw(Lines
++, 0, "%s blinded you!", Enemyname
);
Player
.p_blindness
= TRUE
;
/* fall through to here if monster inflicts a normal hit */
inflict
= drandom() * Curmonster
.m_strength
+ 0.5;
mvprintw(Lines
++, 0, "%s hit you %.0f times!", Enemyname
, inflict
);
if ((Shield
-= inflict
) < 0)
Player
.p_energy
+= Shield
;
/************************************************************************
/ FUNCTION NAME: cancelmonster()
/ FUNCTION: mark current monster as no longer active
/ AUTHOR: E. A. Estes, 12/4/85
/ GLOBAL OUTPUTS: Curmonster
/ Clear current monster's energy, experience, treasure type, and
/ flock. This is the same as having the monster run away.
/************************************************************************/
Curmonster
.m_energy
= 0.0;
Curmonster
.m_experience
= 0.0;
Curmonster
.m_treasuretype
= 0;
Curmonster
.m_flock
= 0.0;
/************************************************************************
/ FUNCTION NAME: hitmonster()
/ FUNCTION: inflict damage upon current monster
/ AUTHOR: E. A. Estes, 12/4/85
/ double inflict - damage to inflict upon monster
/ MODULES CALLED: monsthits(), wmove(), strcmp(), waddstr(), mvprintw()
/ GLOBAL INPUTS: Curmonster, Lines, Player, *stdscr, *Enemyname
/ GLOBAL OUTPUTS: Curmonster, Lines
/ Hit monster specified number of times. Handle when monster dies,
/ and a few special monsters.
/************************************************************************/
mvprintw(Lines
++, 0, "You hit %s %.0f times!", Enemyname
, inflict
);
Curmonster
.m_energy
-= inflict
;
if (Curmonster
.m_energy
> 0.0)
if (Curmonster
.m_type
== SM_DARKLORD
|| Curmonster
.m_type
== SM_SHRIEKER
)
/* special monster didn't die */
/* monster died. print message. */
if (Curmonster
.m_type
== SM_MORGOTH
)
mvaddstr(Lines
++, 0, "You have defeated Morgoth, but he may return. . .");
/* all other types of monsters */
mvprintw(Lines
++, 0, "You killed it. Good work, %s.", Player
.p_name
);
if (Curmonster
.m_type
== SM_MIMIC
&& strcmp(Curmonster
.m_name
, "A Mimic") != 0
mvaddstr(Lines
++, 0, "The body slowly changes into the form of a mimic.");
/************************************************************************
/ FUNCTION NAME: throwspell()
/ FUNCTION: throw a magic spell
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: hitmonster(), cancelmonster(), sqrt(), floor(), wmove(),
/ drandom(), altercoordinates(), longjmp(), infloat(), waddstr(), mvprintw(),
/ GLOBAL INPUTS: Curmonster, Whichmonster, Nomana[], Player, *stdscr,
/ Fightenv[], Illspell[], *Enemyname
/ GLOBAL OUTPUTS: Curmonster, Whichmonster, Shield, Player
/ Prompt player and process magic spells.
/************************************************************************/
double inflict
; /* damage inflicted */
double dtemp
; /* for dtemporary calculations */
mvaddstr(7, 0, "\n\n"); /* clear menu area */
if (Player
.p_magiclvl
>= ML_ALLORNOTHING
)
mvaddstr(7, 0, "1:All or Nothing ");
if (Player
.p_magiclvl
>= ML_MAGICBOLT
)
if (Player
.p_magiclvl
>= ML_FORCEFIELD
)
addstr("3:Force Field ");
if (Player
.p_magiclvl
>= ML_XFORM
)
if (Player
.p_magiclvl
>= ML_INCRMIGHT
)
addstr("5:Increase Might\n");
if (Player
.p_magiclvl
>= ML_INVISIBLE
)
mvaddstr(8, 0, "6:Invisibility ");
if (Player
.p_magiclvl
>= ML_XPORT
)
if (Player
.p_magiclvl
>= ML_PARALYZE
)
if (Player
.p_specialtype
>= SC_COUNCIL
)
mvaddstr(4, 0, "Spell ? ");
ch
= getanswer(" ", TRUE
);
mvaddstr(7, 0, "\n\n"); /* clear menu area */
if (Curmonster
.m_type
== SM_MORGOTH
&& ch
!= '3')
/* can only throw force field against Morgoth */
case '1': /* all or nothing */
inflict
= Curmonster
.m_energy
* 1.01 + 1.0;
if (Curmonster
.m_type
== SM_DARKLORD
)
/* all or nothing doesn't quite work against D. L. */
/* failure -- monster gets stronger and quicker */
Curmonster
.m_o_strength
= Curmonster
.m_strength
*= 2.0;
Curmonster
.m_maxspeed
*= 2.0;
Curmonster
.m_o_speed
*= 2.0;
/* paralyzed monsters wake up a bit */
Curmonster
.m_speed
= MAX(1.0, Curmonster
.m_speed
* 2.0);
if (Player
.p_mana
>= MM_ALLORNOTHING
)
/* take a mana if player has one */
Player
.p_mana
-= MM_ALLORNOTHING
;
case '2': /* magic bolt */
if (Player
.p_magiclvl
< ML_MAGICBOLT
)
/* prompt for amount to expend */
mvaddstr(4, 0, "How much mana for bolt? ");
dtemp
= floor(infloat());
while (dtemp
< 0.0 || dtemp
> Player
.p_mana
);
if (Curmonster
.m_type
== SM_DARKLORD
)
/* magic bolts don't work against D. L. */
inflict
= dtemp
* ROLL(15.0, sqrt(Player
.p_magiclvl
/ 3.0 + 1.0));
mvaddstr(5, 0, "Magic Bolt fired!\n");
case '3': /* force field */
if (Player
.p_magiclvl
< ML_FORCEFIELD
)
else if (Player
.p_mana
< MM_FORCEFIELD
)
Player
.p_mana
-= MM_FORCEFIELD
;
Shield
= (Player
.p_maxenergy
+ Player
.p_shield
) * 4.2 + 45.0;
mvaddstr(5, 0, "Force Field up.\n");
case '4': /* transform */
if (Player
.p_magiclvl
< ML_XFORM
)
else if (Player
.p_mana
< MM_XFORM
)
Player
.p_mana
-= MM_XFORM
;
Whichmonster
= (int) ROLL(0.0, 100.0);
case '5': /* increase might */
if (Player
.p_magiclvl
< ML_INCRMIGHT
)
else if (Player
.p_mana
< MM_INCRMIGHT
)
Player
.p_mana
-= MM_INCRMIGHT
;
(1.2 * (Player
.p_strength
+ Player
.p_sword
)
+ 5.0 - Player
.p_might
) / 2.0;
mvprintw(5, 0, "New strength: %.0f\n", Player
.p_might
);
case '6': /* invisible */
if (Player
.p_magiclvl
< ML_INVISIBLE
)
else if (Player
.p_mana
< MM_INVISIBLE
)
Player
.p_mana
-= MM_INVISIBLE
;
(1.2 * (Player
.p_quickness
+ Player
.p_quksilver
)
+ 5.0 - Player
.p_speed
) / 2.0;
mvprintw(5, 0, "New quickness: %.0f\n", Player
.p_speed
);
case '7': /* transport */
if (Player
.p_magiclvl
< ML_XPORT
)
else if (Player
.p_mana
< MM_XPORT
)
Player
.p_mana
-= MM_XPORT
;
if (Player
.p_brains
+ Player
.p_magiclvl
< Curmonster
.m_experience
/ 200.0 * drandom())
mvaddstr(5, 0, "Transport backfired!\n");
altercoordinates(0.0, 0.0, A_FAR
);
mvprintw(5, 0, "%s is transported.\n", Enemyname
);
/* monster didn't drop its treasure */
Curmonster
.m_treasuretype
= 0;
Curmonster
.m_energy
= 0.0;
if (Player
.p_magiclvl
< ML_PARALYZE
)
else if (Player
.p_mana
< MM_PARALYZE
)
Player
.p_mana
-= MM_PARALYZE
;
Curmonster
.m_experience
/ 1000.0 * drandom())
mvprintw(5, 0, "%s is held.\n", Enemyname
);
Curmonster
.m_speed
= -2.0;
mvaddstr(5, 0, "Monster unaffected.\n");
if (Player
.p_specialtype
< SC_COUNCIL
)
else if (Player
.p_mana
< MM_SPECIFY
)
Player
.p_mana
-= MM_SPECIFY
;
mvaddstr(5, 0, "Which monster do you want [0-99] ? ");
Whichmonster
= (int) infloat();
Whichmonster
= MAX(0, MIN(99, Whichmonster
));
/************************************************************************
/ FUNCTION NAME: callmonster()
/ FUNCTION: read monster from file, and fill structure
/ AUTHOR: E. A. Estes, 2/25/86
/ int which - which monster to call
/ MODULES CALLED: truncstring(), fread(), fseek(), floor(), drandom(),
/ GLOBAL INPUTS: Curmonster, Circle, Player, *Monstfp
/ GLOBAL OUTPUTS: Curmonster, Player, *Enemyname
/ Read specified monster from monster database and fill up
/ current monster structure.
/ Adjust statistics based upon current size.
/ Handle some special monsters.
/************************************************************************/
struct monster Othermonster
; /* to find a name for mimics */
which
= MIN(which
, 99); /* make sure within range */
fseek(Monstfp
, (long) which
* (long) SZ_MONSTERSTRUCT
, 0);
fread((char *) &Curmonster
, SZ_MONSTERSTRUCT
, 1, Monstfp
);
/* handle some special monsters */
if (Curmonster
.m_type
== SM_MODNAR
)
if (Player
.p_specialtype
< SC_COUNCIL
)
/* randomize some stats */
Curmonster
.m_strength
*= drandom() + 0.5;
Curmonster
.m_brains
*= drandom() + 0.5;
Curmonster
.m_speed
*= drandom() + 0.5;
Curmonster
.m_energy
*= drandom() + 0.5;
Curmonster
.m_experience
*= drandom() + 0.5;
Curmonster
.m_treasuretype
=
(int) ROLL(0.0, (double) Curmonster
.m_treasuretype
);
/* make Modnar into Morgoth */
strcpy(Curmonster
.m_name
, "Morgoth");
Curmonster
.m_strength
= drandom() * (Player
.p_maxenergy
+ Player
.p_shield
) / 1.4
+ drandom() * (Player
.p_maxenergy
+ Player
.p_shield
) / 1.5;
Curmonster
.m_brains
= Player
.p_brains
;
Curmonster
.m_energy
= Player
.p_might
* 30.0;
Curmonster
.m_type
= SM_MORGOTH
;
Curmonster
.m_speed
= Player
.p_speed
* 1.1
+ (Player
.p_specialtype
== SC_EXVALAR
) ? Player
.p_speed
: 0.0;
Curmonster
.m_flock
= 0.0;
Curmonster
.m_treasuretype
= 0;
Curmonster
.m_experience
= 0.0;
else if (Curmonster
.m_type
== SM_MIMIC
)
which
= (int) ROLL(0.0, 100.0);
fseek(Monstfp
, (long) which
* (long) SZ_MONSTERSTRUCT
, 0);
fread(&Othermonster
, SZ_MONSTERSTRUCT
, 1, Monstfp
);
strcpy(Curmonster
.m_name
, Othermonster
.m_name
);
truncstring(Curmonster
.m_name
);
if (Curmonster
.m_type
!= SM_MORGOTH
)
/* adjust stats based on which circle player is in */
Curmonster
.m_strength
*= (1.0 + Circle
/ 2.0);
Curmonster
.m_brains
*= Circle
;
Curmonster
.m_speed
+= Circle
* 1.e
-9;
Curmonster
.m_energy
*= Circle
;
Curmonster
.m_experience
*= Circle
;
/* cannot see monster if blind */
Enemyname
= Curmonster
.m_name
;
if (Player
.p_speed
<= 0.0)
/* make Player.p_speed positive */
Curmonster
.m_speed
+= -Player
.p_speed
;
/* fill up the rest of the structure */
Curmonster
.m_o_strength
= Curmonster
.m_strength
;
Curmonster
.m_o_speed
= Curmonster
.m_maxspeed
= Curmonster
.m_speed
;
Curmonster
.m_o_energy
= Curmonster
.m_energy
;
Curmonster
.m_melee
= Curmonster
.m_skirmish
= 0.0;
/************************************************************************
/ FUNCTION NAME: awardtreasure()
/ FUNCTION: select a treasure
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: pickmonster(), collecttaxes(), more(), cursedtreasure(),
/ floor(), wmove(), drandom(), sscanf(), printw(), altercoordinates(),
/ longjmp(), infloat(), waddstr(), getanswer(), getstring(), wclrtobot()
/ GLOBAL INPUTS: Somebetter[], Curmonster, Whichmonster, Circle, Player,
/ *stdscr, Databuf[], *Statptr, Fightenv[]
/ GLOBAL OUTPUTS: Whichmonster, Shield, Player
/ Roll up a treasure based upon monster type and size, and
/ certain player statistics.
/ Handle cursed treasure.
/************************************************************************/
register int whichtreasure
; /* calculated treasure to grant */
int temp
; /* temporary */
double treasuretype
; /* monster's treasure type */
double gold
= 0.0; /* gold awarded */
double gems
= 0.0; /* gems awarded */
double dtemp
; /* for temporary calculations */
whichtreasure
= (int) ROLL(1.0, 3.0); /* pick a treasure */
treasuretype
= (double) Curmonster
.m_treasuretype
;
if (Curmonster
.m_treasuretype
> 7)
gems
= ROLL(1.0, (treasuretype
- 7.0)
* (treasuretype
- 7.0) * (Circle
- 1.0) / 4.0);
printw("You have discovered %.0f gems!", gems
);
gold
= ROLL(treasuretype
* 10.0, treasuretype
* treasuretype
* 10.0 * (Circle
- 1.0));
printw("You have found %.0f gold pieces.", gold
);
addstr(" Do you want to pick them up ? ");
ch
= getanswer("NY", FALSE
);
if (drandom() < treasuretype
/ 35.0 + 0.04)
addstr("They were cursed!\n");
collecttaxes(gold
, gems
);
addstr("You have found some treasure. Do you want to inspect it ? ");
ch
= getanswer("NY", FALSE
);
if (drandom() < 0.08 && Curmonster
.m_treasuretype
!= 4)
addstr("It was cursed!\n");
switch (Curmonster
.m_treasuretype
)
case 1: /* treasure type 1 */
addstr("You've discovered a power booster!\n");
Player
.p_mana
+= ROLL(Circle
* 4.0, Circle
* 30.0);
addstr("You have encountered a druid.\n");
ROLL(0.0, 2000.0 + Circle
* 400.0);
addstr("You have found a holy orb.\n");
Player
.p_sin
= MAX(0.0, Player
.p_sin
- 0.25);
/* end treasure type 1 */
case 2: /* treasure type 2 */
addstr("You have found an amulet.\n");
addstr("You've found some holy water!\n");
addstr("You've met a hermit!\n");
Player
.p_mana
+= 12.0 * Circle
;
/* end treasure type 2 */
case 3: /* treasure type 3 */
dtemp
= ROLL(7.0, 30.0 + Circle
/ 10.0);
printw("You've found a +%.0f shield!\n", dtemp
);
if (dtemp
>= Player
.p_shield
)
addstr("You have rescued a virgin. Will you be honorable ? ");
ch
= getanswer("NY", FALSE
);
Player
.p_experience
+= 2000.0 * Circle
;
addstr("You've discovered some athelas!\n");
/* end treasure type 3 */
case 4: /* treasure type 4 */
addstr("You've found a scroll. Will you read it ? ");
ch
= getanswer("NY", FALSE
);
switch ((int) ROLL(1, 6))
addstr("It throws up a shield for you next monster.\n");
getyx(stdscr
, whichtreasure
, ch
);
(Player
.p_maxenergy
+ Player
.p_energy
) * 5.5 + Circle
* 50.0;
Whichmonster
= pickmonster();
addstr("It makes you invisible for you next monster.\n");
getyx(stdscr
, whichtreasure
, ch
);
Whichmonster
= pickmonster();
addstr("It increases your strength ten fold to fight your next monster.\n");
getyx(stdscr
, whichtreasure
, ch
);
Whichmonster
= pickmonster();
addstr("It is a general knowledge scroll.\n");
Player
.p_brains
+= ROLL(2.0, Circle
);
Player
.p_magiclvl
+= ROLL(1.0, Circle
/ 2.0);
addstr("It tells you how to pick your next monster.\n");
addstr("Which monster do you want [0-99] ? ");
Whichmonster
= (int) infloat();
Whichmonster
= MIN(99, MAX(0, Whichmonster
));
addstr("It was cursed!\n");
/* end treasure type 4 */
case 5: /* treasure type 5 */
dtemp
= ROLL(Circle
/ 4.0 + 5.0, Circle
/ 2.0 + 9.0);
printw("You've discovered a +%.0f dagger.\n", dtemp
);
if (dtemp
>= Player
.p_sword
)
dtemp
= ROLL(7.5 + Circle
* 3.0, Circle
* 2.0 + 160.0);
printw("You have found some +%.0f armour!\n", dtemp
);
if (dtemp
>= Player
.p_shield
)
addstr("You've found a tablet.\n");
Player
.p_brains
+= 4.5 * Circle
;
/* end treasure type 5 */
case 6: /* treasure type 6 */
addstr("You've found a priest.\n");
Player
.p_energy
= Player
.p_maxenergy
+ Player
.p_shield
;
Player
.p_mana
+= 24.0 * Circle
;
Player
.p_brains
+= Circle
;
addstr("You have come upon Robin Hood!\n");
Player
.p_shield
+= Circle
* 2.0;
Player
.p_strength
+= Circle
/ 2.5 + 1.0;
dtemp
= ROLL(2.0 + Circle
/ 4.0, Circle
/ 1.2 + 10.0);
printw("You have found a +%.0f axe!\n", dtemp
);
if (dtemp
>= Player
.p_sword
)
/* end treasure type 6 */
case 7: /* treasure type 7 */
addstr("You've discovered a charm!\n");
addstr("You have encountered Merlyn!\n");
Player
.p_brains
+= Circle
+ 5.0;
Player
.p_magiclvl
+= Circle
/ 3.0 + 5.0;
Player
.p_mana
+= Circle
* 10.0;
dtemp
= ROLL(5.0 + Circle
/ 3.0, Circle
/ 1.5 + 20.0);
printw("You have found a +%.0f war hammer!\n", dtemp
);
if (dtemp
>= Player
.p_sword
)
/* end treasure type 7 */
case 8: /* treasure type 8 */
addstr("You have found a healing potion.\n");
Player
.p_poison
= MIN(-2.0, Player
.p_poison
- 2.0);
addstr("You have discovered a transporter. Do you wish to go anywhere ? ");
ch
= getanswer("NY", FALSE
);
addstr("X Y Coordinates ? ");
getstring(Databuf
, SZ_DATABUF
);
sscanf(Databuf
, "%lf %lf", &x
, &y
);
altercoordinates(x
, y
, A_FORCED
);
dtemp
= ROLL(10.0 + Circle
/ 1.2, Circle
* 3.0 + 30.0);
printw("You've found a +%.0f sword!\n", dtemp
);
if (dtemp
>= Player
.p_sword
)
/* end treasure type 8 */
case 13: /* treasure types 10 - 13 */
if (Curmonster
.m_treasuretype
== 10)
addstr("You've found a pair of elven boots!\n");
Player
.p_quickness
+= 2.0;
else if (Curmonster
.m_treasuretype
== 11
addstr("You've acquired Saruman's palantir.\n");
Player
.p_palantir
= TRUE
;
else if (Player
.p_ring
.ring_type
== R_NONE
&& Player
.p_specialtype
< SC_COUNCIL
&& (Curmonster
.m_treasuretype
== 12
|| Curmonster
.m_treasuretype
== 13))
if (Curmonster
.m_treasuretype
== 12)
whichtreasure
= R_NAZREG
;
temp
= 15 + Statptr
->c_ringduration
+ (int) ROLL(0,5);
addstr("You've discovered a ring. Will you pick it up ? ");
ch
= getanswer("NY", FALSE
);
Player
.p_ring
.ring_type
= whichtreasure
;
Player
.p_ring
.ring_duration
= temp
;
/* end treasure types 10 - 13 */
/* fall through to treasure type 9 if no treasure from above */
case 9: /* treasure type 9 */
if (Player
.p_level
<= 1000.0
&& Player
.p_level
>= 10.0)
addstr("You have found a golden crown!\n");
/* fall through otherwise */
addstr("You've been blessed!\n");
Player
.p_blessing
= TRUE
;
Player
.p_energy
= Player
.p_maxenergy
+ Player
.p_shield
;
Player
.p_mana
+= 100.0 * Circle
;
dtemp
= ROLL(1.0, Circle
/ 5.0 + 5.0);
dtemp
= MIN(dtemp
, 99.0);
printw("You have discovered some +%.0f quicksilver!\n",dtemp
);
if (dtemp
>= Player
.p_quksilver
)
Player
.p_quksilver
= dtemp
;
/* end treasure type 9 */
/************************************************************************
/ FUNCTION NAME: cursedtreasure()
/ FUNCTION: take care of cursed treasure
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: waddstr()
/ GLOBAL INPUTS: Player, *stdscr
/ Handle cursed treasure. Look for amulets and charms to save
/ the player from the curse.
/************************************************************************/
addstr("But your charm saved you!\n");
else if (Player
.p_amulets
> 0)
addstr("But your amulet saved you!\n");
Player
.p_energy
= (Player
.p_maxenergy
+ Player
.p_shield
) / 10.0;
/************************************************************************
/ FUNCTION NAME: scramblestats()
/ FUNCTION: scramble some selected statistics
/ AUTHOR: E. A. Estes, 12/4/85
/ MODULES CALLED: floor(), drandom()
/ Swap a few player statistics randomly.
/************************************************************************/
double dbuf
[6]; /* to put statistic in */
double dtemp1
, dtemp2
; /* for swapping values */
register int first
, second
; /* indices for swapping */
register double *dptr
; /* pointer for filling and emptying buf[] */
*dptr
++ = Player
.p_strength
;
*dptr
++ = Player
.p_brains
;
*dptr
++ = Player
.p_magiclvl
;
*dptr
++ = Player
.p_energy
;
/* pick values to swap */
first
= (int) ROLL(0, 5);
second
= (int) ROLL(0, 5);
/* this expression is split to prevent a compiler loop on some compilers */
Player
.p_strength
= *dptr
++;
Player
.p_brains
= *dptr
++;
Player
.p_magiclvl
= *dptr
++;
Player
.p_energy
= *dptr
++;