package th; import java.util.Vector; import java.io.Serializable; // Structure for a creature (Mon[ster]), including the player, although // the player class extends this one. public class Mon implements Serializable { public static final int HIT_THRESH = 40; // Make higher to make hitting things harder. public static final String[] NOT_TALKATIVE = { " does not share your penchant for conversation.", " isn't much of a conversationalist.", " can't carry on a decent conversation.", " doesn't share your penchant for conversation.", " isn't very talkative." }; public static final String[] RABID_TALK = { "snarl|s|", "growl|s|", "hiss|es|", "make|s| vicious-sounding noises", "stare|s| at you with crazed look", "watch|es| you with murderous intent" }; public static final String[] BORG_TALK = { "YOU WILL BE ASSIMILATED", "RESISTANCE IS FUTILE", "EXTERMINATE! EXTERMINATE!", "YOU WILL BE ASSIMILATED. RESISTANCE IS FUTILE." }; // AI state constants public static final int SLEEPING = 0; public static final int WANDERING = 1; public static final int ATTACKING = 2; public static final int FLEEING = 3; public static final int PET = 4; public static final String[] string_status = { Ifc.color(Ifc.MAGENTA)+"(asleep)"+Ifc.color(), Ifc.color(Ifc.CYAN)+"(peaceful)"+Ifc.color(), Ifc.color(Ifc.BRIGHT_RED)+"(hostile)"+Ifc.color(), Ifc.color(Ifc.YELLOW)+"(fleeing)"+Ifc.color(), Ifc.color(Ifc.GREEN)+"(allied)"+Ifc.color() }; public static final String[] plain_string_status = { "(asleep)", "(peaceful)", "(hostile)", "(fleeing)", "(allied)" }; public String name; public Spe species; public int gender; public static int MALE = 1, FEMALE = 2, NEUTER = 0; public int in, st, hp, dx; public int min, mst, mhp, mdx; public int armor = 0; public int ap = 2; public int xap = 0; public MonSpecial special = null; public static String[] GENDER = {"ungendered", "male", "female", "both"}; boolean pet_attacked = false; // Been attacked by a pet? // Lose turn if stunned. public int stunned = 0; // AI state. public int ai = 0; public boolean xenophobic = false; // Your current alignment. int alignment = 0; String last_damage = "rolling really bad"; // 0 means it is sleeping. It will be passed over for AI until woken // up. public int ai_timer = 0; // Timer for sleep timeouts. // public Vector inventory = null; /// Where am I? Node here = null; // Am I holding anything? Itm wielded = null; boolean rabid = false; boolean cyborg = false; boolean dead = false; boolean resist_gas = false; boolean resist_chemical = false; boolean resist_bullets = false; boolean resist_polymorph = false; String stunner = null; // Stunned by anyone? // Killed any humans? // The player is mildly penalized for attacking // peaceful creatures (such as hamsters), somewhat more // severely punished for killing humans; there is considerable // score loss for canibalism, to discourage these behaviors. // (Note that eating gnomes is not canibalism, and killing the // nemesis is not murder.) int murders = 0; int peacefuls = 0; int canibal = 0; int vanquished = 0; int xp = 0; int level = 0; // Generate a photograph public String photograph(Mon photographer) { if (photographer.dx < Utl.rn(12)) return "A picture of " + Utl.rn("a flesh-tone blob|a blury finger|the lenscap"); if (photographer == this) return "A self-portrait of the photographer"+ (photographer.name != null? ", named "+photographer.name : "") +" as a "+species.name+" at level "+level; if (photographer.in < Utl.rn(8)) return "A picture of a "+photographer.species.name +"'s face, caused by holding the camera backwards."; if (rabid && Utl.rn()) return "A photo of a "+(species.human? "crazed " : "frothing ") +species.name; if (ai == PET && Utl.rn()) return "A photo of your pet " + species.name + (name != null? " named " + name : "") + "."; if (ai == SLEEPING && Utl.rn()) return "A photograph of a sleeping " + species.name; if (ai == ATTACKING && Utl.rn()) return "A blurry photo of an angry " + species.name; switch (Utl.rn(4)) { case 0: return "A photo of a " + species.name + (name != null? " named "+name : ""); case 1: return "A photo of a " + species.name + (name != null? " named "+name : "") +(wielded != null? " wielding a " + wielded.kind.name : ""); case 2: return "A photo of a " + species.name + (name != null? " named "+name : "") +(inventory.isEmpty()? "" : " with a " + ((Itm)Utl.rn(inventory)).kind.name); default: break; } if (species.photos == null) return "A picture of an unidentifiable blurr"; else return Utl.rn(species.photos); } // Do I like this creature? (Be peaceful?) public boolean i_like(Mon player) { if ((Utl.coaligned(this, player) || species.peaceful || (ai == PET && player.ai == PET)) && !player.rabid && !rabid && !(xenophobic && player == g.player)) return true; else return false; } // Check to see if I want to fight another creature. // public boolean will_fight(Mon player) { if (player == this) return false; if ((player.ai == PET || player == g.player) && ai == PET) return false; if (rabid) return true; if (!i_like(player) && !species.flees && hp >= mhp/2) { return true; } else return false; } // Take damage... public int damage(int damage, Mon attacker) { if (attacker == g.player && !rabid) species.peaceful = false; last_damage = (attacker.name != null? "The " + attacker.species.name + " called " + attacker.name : "a "+attacker.species.name) + (attacker.wielded != null? " wielding a " + attacker.wielded.kind.name : ""); damage -= armor; if (damage <= 0) Ifc.your("armor totally protected "+Ifc.him(this)+".", this); else hp -= damage; if (hp <= 0) die(attacker); if (ai == 0) ai = 1; return damage; } // Die... public void die(Mon killer) { if (this == g.player && g.debug && Ifc.yn("are about to die. Survive?")){ g.player.hp = g.player.mhp; g.player.dead = false; Ifc.msg("Okay so somehow you don't die."); return; } if (special != null) special.die(this, killer, here); if (dead) { //Ifc.you("hit|s| the " + species.name + ", but " + Ifc.he(this) + "'s already dead!", killer); return; } if (species.last_words != null) Ifc.msg(Ifc.color(Ifc.MAJOR_RED)+species.last_words+Ifc.color()); if (this.ai == PET) ++g.pets_lost; /*if (this.species == Species.nemesis) { Ifc.you(Ifc.color(Ifc.MAJOR_RED) +"feel a great disturbance in the force!" +Ifc.color()); }*/ ++species.dead; dead = true; if (killer != null) { ++killer.vanquished; killer.xp += 2*level + mhp + mst + (wielded != null? wielded.kind.damage : 0 ) + armor + min + mdx; killer.check_xp(); // note - add deadly weapon rule if (species.human && killer.species.human && !rabid) ++killer.murders; if (killer == g.player && !rabid && species.peaceful) Ifc.you(Ifc.color(Ifc.BRIGHT_RED)+species.die_verb+"|s| the poor "+species.name+"!" +Ifc.color()); else Ifc.you(Ifc.color(Ifc.BRIGHT_RED) +species.die_verb+"|s| "+Ifc.the_mon(this)+"!" +Ifc.color(), killer); } else { Ifc.you("|is| "+species.die_verb+"ed!", this); } here.mons.remove(this); Itm current; int max = inventory.size(); for (int i = 0; i < max; ++i) { current = (Itm)inventory.elementAt(0); current.wielded = false; current.worn = false; drop(current); } if (here != g.player.here) { Ifc.you("hear some noises in the distance."); if (g.debug) if (killer != null) Ifc.msg(Ifc.color(Ifc.MAJOR_CYAN)+"(It sounded like " +Ifc.the_mon(killer)+ "["+killer.species.name+" lv " +killer.level+"] killing " +Ifc.the_mon(this)+ "["+this.species.name+" lv "+this.level +"].)"+Ifc.color()); else Ifc.msg(Ifc.color(Ifc.MAJOR_CYAN)+"(It sounded like " +Ifc.the_mon(this) +"["+this.species.name+" lv "+this.level +"]. dying.)"+Ifc.color()); } else if (species.corpse == null) { Ifc.you("see the body vanish into thin air!"); } else { Ifc.you("see a "+species.corpse.name+" hit the ground."); Itm tmp = species.corpse.make(); tmp.living_form = this; if (name != null) tmp.name = name; if (rabid) tmp.tainted = true; here.add(tmp); } if (special != null) special.after_die(this, killer, here); g.delMon(this); } // Describe self in main display public String describe() { if (Tunnels.gmode == Tunnels.VT100) return describe_vt100(); else return describe_plain(); } public String describe_vt100 () { String tmp = (name != null? "The " + species.name + " named " + name : "A " + species.name); tmp += " " + string_status[ai]; return tmp + " " + (rabid? Ifc.color(Ifc.YELLOW)+(species.human? "(insane)" : "(rabid)")+Ifc.color() : "") + (cyborg? "(borg)" : "" + (stunned != 0? Ifc.color(Ifc.CYAN)+"(stunned)"+Ifc.color() : "")); } public String describe_plain () { String tmp = (name != null? "The " + species.name + " named " + name : "A " + species.name); tmp += " " + plain_string_status[ai]; return tmp + " " + (rabid? (species.human? "(insane)" : "(rabid)") : "") + (cyborg? "(borg)" : "") + (stunned != 0? "(stunned)" : ""); } //// Describe self in look display public String detailed_describe () { String tmp = (name != null? "The " + species.name + " named " + name : "A " + species.name) + " HP: " + Ifc.hpcolor(this) + hp + Ifc.color(); tmp += " " + string_status[ai] + ". "+GENDER[gender]+"\n Inventory:\n"; for (int i = 0; i < inventory.size(); ++i) tmp += " " + ((Itm)inventory.elementAt(i)).describe() +"\n"; return tmp; } public void check_xp() { if (xp > level * (100 + level*20)) { ++level; Ifc.you(Ifc.color(Ifc.BRIGHT_WHITE)+"seem|s| more experienced."+Ifc.color(), this); if (species.level == null) return; species.level.level_up(this); } } //Update the ai state (wake up, flee, etc.) private int update_ai () { if (hp <= 0) { die(null); return SLEEPING; } switch (ai) { // Okay, in state zero the creature isn't normally // going to have this function called at all, unless // the player has enetered the room. So, wake up. case SLEEPING: if (species.wake_text != null) Ifc.msg(Ifc.color(Ifc.MAJOR_WHITE)+species.wake_text+Ifc.color()); if (i_like(g.player)) { return WANDERING; // Peaceful wanderer } else if (will_fight(g.player)) { Ifc.you("wakes up and notices you.", this); return ATTACKING; //attack } else { Ifc.you("sees you and turns to flee!", this); return FLEEING; //flee } case WANDERING: if (here.mons.contains(g.player) && will_fight(g.player)) { Ifc.you("sees you.", this); return ATTACKING;// fight the player } else return WANDERING; //continue to be peaceful case ATTACKING: if (hp < mhp / 5 || species.flees) { Ifc.you("turns to flee!", this); return FLEEING; // run away! } else return ATTACKING; // Continue being hostile case FLEEING: if (hp >= mhp / 2) return WANDERING; else return FLEEING; case PET: return PET; default: Ifc.msg("AI fault"); return 0; } } public void do_talk(boolean pc_talking) { // needs to be rearanged if (pc_talking) { if (this == g.player) Ifc.you("have heard that talking to yourself is a sign of instability..."); if (rabid && !species.smart) Ifc.you(Utl.rn(RABID_TALK) + ".", this); else if (cyborg) Ifc.you("say|s| \"" + Utl.rn(BORG_TALK) + "\".", this); else if (species == Species.programmer) { switch (Utl.rn(4)) { case 0: if (g.player.murders > g.allow_murder) { Ifc.you("say|s| \"You are doomed.\"", this); } else if (g.player.murders == g.allow_murder) Ifc.you("say|s| \"Do not forgot the laws of the surface world.\"",this); else Ifc.you("watches you.", this); break; case 1: if (g.player.peacefuls > Utl.rn(g.player.level)) { Ifc.you("gazes at you, then says: \"Your wicked deeds are known to me, " + g.player.name + "! Prepare to die!", this); ai = ATTACKING; } else Ifc.you("stares at you.", this); break; case 2: if (g.player.canibal != 0) { Ifc.you("says: \"You dare speak to me, filthy cannibal?\"", this); Ifc.msg("\"Then exist as you act: in the form of a beast!\""); Ifc.you("points at you and says, \"g.player.species = Species.hamster;\"", this); g.player.species = Species.hamster; g.player.reroll_stats(); Ifc.you("turn into a hamster!"); } else if (g.player.peacefuls == 0 && g.player.murders == 0) { Ifc.you("says: \"O noble adventurer, I wish you success on your quest.\"", this); Ifc.msg("\"Go forth and vanquish my ancient enemy!\""); g.player.xp += Utl.rn(2000)+2000; g.here.mons.remove(this); Ifc.you("disappears.", this); } break; case 3: // Do not be fooled by spock ears on a jock if (g.player.species.alignment < 0) { Ifc.you("says: \"Embrace the true path or perish, user!\"", this); if (Ifc.yn("Become a computer science major? (y/n)")) { g.player.species = Species.nerd; Ifc.you("turn into a nerd!"); } else { Ifc.msg("\"Your grave shall be here, fool!\""); if (g.here.north != null) { g.here.north = null; Ifc.msg("The northern passage collapses!"); } if (g.here.south != null) { g.here.south = null; Ifc.msg("The southern passage collapses!"); } if (g.here.west != null) { g.here.west = null; Ifc.msg("The western passage collapses!"); } if (g.here.east != null) { g.here.east = null; Ifc.msg("The eastern passage collapses!"); } ai = ATTACKING; Ifc.you("feel a strange force holding you here!"); g.player.in = 1; g.player.dx = 1; g.player.st = 1; g.update.addElement(g.player); } } else { Ifc.you("observes you.", this); } break; } } else if (species.talk != null) if (species.special_talk) Ifc.you(Utl.rn(species.talk), this); else Ifc.you("say|s| \"" + Utl.rn(species.talk) + "\".", this); else Ifc.you("note that " + Ifc.the_mon(this) + Utl.rn(NOT_TALKATIVE)); } else { if (rabid && !species.smart) Ifc.you(Utl.rn(RABID_TALK) + "\".", this); else if (cyborg) Ifc.you("say|s| \"" + Utl.rn(BORG_TALK) + "\".", this); else if (species.talk != null) if (species.special_talk) Ifc.you(Utl.rn(species.talk), this); else Ifc.you("say|s| \"" + Utl.rn(species.talk) + "\".", this); else Ifc.you("mutter|s| incomprehensibly.", this); } } // Take its turn cycle. // public void update () { if (here == null) return; if (hp <= 0) { die(null); return; } if (stunned != 0) { --stunned; Ifc.you("|is| helpless because of " + stunner + ".", this); return; } ai = update_ai(); if ((species.chatty && Utl.d(10) == 10) ||(cyborg && Utl.rn())) do_talk(false); if (g.turns % species.regeneration == 0 && hp < mhp) ++hp; if (hp <= mhp / 2 && hp > 0) if (do_food()) return; if (species.auto_special && species.special.usep(this, this)) { species.special.doSpecial(this, this); return; } switch (ai) { case WANDERING: if (do_goodies()) return; if (do_battle()) return; // if not then Wander, maybe. if (Utl.rn(5) == 0 && !species.no_wander && move_randomly()) return; break; case ATTACKING: if (do_inventory(Kind.OFFENSE)) return; if (do_battle()) return; if (Utl.rn(4) == 0 && hp > mhp/2) { if (species.chase && !here.mons.contains(g.player)) { if (move_nonrandomly()) return; } if (do_goodies()) return; if (Utl.rn() && do_inventory(Kind.DEFENSE)) return; } break; case FLEEING: if (do_inventory(Kind.ESCAPE)) return; if (Utl.rn(5) != 0 && move_randomly()) return; if (do_goodies()) return; if (do_inventory(Kind.DEFENSE)) return; break; case PET: if (this.here != g.player.here) { here.mons.remove(this); g.player.here.add(this); return; //Ifc.your("pet follows you."); } else { if (do_inventory(Kind.OFFENSE)) return; if (do_battle()) return; if (Utl.rn() && do_goodies()) return; if (Utl.rn() && do_inventory(Kind.DEFENSE)) return; } break; } if (do_equip()) return; do_inventory(Kind.MISC); } // pick up stuff, if smart, and use it if you should. // return true if something was picked up private boolean do_goodies() { Itm current; if (inventory.size() >= st && inventory.size() != 0 && Utl.rn(2) == 0) { current = (Itm)Utl.rn(inventory); if (ai == FLEEING && current.kind.drop_if_fleeing) drop(current); else if (!(current.wielded || current.worn || current.kind.pc_only || current.kind.use == Kind.OFFENSE)) drop(current); } if ((inventory.size() >= st && Utl.rn(5) != 0) || here.items.isEmpty()) return false; current = (Itm)Utl.rn(here.items); if (!species.smart && !(species.scavenger && Utl.contains(Items.corpses,(Object)current.kind))) return false; if (current.kind == species.corpse && species.smart) // don't pick up corpses of the same // species: cannibal hobos are not funny... return false; return pick_up(current); } // Try to pick up an item. public boolean pick_up(Itm item) { if (item.kind.fixed || inventory.size() >= st) { Ifc.you("attempt|s| to pick up the " + item.kind.name + ", but cannot lift it.", this); if (this == g.player) Ifc.pk(); return false; } if (item.kind.pc_only && this != g.player) { Ifc.you("looks at the " + item.kind.name + ".", this); return false; } if (item.special != null && !item.special.get(item, this, here)) return false; Ifc.you("pick|s| up the " + item.kind.name + ".", this); inventory.add(item); here.items.remove(item); return true; } // Fight, return false if there was nothing to fight. private boolean do_battle() { Mon target =null; if (ai == PET && Utl.rn()) target = g.player.get_target(); else target = get_target(); if (target == g.player && ai == PET) return false; if (target == null || target == this) return false; else { Ifc.you("attack|s| "+Ifc.the_mon(target)+"!", this); if (!do_attack(target)) Ifc.your(Ifc.color(Ifc.BRIGHT_BLUE)+"attack missed "+Ifc.him(target)+"."+Ifc.color(), this); if (species.special != null && species.special.usep(this, target)) { species.special.doSpecial(this, target); } return true; } } private boolean move_randomly() { Node where = Utl.rn(here); if (where.locked) return false; if (species.teleports && Utl.rn()) { here.mons.remove(this); where = Utl.rn_node(true, here.region);// (Node)Utl.rn(g.nodes); if (this != g.player && here == g.player.here) Ifc.you("see a " + species.name + " disappear in a flash!"); where.add(this); if (this != g.player && where == g.player.here ) Ifc.you("see a " + species.name + " appear from nowhere!"); return true; } if (this != g.player && here == g.player.here) Ifc.you("see a " + species.name + " leave, heading " + Utl.nsew(here, where) + "."); here.mons.remove(this); where.add(this); if (this != g.player && where == g.player.here ) Ifc.you("see a " + species.name + " enter."); return true; } private boolean move_nonrandomly() { if (g.player.dead) return false; Node where = null; if (here.north != null && here.north.mons.contains(g.player)) where = here.north; else if (here.south != null &&here.south.mons.contains(g.player)) where = here.south; else if (here.east != null &&here.east.mons.contains(g.player)) where = here.east; else if (here.west != null &&here.west.mons.contains(g.player)) where = here.west; if (where == null) where = Utl.rn(here); if (where.locked) return false; if (Utl.rn(dx) < Utl.rn(g.player.dx)) { Ifc.you("tries to chase after you, but you evade " + Ifc.him(this) + ".", this); return true; } here.mons.remove(this); where.add(this); if (this != g.player && where == g.player.here ) Ifc.you("see|s| " + Ifc.the_mon(this) + " chase after you!", g.player); return true; } // Now do an attack - return true if it hits. public boolean do_attack(Mon target) { if (st <= 0) { Ifc.you("|is| too weak to attack.", this); return false; } if (target.special != null) target.special.attacked(target, this, here); xp += 2; if (this == g.player && target.ai != FLEEING) target.ai = ATTACKING; boolean hit = true; int hit_modifier = ( // higher == less likely to hit. target.dx + (100 - HIT_THRESH) ) - ( // This line is things that, when higher, increase chance to hit. dx + (target.stunned > 0? 25 : 0) + (wielded != null? wielded.kind.to_hit : 0) ); int mod_modifier = (target.species.size - this.species.size) * 3; if (mod_modifier < 0) mod_modifier *= .8; hit_modifier += mod_modifier; // Cap range if (hit_modifier >= 90) hit_modifier = 90; if (hit_modifier < 10) hit_modifier = 10; if (hit_modifier > Utl.rn(100)) hit = false; // miss if (wielded != null && wielded.special != null) wielded.special.used_as_weapon(wielded, this, here, target, hit); if (hit == false) return false; /* if (((Utl.rn(100) + target.dx - dx + (target.stunned > 0? -25 : 0) + (wielded != null? wielded.kind.to_hit : 0) < HIT_THRESH)) || target.ai == SLEEPING) { if (target.ai == SLEEPING) Ifc.you("attack|s| the sleeping " + target.species.name + "!", this); if (wielded != null && wielded.special != null) wielded.special.used_as_weapon(wielded, this, here, target, false); return false; } else { if (wielded != null && wielded.special != null) wielded.special.used_as_weapon(wielded, this, here, target, true); } */ if (target.ai == SLEEPING) target.ai = WANDERING; xp += 8; if (this.species.attack_verb != null && wielded == null) Ifc.you(Ifc.color(Ifc.BRIGHT_RED)+species.attack_verb+" "+Ifc.the_mon(target)+"!"+Ifc.color(), this); else Ifc.your(Ifc.color(Ifc.BRIGHT_RED)+"hit|s| "+Ifc.him(target)+ (wielded != null? " with " + Ifc.his(this) + " " + wielded.kind.name : "") +"!"+Ifc.color(), this); if (this == g.player && wielded != null) ++g.used_weapon; target.damage(Utl.rn(st) + (wielded != null? wielded.kind.damage : 0), this); return true; } // find something to attack public Mon get_target() { int sel_score = -10000; int current_score = 0; Mon current = null; Mon selection = null; for (int i = 0; i < here.mons.size(); ++i) { current = (Mon)here.mons.elementAt(i); if (current.ai == PET && this == g.player) continue; if (current == g.player && ai == PET) continue; if (will_fight(current) || (ai == ATTACKING && current == g.player)) { current_score = current.st/2 + (current.wielded != null? current.wielded.kind.damage : 0) + (hp - current.hp) + Utl.rn(20) + (current == g.player? -5 : 5); if (current.ai == PET && (ai == PET || ai == WANDERING) && !pet_attacked) current_score -= 20; if (current_score > sel_score) { sel_score = current_score; selection = current; } } } return selection; } public Mon get_wand_target() { int sel_score = -10000; int current_score = 0; Mon current = null; Mon selection = null; for (int i = 0; i < here.mons.size(); ++i) { current = (Mon)here.mons.elementAt(i); if (current.ai == PET && this == g.player) continue; if (current == g.player && ai == PET) continue; if (will_fight(current) || (ai == ATTACKING && current == g.player)) { current_score = current.st/2 + (current.wielded != null? current.wielded.kind.damage : 0) + (current.hp - hp); if (current.ai == PET && (ai == PET || ai == WANDERING) && !pet_attacked) current_score -= 20; if (current_score > sel_score) { sel_score = current_score; selection = current; } } } int my_score = st / 2 + (wielded != null? wielded.kind.damage: 0); if (hp < mhp / 6) my_score -= 30; else if (hp < mhp / 3) my_score -= 20; else if (hp < mhp / 1.5) my_score -= 10; if (my_score > sel_score) return null; return selection; } public void setupInventory() { while (do_equip()) {;} } // This whole casting vector thing is really annoying. If a language is going // to make me keep track of types I shouldn't have to tell it // about it all the time... private boolean do_equip() { for (int i = 0; i < inventory.size(); ++i) { Itm current = (Itm)inventory.elementAt(i); if (((wielded == null || wielded.kind.damage < current.kind.damage) && current.kind.damage != 0) && species.wields) { if (wield(current)) return true; continue; } if (current.kind.armor != 0 && !current.worn && species.wears) { if (wear(current)) return true; continue; } } return false; } private boolean do_inventory(int type) { for (int i = 0; i < inventory.size(); ++i) { Itm current = (Itm)inventory.elementAt(i); if (current.special != null && current.special.monUse(this) && Utl.rn() && (current != wielded||current.kind.using_does_not_destroy) && species.uses && g.phase > 0 && here != null && current.kind.use == type) { if (use(current)) return true; } } return false; } private boolean do_food() { Itm best_food = null; for (int i = 0; i < inventory.size(); ++i) { Itm current = (Itm)inventory.elementAt(i); if (best_food == null && current.kind.heal != 0) best_food = current; else if (current.kind.heal != 0 && current.kind.heal > best_food.kind.heal) best_food = current; } if (best_food != null) { eat(best_food); return true; } return false; } public void eat(Itm food) { if (!species.eats) { if (this == g.player) Ifc.you("aren't able to eat or drink."); return; } if (food.special != null && !food.special.eat(food, this, here)) return; if (food.worn) { if (food.special != null && !food.special.unwear(food, this, here)) return; armor -= food.kind.armor; } if (food.wielded) { wielded = null; food.wielded = false; } if (food.tainted) { Ifc.you(Ifc.color(Ifc.MAGENTA)+"discover|s| that the " + food.kind.name + " was rotten! Yuck!"+Ifc.color(), this); hp -= Utl.rn(food.kind.heal); last_damage = "eating a tainted " + food.kind.name; if (Utl.rn(6) == 0) { Ifc.you("feel|s| very sick.", this); hp = Utl.rn(2); } } else { if (this == g.player) { Ifc.msg(food.kind.tasty); ++g.food; if (food.kind.veg_level < Itm.VEGAN) ++g.vegan; if (food.kind.veg_level < Itm.VEGETARIAN) ++g.vegetarian; } Ifc.you(Ifc.color(Ifc.GREEN)+"eat|s| "+Ifc.his(this)+" "+food.kind.name+", making " + Ifc.him(this) + " healthier."+Ifc.color(), this); hp += food.kind.heal; if (hp > mhp) hp = mhp; } inventory.remove(food); } public boolean wield(Itm weapon) { if (wielded != null) wielded.wielded = false; if (weapon.special != null && !weapon.special.wield(weapon, this, here)) return false; wielded = weapon; weapon.wielded = true; Ifc.you("wield|s| a " + wielded.kind.name + "!", this); return true; } public boolean use(Itm item) { if (this != g.player &&((item.kind.use == Kind.ESCAPE && hp > mhp / 2) || species.boss)) return false; if (item.special.use(item, this, here)) { Ifc.you(Ifc.color(Ifc.CYAN)+"use|s| a " + item.kind.name + "."+Ifc.color(), this); return true; } return false; } public boolean wear(Itm clothes) { if (clothes.worn) { Ifc.you("already wear|s| this " + clothes.kind.name +".", this); return false; } if (armor >= dx/2) { if (ai == PET || this == g.player) Ifc.you("|is| not dexterous enough to wear any more armor.", this); return false; } if (clothes.special != null && !clothes.special.wear(clothes, this, here)) return false; clothes.worn = true; armor += clothes.kind.armor; Ifc.you(Ifc.color(Ifc.BLUE)+"wear|s| a " + clothes.kind.name +"."+Ifc.color(), this); if (clothes.kind.armor > 5) xap++; return true; } public boolean drop(Itm thing) { /*if (thing.wielded && hp > 0) {// only happens with the player // mons know better than to try. Ifc.you("can't drop something you are wielding."); return; }*/ if (thing.wielded && hp > 0) { Ifc.you("|is| no longer wielding the " + thing.kind.name + ".", this); thing.wielded = false; wielded = null; } if (thing.special != null && !thing.special.drop(thing, this, here)) return false; if (thing.worn) { if (thing.special != null && !thing.special.unwear(thing, this, here)) return false; armor -= thing.kind.armor; } thing.wielded = false; thing.worn = false; here.add(thing); inventory.remove((Object)thing); Ifc.you(Ifc.color(Ifc.YELLOW)+"drop|s| a "+thing.kind.name+"."+Ifc.color(), this); return true; } public void reroll_stats() { in = min = species.in + Utl.rn(-species.vin); st = mst = species.st + Utl.rn(-species.vst); hp = mhp = species.hp + Utl.rn(-species.vhp); dx = mdx = species.dx + Utl.rn(-species.vdx); for (int i = 0; i < inventory.size(); ++i) { Itm current = (Itm)inventory.elementAt(i); if (current.worn && current.kind.special != null) { current.worn = false; armor -= current.kind.armor; Ifc.your(current.kind.name+" falls off somehow.", this); } } resist_gas = species.resist_gas; resist_gas = species.resist_gas; resist_bullets = species.resist_bullets; alignment = species.alignment; resist_chemical = species.resist_chemical; resist_polymorph = species.resist_polymorph; ap = species.ap; g.update.addElement(this); } }