Mercurial > hg > early-roguelike
comparison xrogue/actions.c @ 133:e6179860cb76
Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 21 Apr 2015 08:55:20 -0400 |
parents | |
children | f54901b9c39b |
comparison
equal
deleted
inserted
replaced
124:d10fc4a065ac | 133:e6179860cb76 |
---|---|
1 /* | |
2 actions.c - functions for dealing with monster actions | |
3 | |
4 XRogue: Expeditions into the Dungeons of Doom | |
5 Copyright (C) 1991 Robert Pietkivitch | |
6 All rights reserved. | |
7 | |
8 Based on "Advanced Rogue" | |
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T | |
10 All rights reserved. | |
11 | |
12 Based on "Rogue: Exploring the Dungeons of Doom" | |
13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
14 All rights reserved. | |
15 | |
16 See the file LICENSE.TXT for full copyright and licensing information. | |
17 */ | |
18 | |
19 #include <ctype.h> | |
20 #include <curses.h> | |
21 #include <limits.h> | |
22 #include "rogue.h" | |
23 | |
24 int mf_count = 0; /* move_free counter - see actions.c(m_act()) */ | |
25 int mf_jmpcnt = 0; /* move_free counter for # of jumps */ | |
26 | |
27 /* | |
28 * Did we disrupt a spell? | |
29 */ | |
30 dsrpt_monster(tp, always, see_him) | |
31 register struct thing *tp; | |
32 bool always, see_him; | |
33 { | |
34 switch (tp->t_action) { | |
35 case A_SUMMON: | |
36 case A_MISSILE: | |
37 case A_SLOW: | |
38 tp->t_action = A_NIL; /* Just make the old fellow start over again */ | |
39 tp->t_no_move = movement(tp); | |
40 tp->t_using = NULL; /* Just to be on the safe side */ | |
41 turn_on(*tp, WASDISRUPTED); | |
42 if (see_him) | |
43 msg("%s's spell has been disrupted.",prname(monster_name(tp),TRUE)); | |
44 /* | |
45 * maybe choose something else to do next time since player | |
46 * is disrupting us | |
47 */ | |
48 tp->t_summon *= 2; | |
49 tp->t_cast /= 2; | |
50 return; | |
51 } | |
52 | |
53 /* We may want to disrupt other actions, too */ | |
54 if (always) { | |
55 tp->t_action = A_NIL; /* Just make the old fellow start over again */ | |
56 tp->t_no_move = movement(tp); | |
57 tp->t_using = NULL;/* Just to be on the safe side */ | |
58 } | |
59 } | |
60 | |
61 dsrpt_player() | |
62 { | |
63 int which, action; | |
64 struct linked_list *item; | |
65 struct object *obj; | |
66 | |
67 action = player.t_action; | |
68 which = player.t_selection; | |
69 | |
70 switch (action) { | |
71 case C_CAST: /* Did we disrupt a spell? */ | |
72 case C_PRAY: | |
73 case C_CHANT: | |
74 { | |
75 msg("Your %s was disrupted!", action == C_CAST ? "spell" : "prayer"); | |
76 | |
77 /* Charge him 1/4 anyway */ | |
78 if (action == C_CAST) | |
79 spell_power += magic_spells[which].s_cost / 4; | |
80 else if (action == C_PRAY) | |
81 pray_time += cleric_spells[which].s_cost / 4; | |
82 else if (action == C_CHANT) | |
83 chant_time += druid_spells[which].s_cost / 4; | |
84 } | |
85 when C_COUNT: /* counting of gold? */ | |
86 { | |
87 if (purse > 0) { | |
88 msg("Your gold goes flying everywhere!"); | |
89 do { | |
90 item = spec_item(GOLD, NULL, NULL, NULL); | |
91 obj = OBJPTR(item); | |
92 obj->o_count = min(purse, rnd(20)+1); | |
93 purse -= obj->o_count; | |
94 obj->o_pos = hero; | |
95 fall(item, FALSE); | |
96 } while (purse > 0 && rnd(25) != 1); | |
97 } | |
98 } | |
99 when C_EAT: | |
100 msg("Ack! You gag on your food for a moment. "); | |
101 del_pack(player.t_using); | |
102 | |
103 when A_PICKUP: | |
104 msg("You drop what you are picking up! "); | |
105 | |
106 when C_SEARCH: /* searching for traps and secret doors... */ | |
107 msg("Ouch! You decide to stop searching. "); | |
108 count = 0; /* don't search again */ | |
109 | |
110 when C_SETTRAP: | |
111 msg("Ouch! You can't set a trap right now. "); | |
112 | |
113 when A_NIL: | |
114 default: | |
115 return; | |
116 } | |
117 player.t_no_move = movement(&player); /* disoriented for a while */ | |
118 player.t_action = A_NIL; | |
119 player.t_selection = 0; | |
120 } | |
121 | |
122 /* | |
123 * m_act: | |
124 * If the critter isn't doing anything, choose an action for it. | |
125 * Otherwise, let it perform its chosen action. | |
126 */ | |
127 | |
128 m_act(tp) | |
129 register struct thing *tp; | |
130 { | |
131 struct object *obj; | |
132 bool flee; /* Are we scared? */ | |
133 | |
134 /* What are we planning to do? */ | |
135 switch (tp->t_action) { | |
136 default: | |
137 /* An unknown action! */ | |
138 msg("Unknown monster action (%d)", tp->t_action); | |
139 | |
140 /* Fall through */ | |
141 | |
142 case A_NIL: | |
143 /* If the monster is fairly intelligent and about to die, it | |
144 * may turn tail and run. But if we are a FRIENDLY creature | |
145 * in the hero's service, don't run. | |
146 */ | |
147 if (off(*tp, ISFLEE) && | |
148 tp->t_stats.s_hpt < tp->maxstats.s_hpt && | |
149 tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/6) && | |
150 (off(*tp, ISFRIENDLY) || tp->t_dest != &hero) && | |
151 rnd(25) < tp->t_stats.s_intel) { | |
152 turn_on(*tp, ISFLEE); | |
153 | |
154 /* It is okay to turn tail */ | |
155 tp->t_oldpos = tp->t_pos; | |
156 } | |
157 | |
158 /* Should the monster run away? */ | |
159 flee = on(*tp, ISFLEE) || | |
160 ((tp->t_dest == &hero) && on(player, ISINWALL) && | |
161 off(*tp, CANINWALL)); | |
162 | |
163 m_select(tp, flee); /* Select an action */ | |
164 return; | |
165 | |
166 when A_ATTACK: | |
167 /* | |
168 * We're trying to attack the player or monster at t_newpos | |
169 * if the prey moved, do nothing | |
170 */ | |
171 obj = tp->t_using ? OBJPTR(tp->t_using) : NULL; | |
172 if (ce(tp->t_newpos, hero)) { | |
173 attack(tp, obj, FALSE); | |
174 } | |
175 else if (mvwinch(mw, tp->t_newpos.y, tp->t_newpos.x) && | |
176 step_ok(tp->t_newpos.y, tp->t_newpos.x, FIGHTOK, tp)) { | |
177 skirmish(tp, &tp->t_newpos, obj, FALSE); | |
178 } | |
179 | |
180 when A_SELL: | |
181 /* Is the quartermaster still next to us? */ | |
182 if (ce(tp->t_newpos, hero)) sell(tp); | |
183 | |
184 /* The quartermaster moved away */ | |
185 else if (off(player, ISBLIND) && cansee(unc(tp->t_pos)) && | |
186 (off(*tp, ISINVIS) || on(player, CANSEE)) && | |
187 (off(*tp, ISSHADOW) || on(player, CANSEE)) && | |
188 (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT)) && | |
189 (rnd(12) < 4)) | |
190 msg("%s grunts with frustration",prname(monster_name(tp),TRUE)); | |
191 | |
192 when A_MOVE: | |
193 /* Let's try to move */ | |
194 do_chase(tp); | |
195 | |
196 /* If t_no_move > 0, we found that we have to fight! */ | |
197 if (tp->t_no_move > 0) return; | |
198 | |
199 when A_BREATHE: | |
200 /* Breathe on the critter */ | |
201 m_breathe(tp); | |
202 | |
203 when A_SLOW: | |
204 /* make him move slower */ | |
205 add_slow(); | |
206 turn_off(*tp, CANSLOW); | |
207 | |
208 when A_MISSILE: | |
209 /* Start up a magic missile spell */ | |
210 m_spell(tp); | |
211 | |
212 when A_SONIC: | |
213 /* Let out a sonic blast! */ | |
214 m_sonic(tp); | |
215 | |
216 when A_THROW: | |
217 /* We're throwing something (like an arrow) */ | |
218 missile(tp->t_newpos.y, tp->t_newpos.x, tp->t_using, tp); | |
219 | |
220 when A_SUMMON: | |
221 /* We're summoning help */ | |
222 m_summon(tp); | |
223 | |
224 when A_USERELIC: | |
225 /* Use our relic */ | |
226 m_use_relic(tp); | |
227 | |
228 when A_USEWAND: | |
229 /* use the wand we have */ | |
230 m_use_wand(tp); | |
231 } | |
232 | |
233 /* Can we in fact move? (we might have solidified in solid rock) */ | |
234 if (!step_ok(hero.y, hero.x, NOMONST, &player)) { | |
235 | |
236 if (move_free > 1) goto jump_over; /* avoid messages */ | |
237 if (mf_count > 2) goto jump_over; /* limit messages */ | |
238 | |
239 if (pstats.s_hpt < 1) { | |
240 pstats.s_hpt = -1; | |
241 msg("You have merged into the surroundings! --More--"); | |
242 wait_for(' '); | |
243 death(D_PETRIFY); | |
244 } | |
245 else { | |
246 mf_count += 1; /* count number of times we are here */ | |
247 pstats.s_hpt -= rnd(2)+1; | |
248 if (pstats.s_hpt < 1) { | |
249 pstats.s_hpt = -1; | |
250 msg("You have merged into the surroundings! --More--"); | |
251 wait_for(' '); | |
252 death(D_PETRIFY); | |
253 } | |
254 } | |
255 switch (rnd(51)) { | |
256 case 0: msg("Arrrggghhhhh!! "); | |
257 when 5: msg("You can't move! "); | |
258 when 10: msg("You motion angrily! "); | |
259 when 15: msg("You feel so weird! "); | |
260 when 20: msg("If only you could phase. "); | |
261 when 25: msg("The rock maggots are closing in! "); | |
262 when 30: msg("You wrench and wrench and wrench... "); | |
263 when 35: msg("You wish you could teleport out of here! "); | |
264 when 40: msg("Your feel your life force ebbing away... "); | |
265 when 45: msg("You partially regain your senses. "); | |
266 when 50: msg("The rock maggots have found you!!! "); | |
267 otherwise: pstats.s_hpt -= rnd(4)+1; | |
268 } | |
269 if (pstats.s_hpt < 1) { | |
270 pstats.s_hpt = -1; | |
271 msg("You lose the urge to live... --More--"); | |
272 wait_for(' '); | |
273 death(D_PETRIFY); | |
274 } | |
275 jump_over: | |
276 mf_jmpcnt++; /* count this jump */ | |
277 if (mf_jmpcnt > 9) { /* take a few turns, then reset it */ | |
278 mf_jmpcnt = 0; | |
279 mf_count = 0; | |
280 } | |
281 } | |
282 | |
283 /* No action now */ | |
284 tp->t_action = A_NIL; | |
285 tp->t_using = NULL; | |
286 } | |
287 | |
288 /* | |
289 * m_breathe: | |
290 * Breathe in the chosen direction. | |
291 */ | |
292 | |
293 m_breathe(tp) | |
294 register struct thing *tp; | |
295 { | |
296 register int damage; | |
297 register char *breath = NULL; | |
298 | |
299 damage = tp->t_stats.s_hpt; | |
300 turn_off(*tp, CANSURPRISE); | |
301 | |
302 /* Will it breathe at random */ | |
303 if (on(*tp, CANBRANDOM)) { | |
304 /* Turn off random breath */ | |
305 turn_off(*tp, CANBRANDOM); | |
306 | |
307 /* Select type of breath */ | |
308 switch (rnd(10)) { | |
309 case 0: breath = "acid"; | |
310 turn_on(*tp, NOACID); | |
311 when 1: breath = "flame"; | |
312 turn_on(*tp, NOFIRE); | |
313 when 2: breath = "lightning bolt"; | |
314 turn_on(*tp, NOBOLT); | |
315 when 3: breath = "chlorine gas"; | |
316 turn_on(*tp, NOGAS); | |
317 when 4: breath = "ice"; | |
318 turn_on(*tp, NOCOLD); | |
319 when 5: breath = "nerve gas"; | |
320 turn_on(*tp, NOPARALYZE); | |
321 when 6: breath = "sleeping gas"; | |
322 turn_on(*tp, NOSLEEP); | |
323 when 7: breath = "slow gas"; | |
324 turn_on(*tp, NOSLOW); | |
325 when 8: breath = "confusion gas"; | |
326 turn_on(*tp, ISCLEAR); | |
327 when 9: breath = "fear gas"; | |
328 turn_on(*tp, NOFEAR); | |
329 } | |
330 } | |
331 | |
332 /* Or can it breathe acid? */ | |
333 else if (on(*tp, CANBACID)) { | |
334 turn_off(*tp, CANBACID); | |
335 breath = "acid"; | |
336 } | |
337 | |
338 /* Or can it breathe fire */ | |
339 else if (on(*tp, CANBFIRE)) { | |
340 turn_off(*tp, CANBFIRE); | |
341 breath = "flame"; | |
342 } | |
343 | |
344 /* Or can it breathe electricity? */ | |
345 else if (on(*tp, CANBBOLT)) { | |
346 turn_off(*tp, CANBBOLT); | |
347 breath = "lightning bolt"; | |
348 } | |
349 | |
350 /* Or can it breathe gas? */ | |
351 else if (on(*tp, CANBGAS)) { | |
352 turn_off(*tp, CANBGAS); | |
353 breath = "chlorine gas"; | |
354 } | |
355 | |
356 /* Or can it breathe ice? */ | |
357 else if (on(*tp, CANBICE)) { | |
358 turn_off(*tp, CANBICE); | |
359 breath = "ice"; | |
360 } | |
361 |