static bool bhito(struct obj *obj, struct obj *otmp) /* object obj was hit by the effect of wand otmp */ /* returns TRUE if sth was done */ { int res = TRUE; if(obj == uball || obj == uchain) res = FALSE; else switch(otmp->otyp) { case WAN_POLYMORPH: /* preserve symbol and quantity, but turn rocks into gems */ mkobj_at((obj->otyp == ROCK || obj->otyp == ENORMOUS_ROCK) ? GEM_SYM : obj->olet, obj->ox, obj->oy) -> quan = obj->quan; delobj(obj); break; case WAN_STRIKING: if(obj->otyp == ENORMOUS_ROCK) fracture_rock(obj); else res = FALSE; break; case WAN_CANCELLATION: if(obj->spe && obj->olet != AMULET_SYM) { obj->spe = 0; } break; case WAN_TELEPORTATION: rloco(obj); break; case WAN_MAKE_INVISIBLE: obj->oinvis = 1; break; case WAN_UNDEAD_TURNING: res = revive(obj); break; case WAN_SLOW_MONSTER: /* no effect on objects */ case WAN_SPEED_MONSTER: #ifdef WAN_PROBING case WAN_PROBING: #endif /* WAN_PROBING */ res = FALSE; break; default: impossible("What an interesting wand (%u)", otmp->otyp); } return(res); }
/* returns number of scattered objects */ long scatter(int sx, int sy, /* location of objects to scatter */ int blastforce, /* force behind the scattering */ unsigned int scflags, struct obj *obj) { /* only scatter this obj */ struct obj *otmp; struct level *lev = obj ? obj->olev : level; int tmp; int farthest = 0; uchar typ; long qtmp; boolean used_up; boolean individual_object = obj ? TRUE : FALSE; struct monst *mtmp; struct scatter_chain *stmp, *stmp2 = 0; struct scatter_chain *schain = NULL; long total = 0L; boolean visible = (lev == level && cansee(sx, sy)); while ((otmp = individual_object ? obj : lev->objects[sx][sy]) != 0) { if (otmp->quan > 1L) { qtmp = otmp->quan - 1; if (qtmp > LARGEST_INT) qtmp = LARGEST_INT; qtmp = (long)rnd((int)qtmp); otmp = splitobj(otmp, qtmp); } else { obj = NULL; /* all used */ } obj_extract_self(otmp); used_up = FALSE; /* 9 in 10 chance of fracturing boulders or statues */ if ((scflags & MAY_FRACTURE) && ((otmp->otyp == BOULDER) || (otmp->otyp == STATUE)) && rn2(10)) { if (otmp->otyp == BOULDER) { if (visible) pline("%s apart.", Tobjnam(otmp, "break")); fracture_rock(otmp); place_object(otmp, lev, sx, sy); if ((otmp = sobj_at(BOULDER, lev, sx, sy)) != 0) { /* another boulder here, restack it to the top */ obj_extract_self(otmp); place_object(otmp, lev, sx, sy); } } else { struct trap *trap; if ((trap = t_at(lev, sx, sy)) && trap->ttyp == STATUE_TRAP) deltrap(lev, trap); if (visible) pline("%s.", Tobjnam(otmp, "crumble")); break_statue(otmp); place_object(otmp, lev, sx, sy); /* put fragments on floor */ } used_up = TRUE; /* 1 in 10 chance of destruction of obj; glass, egg destruction */ } else if ((scflags & MAY_DESTROY) && (!rn2(10) || (objects[otmp->otyp].oc_material == GLASS || otmp->otyp == EGG))) { if (breaks(otmp, (xchar) sx, (xchar) sy)) used_up = TRUE; } if (!used_up) { stmp = malloc(sizeof (struct scatter_chain)); stmp->next = NULL; stmp->obj = otmp; stmp->ox = sx; stmp->oy = sy; tmp = rn2(8); /* get the direction */ stmp->dx = xdir[tmp]; stmp->dy = ydir[tmp]; tmp = blastforce - (otmp->owt / 40); if (tmp < 1) tmp = 1; stmp->range = rnd(tmp); /* anywhere up to that determ. by wt */ if (farthest < stmp->range) farthest = stmp->range; stmp->stopped = FALSE; if (!schain) schain = stmp; else stmp2->next = stmp; stmp2 = stmp; } } while (farthest-- > 0) { for (stmp = schain; stmp; stmp = stmp->next) { if ((stmp->range-- > 0) && (!stmp->stopped)) { bhitpos.x = stmp->ox + stmp->dx; bhitpos.y = stmp->oy + stmp->dy; typ = lev->locations[bhitpos.x][bhitpos.y].typ; if (!isok(bhitpos.x, bhitpos.y)) { bhitpos.x -= stmp->dx; bhitpos.y -= stmp->dy; stmp->stopped = TRUE; } else if (!ZAP_POS(typ) || closed_door(lev, bhitpos.x, bhitpos.y)) { bhitpos.x -= stmp->dx; bhitpos.y -= stmp->dy; stmp->stopped = TRUE; } else if ((mtmp = m_at(lev, bhitpos.x, bhitpos.y)) != 0) { if (scflags & MAY_HITMON) { stmp->range--; if (ohitmon(mtmp, stmp->obj, 1, FALSE)) { stmp->obj = NULL; stmp->stopped = TRUE; } } } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) { if (scflags & MAY_HITYOU) { int hitvalu, hitu; action_interrupted(); hitvalu = 8 + stmp->obj->spe; if (bigmonst(youmonst.data)) hitvalu++; hitu = thitu(hitvalu, dmgval(stmp->obj, &youmonst), stmp->obj, NULL); if (hitu) stmp->range -= 3; } } else { if (scflags & VIS_EFFECTS) { /* tmpsym_at(bhitpos.x, bhitpos.y); */ /* delay_output(); */ } } stmp->ox = bhitpos.x; stmp->oy = bhitpos.y; } } } for (stmp = schain; stmp; stmp = stmp2) { int x, y; stmp2 = stmp->next; x = stmp->ox; y = stmp->oy; if (stmp->obj) { if (x != sx || y != sy) total += stmp->obj->quan; place_object(stmp->obj, lev, x, y); stackobj(stmp->obj); } free(stmp); if (lev == level) newsym(x, y); } return total; }
static int dig() { struct rm *lev; int dpx = dig_pos.x, dpy = dig_pos.y; /* perhaps a nymph stole his pick-axe while he was busy digging */ /* or perhaps he teleported away */ if(u.uswallow || !uwep || uwep->otyp != PICK_AXE || dig_level != dlevel || ((dig_down && (dpx != u.ux || dpy != u.uy)) || (!dig_down && dist(dpx,dpy) > 2))) return(0); dig_effort += 10 + abon() + uwep->spe + rn2(5); if(dig_down) { if(!xdnstair) { pline("The floor here seems too hard to dig in."); return(0); } if(dig_effort > 250) { dighole(); return(0); /* done with digging */ } if(dig_effort > 50) { struct trap *ttmp = t_at(dpx,dpy); if(!ttmp) { ttmp = maketrap(dpx,dpy,PIT); ttmp->tseen = 1; pline("You have dug a pit."); u.utrap = rn1(4,2); u.utraptype = TT_PIT; return(0); } } } else if (dig_effort > 100) { char *digtxt; struct obj *obj; lev = &levl[dpx][dpy]; if ((obj = sobj_at(ENORMOUS_ROCK, dpx, dpy))) { fracture_rock(obj); digtxt = "The rock falls apart."; } else if(!lev->typ || lev->typ == SCORR) { lev->typ = CORR; digtxt = "You succeeded in cutting away some rock."; } else if(lev->typ == HWALL || lev->typ == VWALL || lev->typ == SDOOR) { lev->typ = xdnstair ? DOOR : ROOM; digtxt = "You just made an opening in the wall."; } else digtxt = "Now what exactly was it that you were digging in?"; mnewsym(dpx, dpy); prl(dpx, dpy); pline(digtxt); /* after mnewsym & prl */ return(0); } else { if(IS_WALL(levl[dpx][dpy].typ)) { int rno = inroom(dpx,dpy); if(rno >= 0 && rooms[rno].rtype >= 8) { pline("This wall seems too hard to dig into."); return(0); } } pline("You hit the rock with all your might."); } return(1); }