/* * fight.c Phantasia monster fighting routine * * 1.1 (2.11BSD) 1996/10/26 */ /* * The code exists here for fight to the finish. Simply add code to * set 'fgttofin = TRUE' as an option. Everything else is here. */ #include "phant.h" void fight(stat,particular) /* monster fighting routine */ reg struct stats *stat; int particular; { bool fghttofin = FALSE, luckout = FALSE; char aline[80]; double monhit, mdamage, sdamage, monspd, maxspd, inflict, monstr, temp, shield; int ch; reg int whichm, size, hwmany, lines; struct mstats monster; fghting = changed = TRUE; shield = 0.0; if (setjmp(fightenv) == 2) shield = roll(100 + (stat->mxn + stat->shd)*6.2,3000); hwmany = 0; size = (valhala) ? stat->lvl/5 : circ(stat->x,stat->y); if (particular >= 0) whichm = particular; else if (marsh) whichm = roll(0,15); else if (size > 24) whichm = roll(14,86); else if (size > 15) whichm = roll(0,50) + roll(14,37); else if (size > 8) whichm = roll(0,50) + roll(14,26); else if (size > 3) whichm = roll(14,50); else whichm = roll(14,25); CALL: move(3,0); clrtobot(); move(5,0); lines = 6; callmonster(whichm,size,&monster); if (stat->blind) strcpy(monster.name,"a monster"); ++hwmany; if (monster.typ == 1) /* unicorn */ if (stat->vrg) { printw("You just subdued %s, thanx to the virgin.",monster.name); stat->vrg = FALSE; goto FINISH; } else { printw("You just saw %s running away!",monster.name); goto LEAVE; } if (monster.typ == 2 && stat->typ > 20) { strcpy(monster.name,"Morgoth"); monster.str = rnd()*(stat->mxn + stat->shd)/1.4 + rnd()*(stat->mxn + stat->shd)/1.5; monster.brn = stat->brn; monster.hit = stat->str*30; monster.typ = 23; monster.spd = speed*1.1 + speed*(stat->typ == 90); monster.flk = monster.trs = monster.exp = 0; mvprintw(4,0,"You've encountered %s, Bane of the Council and Valar.",monster.name); } fghttofin = luckout = FALSE; monstr = monster.str; monhit = monster.hit; mdamage = sdamage = 0; monspd = maxspd = monster.spd; *monster.name = toupper(*monster.name); TOP: mvprintw(5,0,"You are being attacked by %s, EXP: %.0f (Size: %d)",monster.name,monster.exp,size); printstats(stat); mvprintw(1,26,"%20.0f",stat->nrg + shield); if (monster.typ == 4 && stat->bls && stat->chm) { mvprintw(6,0,"You just overpowered %s!",monster.name); lines = 7; stat->bls = FALSE; --stat->chm; goto FINISH; } monster.spd = min(monster.spd + 1,maxspd); if (rnd()*monster.spd > rnd()*speed && monster.typ != 4 && monster.typ != 16) { if (monster.typ) switch (monster.typ) /* do special things */ { case 5: /* Leanan-Sidhe */ if (rnd() > 0.25) goto NORMALHIT; inflict = roll(1,(size - 1)/2); inflict = min(stat->str,inflict); mvprintw(lines++,0,"%s sapped %0.f of your strength!",monster.name,inflict); stat->str -= inflict; strength -= inflict; break; case 6: /* Saruman */ if (stat->pal) { mvprintw(lines++,0,"Wormtongue stole your palantir!"); stat->pal = FALSE; } else if (rnd() > 0.2) goto NORMALHIT; else if (rnd() > 0.5) { mvprintw(lines++,0,"%s transformed your gems into gold!",monster.name); stat->gld += stat->gem; stat->gem = 0.0; } else { mvprintw(lines++,0,"%s scrambled your stats!",monster.name); scramble(stat); } break; case 7: /* Thaumaturgist */ if (rnd() > 0.15) goto NORMALHIT; mvprintw(lines++,0,"%s transported you!",monster.name); stat->x += sgn(stat->x)*roll(50*size,250*size); stat->y += sgn(stat->y)*roll(50*size,250*size); goto LEAVE; case 8: /* Balrog */ inflict = roll(10,monster.str); inflict = min(stat->exp,inflict); mvprintw(lines++,0,"%s took away %0.f experience points.",monster.name,inflict); stat->exp -= inflict; break; case 9: /* Vortex */ if (rnd() > 0.2) goto NORMALHIT; inflict = roll(0,7.5*size); inflict = min(stat->man,floor(inflict)); mvprintw(lines++,0,"%s sucked up %.0f of your manna!",monster.name,inflict); stat->man -= inflict; break; case 10: /* Nazgul */ if (rnd() > 0.3) goto NORMALHIT; if (stat->rng.type && stat->rng.type < 10) { mvaddstr(lines++,0,"Will you relinguish your ring ? "); ch = rgetch(); if (toupper(ch) == 'Y') { stat->rng.type = NONE; goto LEAVE; } } mvprintw(lines++,0,"%s neutralized 1/5 of your brain!",monster.name); stat->brn *= 0.8; break; case 11: /* Tiamat */ if (rnd() > 0.6) goto NORMALHIT; mvprintw(lines++,0,"%s took half your gold and gems and flew off.",monster.name); stat->gld = floor(stat->gld/2); stat->gem = floor(stat->gem/2); goto LEAVE; case 12: /* Kobold */ if (rnd() >.7) goto NORMALHIT; mvprintw(lines++,0,"%s stole one gold piece and ran away.",monster.name); stat->gld = max(0,stat->gld-1); goto LEAVE; case 13: /* Shelob */ if (rnd() > 0.5) goto NORMALHIT; mvprintw(lines++,0,"%s has bitten and poisoned you!",monster.name); ++stat->psn; break; case 14: /* Faeries */ if (!stat->hw) goto NORMALHIT; mvprintw(lines++,0,"Your holy water killed it!"); --stat->hw; goto FINISH; case 15: /* Lamprey */ if (rnd() > 0.7) goto NORMALHIT; mvprintw(lines++,0,"%s bit and poisoned you!",monster.name); stat->psn += 0.25; break; case 17: /* Bonnacon */ if (rnd() > 0.1) goto NORMALHIT; mvprintw(lines++,0,"%s farted and scampered off.",monster.name); stat->nrg /= 2; goto LEAVE; case 18: /* Smeagol */ if (rnd() > 0.5 || !stat->rng.type) goto NORMALHIT; mvprintw(lines++,0,"%s tried to steal your ring, ",monster.name); if (rnd() > 0.1) addstr("but was unsuccessful."); else { addstr("and ran away with it!"); stat->rng.type = NONE; goto LEAVE; } break; case 19: /* Succubus */ if (rnd() > 0.3) goto NORMALHIT; inflict = roll(15,size*10); inflict = min(inflict,stat->nrg); mvprintw(lines++,0,"%s sapped %0.f of your energy.",monster.name,inflict); stat->nrg -= inflict; break; case 20: /* Cerberus */ if (rnd() > 0.25) goto NORMALHIT; mvprintw(lines++,0,"%s took all your metal treasures!",monster.name); stat->swd = stat->shd =stat->gld = stat->crn = 0; goto LEAVE; case 21: /* Ungoliant */ if (rnd() > 0.1) goto NORMALHIT; mvprintw(lines++,0,"%s poisoned you, and took one quik.",monster.name); stat->psn += 5; --stat->quk; break; case 22: /* Jabberwock */ if (rnd() > 0.1) goto NORMALHIT; mvprintw(lines++,0,"%s flew away, and left you to contend with one of its friends.",monster.name); whichm = 55 + 22*(rnd() > 0.5); goto CALL; case 24: /* Troll */ if (rnd() > 0.5) goto NORMALHIT; mvprintw(lines++,0,"%s partially regenerated his energy.!",monster.name); monster.hit += floor((monhit*size - monster.hit)/2); monster.str = monstr; mdamage = sdamage = 0; maxspd = monspd; break; case 25: /* wraith */ if (rnd() > 0.3 || stat->blind) goto NORMALHIT; mvprintw(lines++,0,"%s blindeed you!",monster.name); stat->blind = TRUE; break; default: goto NORMALHIT; } else NORMALHIT: { inflict = rnd()*monster.str + 0.5; mvprintw(lines++,0,"%s hit you %.0f times!",monster.name,inflict); SPECIALHIT: if ((shield -= inflict) < 0) { stat->nrg += shield; shield = 0; } } } else { if (fghttofin) goto MELEE; mvaddstr(3,0,"1:Melee 2:Skirmish 3:Evade 4:Spell 5:Nick "); if (!luckout) if (monster.typ == 23) addstr("6:Ally "); else addstr("6:Luckout "); if (stat->rng.type > 0) addstr("7:Use Ring "); else clrtoeol(); ch = gch(stat->rng.type); move(lines = 6,0); clrtobot(); switch (ch) { default: case '1': /* melee */ MELEE: inflict = roll(strength/2 + 5,1.3*strength) + (stat->rng.type < 0 ? strength : 0); mdamage += inflict; monster.str = monstr - mdamage/monhit*monstr/4; goto HITMONSTER; case '2': /* skirmish */ inflict = roll(strength/3 + 3,1.1*strength) + (stat->rng.type < 0 ? strength : 0); sdamage += inflict; maxspd = monspd - sdamage/monhit*monspd/4; goto HITMONSTER; case '3': /* evade */ if ((monster.typ == 4 || monster.typ == 16 || rnd()*speed*stat->brn > rnd()*monster.spd*monster.brn) && (monster.typ != 23)) { mvaddstr(lines++,0,"You got away!"); stat->x += roll(-2,5); stat->y += roll(-2,5); goto LEAVE; } else mvprintw(lines++,0,"%s is still after you!",monster.name); break; case '4': /* spell */ lines = 7; mvaddstr(3,0,"\n\n"); mvaddstr(3,0,"1:All or Nothing"); if (stat->mag >= 3) mvaddstr(3,18,"2:Magic Bolt"); if (stat->mag >= 7) mvaddstr(3,32,"3:Force Field"); if (stat->mag >= 10) mvaddstr(3,47,"4:Transform"); if(stat->mag >= 15) mvaddstr(3,60,"5:Increase Might\n"); if (stat->mag >= 20) mvaddstr(4,0,"6:Invisibility"); if (stat->mag >= 25) mvaddstr(4,18,"7:Transport"); if (stat->mag >= 30) mvaddstr(4,32,"8:Paralyze"); if (stat->typ > 20) mvaddstr(4,52,"9:Specify"); mvaddstr(6,0,"Spell ? "); ch = rgetch(); mvaddstr(3,0,"\n\n"); if (monster.typ == 23 && ch != '4') illspell(); else switch (ch) { case '1': /* all or nothing */ { inflict = (rnd() < 0.25) ? (monster.hit*1.0001 + 1) : 0; if (monster.typ == 4) inflict *= .9; if (stat->man) --stat->man; maxspd *= 2; monspd *= 2; monster.spd = max(1,monster.spd * 2); monstr = monster.str *= 2; goto HITMONSTER; } case '2': /* magic bolt */ if (stat->mag < 3) illspell(); else { do { mvaddstr(6,0,"How much manna for bolt? "); getstring(aline,80); sscanf(aline,"%F",&temp); } while (temp < 0 || temp > stat->man); stat->man -= floor(temp); inflict = temp*roll(10,sqrt(stat->mag/3.0 + 1.0)); mvaddstr(6,0,"Magic Bolt fired!\n"); if (monster.typ == 4) inflict = 0.0; goto HITMONSTER; } case '5': /* increase might */ { if (stat->mag < 15) illspell(); else if (stat->man < 55) nomanna(); else { stat->man -= 55; strength += (1.2*(stat->str+stat->swd)+5-strength)/2; mvprintw(6,0,"New strength: %.0f\n",strength); } break; } case '3': /* force field */ { if (stat->mag < 7) illspell(); else if (stat->man < 20) nomanna(); else { shield = (stat->mxn + stat->shd)*4.2 + 45; stat->man -= 20; mvaddstr(6,0,"Force Field up.\n"); } break; } case '4': /* transform */ { if (stat->mag < 10) illspell(); else if (stat->man < 35) nomanna(); else { stat->man -= 35; whichm = roll(0,100); goto CALL; } break; } case '6': /* invisible */ { if (stat->mag < 20) illspell(); else if (stat->man < 45) nomanna(); else { stat->man -= 45; speed += (1.2*(stat->quk+stat->quks)+5-speed)/2; mvprintw(6,0,"New quik : %.0f\n",speed); } break; } case '7': /* transport */ { if (stat->mag < 25) illspell(); else if (stat->man < 50) nomanna(); else { stat->man -= 50; if (stat->brn + stat->mag < monster.exp/300*rnd()) { mvaddstr(6,0,"Transport backfired!\n"); stat->x += (250*size*rnd() + 50*size)*sgn(stat->x); stat->y += (250*size*rnd() + 50*size)*sgn(stat->y); goto LEAVE; } else { mvprintw(6,0,"%s is transported.\n",monster.name); monster.trs *= (rnd() > 0.3); goto FINISH; } } break; } case '8': /* paralyze */ { if (stat->mag < 30) illspell(); else if (stat->man < 60) nomanna(); else { stat->man -= 60; if (stat->mag > monster.exp/1000*rnd()) { mvprintw(6,0,"%s is held.\n",monster.name); monster.spd = -2; } else mvaddstr(6,0,"Monster unaffected.\n"); } break; } case '9': /* specify */ { if (stat->typ < 20) illspell(); else if (stat->man < 1000) nomanna(); else { mvaddstr(6,0,"Which monster do you want [0-99] ? "); whichm = inflt(); whichm = max(0,min(99,whichm)); stat->man -= 1000; goto CALL; } break; } } break; case '5': inflict = 1 + stat->swd; stat->exp += floor(monster.exp/10); monster.exp *= 0.92; maxspd += 2; monster.spd = (monster.spd < 0) ? 0 : monster.spd + 2; if (monster.typ == 4) { mvprintw(lines++,0,"You hit %s %.0f times, and made him mad!",monster.name,inflict); stat->quk /= 2; stat->x += sgn(stat->x)*roll(50*size,250*size); stat->y += sgn(stat->y)*roll(50*size,250*size); stat->y += (250*size*rnd() + 50*size)*sgn(stat->y); goto LEAVE; } else goto HITMONSTER; case '6': /* luckout */ if (luckout) mvaddstr(lines++,0,"You already tried that."); else if (monster.typ == 23) if (rnd() < stat->sin/100) { mvprintw(lines++,0,"%s accepted!",monster.name); goto LEAVE; } else { luckout = TRUE; mvaddstr(lines++,0,"Nope, he's not interested."); } else if ((rnd() + .333)*stat->brn < (rnd() + .333)*monster.brn) { luckout = TRUE; mvprintw(lines++,0,"You blew it, %s.",stat->name); } else { mvaddstr(lines++,0,"You made it!"); goto FINISH; } break; case '\014': /* clear screen */ clear(); break; case '7': /* use ring */ if (stat->rng.type > 0) { mvaddstr(lines++,0,"Now using ring."); stat->rng.type = -stat->rng.type; if (abs(stat->rng.type) != DLREG) --stat->rng.duration; goto NORMALHIT; } break; } goto BOT; HITMONSTER: { inflict = floor(inflict); mvprintw(lines++,0,"You hit %s %.0f times!",monster.name,inflict); if ((monster.hit -= inflict) >0) switch (monster.typ) { case 4: /* dark lord */ inflict = stat->nrg + shield +1; goto SPECIALHIT; case 16: /* shrieker */ mvaddstr(lines++,0,"Shreeeek!! You scared it, and it called one of its friends."); paws(lines); whichm = roll(70,30); goto CALL; } else { if (monster.typ == 23) /* morgoth */ mvaddstr(lines++,0,"You have defeated Morgoth, but he may return. . ."); else mvprintw(lines++,0,"You killed it. Good work, %s.",stat->name); goto FINISH; } } } BOT: refresh(); if (lines == 23) { paws(23); move(lines = 6,0); clrtobot(); } if (stat->nrg <= 0) { paws(lines); death(stat); goto LEAVE; } goto TOP; FINISH: stat->exp += monster.exp; if (rnd() < monster.flk/100.0) /* flock monster */ { paws(lines); fghttofin = FALSE; goto CALL; } else if (size > 1 && monster.trs && rnd() > pow(0.6,(double) (hwmany/3 + size/3))) /* this takes # of flocks and size into account */ { paws(lines); treasure(stat,monster.trs,size); } LEAVE: stat->rng.type = abs(stat->rng.type); paws(lines+3); move(4,0); clrtobot(); fghting = FALSE; }