/* create a new shopkeeper in the given room */ static int shkinit ( const struct shclass *shp, struct mkroom *sroom) { int sh, sx, sy; struct monst *shk; /* place the shopkeeper in the given room */ sh = sroom->fdoor; sx = doors[sh].x; sy = doors[sh].y; /* check that the shopkeeper placement is sane */ if(sroom->irregular) { int rmno = (sroom - rooms) + ROOMOFFSET; if (isok(sx-1,sy) && !levl[sx-1][sy].edge && (int) levl[sx-1][sy].roomno == rmno) sx--; else if (isok(sx+1,sy) && !levl[sx+1][sy].edge && (int) levl[sx+1][sy].roomno == rmno) sx++; else if (isok(sx,sy-1) && !levl[sx][sy-1].edge && (int) levl[sx][sy-1].roomno == rmno) sy--; else if (isok(sx,sy+1) && !levl[sx][sy+1].edge && (int) levl[sx][sy+1].roomno == rmno) sx++; else goto shk_failed; } else if(sx == sroom->lx-1) sx++; else if(sx == sroom->hx+1) sx--; else if(sy == sroom->ly-1) sy++; else if(sy == sroom->hy+1) sy--; else { shk_failed: return(-1); } if(MON_AT(sx, sy)) (void) rloc(m_at(sx, sy), false); /* insurance */ /* now initialize the shopkeeper monster structure */ if(!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, NO_MM_FLAGS))) return(-1); shk->isshk = shk->mpeaceful = 1; set_malign(shk); shk->msleeping = 0; shk->mtrapseen = ~0; /* we know all the traps already */ ESHK(shk)->shoproom = (sroom - rooms) + ROOMOFFSET; sroom->resident = shk; ESHK(shk)->shoptype = sroom->rtype; assign_level(&(ESHK(shk)->shoplevel), &u.uz); ESHK(shk)->shd = doors[sh]; ESHK(shk)->shk.x = sx; ESHK(shk)->shk.y = sy; ESHK(shk)->robbed = 0L; ESHK(shk)->credit = 0L; ESHK(shk)->debit = 0L; ESHK(shk)->loan = 0L; ESHK(shk)->visitct = 0; ESHK(shk)->following = 0; ESHK(shk)->billct = 0; shk->mgold = 1000L + 30L*(long)rnd(100); /* initial capital */ if (shp->shknms == shkrings) (void) mongets(shk, TOUCHSTONE); nameshk(shk, shp->shknms); return(sh); }
bool ofchunk::writeBYTES (const char * p, int l) { if (!isok()) return false; if ((remainingchunklen >= 0) && (remainingchunklen < l)) return false; ofs.write (p, l); if (!isok()) return false; if (remainingchunklen >= 0) remainingchunklen -= l; return true; }
bool ofchunk::writeBYTE (int l) { if (!isok()) return false; if ((remainingchunklen >= 0) && (remainingchunklen < 1)) return false; unsigned char buf[4]; buf [0] = l & 0xff; ofs.write ((char *)&buf[0], 1); if (!isok()) return false; if (remainingchunklen >= 0) remainingchunklen -= 1; return true; }
/* * Try to choose a stopping point as near as possible to the starting * position while still adjacent to the hero. If all else fails, try * enexto(). Use enexto() as a last resort because enexto() chooses * its point randomly, which is not what we want. */ STATIC_OVL boolean md_stop(coord *stopp, coord *startp) /* stopping position (we fill it in) */ /* starting positon (read only) */ { int x, y, distance, min_distance = -1; for (x = u.ux-1; x <= u.ux+1; x++) for (y = u.uy-1; y <= u.uy+1; y++) { if (!isok(x, y) || (x == u.ux && y == u.uy)) continue; if (ACCESSIBLE(levl[x][y].typ) && !MON_AT(x,y)) { distance = dist2(x,y,startp->x,startp->y); if (min_distance < 0 || distance < min_distance || (distance == min_distance && rn2(2))) { stopp->x = x; stopp->y = y; min_distance = distance; } } } /* If we didn't find a good spot, try enexto(). */ if (min_distance < 0 && !enexto(stopp, u.ux, u.uy, &mons[PM_MAIL_DAEMON])) return FALSE; return TRUE; }
bool ofchunk::writeWORD (int l) { if (!isok()) return false; if ((remainingchunklen >= 0) && (remainingchunklen < 2)) return false; unsigned char buf[4]; buf [0] = l & 0xff; buf [1] = (l & 0xff00) >> 8; ofs.write ((char *)&buf[0], 2); if (!isok()) return false; if (remainingchunklen >= 0) remainingchunklen -= 2; return true; }
int drawbridge_wall_direction(int x, int y) { struct rm *loc; if (!isok(x,y)) { impossible("drawbridge_wall_direction(%d,%d) not ok.", x, y); return -1; } loc = &level->locations[x][y]; if (loc->typ != DOOR && loc->typ != DBWALL) return -1; if (IS_DRAWBRIDGE(level->locations[x + 1][y].typ) && (level->locations[x + 1][y].drawbridgemask & DB_DIR) == DB_WEST) return DB_WEST; if (IS_DRAWBRIDGE(level->locations[x - 1][y].typ) && (level->locations[x - 1][y].drawbridgemask & DB_DIR) == DB_EAST) return DB_EAST; if (IS_DRAWBRIDGE(level->locations[x][y - 1].typ) && (level->locations[x][y - 1].drawbridgemask & DB_DIR) == DB_SOUTH) return DB_SOUTH; if (IS_DRAWBRIDGE(level->locations[x][y + 1].typ) && (level->locations[x][y + 1].drawbridgemask & DB_DIR) == DB_NORTH) return DB_NORTH; return -1; }
/* * Is (x,y) a good position of mtmp? If mtmp is NULL, then is (x,y) good * for an object? * * This function will only look at mtmp->mdat, so makemon, mplayer, etc can * call it to generate new monster positions with fake monster structures. */ boolean goodpos(struct level *lev, int x, int y, struct monst *mtmp, unsigned gpflags) { const struct permonst *mdat = NULL; boolean ignorewater = ((gpflags & MM_IGNOREWATER) != 0); if (!isok(x, y)) return FALSE; /* in many cases, we're trying to create a new monster, which * can't go on top of the player or any existing monster. * however, occasionally we are relocating engravings or objects, * which could be co-located and thus get restricted a bit too much. * oh well. */ if (mtmp != &youmonst && x == u.ux && y == u.uy && (!u.usteed || mtmp != u.usteed)) return FALSE; if (mtmp) { struct monst *mtmp2 = m_at(lev, x,y); /* Be careful with long worms. A monster may be placed back in * its own location. Normally, if m_at() returns the same monster * that we're trying to place, the monster is being placed in its * own location. However, that is not correct for worm segments, * because all the segments of the worm return the same m_at(). * Actually we overdo the check a little bit--a worm can't be placed * in its own location, period. If we just checked for mtmp->mx * != x || mtmp->my != y, we'd miss the case where we're called * to place the worm segment and the worm's head is at x,y. */ if (mtmp2 && (mtmp2 != mtmp || mtmp->wormno)) return FALSE; mdat = mtmp->data; if (is_pool(lev, x,y) && !ignorewater) { if (mtmp == &youmonst) return !!(HLevitation || Flying || Wwalking || Swimming || Amphibious); else return (is_flyer(mdat) || is_swimmer(mdat) || is_clinger(mdat)); } else if (mdat->mlet == S_EEL && rn2(13) && !ignorewater) { return FALSE; } else if (is_lava(lev, x,y)) { if (mtmp == &youmonst) return !!HLevitation; else return is_flyer(mdat) || likes_lava(mdat); } if (passes_walls(mdat) && may_passwall(lev, x,y)) return TRUE; } if (!ACCESSIBLE(lev->locations[x][y].typ)) { if (!(is_pool(lev, x,y) && ignorewater)) return FALSE; } if (closed_door(lev, x, y) && (!mdat || !amorphous(mdat))) return FALSE; if (sobj_at(BOULDER, lev, x, y) && (!mdat || !throws_rocks(mdat))) return FALSE; return TRUE; }
void nh_describe_pos(int x, int y, struct nh_desc_buf *bufs, int *is_in) { bufs->bgdesc[0] = '\0'; bufs->trapdesc[0] = '\0'; bufs->objdesc[0] = '\0'; bufs->mondesc[0] = '\0'; bufs->invisdesc[0] = '\0'; bufs->effectdesc[0] = '\0'; bufs->feature_described = FALSE; bufs->objcount = -1; if (is_in) *is_in = 0; if (!program_state.game_running || !isok(x, y)) return; API_ENTRY_CHECKPOINT_RETURN_VOID_ON_ERROR(); if (is_in) { if (IS_ROCK(level->locations[x][y].typ) || closed_door(level, x, y)) *is_in = 1; else *is_in = 0; } int monid = dbuf_get_mon(x, y); int mem_bg = level->locations[x][y].mem_bg; describe_bg(x, y, mem_bg, bufs->bgdesc); int tt = level->locations[x][y].mem_trap; if (tt) { strcpy(bufs->trapdesc, trapexplain[level->locations[x][y].mem_trap - 1]); if (tt != BEAR_TRAP && tt != WEB && tt != STATUE_TRAP && mem_bg && is_in) *is_in = 1; } bufs->objcount = describe_object(x, y, level->locations[x][y].mem_obj - 1, bufs->objdesc, mem_bg && is_in, &bufs->feature_described); describe_mon(x, y, monid - 1, bufs->mondesc); if (level->locations[x][y].mem_invis) strcpy(bufs->invisdesc, invisexplain); if (Engulfed && (x != u.ux || y != u.uy)) { /* all locations when swallowed other than the hero are the monster */ snprintf(bufs->effectdesc, SIZE(bufs->effectdesc), "interior of %s", Blind ? "a monster" : a_monnam(u.ustuck)); } API_EXIT(); }
boolean is_any_icewall(int x, int y) { if (!isok(x,y)) return FALSE; if (IS_ANY_ICEWALL(levl[x][y].typ)) return TRUE; return FALSE; }
bool ofchunk::writeLONG (int l) { if (!isok()) return false; if ((remainingchunklen >= 0) && (remainingchunklen < 4)) return false; unsigned char buf[4]; buf [0] = l & 0xff; buf [1] = (l & 0xff00) >> 8; buf [2] = (l & 0xff0000) >> 16; buf [3] = (l & 0xff000000) >> 24; ofs.write ((char *)&buf[0], 4); if (!isok()) return false; if (remainingchunklen >= 0) remainingchunklen -= 4; return true; }
bool ifchunk::readWORD (int &l) { if (!isok()) return false; if ((remainingchunklen >= 0) && (remainingchunklen < 2)) return false; unsigned char buf[2]; ifs.read ((char *)&buf[0], 2); if (!isok()) return false; if (!isok()) return false; if (remainingchunklen >= 0) remainingchunklen -= 2; l = buf [0] + (buf [1] << 8); return true; }
/* * Use is_db_wall where you want to verify that a drawbridge "wall" (i.e., * portcullis) is in the UP position in the location x, y. * * (If you want to find find out the direction or to verify the existence of a * portcullis without regard to whether it's UP or DOWN, then in that case use * drawbridge_wall_direction instead.) */ boolean is_db_wall(int x, int y) { if (!isok(x,y)) { impossible("is_db_wall(%d,%d) not ok.", x, y); return FALSE; /* arbitrary choice */ } return (boolean) (level->locations[x][y].typ == DBWALL); }
bool ifchunk::readLONG (int &l) { if (!isok()) return false; if ((remainingchunklen >= 0) && (remainingchunklen < 4)) return false; unsigned char buf[4]; ifs.read ((char *)&buf[0], 4); if (!isok()) return false; if (!isok()) return false; if (remainingchunklen >= 0) remainingchunklen -= 4; l = buf [0] + (buf [1] << 8) + (buf[2] << 16) + (buf[3] << 24); return true; }
boolean has_upstairs(struct level *lev, struct mkroom *sroom) { if (sroom == lev->upstairs_room) return TRUE; if (isok(lev->sstairs.sx, lev->sstairs.sy) && lev->sstairs.up) return (boolean) (sroom == lev->sstairs_room); return FALSE; }
bool ifchunk::readBYTE (int &l) { if (!isok()) return false; if ((remainingchunklen >= 0) && (remainingchunklen < 1)) return false; unsigned char buf[1]; ifs.read ((char *)&buf[0], 1); if (!isok()) return false; if (!isok()) return false; if (remainingchunklen >= 0) remainingchunklen -= 1; l = buf [0]; return true; }
STATIC_OVL boolean iswall(int x, int y) { register int type; if (!isok(x,y)) return FALSE; type = levl[x][y].typ; return (IS_WALL(type) || IS_DOOR(type) || type == SDOOR || type == IRONBARS); }
boolean is_pool(struct level *lev, int x, int y) { schar ltyp; if (!isok(x,y)) return FALSE; ltyp = lev->locations[x][y].typ; if (ltyp == POOL || ltyp == MOAT || ltyp == WATER) return TRUE; if (ltyp == DRAWBRIDGE_UP && (lev->locations[x][y].drawbridgemask & DB_UNDER) == DB_MOAT) return TRUE; return FALSE; }
boolean is_swamp(struct level *lev, int x, int y) { schar ltyp; if (!isok(x,y)) return FALSE; ltyp = lev->locations[x][y].typ; if (ltyp == BOG || (ltyp == DRAWBRIDGE_UP && (lev->locations[x][y].drawbridgemask & DB_UNDER) == DB_BOG)) return TRUE; return FALSE; }
int check(char s[]) { for(int i=0; s[i]; i++) if(!isok(s[i])) return 0; len=strlen(s); memset(dp,-1,sizeof(dp)); if(dfs(0,0)) return 1; return 0; }
boolean is_ice(int x, int y) { schar ltyp; if (!isok(x,y)) return FALSE; ltyp = levl[x][y].typ; if (ltyp == ICE || (ltyp == DRAWBRIDGE_UP && (levl[x][y].drawbridgemask & DB_UNDER) == DB_ICE)) return TRUE; return FALSE; }
boolean is_lava(int x, int y) { schar ltyp; if (!isok(x,y)) return FALSE; ltyp = levl[x][y].typ; if (ltyp == LAVAPOOL || (ltyp == DRAWBRIDGE_UP && (levl[x][y].drawbridgemask & DB_UNDER) == DB_LAVA)) return TRUE; return FALSE; }
STATIC_OVL boolean iswall_or_stone(int x, int y) { register int type; /* out of bounds = stone */ if (!isok(x,y)) return TRUE; type = levl[x][y].typ; return (type == STONE || IS_WALL(type) || IS_DOOR(type) || type == SDOOR || type == IRONBARS); }
STATIC_OVL boolean rm_waslit() { register xchar x, y; if(levl[u.ux][u.uy].typ == ROOM && levl[u.ux][u.uy].waslit) return(TRUE); for(x = u.ux-2; x < u.ux+3; x++) for(y = u.uy-1; y < u.uy+2; y++) if(isok(x,y) && levl[x][y].waslit) return(TRUE); return(FALSE); }
bool nexttodoor (int sx, int sy) { int dx, dy; struct rm *lev; for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++) { if(!isok(sx+dx, sy+dy)) continue; if(IS_DOOR((lev = &levl[sx+dx][sy+dy])->typ) || lev->typ == SDOOR) return(true); } return(false); }
double Divide::eval(const Metric::IData& mdata) const { double n = m_numerator->eval(mdata); double d = m_denominator->eval(mdata); double z = c_FP_NAN_d; if (isok(d) && d != 0.0) { z = n / d; } AEXPR_CHECK(z); return z; }
boolean is_pool(struct level *lev, int x, int y) { schar ltyp; if (!isok(x, y)) return FALSE; ltyp = lev->locations[x][y].typ; /* The ltyp == MOAT is not redundant to is_moat due to drawbridges and the Juiblex level. There is probably a better way to express this. */ if (ltyp == POOL || ltyp == WATER || ltyp == MOAT || is_moat(lev, x, y)) return TRUE; return FALSE; }
boolean is_moat(struct level * lev, int x, int y) { schar ltyp; if (!isok(x, y)) return FALSE; ltyp = lev->locations[x][y].typ; if (!Is_juiblex_level(&lev->z) && (ltyp == MOAT || (ltyp == DRAWBRIDGE_UP && (lev->locations[x][y].drawbridgemask & DB_UNDER) == DB_MOAT))) return TRUE; return FALSE; }
boolean nexttodoor(struct level * lev, int sx, int sy) { int dx, dy; struct rm *loc; for (dx = -1; dx <= 1; dx++) for (dy = -1; dy <= 1; dy++) { if (!isok(sx + dx, sy + dy)) continue; if (IS_DOOR((loc = &lev->locations[sx + dx][sy + dy])->typ) || loc->typ == SDOOR) return TRUE; } return FALSE; }
/* "Chained" explosions, used by skilled wand users FIXME: make skilled casting of fireball/cone of cold use this */ void chain_explode(int x, int y, int type, int dam, char olet, int expltype, const char *descr, int raylevel, int amount) { int ex = x; int ey = y; while (amount--) { ex = x + rnd(3) - 2; ey = y + rnd(3) - 2; if (!isok(ex, ey) || IS_STWALL(level->locations[ex][ey].typ)) { ex = x; ey = y; } explode(ex, ey, type, dam, olet, expltype, descr, raylevel); } }
/* * If we have drawn a map without walls, this allows us to * auto-magically wallify it. Taken from lev_main.c. */ STATIC_OVL void wallify_map(void) { int x, y, xx, yy; for(x = 1; x < COLNO; x++) for(y = 0; y < ROWNO; y++) if(levl[x][y].typ == STONE) { for(yy = y - 1; yy <= y+1; yy++) for(xx = x - 1; xx <= x+1; xx++) if(isok(xx,yy) && levl[xx][yy].typ == ROOM) { if(yy != y) levl[x][y].typ = HWALL; else levl[x][y].typ = VWALL; } } }