|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T a
Length: 18528 (0x4860) Types: TextFile Names: »arms.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Rog-O-Matic/arms.c«
/* * arms.c: Rog-O-Matic XIV (CMU) Thu Jan 31 15:46:02 1985 - mlm * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin * * This file contains all utility functions which exist for armor, * weapons and rings. */ # include <curses.h> # include "types.h" # include "globals.h" /* * havearmor: Return Kth best armor. K should be in the range 1 to invcount. * If K is greater than the number of pieces of armor we have, * then NONE is returned. Will not return cursed armor or * armor worse than wearing nothing. */ # define swap(x,y) {t=(x); (x)=(y); (y)=t;} int havearmor (k, print, rustproof) { register int i, j, w, t, n=0; int armind[MAXINV], armval[MAXINV]; /* Sort armor by armor class (best first) */ for (i=0; i<invcount; ++i) { if (inven[i].count && inven[i].type == armor && ! (rustproof && willrust (i))) { n++; w = armorclass (i); for (j = n-1; j > 0 && w <= armval[j-1]; j--) { swap (armind[j], armind[j-1]); swap (armval[j], armval[j-1]); } armind[j] = i; armval[j] = w; } } /* Put protected sets of armor with equal ACs first. DR UTexas 19 Jan 84 */ for (j = n-1; j > 0; j--) { if (armval[j] == armval[j-1]) { i = armind[j]; w = armind[j-1]; if (!itemis (w, PROTECTED) && itemis (i, PROTECTED)) swap (armind[j], armind[j-1]); } } if (print) { mvaddstr (1, 0, "Current Armor Rankings"); for (i = 0; i<n; i++) mvprintw (i+3, 8, "%2d: %3d %s", i+1, armval[i], itemstr (armind[i])); } /* Any uncursed, useful armor at or beyond position k? */ for (i=k; i <= n; i++) if (!itemis ((j = armind[i-1]), CURSED) && armval[j] < 10) return (j); /* Return the kth best, even though it is cursed or useless */ return ((k <= n) ? armind[k-1] : NONE); } /* * armorclass: Given the index of a piece of armor, return the armor * class. Assume modifiers of +2 for unknown armor when we have scrolls * of remove curse and -2 for when we don't have a remove curse. */ armorclass (i) int i; { int class; if (inven[i].type != armor) return (1000); if (stlmatch (inven[i].str, "leather")) class = 8; else if (stlmatch (inven[i].str, "ring")) class = 7; else if (stlmatch (inven[i].str, "studded")) class = 7; else if (stlmatch (inven[i].str, "scale")) class = 6; else if (stlmatch (inven[i].str, "chain")) class = 5; else if (stlmatch (inven[i].str, "splint")) class = 4; else if (stlmatch (inven[i].str, "banded")) class = 4; else if (stlmatch (inven[i].str, "plate")) class = 3; else class = 1000; /* Know the modifier exactly */ if (inven[i].phit != UNKNOWN) class -= inven[i].phit; /* Can remove curse, so assume it is +2 armor */ else if (havenamed (scroll, "remove curse") != NONE) class -= 2; /* Can't remove curse, assume it is -2 armor */ else class += 2; return (class); } /* * haveweapon: Return Kth best weapon. K should be in the range 1 to invcount. * If K is greater than the number of weapons we have, * then NONE is returned. */ int haveweapon (k, print) { register int i, j, w, t, n=0; int weapind[MAXINV], weapval[MAXINV]; for (i=0; i<invcount; ++i) if (inven[i].count && (w = weaponclass (i)) > 0) { n++; for (j = n-1; j > 0 && w >= weapval[j-1]; j--) { swap (weapind[j], weapind[j-1]); swap (weapval[j], weapval[j-1]); } weapind[j] = i; weapval[j] = w; } /* * Put enchanted weapons above unenchanted ones if the weapon * ratings are equal. DR UTexas 25 Jan 84 */ for (j = n-1; j > 0; j--) { if (weapval[j] == weapval[j-1]) { i = weapind[j]; w = weapind[j-1]; if (!itemis (w, ENCHANTED) && itemis (i, ENCHANTED) && !itemis (w, KNOWN) && !itemis (i, KNOWN)) { swap (weapind[j], weapind[j-1]); } } } if (print) { mvaddstr (1, 0, "Current Weapon Rankings"); for (i = 0; i<n; i++) mvprintw (i+3, 8, "%2d: %5d %s", i+1, weapval[i], itemstr (weapind[i])); } return ((k <= n) ? weapind[k-1] : NONE); } /* * weaponclass: Given the index of a weapon, return the weapon class. * This is the average damage done + 3/2 the plus to * hit, multiplied by 10. Magic arrows are given very * high numbers. */ weaponclass (i) int i; { int class, hitplus = 0, damplus = 0; /* Swords and maces are always valid weapons */ if (inven[i].type == hitter) ; /* Under special circumstances, arrows are valid weapons (Hee hee) */ else if (cheat && inven[i].type == missile && stlmatch (inven[i].str, "arrow")) ; /* Not a valid weapon */ else return (0); /* * Set the basic expected damage done by the weapon. */ if (stlmatch (inven[i].str, "mace")) class = 50; else if (stlmatch (inven[i].str, "two handed sword")) class = (version < RV52A) ? 105 : 100; else if (stlmatch (inven[i].str, "long sword")) class = (version < RV52A) ? 55 : 75; else if (stlmatch (inven[i].str, "arrow")) class = 10; else class = 0; /* Know the modifier exactly */ if (inven[i].phit != UNKNOWN) { hitplus += inven[i].phit; if (inven[i].pdam != UNKNOWN) damplus = inven[i].pdam; } /* * Strategy for "Magic Arrows". These are single arrows when * we are cheating. Since arrows normally come in clumps, and * since we have never (in cheat mode) thrown any, then a * single arrow must have come from a trap, and until it fails * to kill something, we assume it is a valuable arrow. */ else if (cheat && version <= RV36B && usingarrow && goodarrow > 20 && i == currentweapon) return (1800); else if (cheat && version <= RV36B && stlmatch (inven[i].str, "arrow") && inven[i].count == 1 && !itemis (i, WORTHLESS) && (!badarrow || i != currentweapon)) { hitplus = 50; damplus = 50; } hitplus = (hitplus < 100) ? hitplus : 100; damplus = (damplus < 200) ? damplus : 200; return (class + 12*hitplus + 10*damplus); } /* * havering: Return Kth best ring. K should be in the range 1 to invcount. * If K is greater than the number of rings we have, * then NONE is returned. */ int havering (k, print) { register int i, j, r, t, n=0; int ringind[MAXINV], ringval[MAXINV]; for (i=0; i<invcount; ++i) if (inven[i].count && (r = ringclass (i)) > 0) { n++; for (j = n-1; j > 0 && r >= ringval[j-1]; j--) { swap (ringind[j], ringind[j-1]); swap (ringval[j], ringval[j-1]); } ringind[j] = i; ringval[j] = r; } if (print) { mvaddstr (1, 0, "Current Ring Rankings"); for (i = 0; i<n; i++) mvprintw (i+3, 8, "%2d: %5d %s", i+1, ringval[i], itemstr (ringind[i])); } /* * Since rings are class [1-1000] if we don't want to wear them, * return the ring index only if its value is greater than 1000. */ return ((k <= n && ringval[k-1] > 1000) ? ringind[k-1] : NONE); } /* * ringclass: Given the index of a ring, return the ring class. * This is a subjective measure of how much good it * would do us to wear this ring. Values of [1-1000] indicates * that we should not wear this ring at all. A value of 0 * indicates a worthless ring. This routine uses the amount * of food available to decide how valuable rings are. * Worth evaluates the value of a ring by subtracting 1000 if * the ringclass is over 1000 to decide how valuable the ring * is, so we add 1000 to indicate that the ring should be worn * and try to assign values from 0 to 999 to determine the * value of the ring. */ ringclass (i) int i; { int class = 0, magicplus = 0; if (inven[i].type != ring) return (0); /* Get the magic plus */ if (inven[i].phit != UNKNOWN) { magicplus = inven[i].phit; } /* A ring of protection */ if (stlmatch (inven[i].str, "protection")) { if (magicplus > 0) class = (havefood (1) ? 1000 : 0) + 450; } /* A ring of add strength */ else if (stlmatch (inven[i].str, "add strength")) { if (itemis (i, INUSE) && magicplus > 0) { if (hitbonus (Str) == hitbonus (Str - magicplus * 100) && damagebonus (Str) == damagebonus (Str - magicplus * 100)) class = 400; else class = (havefood (1) ? 1000 : 0) + 400; } else if (magicplus > 0) { if (hitbonus (Str) == hitbonus (Str + magicplus * 100) && damagebonus (Str) == damagebonus (Str + magicplus * 100)) class = 400; else class = (havefood (1) ? 1000 : 0) + 400; } } /* A ring of sustain strength */ else if (stlmatch (inven[i].str, "sustain strength")) { /* A second ring of sustain strength is useless */ if (!itemis (i, INUSE) && wearing ("sustain strength") != NONE) class = 0; else class = (havefood (3) ? 1000 : 0) + (Level > 12 ? 150 : Str > 2000 ? 700 : Str > 1600 ? Str - 1200 : 100); } /* A ring of searching */ else if (stlmatch (inven[i].str, "searching")) { class = (havefood (0) ? 1000 : 0) + 250; } /* A ring of see invisible */ else if (stlmatch (inven[i].str, "see invisible")) { /* A second ring of see invisible is useless */ if (!itemis (i, INUSE) && wearing ("see invisible") != NONE) class = 0; /* * If we are beingstalked and we are wearing this ring, then * we should take it off and put it on to set the Rogue CANSEE * bit, which can be unset by a second ring of see invisible or * by a see invisible potion wearing off. MLM */ else if (itemis (i, INUSE) && beingstalked) class = 800; /* * When we put the ring on, keep its importance high for 20 * turns, just in case the beast comes back to haunt us. MLM */ else class = (beingstalked || turns - putonseeinv < 20) ? 1999 : ((havefood (0) && Level > 15 && Level < 26) ? 1000 : 0) + 300; } /* A ring of adornment */ else if (stlmatch (inven[i].str, "adornment")) { class = 0; } /* A ring of aggravate monster */ else if (stlmatch (inven[i].str, "aggravate monster")) { class = 0; } /* A ring of dexterity */ else if (stlmatch (inven[i].str, "dexterity")) { if (magicplus > 0) class = (havefood (0) ? 1000 : 0) + 475; } /* A ring of increase damage */ else if (stlmatch (inven[i].str, "increase damage")) { if (magicplus > 0) class = (havefood (0) ? 1000 : 0) + 500; } /* A ring of regeneration */ else if (stlmatch (inven[i].str, "regeneration")) { /* Analysis indicates that rings of regenerate DO NOT hold back */ /* the character after any level. They each add one hit point per */ /* turn of rest regardless of your level! MLM */ class = 50*(Hpmax-Hp-Explev) + 500; } /* A ring of slow digestion */ else if (stlmatch (inven[i].str, "slow digestion")) { /* A second ring of slow digestion is not too useful */ if (havefood (0) && !itemis (i, INUSE) && wearing ("slow digestion") != NONE) class = 1001; else { class = havefood (3) ? 1100 : havefood (2) ? 1300 : havefood (1) ? 1500 : havefood (0) ? 1900 : 1999 ; } } /* A ring of teleportation */ else if (stlmatch (inven[i].str, "telportation") || stlmatch (inven[i].str, "teleportation")) { class = 0; } /* A ring of stealth */ else if (stlmatch (inven[i].str, "stealth")) { /* A second ring of stealth is useless */ if (!itemis (i, INUSE) && wearing ("stealth") != NONE) class = 0; else { class = (havefood (1) ? 1000 : 0) + (Level > 17 ? 850 : Level > 12 ? 700 : 300); } } /* A ring of maintain armor */ else if (stlmatch (inven[i].str, "maintain armor")) { int bestarm, nextarm, armdiff; /* No rust monsters yet or cursed armor */ if (Level < 9 || cursedarmor) return (900); /* Past the rust monsters */ else if (Level > 18) return (300); /* A second ring of maintain armor is useless */ else if (!itemis (i, INUSE) && wearing ("maintain armor") != NONE) class = 0; else { bestarm = havearmor (1, NOPRINT, ANY); nextarm = havearmor (1, NOPRINT, RUSTPROOF); if (bestarm < 0) /* No armor to protect */ return (700); else if (!willrust (bestarm)) /* Armor wont rust anyway */ return (0); else if (nextarm < 0) /* Naked is AC 10 */ armdiff = 10 - armorclass (bestarm); else /* Get difference in classes */ armdiff = armorclass (nextarm) - armorclass (bestarm); class = (havefood (1) ? 1000 : 0) + 200 * armdiff; } } /* Not a known ring, forget it */ else return (0); /* A magical plus is worth 100 */ return (class + 100*magicplus); } /* * havebow: Return Kth best thrower. K should be in the range 1 to invcount. * If K is greater than the number of weapons we have, * then NONE is returned. */ int havebow (k, print) { register int i, j, w, t, n=0; int bowind[MAXINV], bowval[MAXINV]; for (i=0; i<invcount; ++i) if (inven[i].count && (w = bowclass (i)) > 0) { n++; for (j = n-1; j > 0 && w >= bowval[j-1]; j--) { swap (bowind[j], bowind[j-1]); swap (bowval[j], bowval[j-1]); } bowind[j] = i; bowval[j] = w; } if (print) { mvaddstr (1, 0, "Current Bow Rankings"); for (i = 0; i<n; i++) mvprintw (i+3, 8, "%2d: %5d %s", i+1, bowval[i], itemstr (bowind[i])); } return ((k <= n) ? bowind[k-1] : NONE); } /* * bowclass: Given the index of a bow, return the bow class. * This is the average damage done + 6/5 the plus to * hit, multiplied by 10. */ bowclass (i) int i; { int class, hitplus = 0, damplus = 0; if (inven[i].type == thrower && stlmatch (inven[i].str, "short bow") && havemult (missile, "arrow", 5) != NONE) class = 35; else return (0); /* Find the modifiers */ if (inven[i].phit != UNKNOWN) { hitplus += inven[i].phit; if (inven[i].pdam != UNKNOWN) damplus = inven[i].pdam; } return (class + 12*hitplus + 10*damplus); } /* * havemissile: Return best missile. Dont consider arrows if we * are cheating. Consider arrows first if we are wielding our bow. */ int havemissile () { register int i, fewest = 9999, obj = NONE; if (wielding (thrower)) /* Wielding bow, use arrows */ { for (i=0; i<invcount; ++i) if (inven[i].count > 0 && inven[i].count < fewest && inven[i].type == missile && stlmatch(inven[i].str,"arrow")) { obj = i; fewest = inven[i].count; } } if (obj < 0) /* Not wielding bow or no arrows */ { for (i=0; i<invcount; ++i) if (inven[i].count > 0 && inven[i].count < fewest && !itemis (i, INUSE) && (inven[i].type == missile || stlmatch(inven[i].str,"spear") || stlmatch(inven[i].str,"dagger") || stlmatch(inven[i].str,"mace") && inven[i].phit <= 0 || stlmatch(inven[i].str,"long sword") && inven[i].phit < 0)) { obj = i; fewest = inven[i].count; } } if (obj != NONE) dwait (D_BATTLE, "Havemissile returns (%s", itemstr (obj)); else dwait (D_BATTLE, "Havemissile fails"); return (obj); } /* * havearrow: return the index of any arrow which has count 1. */ havearrow () { int arr; for (arr = 0; arr<invcount; arr++) if (inven[arr].type == missile && inven[arr].count == 1 && stlmatch(inven[arr].str,"arrow")) return (arr); return (NONE); } /* * plusweapon: we just enchanted our current weapon. * Do a picky identify to try to find its plusses. */ plusweapon () { cursedweapon = 0; newweapon = 1; forget (currentweapon, CURSED); usesynch = 0; } /* * hitbonus: Return the bonus to hit. */ hitbonus (strength) int strength; { int bonus = 0; if (strength < 700) bonus = strength/100 - 7; else if (version > RV36B) { if (strength < 1700) bonus = 0; else if (strength < 2100) bonus = 1; else if (strength < 3100) bonus = 2; else bonus = 3; } else { if (strength < 1700) bonus = 0; else if (strength < 1851) bonus = 1; else if (strength < 1900) bonus = 2; else bonus = 3; } return (bonus); } /* * damagebonus: bonus = the damage bonus. */ damagebonus (strength) int strength; { int bonus = 0; if (strength < 700) bonus = strength/100 - 7; else if (version > RV36B) { if (strength < 1600) bonus = 0; else if (strength < 1800) bonus = 1; else if (strength < 1900) bonus = 2; else if (strength < 2100) bonus = 3; else if (strength < 2200) bonus = 4; else if (strength < 1600) bonus = 5; else bonus = 6; } else { if (strength < 1600) bonus = 0; else if (strength < 1800) bonus = 1; else if (strength < 1801) bonus = 2; else if (strength < 1876) bonus = 3; else if (strength < 1891) bonus = 4; else if (strength < 1900) bonus = 5; else bonus = 6; } return (bonus); } /* * setbonuses: Set global hit and damage pluses. */ setbonuses () { /* Set global Hit bonus */ gplushit = hitbonus (Str); if (leftring != NONE && stlmatch (inven[leftring].str, "dexterity") && inven[leftring].phit != UNKNOWN) gplushit += inven[leftring].phit; if (rightring != NONE && stlmatch (inven[rightring].str, "dexterity") && inven[rightring].phit != UNKNOWN) gplushit += inven[rightring].phit; /* Set global Damage Bonus */ gplusdam = damagebonus (Str); if (leftring != NONE && stlmatch (inven[leftring].str, "add damage") && inven[leftring].pdam != UNKNOWN) gplusdam += inven[leftring].pdam; if (rightring != NONE && stlmatch (inven[rightring].str, "add damage") && inven[rightring].pdam != UNKNOWN) gplusdam += inven[rightring].pdam; /* Set bonuses for weapons */ wplushit = gplushit; wplusdam = gplusdam; if (currentweapon != NONE) { if (inven[currentweapon].phit != UNKNOWN) wplushit += inven[currentweapon].phit; if (inven[currentweapon].pdam != UNKNOWN) wplusdam += inven[currentweapon].pdam; } }