comparison arogue7/actions.c @ 125:adfa37e67084

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