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 |
