Apply the new ground_level method.
[crawl.git] / crawl-ref / source / actor.cc
blob38eda7166eb3e19f6b34962a0cb6caf5b54b319d
1 #include "AppHdr.h"
3 #include "actor.h"
4 #include "areas.h"
5 #include "artefact.h"
6 #include "coord.h"
7 #include "coordit.h"
8 #include "env.h"
9 #include "itemprop.h"
10 #include "los.h"
11 #include "mon-death.h"
12 #include "player.h"
13 #include "random.h"
14 #include "state.h"
15 #include "stuff.h"
16 #include "terrain.h"
17 #include "traps.h"
19 actor::~actor()
23 bool actor::has_equipped(equipment_type eq, int sub_type) const
25 const item_def *item = slot_item(eq, false);
26 return (item && item->sub_type == sub_type);
29 bool actor::will_trigger_shaft() const
31 return (ground_level() && total_weight() > 0 && is_valid_shaft_level()
32 // let's pretend that they always make their saving roll
33 && !(atype() == ACT_MONSTER
34 && mons_is_elven_twin(static_cast<const monster* >(this))));
37 level_id actor::shaft_dest(bool known = false) const
39 return generic_shaft_dest(pos(), known);
42 bool actor::airborne() const
44 return (is_levitating() || (flight_mode() == FL_FLY && !cannot_move()));
47 /**
48 * Check if the actor is on the ground (or in water).
50 bool actor::ground_level() const
52 return (!airborne() && !is_wall_clinging());
55 bool actor::can_wield(const item_def* item, bool ignore_curse,
56 bool ignore_brand, bool ignore_shield,
57 bool ignore_transform) const
59 if (item == NULL)
61 // Unarmed combat.
62 item_def fake;
63 fake.base_type = OBJ_UNASSIGNED;
64 return can_wield(fake, ignore_curse, ignore_brand, ignore_transform);
66 else
67 return can_wield(*item, ignore_curse, ignore_brand, ignore_transform);
70 bool actor::can_pass_through(int x, int y) const
72 return can_pass_through_feat(grd[x][y]);
75 bool actor::can_pass_through(const coord_def &c) const
77 return can_pass_through_feat(grd(c));
80 bool actor::is_habitable(const coord_def &_pos) const
82 if (can_cling_to(_pos))
83 return true;
85 return is_habitable_feat(grd(_pos));
88 bool actor::handle_trap()
90 trap_def* trap = find_trap(pos());
91 if (trap)
92 trap->trigger(*this);
93 return (trap != NULL);
97 int actor::res_holy_fire() const
99 if (is_evil() || is_unholy())
100 return (-1);
101 else if (is_holy())
102 return (3);
103 return (0);
106 int actor::check_res_magic(int power)
108 const int mrs = res_magic();
110 if (mrs == MAG_IMMUNE)
111 return (100);
113 // Evil, evil hack to make weak one hd monsters easier for first level
114 // characters who have resistable 1st level spells. Six is a very special
115 // value because mrs = hd * 2 * 3 for most monsters, and the weak, low
116 // level monsters have been adjusted so that the "3" is typically a 1.
117 // There are some notable one hd monsters that shouldn't fall under this,
118 // so we do < 6, instead of <= 6... or checking mons->hit_dice. The
119 // goal here is to make the first level easier for these classes and give
120 // them a better shot at getting to level two or three and spells that can
121 // help them out (or building a level or two of their base skill so they
122 // aren't resisted as often). - bwr
123 if (atype() == ACT_MONSTER && mrs < 6 && coinflip())
124 return (-1);
126 power = stepdown_value(power, 30, 40, 100, 120);
128 const int mrchance = (100 + mrs) - power;
129 const int mrch2 = random2(100) + random2(101);
131 dprf("Power: %d, MR: %d, target: %d, roll: %d",
132 power, mrs, mrchance, mrch2);
134 return (mrchance - mrch2);
137 void actor::set_position(const coord_def &c)
139 const coord_def oldpos = position;
140 position = c;
141 los_actor_moved(this, oldpos);
142 areas_actor_moved(this, oldpos);
145 bool actor::can_hibernate(bool holi_only) const
147 // Undead, nonliving, and plants don't sleep.
148 const mon_holy_type holi = holiness();
149 if (holi == MH_UNDEAD || holi == MH_NONLIVING || holi == MH_PLANT)
150 return (false);
152 if (!holi_only)
154 // The monster is berserk or already asleep.
155 if (!can_sleep())
156 return (false);
158 // The monster is cold-resistant and can't be hibernated.
159 if (res_cold() > 0)
160 return (false);
162 // The monster has slept recently.
163 if (atype() == ACT_MONSTER
164 && static_cast<const monster* >(this)->has_ench(ENCH_SLEEP_WARY))
166 return (false);
170 return (true);
173 bool actor::can_sleep() const
175 const mon_holy_type holi = holiness();
176 if (holi == MH_UNDEAD || holi == MH_NONLIVING || holi == MH_PLANT)
177 return (false);
178 return !(berserk() || asleep());
181 void actor::shield_block_succeeded(actor *foe)
183 item_def *sh = shield();
184 unrandart_entry *unrand_entry;
186 if (sh
187 && sh->base_type == OBJ_ARMOUR
188 && get_armour_slot(*sh) == EQ_SHIELD
189 && is_artefact(*sh)
190 && is_unrandom_artefact(*sh)
191 && (unrand_entry = get_unrand_entry(sh->special))
192 && unrand_entry->fight_func.melee_effects)
194 unrand_entry->fight_func.melee_effects(sh, this, foe, false);
198 int actor::body_weight(bool base) const
200 switch (body_size(PSIZE_BODY, base))
202 case SIZE_TINY:
203 return (150);
204 case SIZE_LITTLE:
205 return (300);
206 case SIZE_SMALL:
207 return (425);
208 case SIZE_MEDIUM:
209 return (550);
210 case SIZE_LARGE:
211 return (1300);
212 case SIZE_BIG:
213 return (1500);
214 case SIZE_GIANT:
215 return (1800);
216 case SIZE_HUGE:
217 return (2200);
218 default:
219 mpr("ERROR: invalid body weight");
220 perror("actor::body_weight(): invalid body weight");
221 end(0);
222 return (0);
226 kill_category actor_kill_alignment(const actor *act)
228 return (act? act->kill_alignment() : KC_OTHER);
231 bool actor_slime_wall_immune(const actor *act)
233 return (act->atype() == ACT_PLAYER?
234 you.religion == GOD_JIYVA && !you.penance[GOD_JIYVA]
235 : act->res_acid() == 3);
238 bool actor::is_wall_clinging() const
240 return (clinging);
243 bool actor::can_cling_to(const coord_def& p) const
245 if (!in_bounds(p))
246 return (false);
248 if (!is_wall_clinging())
249 return (false);
251 if (!can_pass_through_feat(grd(p)))
252 return (false);
254 for (orth_adjacent_iterator ai(p); ai; ++ai)
255 if (feat_is_wall(env.grid(*ai)))
256 for (orth_adjacent_iterator ai2(*ai, false); ai2; ++ai2)
257 for (int i = 0, size = cling_to.size(); i < size; ++i)
258 if (cling_to[i] == *ai2)
259 return (true);
261 return (false);
264 void actor::check_clinging()
266 if (!can_cling_to_walls())
267 return;
269 cling_to.clear();
270 for (orth_adjacent_iterator ai(pos()); ai; ++ai)
271 if (feat_is_wall(env.grid(*ai)))
272 cling_to.push_back(*ai);
274 clinging = (cling_to.size() > 0) ? true : false;