| File: | src/games/hack/hack.zap.c |
| Warning: | line 664, column 2 Undefined or garbage value returned to caller |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: hack.zap.c,v 1.11 2016/01/09 18:33:15 mestre Exp $ */ | |||
| 2 | ||||
| 3 | /* | |||
| 4 | * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, | |||
| 5 | * Amsterdam | |||
| 6 | * All rights reserved. | |||
| 7 | * | |||
| 8 | * Redistribution and use in source and binary forms, with or without | |||
| 9 | * modification, are permitted provided that the following conditions are | |||
| 10 | * met: | |||
| 11 | * | |||
| 12 | * - Redistributions of source code must retain the above copyright notice, | |||
| 13 | * this list of conditions and the following disclaimer. | |||
| 14 | * | |||
| 15 | * - Redistributions in binary form must reproduce the above copyright | |||
| 16 | * notice, this list of conditions and the following disclaimer in the | |||
| 17 | * documentation and/or other materials provided with the distribution. | |||
| 18 | * | |||
| 19 | * - Neither the name of the Stichting Centrum voor Wiskunde en | |||
| 20 | * Informatica, nor the names of its contributors may be used to endorse or | |||
| 21 | * promote products derived from this software without specific prior | |||
| 22 | * written permission. | |||
| 23 | * | |||
| 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |||
| 25 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||
| 26 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |||
| 27 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | |||
| 28 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
| 29 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
| 30 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |||
| 31 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |||
| 32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |||
| 33 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||
| 34 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| 35 | */ | |||
| 36 | ||||
| 37 | /* | |||
| 38 | * Copyright (c) 1982 Jay Fenlason <hack@gnu.org> | |||
| 39 | * All rights reserved. | |||
| 40 | * | |||
| 41 | * Redistribution and use in source and binary forms, with or without | |||
| 42 | * modification, are permitted provided that the following conditions | |||
| 43 | * are met: | |||
| 44 | * 1. Redistributions of source code must retain the above copyright | |||
| 45 | * notice, this list of conditions and the following disclaimer. | |||
| 46 | * 2. Redistributions in binary form must reproduce the above copyright | |||
| 47 | * notice, this list of conditions and the following disclaimer in the | |||
| 48 | * documentation and/or other materials provided with the distribution. | |||
| 49 | * 3. The name of the author may not be used to endorse or promote products | |||
| 50 | * derived from this software without specific prior written permission. | |||
| 51 | * | |||
| 52 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
| 53 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |||
| 54 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |||
| 55 | * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
| 56 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
| 57 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |||
| 58 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |||
| 59 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |||
| 60 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
| 61 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| 62 | */ | |||
| 63 | ||||
| 64 | #include <stdlib.h> | |||
| 65 | ||||
| 66 | #include "hack.h" | |||
| 67 | ||||
| 68 | extern struct monst youmonst; | |||
| 69 | ||||
| 70 | char *fl[]= { | |||
| 71 | "magic missile", | |||
| 72 | "bolt of fire", | |||
| 73 | "sleep ray", | |||
| 74 | "bolt of cold", | |||
| 75 | "death ray" | |||
| 76 | }; | |||
| 77 | ||||
| 78 | static char dirlet(int, int); | |||
| 79 | static int zhit(struct monst *, int); | |||
| 80 | static boolean revive(struct obj *); | |||
| 81 | static void rloco(struct obj *); | |||
| 82 | static void burn_scrolls(void); | |||
| 83 | ||||
| 84 | /* Routines for IMMEDIATE wands. */ | |||
| 85 | /* bhitm: monster mtmp was hit by the effect of wand otmp */ | |||
| 86 | void | |||
| 87 | bhitm(struct monst *mtmp, struct obj *otmp) | |||
| 88 | { | |||
| 89 | wakeup(mtmp); | |||
| 90 | switch(otmp->otyp) { | |||
| 91 | case WAN_STRIKING159: | |||
| 92 | if(u.uswallow || rnd(20) < 10+mtmp->data->ac) { | |||
| 93 | int tmp = d(2,12); | |||
| 94 | hit("wand", mtmp, exclam(tmp)); | |||
| 95 | mtmp->mhp -= tmp; | |||
| 96 | if(mtmp->mhp < 1) killed(mtmp); | |||
| 97 | } else miss("wand", mtmp); | |||
| 98 | break; | |||
| 99 | case WAN_SLOW_MONSTER160: | |||
| 100 | mtmp->mspeed = MSLOW1; | |||
| 101 | break; | |||
| 102 | case WAN_SPEED_MONSTER161: | |||
| 103 | mtmp->mspeed = MFAST2; | |||
| 104 | break; | |||
| 105 | case WAN_UNDEAD_TURNING162: | |||
| 106 | if(strchr(UNDEAD"ZVW ",mtmp->data->mlet)) { | |||
| 107 | mtmp->mhp -= rnd(8); | |||
| 108 | if(mtmp->mhp < 1) killed(mtmp); | |||
| 109 | else mtmp->mflee = 1; | |||
| 110 | } | |||
| 111 | break; | |||
| 112 | case WAN_POLYMORPH163: | |||
| 113 | if( newcham(mtmp,&mons[rn2(CMNUM55)]) ) | |||
| 114 | objects[otmp->otyp].oc_name_known = 1; | |||
| 115 | break; | |||
| 116 | case WAN_CANCELLATION164: | |||
| 117 | mtmp->mcan = 1; | |||
| 118 | break; | |||
| 119 | case WAN_TELEPORTATION165: | |||
| 120 | rloc(mtmp); | |||
| 121 | break; | |||
| 122 | case WAN_MAKE_INVISIBLE166: | |||
| 123 | mtmp->minvis = 1; | |||
| 124 | break; | |||
| 125 | #ifdef WAN_PROBING | |||
| 126 | case WAN_PROBING: | |||
| 127 | mstatusline(mtmp); | |||
| 128 | break; | |||
| 129 | #endif /* WAN_PROBING */ | |||
| 130 | default: | |||
| 131 | impossible("What an interesting wand (%u)", otmp->otyp); | |||
| 132 | } | |||
| 133 | } | |||
| 134 | ||||
| 135 | /* returns TRUE if sth was done */ | |||
| 136 | /* object obj was hit by the effect of wand otmp */ | |||
| 137 | boolean | |||
| 138 | bhito(struct obj *obj, struct obj *otmp) | |||
| 139 | { | |||
| 140 | int res = TRUE1; | |||
| 141 | ||||
| 142 | if(obj == uball || obj == uchain) | |||
| 143 | res = FALSE0; | |||
| 144 | else | |||
| 145 | switch(otmp->otyp) { | |||
| 146 | case WAN_POLYMORPH163: | |||
| 147 | /* preserve symbol and quantity, but turn rocks into gems */ | |||
| 148 | mkobj_at((obj->otyp == ROCK75 || obj->otyp == ENORMOUS_ROCK97) | |||
| 149 | ? GEM_SYM'*' : obj->olet, | |||
| 150 | obj->ox, obj->oy) -> quan = obj->quan; | |||
| 151 | delobj(obj); | |||
| 152 | break; | |||
| 153 | case WAN_STRIKING159: | |||
| 154 | if(obj->otyp == ENORMOUS_ROCK97) | |||
| 155 | fracture_rock(obj); | |||
| 156 | else | |||
| 157 | res = FALSE0; | |||
| 158 | break; | |||
| 159 | case WAN_CANCELLATION164: | |||
| 160 | if(obj->spe && obj->olet != AMULET_SYM'"') { | |||
| 161 | obj->known = 0; | |||
| 162 | obj->spe = 0; | |||
| 163 | } | |||
| 164 | break; | |||
| 165 | case WAN_TELEPORTATION165: | |||
| 166 | rloco(obj); | |||
| 167 | break; | |||
| 168 | case WAN_MAKE_INVISIBLE166: | |||
| 169 | obj->oinvis = 1; | |||
| 170 | break; | |||
| 171 | case WAN_UNDEAD_TURNING162: | |||
| 172 | res = revive(obj); | |||
| 173 | break; | |||
| 174 | case WAN_SLOW_MONSTER160: /* no effect on objects */ | |||
| 175 | case WAN_SPEED_MONSTER161: | |||
| 176 | #ifdef WAN_PROBING | |||
| 177 | case WAN_PROBING: | |||
| 178 | #endif /* WAN_PROBING */ | |||
| 179 | res = FALSE0; | |||
| 180 | break; | |||
| 181 | default: | |||
| 182 | impossible("What an interesting wand (%u)", otmp->otyp); | |||
| 183 | } | |||
| 184 | return(res); | |||
| 185 | } | |||
| 186 | ||||
| 187 | int | |||
| 188 | dozap(void) | |||
| 189 | { | |||
| 190 | struct obj *obj; | |||
| 191 | xchar zx,zy; | |||
| 192 | ||||
| 193 | obj = getobj("/", "zap"); | |||
| 194 | if(!obj) return(0); | |||
| ||||
| 195 | if(obj->spe < 0 || (obj->spe == 0 && rn2(121))) { | |||
| 196 | pline("Nothing Happens."); | |||
| 197 | return(1); | |||
| 198 | } | |||
| 199 | if(obj->spe
| |||
| 200 | pline("You wrest one more spell from the worn-out wand."); | |||
| 201 | if(!(objects[obj->otyp].bitsoc_oc1 & NODIR1) && !getdir(1)) | |||
| 202 | return(1); /* make him pay for knowing !NODIR */ | |||
| 203 | obj->spe--; | |||
| 204 | if(objects[obj->otyp].bitsoc_oc1 & IMMEDIATE2) { | |||
| 205 | if(u.uswallow) | |||
| 206 | bhitm(u.ustuck, obj); | |||
| 207 | else if(u.dz) { | |||
| 208 | if(u.dz > 0) { | |||
| 209 | struct obj *otmp = o_at(u.ux, u.uy); | |||
| 210 | if(otmp) | |||
| 211 | (void) bhito(otmp, obj); | |||
| 212 | } | |||
| 213 | } else | |||
| 214 | (void) bhit(u.dx,u.dy,rn1(8,6),0,bhitm,bhito,obj); | |||
| 215 | } else { | |||
| 216 | switch(obj->otyp){ | |||
| 217 | case WAN_LIGHT155: | |||
| 218 | litroom(TRUE1); | |||
| 219 | break; | |||
| 220 | case WAN_SECRET_DOOR_DETECTION156: | |||
| 221 | if(!findit()) return(1); | |||
| 222 | break; | |||
| 223 | case WAN_CREATE_MONSTER157: | |||
| 224 | { int cnt = 1; | |||
| 225 | if(!rn2(23)) cnt += rn2(7) + 1; | |||
| 226 | while(cnt--) | |||
| 227 | (void) makemon((struct permonst *) 0, u.ux, u.uy); | |||
| 228 | } | |||
| 229 | break; | |||
| 230 | case WAN_WISHING158: | |||
| 231 | { char buf[BUFSZ256]; | |||
| 232 | struct obj *otmp; | |||
| 233 | if(u.uluck + rn2(5) < 0) { | |||
| 234 | pline("Unfortunately, nothing happens."); | |||
| 235 | break; | |||
| 236 | } | |||
| 237 | pline("You may wish for an object. What do you want? "); | |||
| 238 | getlin(buf); | |||
| 239 | if(buf[0] == '\033') buf[0] = 0; | |||
| 240 | otmp = readobjnam(buf, sizeof buf); | |||
| 241 | otmp = addinv(otmp); | |||
| 242 | prinv(otmp); | |||
| 243 | break; | |||
| 244 | } | |||
| 245 | case WAN_DIGGING167: | |||
| 246 | /* Original effect (approximately): | |||
| 247 | * from CORR: dig until we pierce a wall | |||
| 248 | * from ROOM: piece wall and dig until we reach | |||
| 249 | * an ACCESSIBLE place. | |||
| 250 | * Currently: dig for digdepth positions; | |||
| 251 | * also down on request of Lennart Augustsson. | |||
| 252 | */ | |||
| 253 | { struct rm *room; | |||
| 254 | int digdepth; | |||
| 255 | if(u.uswallow) { | |||
| 256 | struct monst *mtmp = u.ustuck; | |||
| 257 | ||||
| 258 | pline("You pierce %s's stomach wall!", | |||
| 259 | monnam(mtmp)); | |||
| 260 | mtmp->mhp = 1; /* almost dead */ | |||
| 261 | unstuck(mtmp); | |||
| 262 | mnexto(mtmp); | |||
| 263 | break; | |||
| 264 | } | |||
| 265 | if(u.dz) { | |||
| 266 | if(u.dz < 0) { | |||
| 267 | pline("You loosen a rock from the ceiling."); | |||
| 268 | pline("It falls on your head!"); | |||
| 269 | losehp(1, "falling rock"); | |||
| 270 | mksobj_at(ROCK75, u.ux, u.uy); | |||
| 271 | fobj->quan = 1; | |||
| 272 | stackobj(fobj); | |||
| 273 | if(Invisible(u.uprops[(19 +3)].p_flgs && !u.uprops[4].p_flgs)) newsym(u.ux, u.uy); | |||
| 274 | } else { | |||
| 275 | dighole(); | |||
| 276 | } | |||
| 277 | break; | |||
| 278 | } | |||
| 279 | zx = u.ux+u.dx; | |||
| 280 | zy = u.uy+u.dy; | |||
| 281 | digdepth = 8 + rn2(18); | |||
| 282 | Tmp_at(-1, '*'); /* open call */ | |||
| 283 | while(--digdepth >= 0) { | |||
| 284 | if(!isok(zx,zy)) break; | |||
| 285 | room = &levl[(int)zx][(int)zy]; | |||
| 286 | Tmp_at(zx,zy); | |||
| 287 | if(!xdnstair){ | |||
| 288 | if(zx < 3 || zx > COLNO80-3 || | |||
| 289 | zy < 3 || zy > ROWNO22-3) | |||
| 290 | break; | |||
| 291 | if(room->typ == HWALL1 || | |||
| 292 | room->typ == VWALL2){ | |||
| 293 | room->typ = ROOM9; | |||
| 294 | break; | |||
| 295 | } | |||
| 296 | } else | |||
| 297 | if(room->typ == HWALL1 || room->typ == VWALL2 || | |||
| 298 | room->typ == SDOOR3 || room->typ == LDOOR5){ | |||
| 299 | room->typ = DOOR7; | |||
| 300 | digdepth -= 2; | |||
| 301 | } else | |||
| 302 | if(room->typ == SCORR4 || !room->typ) { | |||
| 303 | room->typ = CORR8; | |||
| 304 | digdepth--; | |||
| 305 | } | |||
| 306 | mnewsym(zx,zy); | |||
| 307 | zx += u.dx; | |||
| 308 | zy += u.dy; | |||
| 309 | } | |||
| 310 | mnewsym(zx,zy); /* not always necessary */ | |||
| 311 | Tmp_at(-1,-1); /* closing call */ | |||
| 312 | break; | |||
| 313 | } | |||
| 314 | default: | |||
| 315 | buzz((int) obj->otyp - WAN_MAGIC_MISSILE168, | |||
| 316 | u.ux, u.uy, u.dx, u.dy); | |||
| 317 | break; | |||
| 318 | } | |||
| 319 | if(!objects[obj->otyp].oc_name_known) { | |||
| 320 | objects[obj->otyp].oc_name_known = 1; | |||
| 321 | more_experienced(0,10); | |||
| 322 | } | |||
| 323 | } | |||
| 324 | return(1); | |||
| 325 | } | |||
| 326 | ||||
| 327 | char * | |||
| 328 | exclam(int force) | |||
| 329 | { | |||
| 330 | /* force == 0 occurs e.g. with sleep ray */ | |||
| 331 | /* note that large force is usual with wands so that !! would | |||
| 332 | * require information about hand/weapon/wand | |||
| 333 | */ | |||
| 334 | return( (force < 0) ? "?" : (force <= 4) ? "." : "!" ); | |||
| 335 | } | |||
| 336 | ||||
| 337 | /* force is usually either "." or "!" */ | |||
| 338 | void | |||
| 339 | hit(char *str, struct monst *mtmp, char *force) | |||
| 340 | { | |||
| 341 | if(!cansee(mtmp->mx,mtmp->my)) pline("The %s hits it.", str); | |||
| 342 | else pline("The %s hits %s%s", str, monnam(mtmp), force); | |||
| 343 | } | |||
| 344 | ||||
| 345 | void | |||
| 346 | miss(char *str, struct monst *mtmp) | |||
| 347 | { | |||
| 348 | if(!cansee(mtmp->mx,mtmp->my)) pline("The %s misses it.",str); | |||
| 349 | else pline("The %s misses %s.",str,monnam(mtmp)); | |||
| 350 | } | |||
| 351 | ||||
| 352 | /* bhit: called when a weapon is thrown (sym = obj->olet) or when an | |||
| 353 | * IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of | |||
| 354 | * range or when a monster is hit; the monster is returned, and bhitpos | |||
| 355 | * is set to the final position of the weapon thrown; the ray of a wand | |||
| 356 | * may affect several objects and monsters on its path - for each of | |||
| 357 | * these an argument function is called. */ | |||
| 358 | /* check !u.uswallow before calling bhit() */ | |||
| 359 | ||||
| 360 | /* | |||
| 361 | * int ddx,ddy,range; direction and range | |||
| 362 | * char sym; symbol displayed on path | |||
| 363 | * int (*fhitm)(), (*fhito)(); fns called when mon/obj hit | |||
| 364 | * struct obj *obj; 2nd arg to fhitm/fhito | |||
| 365 | * struct monst * | |||
| 366 | */ | |||
| 367 | struct monst * | |||
| 368 | bhit(int ddx, int ddy, int range, char sym, | |||
| 369 | void (*fhitm)(struct monst *, struct obj *), | |||
| 370 | boolean (*fhito)(struct obj *, struct obj *), | |||
| 371 | struct obj *obj) | |||
| 372 | { | |||
| 373 | struct monst *mtmp; | |||
| 374 | struct obj *otmp; | |||
| 375 | int typ; | |||
| 376 | ||||
| 377 | bhitpos.x = u.ux; | |||
| 378 | bhitpos.y = u.uy; | |||
| 379 | ||||
| 380 | if(sym) tmp_at(-1, sym); /* open call */ | |||
| 381 | while(range-- > 0) { | |||
| 382 | bhitpos.x += ddx; | |||
| 383 | bhitpos.y += ddy; | |||
| 384 | typ = levl[(int)bhitpos.x][(int)bhitpos.y].typ; | |||
| 385 | if ((mtmp = m_at(bhitpos.x,bhitpos.y))) { | |||
| 386 | if(sym) { | |||
| 387 | tmp_at(-1, -1); /* close call */ | |||
| 388 | return(mtmp); | |||
| 389 | } | |||
| 390 | if (fhitm) | |||
| 391 | (*fhitm)(mtmp, obj); | |||
| 392 | range -= 3; | |||
| 393 | } | |||
| 394 | if ((otmp = o_at(bhitpos.x,bhitpos.y))){ | |||
| 395 | if(fhito && (*fhito)(otmp, obj)) | |||
| 396 | range--; | |||
| 397 | } | |||
| 398 | if (!ZAP_POS(typ)((typ) > 7)) { | |||
| 399 | bhitpos.x -= ddx; | |||
| 400 | bhitpos.y -= ddy; | |||
| 401 | break; | |||
| 402 | } | |||
| 403 | if(sym) tmp_at(bhitpos.x, bhitpos.y); | |||
| 404 | } | |||
| 405 | ||||
| 406 | /* leave last symbol unless in a pool */ | |||
| 407 | if(sym) | |||
| 408 | tmp_at(-1, (levl[(int)bhitpos.x][(int)bhitpos.y].typ == POOL6) ? -1 : 0); | |||
| 409 | return(NULL((void *)0)); | |||
| 410 | } | |||
| 411 | ||||
| 412 | struct monst * | |||
| 413 | boomhit(int dx, int dy) | |||
| 414 | { | |||
| 415 | int i, ct; | |||
| 416 | struct monst *mtmp; | |||
| 417 | char sym = ')'; | |||
| 418 | extern schar xdir[], ydir[]; | |||
| 419 | ||||
| 420 | bhitpos.x = u.ux; | |||
| 421 | bhitpos.y = u.uy; | |||
| 422 | ||||
| 423 | for(i=0; i<8; i++) if(xdir[i] == dx && ydir[i] == dy) break; | |||
| 424 | tmp_at(-1, sym); /* open call */ | |||
| 425 | for(ct=0; ct<10; ct++) { | |||
| 426 | if(i == 8) i = 0; | |||
| 427 | sym = ')' + '(' - sym; | |||
| 428 | tmp_at(-2, sym); /* change let call */ | |||
| 429 | dx = xdir[i]; | |||
| 430 | dy = ydir[i]; | |||
| 431 | bhitpos.x += dx; | |||
| 432 | bhitpos.y += dy; | |||
| 433 | if ((mtmp = m_at(bhitpos.x, bhitpos.y))) { | |||
| 434 | tmp_at(-1,-1); | |||
| 435 | return(mtmp); | |||
| 436 | } | |||
| 437 | if (!ZAP_POS(levl[(int)bhitpos.x][(int)bhitpos.y].typ)((levl[(int)bhitpos.x][(int)bhitpos.y].typ) > 7)) { | |||
| 438 | bhitpos.x -= dx; | |||
| 439 | bhitpos.y -= dy; | |||
| 440 | break; | |||
| 441 | } | |||
| 442 | if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */ | |||
| 443 | if(rn2(20) >= 10+u.ulevel){ /* we hit ourselves */ | |||
| 444 | (void) thitu(10, rnd(10), "boomerang"); | |||
| 445 | break; | |||
| 446 | } else { /* we catch it */ | |||
| 447 | tmp_at(-1,-1); | |||
| 448 | pline("Skillfully, you catch the boomerang."); | |||
| 449 | return(&youmonst); | |||
| 450 | } | |||
| 451 | } | |||
| 452 | tmp_at(bhitpos.x, bhitpos.y); | |||
| 453 | if(ct % 5 != 0) i++; | |||
| 454 | } | |||
| 455 | tmp_at(-1, -1); /* do not leave last symbol */ | |||
| 456 | return(0); | |||
| 457 | } | |||
| 458 | ||||
| 459 | static char | |||
| 460 | dirlet(int dx, int dy) | |||
| 461 | { | |||
| 462 | return (dx == dy) ? '\\' : (dx && dy) ? '/' : dx ? '-' : '|'; | |||
| 463 | } | |||
| 464 | ||||
| 465 | /* type == -1: monster spitting fire at you */ | |||
| 466 | /* type == -1,-2,-3: bolts sent out by wizard */ | |||
| 467 | /* called with dx = dy = 0 with vertical bolts */ | |||
| 468 | void | |||
| 469 | buzz(int type, xchar sx, xchar sy, int dx, int dy) | |||
| 470 | { | |||
| 471 | int abstype = abs(type); | |||
| 472 | char *fltxt = (type == -1) ? "blaze of fire" : fl[abstype]; | |||
| 473 | struct rm *lev; | |||
| 474 | xchar range; | |||
| 475 | struct monst *mon; | |||
| 476 | ||||
| 477 | if(u.uswallow) { | |||
| 478 | int tmp; | |||
| 479 | ||||
| 480 | if(type < 0) return; | |||
| 481 | tmp = zhit(u.ustuck, type); | |||
| 482 | pline("The %s rips into %s%s", | |||
| 483 | fltxt, monnam(u.ustuck), exclam(tmp)); | |||
| 484 | return; | |||
| 485 | } | |||
| 486 | if(type < 0) pru(); | |||
| 487 | range = rn1(7,7); | |||
| 488 | Tmp_at(-1, dirlet(dx,dy)); /* open call */ | |||
| 489 | while(range-- > 0) { | |||
| 490 | sx += dx; | |||
| 491 | sy += dy; | |||
| 492 | if ((lev = &levl[(int)sx][(int)sy])->typ) | |||
| 493 | Tmp_at(sx,sy); | |||
| 494 | else { | |||
| 495 | int bounce = 0; | |||
| 496 | if (cansee(sx-dx,sy-dy)) | |||
| 497 | pline("The %s bounces!", fltxt); | |||
| 498 | if (ZAP_POS(levl[(int)sx][sy-dy].typ)((levl[(int)sx][sy-dy].typ) > 7)) | |||
| 499 | bounce = 1; | |||
| 500 | if (ZAP_POS(levl[sx-dx][(int)sy].typ)((levl[sx-dx][(int)sy].typ) > 7)) { | |||
| 501 | if(!bounce || rn2(2)) | |||
| 502 | bounce = 2; | |||
| 503 | } | |||
| 504 | switch(bounce){ | |||
| 505 | case 0: | |||
| 506 | dx = -dx; | |||
| 507 | dy = -dy; | |||
| 508 | continue; | |||
| 509 | case 1: | |||
| 510 | dy = -dy; | |||
| 511 | sx -= dx; | |||
| 512 | break; | |||
| 513 | case 2: | |||
| 514 | dx = -dx; | |||
| 515 | sy -= dy; | |||
| 516 | break; | |||
| 517 | } | |||
| 518 | Tmp_at(-2,dirlet(dx,dy)); | |||
| 519 | continue; | |||
| 520 | } | |||
| 521 | if(lev->typ == POOL6 && abstype == 1 /* fire */) { | |||
| 522 | range -= 3; | |||
| 523 | lev->typ = ROOM9; | |||
| 524 | if(cansee(sx,sy)) { | |||
| 525 | mnewsym(sx,sy); | |||
| 526 | pline("The water evaporates."); | |||
| 527 | } else | |||
| 528 | pline("You hear a hissing sound."); | |||
| 529 | } | |||
| 530 | if((mon = m_at(sx,sy)) && | |||
| 531 | (type != -1 || mon->data->mlet != 'D')) { | |||
| 532 | wakeup(mon); | |||
| 533 | if(rnd(20) < 18 + mon->data->ac) { | |||
| 534 | int tmp = zhit(mon,abstype); | |||
| 535 | if(mon->mhp < 1) { | |||
| 536 | if(type < 0) { | |||
| 537 | if(cansee(mon->mx,mon->my)) | |||
| 538 | pline("%s is killed by the %s!", | |||
| 539 | Monnam(mon), fltxt); | |||
| 540 | mondied(mon); | |||
| 541 | } else | |||
| 542 | killed(mon); | |||
| 543 | } else | |||
| 544 | hit(fltxt, mon, exclam(tmp)); | |||
| 545 | range -= 2; | |||
| 546 | } else | |||
| 547 | miss(fltxt,mon); | |||
| 548 | } else if(sx == u.ux && sy == u.uy) { | |||
| 549 | nomul(0); | |||
| 550 | if(rnd(20) < 18+u.uac) { | |||
| 551 | int dam = 0; | |||
| 552 | range -= 2; | |||
| 553 | pline("The %s hits you!",fltxt); | |||
| 554 | switch(abstype) { | |||
| 555 | case 0: | |||
| 556 | dam = d(2,6); | |||
| 557 | break; | |||
| 558 | case 1: | |||
| 559 | if(Fire_resistanceu.uprops[10].p_flgs) | |||
| 560 | pline("You don't feel hot!"); | |||
| 561 | else dam = d(6,6); | |||
| 562 | if(!rn2(3)) | |||
| 563 | burn_scrolls(); | |||
| 564 | break; | |||
| 565 | case 2: | |||
| 566 | nomul(-rnd(25)); /* sleep ray */ | |||
| 567 | break; | |||
| 568 | case 3: | |||
| 569 | if(Cold_resistanceu.uprops[11].p_flgs) | |||
| 570 | pline("You don't feel cold!"); | |||
| 571 | else dam = d(6,6); | |||
| 572 | break; | |||
| 573 | case 4: | |||
| 574 | u.uhp = -1; | |||
| 575 | } | |||
| 576 | losehp(dam,fltxt); | |||
| 577 | } else pline("The %s whizzes by you!",fltxt); | |||
| 578 | stop_occupation(); | |||
| 579 | } | |||
| 580 | if(!ZAP_POS(lev->typ)((lev->typ) > 7)) { | |||
| 581 | int bounce = 0, rmn; | |||
| 582 | if(cansee(sx,sy)) pline("The %s bounces!",fltxt); | |||
| 583 | range--; | |||
| 584 | if(!dx || !dy || !rn2(20)){ | |||
| 585 | dx = -dx; | |||
| 586 | dy = -dy; | |||
| 587 | } else { | |||
| 588 | if(ZAP_POS(rmn = levl[(int)sx][sy-dy].typ)((rmn = levl[(int)sx][sy-dy].typ) > 7) && | |||
| 589 | (IS_ROOM(rmn)((rmn) >= 9) || ZAP_POS(levl[sx+dx][sy-dy].typ)((levl[sx+dx][sy-dy].typ) > 7))) | |||
| 590 | bounce = 1; | |||
| 591 | if(ZAP_POS(rmn = levl[sx-dx][(int)sy].typ)((rmn = levl[sx-dx][(int)sy].typ) > 7) && | |||
| 592 | (IS_ROOM(rmn)((rmn) >= 9) || ZAP_POS(levl[sx-dx][sy+dy].typ)((levl[sx-dx][sy+dy].typ) > 7))) | |||
| 593 | if(!bounce || rn2(2)) | |||
| 594 | bounce = 2; | |||
| 595 | ||||
| 596 | switch(bounce){ | |||
| 597 | case 0: | |||
| 598 | dy = -dy; | |||
| 599 | dx = -dx; | |||
| 600 | break; | |||
| 601 | case 1: | |||
| 602 | dy = -dy; | |||
| 603 | break; | |||
| 604 | case 2: | |||
| 605 | dx = -dx; | |||
| 606 | break; | |||
| 607 | } | |||
| 608 | Tmp_at(-2, dirlet(dx,dy)); | |||
| 609 | } | |||
| 610 | } | |||
| 611 | } | |||
| 612 | Tmp_at(-1,-1); | |||
| 613 | } | |||
| 614 | ||||
| 615 | /* returns damage to mon */ | |||
| 616 | static int | |||
| 617 | zhit(struct monst *mon, int type) | |||
| 618 | { | |||
| 619 | int tmp = 0; | |||
| 620 | ||||
| 621 | switch(type) { | |||
| 622 | case 0: /* magic missile */ | |||
| 623 | tmp = d(2,6); | |||
| 624 | break; | |||
| 625 | case -1: /* Dragon blazing fire */ | |||
| 626 | case 1: /* fire */ | |||
| 627 | if(strchr("Dg", mon->data->mlet)) break; | |||
| 628 | tmp = d(6,6); | |||
| 629 | if(strchr("YF", mon->data->mlet)) tmp += 7; | |||
| 630 | break; | |||
| 631 | case 2: /* sleep*/ | |||
| 632 | mon->mfroz = 1; | |||
| 633 | break; | |||
| 634 | case 3: /* cold */ | |||
| 635 | if(strchr("YFgf", mon->data->mlet)) break; | |||
| 636 | tmp = d(6,6); | |||
| 637 | if(mon->data->mlet == 'D') tmp += 7; | |||
| 638 | break; | |||
| 639 | case 4: /* death*/ | |||
| 640 | if(strchr(UNDEAD"ZVW ", mon->data->mlet)) break; | |||
| 641 | tmp = mon->mhp+1; | |||
| 642 | break; | |||
| 643 | } | |||
| 644 | mon->mhp -= tmp; | |||
| 645 | return(tmp); | |||
| 646 | } | |||
| 647 | ||||
| 648 | #define CORPSE_I_TO_C(otyp)(char) ((otyp >= 45) ? 'a' + (otyp - 45) : '@' + (otyp - 18 )) (char) ((otyp >= DEAD_ACID_BLOB45)\ | |||
| 649 | ? 'a' + (otyp - DEAD_ACID_BLOB45)\ | |||
| 650 | : '@' + (otyp - DEAD_HUMAN18)) | |||
| 651 | ||||
| 652 | static boolean | |||
| 653 | revive(struct obj *obj) | |||
| 654 | { | |||
| 655 | struct monst *mtmp; | |||
| 656 | ||||
| 657 | if(obj->olet == FOOD_SYM'%' && obj->otyp > CORPSE18) { | |||
| 658 | /* do not (yet) revive shopkeepers */ | |||
| 659 | /* Note: this might conceivably produce two monsters | |||
| 660 | at the same position - strange, but harmless */ | |||
| 661 | mtmp = mkmon_at(CORPSE_I_TO_C(obj->otyp)(char) ((obj->otyp >= 45) ? 'a' + (obj->otyp - 45) : '@' + (obj->otyp - 18)),obj->ox,obj->oy); | |||
| 662 | delobj(obj); | |||
| 663 | } | |||
| 664 | return(!!mtmp); /* TRUE if some monster created */ | |||
| ||||
| 665 | } | |||
| 666 | ||||
| 667 | static void | |||
| 668 | rloco(struct obj *obj) | |||
| 669 | { | |||
| 670 | int tx,ty,otx,oty; | |||
| 671 | ||||
| 672 | otx = obj->ox; | |||
| 673 | oty = obj->oy; | |||
| 674 | do { | |||
| 675 | tx = rn1(COLNO80-3,2); | |||
| 676 | ty = rn2(ROWNO22); | |||
| 677 | } while(!goodpos(tx,ty)); | |||
| 678 | obj->ox = tx; | |||
| 679 | obj->oy = ty; | |||
| 680 | if(cansee(otx,oty)) | |||
| 681 | newsym(otx,oty); | |||
| 682 | } | |||
| 683 | ||||
| 684 | /* fractured by pick-axe or wand of striking */ | |||
| 685 | void | |||
| 686 | fracture_rock(struct obj *obj) | |||
| 687 | { | |||
| 688 | /* unpobj(obj); */ | |||
| 689 | obj->otyp = ROCK75; | |||
| 690 | obj->quan = 7 + rn2(60); | |||
| 691 | obj->owt = weight(obj); | |||
| 692 | obj->olet = WEAPON_SYM')'; | |||
| 693 | if(cansee(obj->ox,obj->oy)) | |||
| 694 | prl(obj->ox,obj->oy); | |||
| 695 | } | |||
| 696 | ||||
| 697 | static void | |||
| 698 | burn_scrolls(void) | |||
| 699 | { | |||
| 700 | struct obj *obj, *obj2; | |||
| 701 | int cnt = 0; | |||
| 702 | ||||
| 703 | for(obj = invent; obj; obj = obj2) { | |||
| 704 | obj2 = obj->nobj; | |||
| 705 | if(obj->olet == SCROLL_SYM'?') { | |||
| 706 | cnt++; | |||
| 707 | useup(obj); | |||
| 708 | } | |||
| 709 | } | |||
| 710 | if(cnt > 1) { | |||
| 711 | pline("Your scrolls catch fire!"); | |||
| 712 | losehp(cnt, "burning scrolls"); | |||
| 713 | } else if(cnt) { | |||
| 714 | pline("Your scroll catches fire!"); | |||
| 715 | losehp(1, "burning scroll"); | |||
| 716 | } | |||
| 717 | } |