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