1 1.12 rillig /* $NetBSD: hack.c,v 1.12 2021/05/02 12:50:44 rillig Exp $ */ 2 1.4 christos 3 1.2 mycroft /* 4 1.6 jsm * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, 5 1.6 jsm * Amsterdam 6 1.6 jsm * All rights reserved. 7 1.6 jsm * 8 1.6 jsm * Redistribution and use in source and binary forms, with or without 9 1.6 jsm * modification, are permitted provided that the following conditions are 10 1.6 jsm * met: 11 1.6 jsm * 12 1.6 jsm * - Redistributions of source code must retain the above copyright notice, 13 1.6 jsm * this list of conditions and the following disclaimer. 14 1.6 jsm * 15 1.6 jsm * - Redistributions in binary form must reproduce the above copyright 16 1.6 jsm * notice, this list of conditions and the following disclaimer in the 17 1.6 jsm * documentation and/or other materials provided with the distribution. 18 1.6 jsm * 19 1.6 jsm * - Neither the name of the Stichting Centrum voor Wiskunde en 20 1.6 jsm * Informatica, nor the names of its contributors may be used to endorse or 21 1.6 jsm * promote products derived from this software without specific prior 22 1.6 jsm * written permission. 23 1.6 jsm * 24 1.6 jsm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 25 1.6 jsm * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 1.6 jsm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 27 1.6 jsm * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 28 1.6 jsm * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29 1.6 jsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30 1.6 jsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 1.6 jsm * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 1.6 jsm * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 1.6 jsm * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 1.6 jsm * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 1.6 jsm */ 36 1.6 jsm 37 1.6 jsm /* 38 1.6 jsm * Copyright (c) 1982 Jay Fenlason <hack (at) gnu.org> 39 1.6 jsm * All rights reserved. 40 1.6 jsm * 41 1.6 jsm * Redistribution and use in source and binary forms, with or without 42 1.6 jsm * modification, are permitted provided that the following conditions 43 1.6 jsm * are met: 44 1.6 jsm * 1. Redistributions of source code must retain the above copyright 45 1.6 jsm * notice, this list of conditions and the following disclaimer. 46 1.6 jsm * 2. Redistributions in binary form must reproduce the above copyright 47 1.6 jsm * notice, this list of conditions and the following disclaimer in the 48 1.6 jsm * documentation and/or other materials provided with the distribution. 49 1.6 jsm * 3. The name of the author may not be used to endorse or promote products 50 1.6 jsm * derived from this software without specific prior written permission. 51 1.6 jsm * 52 1.6 jsm * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 53 1.6 jsm * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 54 1.6 jsm * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 55 1.6 jsm * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 56 1.6 jsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 57 1.6 jsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 58 1.6 jsm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 59 1.6 jsm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 60 1.6 jsm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 61 1.6 jsm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 1.2 mycroft */ 63 1.2 mycroft 64 1.4 christos #include <sys/cdefs.h> 65 1.2 mycroft #ifndef lint 66 1.12 rillig __RCSID("$NetBSD: hack.c,v 1.12 2021/05/02 12:50:44 rillig Exp $"); 67 1.4 christos #endif /* not lint */ 68 1.1 cgd 69 1.1 cgd #include "hack.h" 70 1.4 christos #include "extern.h" 71 1.1 cgd 72 1.9 dholland static void movobj(struct obj *, int, int); 73 1.9 dholland static int inv_cnt(void); 74 1.9 dholland 75 1.4 christos /* 76 1.4 christos * called on movement: 1. when throwing ball+chain far away 2. when 77 1.4 christos * teleporting 3. when walking out of a lit room 78 1.1 cgd */ 79 1.4 christos void 80 1.8 dholland unsee(void) 81 1.4 christos { 82 1.4 christos int x, y; 83 1.4 christos struct rm *lev; 84 1.1 cgd 85 1.4 christos /* 86 1.4 christos if(u.udispl){ 87 1.4 christos u.udispl = 0; 88 1.4 christos newsym(u.udisx, u.udisy); 89 1.4 christos } 90 1.4 christos */ 91 1.1 cgd #ifndef QUEST 92 1.4 christos if (seehx) { 93 1.1 cgd seehx = 0; 94 1.1 cgd } else 95 1.4 christos #endif /* QUEST */ 96 1.4 christos for (x = u.ux - 1; x < u.ux + 2; x++) 97 1.4 christos for (y = u.uy - 1; y < u.uy + 2; y++) { 98 1.4 christos if (!isok(x, y)) 99 1.4 christos continue; 100 1.4 christos lev = &levl[x][y]; 101 1.4 christos if (!lev->lit && lev->scrsym == '.') { 102 1.4 christos lev->scrsym = ' '; 103 1.4 christos lev->new = 1; 104 1.4 christos on_scr(x, y); 105 1.4 christos } 106 1.4 christos } 107 1.1 cgd } 108 1.1 cgd 109 1.4 christos /* 110 1.4 christos * called: in hack.eat.c: seeoff(0) - blind after eating rotten food in 111 1.4 christos * hack.mon.c: seeoff(0) - blinded by a yellow light in hack.mon.c: seeoff(1) 112 1.4 christos * - swallowed in hack.do.c: seeoff(0) - blind after drinking potion in 113 1.4 christos * hack.do.c: seeoff(1) - go up or down the stairs in hack.trap.c:seeoff(1) 114 1.4 christos * - fall through trapdoor 115 1.1 cgd */ 116 1.8 dholland /* mode: */ 117 1.8 dholland /* 1 to redo @, 0 to leave them *//* 1 means 118 1.8 dholland * misc movement, 0 means blindness */ 119 1.4 christos void 120 1.8 dholland seeoff(int mode) 121 1.4 christos { 122 1.4 christos int x, y; 123 1.4 christos struct rm *lev; 124 1.1 cgd 125 1.4 christos if (u.udispl && mode) { 126 1.1 cgd u.udispl = 0; 127 1.4 christos levl[u.udisx][u.udisy].scrsym = news0(u.udisx, u.udisy); 128 1.1 cgd } 129 1.1 cgd #ifndef QUEST 130 1.4 christos if (seehx) { 131 1.1 cgd seehx = 0; 132 1.1 cgd } else 133 1.4 christos #endif /* QUEST */ 134 1.4 christos if (!mode) { 135 1.4 christos for (x = u.ux - 1; x < u.ux + 2; x++) 136 1.4 christos for (y = u.uy - 1; y < u.uy + 2; y++) { 137 1.4 christos if (!isok(x, y)) 138 1.4 christos continue; 139 1.1 cgd lev = &levl[x][y]; 140 1.4 christos if (!lev->lit && lev->scrsym == '.') 141 1.1 cgd lev->seen = 0; 142 1.1 cgd } 143 1.1 cgd } 144 1.1 cgd } 145 1.1 cgd 146 1.4 christos void 147 1.8 dholland domove(void) 148 1.1 cgd { 149 1.4 christos xchar oldx, oldy; 150 1.4 christos struct monst *mtmp = NULL; 151 1.4 christos struct rm *tmpr, *ust; 152 1.4 christos struct trap *trap = NULL; 153 1.4 christos struct obj *otmp = NULL; 154 1.1 cgd 155 1.1 cgd u_wipe_engr(rnd(5)); 156 1.1 cgd 157 1.4 christos if (inv_weight() > 0) { 158 1.1 cgd pline("You collapse under your load."); 159 1.1 cgd nomul(0); 160 1.1 cgd return; 161 1.1 cgd } 162 1.4 christos if (u.uswallow) { 163 1.1 cgd u.dx = u.dy = 0; 164 1.1 cgd u.ux = u.ustuck->mx; 165 1.1 cgd u.uy = u.ustuck->my; 166 1.1 cgd } else { 167 1.4 christos if (Confusion) { 168 1.1 cgd do { 169 1.1 cgd confdir(); 170 1.4 christos } while (!isok(u.ux + u.dx, u.uy + u.dy) || 171 1.4 christos IS_ROCK(levl[u.ux + u.dx][u.uy + u.dy].typ)); 172 1.1 cgd } 173 1.4 christos if (!isok(u.ux + u.dx, u.uy + u.dy)) { 174 1.1 cgd nomul(0); 175 1.1 cgd return; 176 1.1 cgd } 177 1.1 cgd } 178 1.1 cgd 179 1.1 cgd ust = &levl[u.ux][u.uy]; 180 1.1 cgd oldx = u.ux; 181 1.1 cgd oldy = u.uy; 182 1.4 christos if (!u.uswallow && (trap = t_at(u.ux + u.dx, u.uy + u.dy)) && trap->tseen) 183 1.1 cgd nomul(0); 184 1.4 christos if (u.ustuck && !u.uswallow && (u.ux + u.dx != u.ustuck->mx || 185 1.4 christos u.uy + u.dy != u.ustuck->my)) { 186 1.4 christos if (dist(u.ustuck->mx, u.ustuck->my) > 2) { 187 1.1 cgd /* perhaps it fled (or was teleported or ... ) */ 188 1.1 cgd u.ustuck = 0; 189 1.1 cgd } else { 190 1.4 christos if (Blind) 191 1.4 christos pline("You cannot escape from it!"); 192 1.4 christos else 193 1.4 christos pline("You cannot escape from %s!", 194 1.4 christos monnam(u.ustuck)); 195 1.1 cgd nomul(0); 196 1.1 cgd return; 197 1.1 cgd } 198 1.1 cgd } 199 1.4 christos if (u.uswallow || (mtmp = m_at(u.ux + u.dx, u.uy + u.dy))) { 200 1.4 christos /* attack monster */ 201 1.1 cgd 202 1.1 cgd nomul(0); 203 1.1 cgd gethungry(); 204 1.4 christos if (multi < 0) 205 1.4 christos return; /* we just fainted */ 206 1.1 cgd 207 1.1 cgd /* try to attack; note that it might evade */ 208 1.4 christos if (attack(u.uswallow ? u.ustuck : mtmp)) 209 1.1 cgd return; 210 1.1 cgd } 211 1.1 cgd /* not attacking an animal, so we try to move */ 212 1.4 christos if (u.utrap) { 213 1.4 christos if (u.utraptype == TT_PIT) { 214 1.1 cgd pline("You are still in a pit."); 215 1.1 cgd u.utrap--; 216 1.1 cgd } else { 217 1.1 cgd pline("You are caught in a beartrap."); 218 1.4 christos if ((u.dx && u.dy) || !rn2(5)) 219 1.4 christos u.utrap--; 220 1.1 cgd } 221 1.1 cgd return; 222 1.1 cgd } 223 1.4 christos tmpr = &levl[u.ux + u.dx][u.uy + u.dy]; 224 1.4 christos if (IS_ROCK(tmpr->typ) || 225 1.4 christos (u.dx && u.dy && (tmpr->typ == DOOR || ust->typ == DOOR))) { 226 1.1 cgd flags.move = 0; 227 1.1 cgd nomul(0); 228 1.1 cgd return; 229 1.1 cgd } 230 1.4 christos while ((otmp = sobj_at(ENORMOUS_ROCK, u.ux + u.dx, u.uy + u.dy)) != NULL){ 231 1.4 christos xchar rx = u.ux + 2 * u.dx, ry = u.uy + 2 * u.dy; 232 1.4 christos struct trap *ttmp; 233 1.1 cgd nomul(0); 234 1.4 christos if (isok(rx, ry) && !IS_ROCK(levl[rx][ry].typ) && 235 1.1 cgd (levl[rx][ry].typ != DOOR || !(u.dx && u.dy)) && 236 1.1 cgd !sobj_at(ENORMOUS_ROCK, rx, ry)) { 237 1.4 christos if (m_at(rx, ry)) { 238 1.4 christos pline("You hear a monster behind the rock."); 239 1.4 christos pline("Perhaps that's why you cannot move it."); 240 1.4 christos goto cannot_push; 241 1.4 christos } 242 1.4 christos if ((ttmp = t_at(rx, ry)) != NULL) 243 1.4 christos switch (ttmp->ttyp) { 244 1.4 christos case PIT: 245 1.4 christos pline("You push the rock into a pit!"); 246 1.4 christos deltrap(ttmp); 247 1.4 christos delobj(otmp); 248 1.4 christos pline("It completely fills the pit!"); 249 1.4 christos continue; 250 1.4 christos case TELEP_TRAP: 251 1.4 christos pline("You push the rock and suddenly it disappears!"); 252 1.4 christos delobj(otmp); 253 1.4 christos continue; 254 1.4 christos } 255 1.4 christos if (levl[rx][ry].typ == POOL) { 256 1.1 cgd levl[rx][ry].typ = ROOM; 257 1.4 christos mnewsym(rx, ry); 258 1.4 christos prl(rx, ry); 259 1.1 cgd pline("You push the rock into the water."); 260 1.1 cgd pline("Now you can cross the water!"); 261 1.1 cgd delobj(otmp); 262 1.1 cgd continue; 263 1.1 cgd } 264 1.1 cgd otmp->ox = rx; 265 1.1 cgd otmp->oy = ry; 266 1.1 cgd /* pobj(otmp); */ 267 1.4 christos if (cansee(rx, ry)) 268 1.4 christos atl(rx, ry, otmp->olet); 269 1.4 christos if (Invisible) 270 1.4 christos newsym(u.ux + u.dx, u.uy + u.dy); 271 1.4 christos 272 1.4 christos { 273 1.4 christos static long lastmovetime; 274 1.4 christos /* 275 1.4 christos * note: this var contains garbage initially 276 1.4 christos * and after a restore 277 1.4 christos */ 278 1.4 christos if (moves > lastmovetime + 2 || moves < lastmovetime) 279 1.4 christos pline("With great effort you move the enormous rock."); 280 1.4 christos lastmovetime = moves; 281 1.1 cgd } 282 1.1 cgd } else { 283 1.4 christos pline("You try to move the enormous rock, but in vain."); 284 1.4 christos cannot_push: 285 1.4 christos if ((!invent || inv_weight() + 90 <= 0) && 286 1.4 christos (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][u.uy + u.dy].typ) 287 1.4 christos && IS_ROCK(levl[u.ux + u.dx][u.uy].typ)))) { 288 1.4 christos pline("However, you can squeeze yourself into a small opening."); 289 1.4 christos break; 290 1.4 christos } else 291 1.4 christos return; 292 1.1 cgd } 293 1.4 christos } 294 1.4 christos if (u.dx && u.dy && IS_ROCK(levl[u.ux][u.uy + u.dy].typ) && 295 1.4 christos IS_ROCK(levl[u.ux + u.dx][u.uy].typ) && 296 1.4 christos invent && inv_weight() + 40 > 0) { 297 1.1 cgd pline("You are carrying too much to get through."); 298 1.1 cgd nomul(0); 299 1.1 cgd return; 300 1.1 cgd } 301 1.4 christos if (Punished && 302 1.4 christos DIST(u.ux + u.dx, u.uy + u.dy, uchain->ox, uchain->oy) > 2) { 303 1.4 christos if (carried(uball)) { 304 1.1 cgd movobj(uchain, u.ux, u.uy); 305 1.1 cgd goto nodrag; 306 1.1 cgd } 307 1.4 christos if (DIST(u.ux + u.dx, u.uy + u.dy, uball->ox, uball->oy) < 3) { 308 1.1 cgd /* leave ball, move chain under/over ball */ 309 1.1 cgd movobj(uchain, uball->ox, uball->oy); 310 1.1 cgd goto nodrag; 311 1.1 cgd } 312 1.4 christos if (inv_weight() + (int) uball->owt / 2 > 0) { 313 1.1 cgd pline("You cannot %sdrag the heavy iron ball.", 314 1.4 christos invent ? "carry all that and also " : ""); 315 1.1 cgd nomul(0); 316 1.1 cgd return; 317 1.1 cgd } 318 1.1 cgd movobj(uball, uchain->ox, uchain->oy); 319 1.4 christos unpobj(uball); /* BAH %% */ 320 1.1 cgd uchain->ox = u.ux; 321 1.1 cgd uchain->oy = u.uy; 322 1.1 cgd nomul(-2); 323 1.1 cgd nomovemsg = ""; 324 1.4 christos nodrag: ; 325 1.1 cgd } 326 1.1 cgd u.ux += u.dx; 327 1.1 cgd u.uy += u.dy; 328 1.4 christos if (flags.run) { 329 1.4 christos if (tmpr->typ == DOOR || 330 1.4 christos (xupstair == u.ux && yupstair == u.uy) || 331 1.4 christos (xdnstair == u.ux && ydnstair == u.uy)) 332 1.1 cgd nomul(0); 333 1.1 cgd } 334 1.4 christos if (tmpr->typ == POOL && !Levitation) 335 1.1 cgd drown(); /* not necessarily fatal */ 336 1.1 cgd 337 1.4 christos /* 338 1.4 christos if(u.udispl) { 339 1.4 christos u.udispl = 0; 340 1.4 christos newsym(oldx,oldy); 341 1.4 christos } 342 1.4 christos */ 343 1.4 christos if (!Blind) { 344 1.1 cgd #ifdef QUEST 345 1.1 cgd setsee(); 346 1.1 cgd #else 347 1.4 christos if (ust->lit) { 348 1.4 christos if (tmpr->lit) { 349 1.4 christos if (tmpr->typ == DOOR) 350 1.4 christos prl1(u.ux + u.dx, u.uy + u.dy); 351 1.4 christos else if (ust->typ == DOOR) 352 1.4 christos nose1(oldx - u.dx, oldy - u.dy); 353 1.1 cgd } else { 354 1.1 cgd unsee(); 355 1.4 christos prl1(u.ux + u.dx, u.uy + u.dy); 356 1.1 cgd } 357 1.1 cgd } else { 358 1.4 christos if (tmpr->lit) 359 1.4 christos setsee(); 360 1.1 cgd else { 361 1.4 christos prl1(u.ux + u.dx, u.uy + u.dy); 362 1.4 christos if (tmpr->typ == DOOR) { 363 1.4 christos if (u.dy) { 364 1.4 christos prl(u.ux - 1, u.uy); 365 1.4 christos prl(u.ux + 1, u.uy); 366 1.1 cgd } else { 367 1.4 christos prl(u.ux, u.uy - 1); 368 1.4 christos prl(u.ux, u.uy + 1); 369 1.1 cgd } 370 1.1 cgd } 371 1.1 cgd } 372 1.4 christos nose1(oldx - u.dx, oldy - u.dy); 373 1.1 cgd } 374 1.4 christos #endif /* QUEST */ 375 1.1 cgd } else { 376 1.1 cgd pru(); 377 1.1 cgd } 378 1.4 christos if (!flags.nopick) 379 1.4 christos pickup(1); 380 1.4 christos if (trap) 381 1.4 christos dotrap(trap); /* fall into pit, arrow trap, etc. */ 382 1.1 cgd (void) inshop(); 383 1.4 christos if (!Blind) 384 1.4 christos read_engr_at(u.ux, u.uy); 385 1.1 cgd } 386 1.1 cgd 387 1.9 dholland static void 388 1.8 dholland movobj(struct obj *obj, int ox, int oy) 389 1.1 cgd { 390 1.1 cgd /* Some dirty programming to get display right */ 391 1.1 cgd freeobj(obj); 392 1.1 cgd unpobj(obj); 393 1.1 cgd obj->nobj = fobj; 394 1.1 cgd fobj = obj; 395 1.1 cgd obj->ox = ox; 396 1.1 cgd obj->oy = oy; 397 1.1 cgd } 398 1.1 cgd 399 1.4 christos int 400 1.8 dholland dopickup(void) 401 1.4 christos { 402 1.4 christos if (!g_at(u.ux, u.uy) && !o_at(u.ux, u.uy)) { 403 1.1 cgd pline("There is nothing here to pick up."); 404 1.4 christos return (0); 405 1.1 cgd } 406 1.4 christos if (Levitation) { 407 1.1 cgd pline("You cannot reach the floor."); 408 1.4 christos return (1); 409 1.1 cgd } 410 1.1 cgd pickup(0); 411 1.4 christos return (1); 412 1.1 cgd } 413 1.1 cgd 414 1.4 christos void 415 1.5 jsm pickup(int all) 416 1.1 cgd { 417 1.4 christos struct gold *gold; 418 1.4 christos struct obj *obj, *obj2; 419 1.4 christos int wt; 420 1.1 cgd 421 1.4 christos if (Levitation) 422 1.4 christos return; 423 1.4 christos while ((gold = g_at(u.ux, u.uy)) != NULL) { 424 1.1 cgd pline("%ld gold piece%s.", gold->amount, plur(gold->amount)); 425 1.1 cgd u.ugold += gold->amount; 426 1.1 cgd flags.botl = 1; 427 1.1 cgd freegold(gold); 428 1.4 christos if (flags.run) 429 1.4 christos nomul(0); 430 1.4 christos if (Invisible) 431 1.4 christos newsym(u.ux, u.uy); 432 1.1 cgd } 433 1.1 cgd 434 1.1 cgd /* check for more than one object */ 435 1.4 christos if (!all) { 436 1.4 christos int ct = 0; 437 1.1 cgd 438 1.4 christos for (obj = fobj; obj; obj = obj->nobj) 439 1.4 christos if (obj->ox == u.ux && obj->oy == u.uy) 440 1.4 christos if (!Punished || obj != uchain) 441 1.1 cgd ct++; 442 1.4 christos if (ct < 2) 443 1.1 cgd all++; 444 1.1 cgd else 445 1.1 cgd pline("There are several objects here."); 446 1.1 cgd } 447 1.4 christos for (obj = fobj; obj; obj = obj2) { 448 1.4 christos obj2 = obj->nobj; /* perhaps obj will be picked up */ 449 1.4 christos if (obj->ox == u.ux && obj->oy == u.uy) { 450 1.4 christos if (flags.run) 451 1.4 christos nomul(0); 452 1.1 cgd 453 1.4 christos /* do not pick up uchain */ 454 1.4 christos if (Punished && obj == uchain) 455 1.4 christos continue; 456 1.4 christos 457 1.4 christos if (!all) { 458 1.4 christos char c; 459 1.4 christos 460 1.4 christos pline("Pick up %s ? [ynaq]", doname(obj)); 461 1.4 christos while (!strchr("ynaq ", (c = readchar()))) 462 1.10 roy sound_bell(); 463 1.4 christos if (c == 'q') 464 1.4 christos return; 465 1.4 christos if (c == 'n') 466 1.4 christos continue; 467 1.4 christos if (c == 'a') 468 1.4 christos all = 1; 469 1.4 christos } 470 1.4 christos if (obj->otyp == DEAD_COCKATRICE && !uarmg) { 471 1.4 christos pline("Touching the dead cockatrice is a fatal mistake."); 472 1.4 christos pline("You turn to stone."); 473 1.4 christos killer = "cockatrice cadaver"; 474 1.4 christos done("died"); 475 1.4 christos } 476 1.4 christos if (obj->otyp == SCR_SCARE_MONSTER) { 477 1.4 christos if (!obj->spe) 478 1.4 christos obj->spe = 1; 479 1.4 christos else { 480 1.4 christos /* 481 1.4 christos * Note: perhaps the 1st pickup 482 1.4 christos * failed: you cannot carry anymore, 483 1.4 christos * and so we never dropped it - let's 484 1.4 christos * assume that treading on it twice 485 1.4 christos * also destroys the scroll 486 1.4 christos */ 487 1.4 christos pline("The scroll turns to dust as you pick it up."); 488 1.4 christos delobj(obj); 489 1.4 christos continue; 490 1.1 cgd } 491 1.1 cgd } 492 1.4 christos wt = inv_weight() + obj->owt; 493 1.4 christos if (wt > 0) { 494 1.4 christos if (obj->quan > 1) { 495 1.4 christos /* see how many we can lift */ 496 1.4 christos int savequan = obj->quan; 497 1.4 christos int iw = inv_weight(); 498 1.4 christos int qq; 499 1.4 christos for (qq = 1; qq < savequan; qq++) { 500 1.4 christos obj->quan = qq; 501 1.4 christos if (iw + weight(obj) > 0) 502 1.4 christos break; 503 1.4 christos } 504 1.4 christos obj->quan = savequan; 505 1.4 christos qq--; 506 1.4 christos /* we can carry qq of them */ 507 1.4 christos if (!qq) 508 1.4 christos goto too_heavy; 509 1.4 christos pline("You can only carry %s of the %s lying here.", 510 1.4 christos (qq == 1) ? "one" : "some", 511 1.4 christos doname(obj)); 512 1.4 christos (void) splitobj(obj, qq); 513 1.4 christos /* 514 1.4 christos * note: obj2 is set already, so 515 1.4 christos * we'll never encounter the other 516 1.4 christos * half; if it should be otherwise 517 1.4 christos * then write obj2 = 518 1.4 christos * splitobj(obj,qq); 519 1.4 christos */ 520 1.4 christos goto lift_some; 521 1.4 christos } 522 1.1 cgd too_heavy: 523 1.4 christos pline("There %s %s here, but %s.", 524 1.4 christos (obj->quan == 1) ? "is" : "are", 525 1.4 christos doname(obj), 526 1.4 christos !invent ? "it is too heavy for you to lift" 527 1.4 christos : "you cannot carry anymore"); 528 1.4 christos break; 529 1.4 christos } 530 1.1 cgd lift_some: 531 1.4 christos if (inv_cnt() >= 52) { 532 1.7 christos pline("Your knapsack cannot accommodate anymore items."); 533 1.4 christos break; 534 1.4 christos } 535 1.4 christos if (wt > -5) 536 1.4 christos pline("You have a little trouble lifting"); 537 1.4 christos freeobj(obj); 538 1.4 christos if (Invisible) 539 1.4 christos newsym(u.ux, u.uy); 540 1.4 christos addtobill(obj); /* sets obj->unpaid if necessary */ 541 1.4 christos { 542 1.4 christos int pickquan = obj->quan; 543 1.4 christos int mergquan; 544 1.4 christos if (!Blind) 545 1.4 christos obj->dknown = 1; /* this is done by 546 1.4 christos * prinv(), but addinv() 547 1.4 christos * needs it already for 548 1.4 christos * merging */ 549 1.4 christos obj = addinv(obj); /* might merge it with 550 1.4 christos * other objects */ 551 1.4 christos mergquan = obj->quan; 552 1.4 christos obj->quan = pickquan; /* to fool prinv() */ 553 1.4 christos prinv(obj); 554 1.4 christos obj->quan = mergquan; 555 1.4 christos } 556 1.1 cgd } 557 1.1 cgd } 558 1.1 cgd } 559 1.1 cgd 560 1.1 cgd /* stop running if we see something interesting */ 561 1.1 cgd /* turn around a corner if that is the only way we can proceed */ 562 1.1 cgd /* do not turn left or right twice */ 563 1.4 christos void 564 1.8 dholland lookaround(void) 565 1.4 christos { 566 1.4 christos int x, y, i, x0 = 0, y0 = 0, m0 = 0, i0 = 9; 567 1.4 christos int corrct = 0, noturn = 0; 568 1.4 christos struct monst *mtmp; 569 1.4 christos if (Blind || flags.run == 0) 570 1.4 christos return; 571 1.4 christos if (flags.run == 1 && levl[u.ux][u.uy].typ == ROOM) 572 1.4 christos return; 573 1.1 cgd #ifdef QUEST 574 1.4 christos if (u.ux0 == u.ux + u.dx && u.uy0 == u.uy + u.dy) 575 1.4 christos goto stop; 576 1.4 christos #endif /* QUEST */ 577 1.4 christos for (x = u.ux - 1; x <= u.ux + 1; x++) 578 1.4 christos for (y = u.uy - 1; y <= u.uy + 1; y++) { 579 1.4 christos if (x == u.ux && y == u.uy) 580 1.4 christos continue; 581 1.4 christos if (!levl[x][y].typ) 582 1.4 christos continue; 583 1.4 christos if ((mtmp = m_at(x, y)) && !mtmp->mimic && 584 1.4 christos (!mtmp->minvis || See_invisible)) { 585 1.4 christos if (!mtmp->mtame || (x == u.ux + u.dx && y == u.uy + u.dy)) 586 1.4 christos goto stop; 587 1.4 christos } else 588 1.4 christos mtmp = 0; /* invisible M cannot 589 1.4 christos * influence us */ 590 1.4 christos if (x == u.ux - u.dx && y == u.uy - u.dy) 591 1.4 christos continue; 592 1.4 christos switch (levl[x][y].scrsym) { 593 1.4 christos case '|': 594 1.4 christos case '-': 595 1.4 christos case '.': 596 1.4 christos case ' ': 597 1.4 christos break; 598 1.4 christos case '+': 599 1.4 christos if (x != u.ux && y != u.uy) 600 1.4 christos break; 601 1.4 christos if (flags.run != 1) 602 1.4 christos goto stop; 603 1.11 dholland /* FALLTHROUGH */ 604 1.4 christos case CORR_SYM: 605 1.1 cgd corr: 606 1.4 christos if (flags.run == 1 || flags.run == 3) { 607 1.4 christos i = DIST(x, y, u.ux + u.dx, u.uy + u.dy); 608 1.4 christos if (i > 2) 609 1.4 christos break; 610 1.4 christos if (corrct == 1 && DIST(x, y, x0, y0) != 1) 611 1.4 christos noturn = 1; 612 1.4 christos if (i < i0) { 613 1.4 christos i0 = i; 614 1.4 christos x0 = x; 615 1.4 christos y0 = y; 616 1.4 christos m0 = mtmp ? 1 : 0; 617 1.4 christos } 618 1.1 cgd } 619 1.4 christos corrct++; 620 1.4 christos break; 621 1.4 christos case '^': 622 1.4 christos if (flags.run == 1) 623 1.4 christos goto corr; /* if you must */ 624 1.4 christos if (x == u.ux + u.dx && y == u.uy + u.dy) 625 1.4 christos goto stop; 626 1.4 christos break; 627 1.4 christos default: /* e.g. objects or trap or stairs */ 628 1.4 christos if (flags.run == 1) 629 1.4 christos goto corr; 630 1.4 christos if (mtmp) 631 1.4 christos break; /* d */ 632 1.4 christos stop: 633 1.4 christos nomul(0); 634 1.4 christos return; 635 1.1 cgd } 636 1.1 cgd } 637 1.1 cgd #ifdef QUEST 638 1.4 christos if (corrct > 0 && (flags.run == 4 || flags.run == 5)) 639 1.4 christos goto stop; 640 1.4 christos #endif /* QUEST */ 641 1.4 christos if (corrct > 1 && flags.run == 2) 642 1.4 christos goto stop; 643 1.4 christos if ((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 && 644 1.4 christos (corrct == 1 || (corrct == 2 && i0 == 1))) { 645 1.1 cgd /* make sure that we do not turn too far */ 646 1.4 christos if (i0 == 2) { 647 1.4 christos if (u.dx == y0 - u.uy && u.dy == u.ux - x0) 648 1.4 christos i = 2; /* straight turn right */ 649 1.4 christos else 650 1.4 christos i = -2; /* straight turn left */ 651 1.4 christos } else if (u.dx && u.dy) { 652 1.4 christos if ((u.dx == u.dy && y0 == u.uy) || 653 1.4 christos (u.dx != u.dy && y0 != u.uy)) 654 1.4 christos i = -1; /* half turn left */ 655 1.4 christos else 656 1.4 christos i = 1; /* half turn right */ 657 1.1 cgd } else { 658 1.4 christos if ((x0 - u.ux == y0 - u.uy && !u.dy) || 659 1.4 christos (x0 - u.ux != y0 - u.uy && u.dy)) 660 1.4 christos i = 1; /* half turn right */ 661 1.4 christos else 662 1.4 christos i = -1; /* half turn left */ 663 1.1 cgd } 664 1.1 cgd i += u.last_str_turn; 665 1.4 christos if (i <= 2 && i >= -2) { 666 1.1 cgd u.last_str_turn = i; 667 1.4 christos u.dx = x0 - u.ux, u.dy = y0 - u.uy; 668 1.1 cgd } 669 1.1 cgd } 670 1.1 cgd } 671 1.1 cgd 672 1.1 cgd /* something like lookaround, but we are not running */ 673 1.1 cgd /* react only to monsters that might hit us */ 674 1.4 christos int 675 1.8 dholland monster_nearby(void) 676 1.4 christos { 677 1.4 christos int x, y; 678 1.4 christos struct monst *mtmp; 679 1.4 christos if (!Blind) 680 1.4 christos for (x = u.ux - 1; x <= u.ux + 1; x++) 681 1.4 christos for (y = u.uy - 1; y <= u.uy + 1; y++) { 682 1.4 christos if (x == u.ux && y == u.uy) 683 1.4 christos continue; 684 1.4 christos if ((mtmp = m_at(x, y)) && !mtmp->mimic && !mtmp->mtame && 685 1.4 christos !mtmp->mpeaceful && !strchr("Ea", mtmp->data->mlet) && 686 1.4 christos !mtmp->mfroz && !mtmp->msleep && /* aplvax!jcn */ 687 1.4 christos (!mtmp->minvis || See_invisible)) 688 1.4 christos return (1); 689 1.4 christos } 690 1.4 christos return (0); 691 1.1 cgd } 692 1.1 cgd 693 1.1 cgd #ifdef QUEST 694 1.4 christos int 695 1.8 dholland cansee(xchar x, xchar y) 696 1.4 christos { 697 1.4 christos int dx, dy, adx, ady, sdx, sdy, dmax, d; 698 1.4 christos if (Blind) 699 1.4 christos return (0); 700 1.4 christos if (!isok(x, y)) 701 1.4 christos return (0); 702 1.4 christos d = dist(x, y); 703 1.4 christos if (d < 3) 704 1.4 christos return (1); 705 1.4 christos if (d > u.uhorizon * u.uhorizon) 706 1.4 christos return (0); 707 1.4 christos if (!levl[x][y].lit) 708 1.4 christos return (0); 709 1.4 christos dx = x - u.ux; 710 1.4 christos adx = abs(dx); 711 1.4 christos sdx = sgn(dx); 712 1.4 christos dy = y - u.uy; 713 1.4 christos ady = abs(dy); 714 1.4 christos sdy = sgn(dy); 715 1.4 christos if (dx == 0 || dy == 0 || adx == ady) { 716 1.1 cgd dmax = (dx == 0) ? ady : adx; 717 1.4 christos for (d = 1; d <= dmax; d++) 718 1.4 christos if (!rroom(sdx * d, sdy * d)) 719 1.4 christos return (0); 720 1.4 christos return (1); 721 1.4 christos } else if (ady > adx) { 722 1.4 christos for (d = 1; d <= ady; d++) { 723 1.4 christos if (!rroom(sdx * ((d * adx) / ady), sdy * d) || 724 1.4 christos !rroom(sdx * ((d * adx - 1) / ady + 1), sdy * d)) 725 1.4 christos return (0); 726 1.1 cgd } 727 1.4 christos return (1); 728 1.1 cgd } else { 729 1.4 christos for (d = 1; d <= adx; d++) { 730 1.4 christos if (!rroom(sdx * d, sdy * ((d * ady) / adx)) || 731 1.4 christos !rroom(sdx * d, sdy * ((d * ady - 1) / adx + 1))) 732 1.4 christos return (0); 733 1.1 cgd } 734 1.4 christos return (1); 735 1.1 cgd } 736 1.1 cgd } 737 1.1 cgd 738 1.4 christos int 739 1.8 dholland rroom(int x, int y) 740 1.4 christos { 741 1.4 christos return (IS_ROOM(levl[u.ux + x][u.uy + y].typ)); 742 1.1 cgd } 743 1.1 cgd 744 1.1 cgd #else 745 1.1 cgd 746 1.4 christos int 747 1.8 dholland cansee(xchar x, xchar y) 748 1.4 christos { 749 1.4 christos if (Blind || u.uswallow) 750 1.4 christos return (0); 751 1.4 christos if (dist(x, y) < 3) 752 1.4 christos return (1); 753 1.4 christos if (levl[x][y].lit && seelx <= x && x <= seehx && seely <= y && 754 1.4 christos y <= seehy) 755 1.4 christos return (1); 756 1.4 christos return (0); 757 1.4 christos } 758 1.4 christos #endif /* QUEST */ 759 1.4 christos 760 1.4 christos int 761 1.8 dholland sgn(int a) 762 1.4 christos { 763 1.4 christos return ((a > 0) ? 1 : (a == 0) ? 0 : -1); 764 1.1 cgd } 765 1.1 cgd 766 1.1 cgd #ifdef QUEST 767 1.4 christos void 768 1.8 dholland setsee(void) 769 1.1 cgd { 770 1.4 christos int x, y; 771 1.1 cgd 772 1.4 christos if (Blind) { 773 1.1 cgd pru(); 774 1.1 cgd return; 775 1.1 cgd } 776 1.4 christos for (y = u.uy - u.uhorizon; y <= u.uy + u.uhorizon; y++) 777 1.4 christos for (x = u.ux - u.uhorizon; x <= u.ux + u.uhorizon; x++) { 778 1.4 christos if (cansee(x, y)) 779 1.4 christos prl(x, y); 780 1.4 christos } 781 1.1 cgd } 782 1.1 cgd 783 1.1 cgd #else 784 1.1 cgd 785 1.4 christos void 786 1.8 dholland setsee(void) 787 1.1 cgd { 788 1.4 christos int x, y; 789 1.1 cgd 790 1.4 christos if (Blind) { 791 1.1 cgd pru(); 792 1.1 cgd return; 793 1.1 cgd } 794 1.4 christos if (!levl[u.ux][u.uy].lit) { 795 1.4 christos seelx = u.ux - 1; 796 1.4 christos seehx = u.ux + 1; 797 1.4 christos seely = u.uy - 1; 798 1.4 christos seehy = u.uy + 1; 799 1.1 cgd } else { 800 1.4 christos for (seelx = u.ux; levl[seelx - 1][u.uy].lit; seelx--); 801 1.4 christos for (seehx = u.ux; levl[seehx + 1][u.uy].lit; seehx++); 802 1.4 christos for (seely = u.uy; levl[u.ux][seely - 1].lit; seely--); 803 1.4 christos for (seehy = u.uy; levl[u.ux][seehy + 1].lit; seehy++); 804 1.4 christos } 805 1.4 christos for (y = seely; y <= seehy; y++) 806 1.4 christos for (x = seelx; x <= seehx; x++) { 807 1.4 christos prl(x, y); 808 1.4 christos } 809 1.4 christos if (!levl[u.ux][u.uy].lit) 810 1.4 christos seehx = 0; /* seems necessary elsewhere */ 811 1.1 cgd else { 812 1.4 christos if (seely == u.uy) 813 1.4 christos for (x = u.ux - 1; x <= u.ux + 1; x++) 814 1.4 christos prl(x, seely - 1); 815 1.4 christos if (seehy == u.uy) 816 1.4 christos for (x = u.ux - 1; x <= u.ux + 1; x++) 817 1.4 christos prl(x, seehy + 1); 818 1.4 christos if (seelx == u.ux) 819 1.4 christos for (y = u.uy - 1; y <= u.uy + 1; y++) 820 1.4 christos prl(seelx - 1, y); 821 1.4 christos if (seehx == u.ux) 822 1.4 christos for (y = u.uy - 1; y <= u.uy + 1; y++) 823 1.4 christos prl(seehx + 1, y); 824 1.1 cgd } 825 1.1 cgd } 826 1.4 christos #endif /* QUEST */ 827 1.1 cgd 828 1.4 christos void 829 1.8 dholland nomul(int nval) 830 1.1 cgd { 831 1.4 christos if (multi < 0) 832 1.4 christos return; 833 1.1 cgd multi = nval; 834 1.1 cgd flags.mv = flags.run = 0; 835 1.1 cgd } 836 1.1 cgd 837 1.4 christos int 838 1.8 dholland abon(void) 839 1.1 cgd { 840 1.4 christos if (u.ustr == 3) 841 1.4 christos return (-3); 842 1.4 christos else if (u.ustr < 6) 843 1.4 christos return (-2); 844 1.4 christos else if (u.ustr < 8) 845 1.4 christos return (-1); 846 1.4 christos else if (u.ustr < 17) 847 1.4 christos return (0); 848 1.4 christos else if (u.ustr < 69) 849 1.4 christos return (1); /* up to 18/50 */ 850 1.4 christos else if (u.ustr < 118) 851 1.4 christos return (2); 852 1.4 christos else 853 1.4 christos return (3); 854 1.1 cgd } 855 1.1 cgd 856 1.4 christos int 857 1.8 dholland dbon(void) 858 1.1 cgd { 859 1.4 christos if (u.ustr < 6) 860 1.4 christos return (-1); 861 1.4 christos else if (u.ustr < 16) 862 1.4 christos return (0); 863 1.4 christos else if (u.ustr < 18) 864 1.4 christos return (1); 865 1.4 christos else if (u.ustr == 18) 866 1.4 christos return (2); /* up to 18 */ 867 1.4 christos else if (u.ustr < 94) 868 1.4 christos return (3); /* up to 18/75 */ 869 1.4 christos else if (u.ustr < 109) 870 1.4 christos return (4); /* up to 18/90 */ 871 1.4 christos else if (u.ustr < 118) 872 1.4 christos return (5); /* up to 18/99 */ 873 1.4 christos else 874 1.4 christos return (6); 875 1.1 cgd } 876 1.1 cgd 877 1.8 dholland /* may kill you; cause may be poison or */ 878 1.8 dholland /* monster like 'A' */ 879 1.4 christos void 880 1.12 rillig losestr(int num) 881 1.1 cgd { 882 1.1 cgd u.ustr -= num; 883 1.4 christos while (u.ustr < 3) { 884 1.1 cgd u.ustr++; 885 1.1 cgd u.uhp -= 6; 886 1.1 cgd u.uhpmax -= 6; 887 1.1 cgd } 888 1.1 cgd flags.botl = 1; 889 1.1 cgd } 890 1.1 cgd 891 1.4 christos void 892 1.8 dholland losehp(int n, const char *knam) 893 1.1 cgd { 894 1.1 cgd u.uhp -= n; 895 1.4 christos if (u.uhp > u.uhpmax) 896 1.1 cgd u.uhpmax = u.uhp; /* perhaps n was negative */ 897 1.1 cgd flags.botl = 1; 898 1.4 christos if (u.uhp < 1) { 899 1.1 cgd killer = knam; /* the thing that killed you */ 900 1.1 cgd done("died"); 901 1.1 cgd } 902 1.1 cgd } 903 1.1 cgd 904 1.4 christos void 905 1.8 dholland losehp_m(int n, struct monst *mtmp) 906 1.1 cgd { 907 1.1 cgd u.uhp -= n; 908 1.1 cgd flags.botl = 1; 909 1.4 christos if (u.uhp < 1) 910 1.1 cgd done_in_by(mtmp); 911 1.1 cgd } 912 1.1 cgd 913 1.4 christos void 914 1.8 dholland losexp(void) 915 1.4 christos { /* hit by V or W */ 916 1.4 christos int num; 917 1.1 cgd 918 1.4 christos if (u.ulevel > 1) 919 1.1 cgd pline("Goodbye level %u.", u.ulevel--); 920 1.1 cgd else 921 1.1 cgd u.uhp = -1; 922 1.1 cgd num = rnd(10); 923 1.1 cgd u.uhp -= num; 924 1.1 cgd u.uhpmax -= num; 925 1.1 cgd u.uexp = newuexp(); 926 1.1 cgd flags.botl = 1; 927 1.1 cgd } 928 1.1 cgd 929 1.4 christos int 930 1.8 dholland inv_weight(void) 931 1.4 christos { 932 1.4 christos struct obj *otmp = invent; 933 1.4 christos int wt = (u.ugold + 500) / 1000; 934 1.4 christos int carrcap; 935 1.4 christos if (Levitation) /* pugh@cornell */ 936 1.1 cgd carrcap = MAX_CARR_CAP; 937 1.1 cgd else { 938 1.4 christos carrcap = 5 * (((u.ustr > 18) ? 20 : u.ustr) + u.ulevel); 939 1.4 christos if (carrcap > MAX_CARR_CAP) 940 1.4 christos carrcap = MAX_CARR_CAP; 941 1.4 christos if (Wounded_legs & LEFT_SIDE) 942 1.4 christos carrcap -= 10; 943 1.4 christos if (Wounded_legs & RIGHT_SIDE) 944 1.4 christos carrcap -= 10; 945 1.1 cgd } 946 1.4 christos while (otmp) { 947 1.1 cgd wt += otmp->owt; 948 1.1 cgd otmp = otmp->nobj; 949 1.1 cgd } 950 1.4 christos return (wt - carrcap); 951 1.1 cgd } 952 1.1 cgd 953 1.9 dholland static int 954 1.8 dholland inv_cnt(void) 955 1.4 christos { 956 1.4 christos struct obj *otmp = invent; 957 1.4 christos int ct = 0; 958 1.4 christos while (otmp) { 959 1.1 cgd ct++; 960 1.1 cgd otmp = otmp->nobj; 961 1.1 cgd } 962 1.4 christos return (ct); 963 1.1 cgd } 964 1.1 cgd 965 1.1 cgd long 966 1.8 dholland newuexp(void) 967 1.1 cgd { 968 1.4 christos return (10 * (1L << (u.ulevel - 1))); 969 1.1 cgd } 970