// ----------------------------------------------------------------------------- // Return true if ok for buddy to talk, else return false. // Buddy is allowed to talk if the segment he is in does not contain a blastable wall that has not been blasted // AND he has never yet, since being initialized for level, been allowed to talk. int BuddyMayTalk(void) { int i; segment *segp; if (gameData.objs.objects[gameData.escort.nObjNum].type != OBJ_ROBOT) { gameData.escort.bMayTalk = 0; return 0; } if (gameData.escort.bMayTalk) return 1; if ((gameData.objs.objects[gameData.escort.nObjNum].type == OBJ_ROBOT) && (gameData.escort.nObjNum <= gameData.objs.nLastObject) && !gameData.bots.pInfo[gameData.objs.objects[gameData.escort.nObjNum].id].companion) { for (i=0; i<=gameData.objs.nLastObject; i++) if (gameData.bots.pInfo[gameData.objs.objects[i].id].companion) break; if (i > gameData.objs.nLastObject) return 0; else gameData.escort.nObjNum = i; } segp = gameData.segs.segments + gameData.objs.objects[gameData.escort.nObjNum].segnum; for (i=0; i<MAX_SIDES_PER_SEGMENT; i++) { short wall_num = WallNumP (segp, (short) i); if (IS_WALL (wall_num)) { if ((gameData.walls.walls[wall_num].type == WALL_BLASTABLE) && !(gameData.walls.walls[wall_num].flags & WALL_BLASTED)) return 0; } // Check one level deeper. if (IS_CHILD(segp->children[i])) { int j; segment *csegp = &gameData.segs.segments[segp->children[i]]; for (j=0; j<MAX_SIDES_PER_SEGMENT; j++) { short wall2 = WallNumP (csegp, (short) j); if (IS_WALL (wall2)) { if ((gameData.walls.walls[wall2].type == WALL_BLASTABLE) && !(gameData.walls.walls[wall2].flags & WALL_BLASTED)) return 0; } } } } gameData.escort.bMayTalk = 1; return 1; }
//----------------------------------------------------------------- // Opens a door void CSegment::OpenDoor (int nSide) { CWall* wallP; if (!(wallP = Wall (nSide))) return; CActiveDoor* doorP; if (!(doorP = wallP->OpenDoor ())) return; short nConnSide, nConnWall = NO_WALL; CSegment *connSegP; // So that door can't be shot while opening if (m_children [nSide] < 0) { if (gameOpts->legacy.bWalls) Warning (TXT_OPEN_SINGLE, this - SEGMENTS, nSide, WallNum (nSide)); connSegP = NULL; nConnSide = -1; nConnWall = NO_WALL; } else { connSegP = SEGMENTS + m_children [nSide]; nConnSide = ConnectedSide (connSegP); if (nConnSide >= 0) { CWall* wallP = connSegP->Wall (nConnSide); if (wallP) wallP->state = WALL_DOOR_OPENING; } } //KillStuckObjects(WallNumP (connSegP, nConnSide)); doorP->nFrontWall [0] = WallNum (nSide); doorP->nBackWall [0] = nConnWall; Assert(SEG_IDX (this) != -1); if (gameData.demo.nState == ND_STATE_RECORDING) NDRecordDoorOpening (SEG_IDX (this), nSide); if (IS_WALL (wallP->nLinkedWall) && IS_WALL (nConnWall) && (wallP->nLinkedWall == nConnWall)) { CWall *linkedWallP = WALLS + wallP->nLinkedWall; CSegment *linkedSegP = SEGMENTS + linkedWallP->nSegment; linkedWallP->state = WALL_DOOR_OPENING; connSegP = SEGMENTS + linkedSegP->m_children [linkedWallP->nSide]; if (IS_WALL (nConnWall)) WALLS [nConnWall].state = WALL_DOOR_OPENING; doorP->nPartCount = 2; doorP->nFrontWall [1] = wallP->nLinkedWall; doorP->nBackWall [1] = linkedSegP->ConnectedSide (connSegP); } else doorP->nPartCount = 1; if (gameData.demo.nState != ND_STATE_PLAYBACK) { if (gameData.walls.animP [wallP->nClip].openSound > -1) CreateSound (gameData.walls.animP [wallP->nClip].openSound, nSide); } }
tRgbaColorf *ColoredSegmentColor (int nSegment, int nSide, char nColor) { short nConnSeg; int owner; int special; if (nColor > 0) nColor--; else { if ((gameData.app.nGameMode & GM_ENTROPY) && (extraGameInfo [1].entropy.nOverrideTextures == 2) && ((owner = SEGMENTS [nSegment].m_owner) > 0)) { nConnSeg = SEGMENTS [nSegment].m_children [nSide]; if ((nConnSeg >= 0) && (SEGMENTS [nConnSeg].m_owner == owner)) return NULL; nColor = (owner == 1); } special = SEGMENTS [nSegment].m_nType; if (special == SEGMENT_IS_WATER) nColor = 2; else if (special == SEGMENT_IS_LAVA) nColor = 3; else return NULL; nConnSeg = SEGMENTS [nSegment].m_children [nSide]; if (nConnSeg >= 0) { if (special == SEGMENTS [nConnSeg].m_nType) return NULL; if (IS_WALL (SEGMENTS [nSegment].WallNum (nSide))) return NULL; } } return segmentColors + nColor; }
const char *ceiling(int x, int y) { struct rm *loc = &level->locations[x][y]; const char *what; /* other room types will no longer exist when we're interested -- * see check_special_room() */ if (*in_rooms(level, x, y, VAULT)) what = "vault's ceiling"; else if (*in_rooms(level, x, y, TEMPLE)) what = "temple's ceiling"; else if (*in_rooms(level, x, y, SHOPBASE)) what = "shop's ceiling"; else if (IS_AIR(loc->typ)) what = "sky"; else if (Underwater) what = "water's surface"; else if ((IS_ROOM(loc->typ) && !Is_earthlevel(&u.uz)) || IS_WALL(loc->typ) || IS_DOOR(loc->typ) || loc->typ == SDOOR) what = "ceiling"; else what = "rock above"; return what; }
/* * Wall cleanup. This function has two purposes: (1) remove walls that * are totally surrounded by stone - they are redundant. (2) correct * the types so that they extend and connect to each other. */ void wallification(int x1, int y1, int x2, int y2) { uchar type; register int x,y; struct rm *lev; /* sanity check on incoming variables */ if (x1<0 || x2>=COLNO || x1>x2 || y1<0 || y2>=ROWNO || y1>y2) panic("wallification: bad bounds (%d,%d) to (%d,%d)",x1,y1,x2,y2); /* Step 1: change walls surrounded by rock to rock. */ for(x = x1; x <= x2; x++) for(y = y1; y <= y2; y++) { lev = &levl[x][y]; type = lev->typ; if (IS_WALL(type) && type != DBWALL) { if (is_solid(x-1,y-1) && is_solid(x-1,y ) && is_solid(x-1,y+1) && is_solid(x, y-1) && is_solid(x, y+1) && is_solid(x+1,y-1) && is_solid(x+1,y ) && is_solid(x+1,y+1)) lev->typ = STONE; } } wall_extends(x1,y1,x2,y2); }
const char *surface(int x, int y) { struct rm *loc = &level->locations[x][y]; if ((x == u.ux) && (y == u.uy) && u.uswallow && is_animal(u.ustuck->data)) return "maw"; else if (IS_AIR(loc->typ) && Is_airlevel(&u.uz)) return "air"; else if (is_pool(level, x, y)) return (Underwater && !Is_waterlevel(&u.uz)) ? "bottom" : "water"; else if (is_ice(level, x, y)) return "ice"; else if (is_lava(level, x, y)) return "lava"; else if (loc->typ == DRAWBRIDGE_DOWN) return "bridge"; else if (IS_ALTAR(level->locations[x][y].typ)) return "altar"; else if (IS_GRAVE(level->locations[x][y].typ)) return "headstone"; else if (IS_FOUNTAIN(level->locations[x][y].typ)) return "fountain"; else if ((IS_ROOM(loc->typ) && !Is_earthlevel(&u.uz)) || IS_WALL(loc->typ) || IS_DOOR(loc->typ) || loc->typ == SDOOR) return "floor"; else return "ground"; }
static void finish_map(struct level *lev, schar fg_typ, schar bg_typ, boolean lit, boolean walled) { int i, j; if (walled) wallify_map(lev); if (lit) { for (i = 0; i < COLNO; i++) for (j = 0; j < ROWNO; j++) if ((!IS_ROCK(fg_typ) && lev->locations[i][j].typ == fg_typ) || (!IS_ROCK(bg_typ) && lev->locations[i][j].typ == bg_typ) || (bg_typ == TREE && lev->locations[i][j].typ == bg_typ) || (walled && IS_WALL(lev->locations[i][j].typ))) lev->locations[i][j].lit = TRUE; for (i = 0; i < lev->nroom; i++) lev->rooms[i].rlit = 1; } /* light lava even if everything's otherwise unlit */ for (i = 0; i < COLNO; i++) for (j = 0; j < ROWNO; j++) if (lev->locations[i][j].typ == LAVAPOOL) lev->locations[i][j].lit = TRUE; }
int CountLights (void) { int nLights = 0; short segNum, sideNum; tSegment *segP; tSide *sideP; if (!(gameOpts->render.color.bUseLightMaps && gameStates.render.color.bLightMapsOk)) return 0; #ifdef _DEBUG memset (sideFlags, 0, sizeof (sideFlags)); #endif for (segNum = 0, segP = gameData.segs.segments; segNum <= gameData.segs.nLastSegment; segNum++, segP++) { for (sideNum = 0, sideP = segP->sides; sideNum < 6; sideNum++, sideP++) { #if TEXTURE_CHECK if ((gameData.segs.segments [segNum].children [sideNum] >= 0) && !IS_WALL (WallNumI (segNum, sideNum))) continue; //skip open sides #endif if (IsLight (sideP->nBaseTex) || IsLight (sideP->nOvlTex) || (gameStates.app.bD2XLevel && gameData.render.color.lights [segNum * 6 + sideNum].index)) { nLights++; #ifdef _DEBUG sideFlags [segNum * 6 + sideNum] = 1; #endif } } } return nLights; }
static double chck_verti_inters(t_env *env, double angl) { double x; double y; double x_plus; double y_plus; x = (int)(POS_X / BOX_SZE); x = ANGL_LEFT ? x * BOX_SZE - 1 : (x + 1) * BOX_SZE; y = POS_Y + (POS_X - x) * tan(angl); y_plus = ANGL_HORIZ ? 0 : BOX_SZE * tan(angl); y_plus *= ANGL_LEFT ? 1 : -1; x_plus = ANGL_VERTI ? 0 : BOX_SZE; x_plus *= ANGL_LEFT ? -1 : 1; while (WITHIN_MAP && !IS_WALL(x, y)) { x += x_plus; y += y_plus; } if (!WITHIN_MAP) return (MAX_WDT); angl = sqrt(pow(POS_X - x, 2) + pow(POS_Y - y, 2)); angl = (angl > MAX_WDT) ? MAX_WDT : angl; return (angl); }
static double chck_horiz_inters(t_env *env, double angl) { double x; double y; double x_plus; double y_plus; y = (int)(POS_Y / BOX_SZE); y = ANGL_UP ? y * BOX_SZE - 1 : (y + 1) * BOX_SZE; x = POS_X + (POS_Y - y) / tan(angl); x_plus = ANGL_VERTI ? 0 : BOX_SZE / tan(angl); x_plus *= ANGL_UP ? 1 : -1; y_plus = ANGL_HORIZ ? 0 : BOX_SZE; y_plus *= ANGL_UP ? -1 : 1; while (WITHIN_MAP && !IS_WALL(x, y)) { x += x_plus; y += y_plus; } if (!WITHIN_MAP) return (MAX_HGT); angl = sqrt(pow(POS_X - x, 2) + pow(POS_Y - y, 2)); angl = (angl > MAX_HGT) ? MAX_HGT : angl; return (angl); }
void SokobanState::CalcCost() { // TODO: Test if there exists a bipartite matching of goals and boxes // For every goal previously reachable by this box, // make sure there still is some box that can reach the goal int goals_left = (1<<num_boxes)-1; for (int i = 0; i < num_boxes; ++i) { // Add the boxes reachable from this position to the list of reachable goals goals_left &= ~(scribble->GoalsReachable(boxes[i])); if (goals_left == 0) break; } // If there is a goal we cant reach with any box, the state is useless if (goals_left != 0) { cost = unsigned(-1); return; } cost = 0; for (int i = 0; i < num_boxes; ++i) { int pos_cost = POSCOST(boxes[i]); if (pos_cost < 0) { cost = unsigned(-1); return; } if (pos_cost > 0) cost += pos_cost + 100; else { // Make goals next to walls slightly more attractive if (!IS_WALL(boxes[i])) cost += 1; for (int j=0; j<4; j++) { if (!IS_WALL(boxes[i]+forward[j])) cost += 1; } } } }
// start the transition from closed -> open CWall void CSegment::StartCloak (int nSide) { if (gameData.demo.nState == ND_STATE_PLAYBACK) return; CWall* wallP = Wall (nSide); if (!wallP) return; if (wallP->nType == WALL_OPEN || wallP->state == WALL_DOOR_CLOAKING) //already open or cloaking return; CCloakingWall* cloakWallP; CSegment* connSegP; short nConnSide; int i; short nConnWall; connSegP = SEGMENTS + m_children [nSide]; nConnSide = ConnectedSide (connSegP); if (!(cloakWallP = wallP->StartCloak ())) { wallP->nType = WALL_OPEN; if ((wallP = connSegP->Wall (nConnSide))) wallP->nType = WALL_OPEN; return; } nConnWall = connSegP->WallNum (nConnSide); if (IS_WALL (nConnWall)) WALLS [nConnWall].state = WALL_DOOR_CLOAKING; cloakWallP->nFrontWall = WallNum (nSide); cloakWallP->nBackWall = nConnWall; Assert(SEG_IDX (this) != -1); //Assert(!IS_WALL (wallP->nLinkedWall)); if (gameData.demo.nState != ND_STATE_PLAYBACK) { CreateSound (SOUND_WALL_CLOAK_ON, nSide); } for (i = 0; i < 4; i++) { cloakWallP->front_ls [i] = m_sides [nSide].m_uvls [i].l; if (IS_WALL (nConnWall)) cloakWallP->back_ls [i] = connSegP->m_sides [nConnSide].m_uvls [i].l; } }
bool RenderWallFace (CSegment *segP, CSegFace *faceP, int bDepthOnly) { if (!(faceP->widFlags & WID_RENDER_FLAG)) return false; if (!IS_WALL (faceP->nWall)) return false; LoadFaceBitmaps (segP, faceP); g3FaceDrawer (faceP, faceP->bmBot, faceP->bmTop, (faceP->nCamera < 0) || faceP->bTeleport, !bDepthOnly && faceP->bTextured, bDepthOnly); 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); }
void wall_extends(int x1, int y1, int x2, int y2) { uchar type; register int x,y; struct rm *lev; int bits; int locale[3][3]; /* rock or wall status surrounding positions */ /* * Value 0 represents a free-standing wall. It could be anything, * so even though this table says VWALL, we actually leave whatever * typ was there alone. */ static xchar spine_array[16] = { VWALL, HWALL, HWALL, HWALL, VWALL, TRCORNER, TLCORNER, TDWALL, VWALL, BRCORNER, BLCORNER, TUWALL, VWALL, TLWALL, TRWALL, CROSSWALL }; /* sanity check on incoming variables */ if (x1<0 || x2>=COLNO || x1>x2 || y1<0 || y2>=ROWNO || y1>y2) panic("wall_extends: bad bounds (%d,%d) to (%d,%d)",x1,y1,x2,y2); for(x = x1; x <= x2; x++) for(y = y1; y <= y2; y++) { lev = &levl[x][y]; type = lev->typ; if ( !(IS_WALL(type) && type != DBWALL)) continue; /* set the locations TRUE if rock or wall or out of bounds */ locale[0][0] = iswall_or_stone(x-1,y-1); locale[1][0] = iswall_or_stone( x,y-1); locale[2][0] = iswall_or_stone(x+1,y-1); locale[0][1] = iswall_or_stone(x-1, y); locale[2][1] = iswall_or_stone(x+1, y); locale[0][2] = iswall_or_stone(x-1,y+1); locale[1][2] = iswall_or_stone( x,y+1); locale[2][2] = iswall_or_stone(x+1,y+1); /* determine if wall should extend to each direction NSEW */ bits = (extend_spine(locale, iswall(x,y-1), 0, -1) << 3) | (extend_spine(locale, iswall(x,y+1), 0, 1) << 2) | (extend_spine(locale, iswall(x+1,y), 1, 0) << 1) | extend_spine(locale, iswall(x-1,y), -1, 0); /* don't change typ if wall is free-standing */ if (bits) lev->typ = spine_array[bits]; } }
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); }
//----------------------------------------------------------------- // Closes a door void CSegment::CloseDoor (int nSide) { CWall* wallP; if (!(wallP = Wall (nSide))) return; if ((wallP->state == WALL_DOOR_CLOSING) || //already closing (wallP->state == WALL_DOOR_WAITING) || //open, waiting to close (wallP->state == WALL_DOOR_CLOSED)) //closed return; if (DoorIsBlocked (nSide)) return; CActiveDoor* doorP; if (!(doorP = wallP->CloseDoor ())) return; CSegment* connSegP; short nConnSide, nConnWall; connSegP = SEGMENTS + m_children [nSide]; nConnSide = ConnectedSide (connSegP); nConnWall = connSegP->WallNum (nConnSide); if (IS_WALL (nConnWall)) WALLS [nConnWall].state = WALL_DOOR_CLOSING; doorP->nFrontWall [0] = WallNum (nSide); doorP->nBackWall [0] = nConnWall; Assert(SEG_IDX (this) != -1); if (gameData.demo.nState == ND_STATE_RECORDING) NDRecordDoorOpening (SEG_IDX (this), nSide); if (IS_WALL (wallP->nLinkedWall)) Int3(); //don't think we ever used linked walls else doorP->nPartCount = 1; if (gameData.demo.nState != ND_STATE_PLAYBACK) { if (gameData.walls.animP [wallP->nClip].openSound > -1) CreateSound (gameData.walls.animP [wallP->nClip].openSound, nSide); } }
// ---------------------------------------------------------------------------- void write_wall_text(FILE *my_file) { int i, j; byte wallFlags[MAX_WALLS]; tSegment *segp; tSide *sideP; tWall *wallP; fprintf(my_file, "-----------------------------------------------------------------------------\n"); fprintf(my_file, "gameData.walls.walls:\n"); for (i=0, wallP = gameData.walls.walls; i<gameData.walls.nWalls; i++, wallP++) { int nSegment, nSide; fprintf(my_file, "Wall %03i: seg=%3i, tSide=%2i, nLinkedWall=%3i, nType=%s, flags=%4x, hps=%3i, tTrigger=%2i, nClip=%2i, keys=%2i, state=%i\n", i, wallP->nSegment, wallP->nSide, wallP->nLinkedWall, pszWallNames[wallP->nType], wallP->flags, wallP->hps >> 16, wallP->nTrigger, wallP->nClip, wallP->keys, wallP->state); if (wallP->nTrigger >= gameData.trigs.nTriggers) fprintf(my_file, "Wall %03d points to invalid tTrigger %d\n",i,wallP->nTrigger); nSegment = wallP->nSegment; nSide = wallP->nSide; if (WallNumI (nSegment, nSide) != i) err_printf(my_file, "Error: Wall %i points at tSegment %i, tSide %i, but that tSegment doesn't point back (it's nWall = %i)\n", i, nSegment, nSide, WallNumI (nSegment, nSide)); } for (i=0; i<MAX_WALLS; i++) wallFlags[i] = 0; for (i=0, segp = gameData.segs.segments; i<=gameData.segs.nLastSegment; i++, segp++) { for (j=0, sideP = segp->sides; j<MAX_SIDES_PER_SEGMENT; j++, sideP++) { short nWall = WallNumP (sideP); if (IS_WALL (nWall)) if (wallFlags[nWall]) err_printf(my_file, "Error: Wall %i appears in two or more segments, including tSegment %i, tSide %i.\n", sideP->nWall, i, j); else wallFlags[nWall] = 1; } } }
static int describe_object(int x, int y, int votyp, char *buf) { int num_objs = 0; struct obj *otmp; if (votyp == -1) return -1; otmp = vobj_at(x,y); if (!otmp || otmp->otyp != votyp) { if (votyp != STRANGE_OBJECT) { otmp = mksobj(level, votyp, FALSE, FALSE); if (otmp->oclass == COIN_CLASS) otmp->quan = 1L; /* to force pluralization off */ else if (otmp->otyp == SLIME_MOLD) otmp->spe = current_fruit; /* give the fruit a type */ strcpy(buf, distant_name(otmp, xname)); dealloc_obj(otmp); otmp = vobj_at(x,y); /* make sure we don't point to the temp obj any more */ } } else strcpy(buf, distant_name(otmp, xname)); if (level->locations[x][y].typ == STONE || level->locations[x][y].typ == SCORR) strcat(buf, " embedded in stone"); else if (IS_WALL(level->locations[x][y].typ) || level->locations[x][y].typ == SDOOR) strcat(buf, " embedded in a wall"); else if (closed_door(level, x,y)) strcat(buf, " embedded in a door"); else if (is_pool(level, x,y)) strcat(buf, " in water"); else if (is_lava(level, x,y)) strcat(buf, " in molten lava"); /* [can this ever happen?] */ if (!cansee(x, y)) return -1; /* don't disclose the number of objects for location out of LOS */ if (!otmp) /* There is no object here. Since the player sees one it must be a mimic */ return 1; if (otmp->otyp != votyp) /* Hero sees something other than the actual top object. Probably a mimic */ num_objs++; for ( ; otmp; otmp = otmp->nexthere) num_objs++; return num_objs; }
boolean create_drawbridge(struct level *lev, int x, int y, int dir, boolean flag) { int x2, y2; boolean horiz; boolean lava = lev->locations[x][y].typ == LAVAPOOL; /* assume initialized map */ x2 = x; y2 = y; switch (dir) { case DB_NORTH: horiz = TRUE; y2--; break; case DB_SOUTH: horiz = TRUE; y2++; break; case DB_EAST: horiz = FALSE; x2++; break; default: impossible("bad direction in create_drawbridge"); /* fall through */ case DB_WEST: horiz = FALSE; x2--; break; } if (!IS_WALL(lev->locations[x2][y2].typ)) return FALSE; if (flag) { /* We want the bridge open */ lev->locations[x][y].typ = DRAWBRIDGE_DOWN; lev->locations[x2][y2].typ = DOOR; lev->locations[x2][y2].doormask = D_NODOOR; } else { lev->locations[x][y].typ = DRAWBRIDGE_UP; lev->locations[x2][y2].typ = DBWALL; /* Drawbridges are non-diggable. */ lev->locations[x2][y2].wall_info = W_NONDIGGABLE; } lev->locations[x][y].horizontal = !horiz; lev->locations[x2][y2].horizontal = horiz; lev->locations[x][y].drawbridgemask = dir; if (lava) lev->locations[x][y].drawbridgemask |= DB_LAVA; return TRUE; }
int RenderWall (tFaceProps *propsP, g3sPoint **pointList, int bIsMonitor) { short c, nWallNum = SEGMENTS [propsP->segNum].WallNum (propsP->sideNum); static tRgbaColorf cloakColor = {0, 0, 0, -1}; if (IS_WALL (nWallNum)) { if (propsP->widFlags & (WID_CLOAKED_FLAG | WID_TRANSPARENT_FLAG)) { if (!bIsMonitor) { if (!RenderColoredSegFace (propsP->segNum, propsP->sideNum, propsP->nVertices, pointList)) { c = WALLS [nWallNum].cloakValue; if (propsP->widFlags & WID_CLOAKED_FLAG) { if (c < FADE_LEVELS) { gameStates.render.grAlpha = GrAlpha (ubyte (c)); G3DrawPolyAlpha (propsP->nVertices, pointList, &cloakColor, 1, propsP->segNum); //draw as flat poly } } else { if (!gameOpts->render.color.bWalls) c = 0; if (WALLS [nWallNum].hps) gameStates.render.grAlpha = float (WALLS [nWallNum].hps) / float (I2X (100)); else if (IsMultiGame && gameStates.app.bHaveExtraGameInfo [1]) gameStates.render.grAlpha = COMPETITION ? 2.0f / 3.0f : GrAlpha (FADE_LEVELS - extraGameInfo [1].grWallTransparency); else gameStates.render.grAlpha = GrAlpha (ubyte (FADE_LEVELS - extraGameInfo [0].grWallTransparency)); if (gameStates.render.grAlpha < 1.0f) { tRgbaColorf wallColor; paletteManager.Game ()->ToRgbaf ((ubyte) c, wallColor); G3DrawPolyAlpha (propsP->nVertices, pointList, &wallColor, 1, propsP->segNum); //draw as flat poly } } } gameStates.render.grAlpha = 1.0f; return 1; } } else if (gameStates.app.bD2XLevel) { c = WALLS [nWallNum].cloakValue; if (c && (c < FADE_LEVELS)) gameStates.render.grAlpha = GrAlpha (FADE_LEVELS - c); } else if (gameOpts->render.effects.bAutoTransparency && IsTransparentFace (propsP)) gameStates.render.grAlpha = 0.8f; else gameStates.render.grAlpha = 1.0f; } return 0; }
bool somexy (struct mkroom *croom, coord *c) { int try_cnt = 0; int i; if (croom->irregular) { i = (croom - rooms) + ROOMOFFSET; while(try_cnt++ < 100) { c->x = somex(croom); c->y = somey(croom); if (!levl[c->x][c->y].edge && (int) levl[c->x][c->y].roomno == i) return true; } /* try harder; exhaustively search until one is found */ for(c->x = croom->lx; c->x <= croom->hx; c->x++) for(c->y = croom->ly; c->y <= croom->hy; c->y++) if (!levl[c->x][c->y].edge && (int) levl[c->x][c->y].roomno == i) return true; return false; } if (!croom->nsubrooms) { c->x = somex(croom); c->y = somey(croom); return true; } /* Check that coords doesn't fall into a subroom or into a wall */ while(try_cnt++ < 100) { c->x = somex(croom); c->y = somey(croom); if (IS_WALL(levl[c->x][c->y].typ)) continue; for(i=0 ; i<croom->nsubrooms;i++) if(inside_room(croom->sbrooms[i], c->x, c->y)) goto you_lose; break; you_lose: ; } if (try_cnt >= 100) return false; return true; }
//----------------------------------------------------------------- // Deteriorate appearance of CWall. (Changes bitmap (paste-ons)) void CSegment::DamageWall (int nSide, fix damage) { int a, i, n; short nConnSide, nConnWall; CWall *wallP = Wall (nSide); CSegment *connSegP; if (!wallP) { #if TRACE console.printf (CON_DBG, "Damaging illegal CWall\n"); #endif return; } if (wallP->nType != WALL_BLASTABLE) return; if ((wallP->flags & WALL_BLASTED) || (wallP->hps < 0)) return; if (m_children [nSide] < 0) { if (gameOpts->legacy.bWalls) Warning (TXT_DMG_SINGLE, this - SEGMENTS, nSide, wallP - WALLS); connSegP = NULL; nConnSide = -1; nConnWall = NO_WALL; } else { connSegP = SEGMENTS + m_children [nSide]; nConnSide = ConnectedSide (connSegP); Assert(nConnSide != -1); nConnWall = connSegP->WallNum (nConnSide); } wallP->hps -= damage; if (IS_WALL (nConnWall)) WALLS [nConnWall].hps -= damage; a = wallP->nClip; n = AnimFrameCount (gameData.walls.animP + a); if (wallP->hps < WALL_HPS * 1 / n) { BlastWall (nSide); if (IsMultiGame) MultiSendDoorOpen (SEG_IDX (this), nSide, wallP->flags); } else { for (i = 0; i < n; i++) if (wallP->hps < WALL_HPS * (n - i) / n) SetTexture (nSide, connSegP, nConnSide, a, i); } }
int ft_trans_to_print(int pos, t_map *map, int pos_col, int pos_row) { if (pos_col == map->entrance_x && pos_row == map->entrance_y) ft_putchar(map->entrance); else if (IS_WALL(pos)) ft_putchar(map->wall); else if (IS_EXIT(pos)) ft_putchar(map->exit); else if (IS_SPACE(pos)) ft_putchar(map->space); else if (IS_PATH(pos)) ft_putchar(map->path); else { map->error = UNRECOGNISED_MAP_CHAR; return (0); } return (1); }
/* SpawnChildren creates new states from possible moves * Tries to push each box in every straight direction several steps * making sure the moves are valid. */ void SokobanState::SpawnChildren(std::vector<SokobanState*> &moves_to_add) const { PrepareScribble(); #ifdef VERBOSE_DEBUG Print(); #endif // Try to push all boxes from every direction for (int i = 0; i < num_boxes; ++i) { if (IS_WALL(boxes[i])) { PRINT_VERBOSE("disregards moving box %d because it is locked\n", i); continue; } SpawnChildrenFrom(i, moves_to_add); } }
// ----------------------------------------------------------------------------- //go through all triggers, killing unused ones static void CheckAndFixTriggers (void) { int i, j; short nSegment, nSide, nWall; for (i = 0; i < gameData.trigs.m_nTriggers; ) { // Find which CWall this CTrigger is connected to. for (j = 0; j < gameData.walls.nWalls; j++) if (WALLS [j].nTrigger == i) break; i++; } for (i = 0; i < gameData.walls.nWalls; i++) WALLS [i].controllingTrigger = -1; // MK, 10/17/95: Make walls point back at the triggers that control them. // Go through all triggers, stuffing controllingTrigger field in WALLS. CTrigger* trigP = TRIGGERS.Buffer (); for (i = 0; i < gameData.trigs.m_nTriggers; i++, trigP++) { for (j = 0; j < trigP->m_info.nLinks; j++) { nSegment = trigP->m_info.segments [j]; nSide = trigP->m_info.sides [j]; nWall = SEGMENTS [nSegment].WallNum (nSide); //check to see that if a CTrigger requires a CWall that it has one, //and if it requires a botGen that it has one if (trigP->m_info.nType == TT_MATCEN) { if (SEGMENTS [nSegment].m_nType != SEGMENT_IS_ROBOTMAKER) continue; //botGen CTrigger doesn'i point to botGen } else if ((trigP->m_info.nType != TT_LIGHT_OFF) && (trigP->m_info.nType != TT_LIGHT_ON)) { //light triggers don't require walls if (IS_WALL (nWall)) WALLS [nWall].controllingTrigger = i; else { Int3(); // This is illegal. This ttrigger requires a CWall } } } } }
static void dosdoor(int x, int y, struct mkroom *aroom, int type) { struct mkroom *broom; int tmp; if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs with '+' as scrsym */ type = DOOR; levl[x][y].typ = type; if(type == DOOR) levl[x][y].scrsym = '+'; aroom->doorct++; broom = aroom+1; if(broom->hx < 0) tmp = doorindex; else for(tmp = doorindex; tmp > broom->fdoor; tmp--) doors[tmp] = doors[tmp-1]; doorindex++; doors[tmp].x = x; doors[tmp].y = y; for( ; broom->hx >= 0; broom++) broom->fdoor++; }
// ------------------------------------------------------------------------------- //when the CWall has used all its hitpoints, this will destroy it void CSegment::BlastWall (int nSide) { short nConnSide; CSegment* connSegP; int a, n; short nConnWall; CWall* wallP = Wall (nSide); if (!wallP) return; wallP->hps = -1; //say it's blasted if (m_children [nSide] < 0) { if (gameOpts->legacy.bWalls) Warning (TXT_BLAST_SINGLE, this - SEGMENTS, nSide, wallP - WALLS); connSegP = NULL; nConnSide = -1; nConnWall = NO_WALL; } else { connSegP = SEGMENTS + m_children [nSide]; nConnSide = ConnectedSide (connSegP); Assert (nConnSide != -1); nConnWall = connSegP->WallNum (nConnSide); KillStuckObjects (nConnWall); } KillStuckObjects (WallNum (nSide)); //if this is an exploding wall, explode it if ((gameData.walls.animP [wallP->nClip].flags & WCF_EXPLODES) && !(wallP->flags & WALL_BLASTED)) ExplodeWall (Index (), nSide); else { //if not exploding, set final frame, and make door passable a = wallP->nClip; n = AnimFrameCount (gameData.walls.animP + a); SetTexture (nSide, connSegP, nConnSide, a, n - 1); wallP->flags |= WALL_BLASTED; if (IS_WALL (nConnWall)) WALLS [nConnWall].flags |= WALL_BLASTED; } }
/* * use a flooding algorithm to find all locations that should * have the same rm number as the current location. * if anyroom is TRUE, use IS_ROOM to check room membership instead of * exactly matching level->locations[sx][sy].typ and walls are included as well. */ void flood_fill_rm(struct level *lev, int sx, int sy, int rmno, boolean lit, boolean anyroom) { int i; int nx; schar fg_typ = lev->locations[sx][sy].typ; /* back up to find leftmost uninitialized location */ while (sx >= 0 && (anyroom ? IS_ROOM(lev->locations[sx][sy].typ) : lev->locations[sx][sy].typ == fg_typ) && (int)lev->locations[sx][sy].roomno != rmno) sx--; sx++; /* compensate for extra decrement */ /* assume sx,sy is valid */ if (sx < min_rx) min_rx = sx; if (sy < min_ry) min_ry = sy; for (i = sx; i <= WIDTH && lev->locations[i][sy].typ == fg_typ; i++) { lev->locations[i][sy].roomno = rmno; lev->locations[i][sy].lit = lit; if (anyroom) { /* add walls to room as well */ int ii, jj; for (ii = (i == sx ? i - 1 : i); ii <= i + 1; ii++) for (jj = sy - 1; jj <= sy + 1; jj++) if (isok(ii, jj) && (IS_WALL(lev->locations[ii][jj].typ) || IS_DOOR(lev->locations[ii][jj].typ))) { lev->locations[ii][jj].edge = 1; if (lit) lev->locations[ii][jj].lit = lit; if ((int)lev->locations[ii][jj].roomno != rmno) lev->locations[ii][jj].roomno = SHARED; } } n_loc_filled++; } nx = i; if (isok(sx, sy - 1)) { for (i = sx; i < nx; i++) if (lev->locations[i][sy - 1].typ == fg_typ) { if ((int)lev->locations[i][sy - 1].roomno != rmno) flood_fill_rm(lev, i, sy - 1, rmno, lit, anyroom); } else { if ((i > sx || isok(i - 1, sy - 1)) && lev->locations[i - 1][sy - 1].typ == fg_typ) { if ((int)lev->locations[i - 1][sy - 1].roomno != rmno) flood_fill_rm(lev, i - 1, sy - 1, rmno, lit, anyroom); } if ((i < nx - 1 || isok(i + 1, sy - 1)) && lev->locations[i + 1][sy - 1].typ == fg_typ) { if ((int)lev->locations[i + 1][sy - 1].roomno != rmno) flood_fill_rm(lev, i + 1, sy - 1, rmno, lit, anyroom); } } } if (isok(sx, sy + 1)) { for (i = sx; i < nx; i++) if (lev->locations[i][sy + 1].typ == fg_typ) { if ((int)lev->locations[i][sy + 1].roomno != rmno) flood_fill_rm(lev, i, sy + 1, rmno, lit, anyroom); } else { if ((i > sx || isok(i - 1, sy + 1)) && lev->locations[i - 1][sy + 1].typ == fg_typ) { if ((int)lev->locations[i - 1][sy + 1].roomno != rmno) flood_fill_rm(lev, i - 1, sy + 1, rmno, lit, anyroom); } if ((i < nx - 1 || isok(i + 1, sy + 1)) && lev->locations[i + 1][sy + 1].typ == fg_typ) { if ((int)lev->locations[i + 1][sy + 1].roomno != rmno) flood_fill_rm(lev, i + 1, sy + 1, rmno, lit, anyroom); } } } if (nx > max_rx) max_rx = nx - 1; /* nx is just past valid region */ if (sy > max_ry) max_ry = sy; }
int gd_move() { int x,y,dx,dy,gx,gy,nx,ny,typ; struct fakecorridor *fcp; struct rm *crm; if(!guard || gdlevel != dlevel){ impossible("Where is the guard?"); return(2); /* died */ } if(u.ugold || goldincorridor()) return(0); /* didnt move */ if(dist(guard->mx,guard->my) > 1 || EGD->gddone) { restfakecorr(); return(0); /* didnt move */ } x = guard->mx; y = guard->my; /* look around (hor & vert only) for accessible places */ for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) { if(nx == x || ny == y) if(nx != x || ny != y) if(isok(nx,ny)) if(!IS_WALL(typ = (crm = &levl[nx][ny])->typ) && typ != POOL) { int i; for(i = EGD->fcbeg; i < EGD->fcend; i++) if(EGD->fakecorr[i].fx == nx && EGD->fakecorr[i].fy == ny) goto nextnxy; if((i = inroom(nx,ny)) >= 0 && rooms[i].rtype == VAULT) goto nextnxy; /* seems we found a good place to leave him alone */ EGD->gddone = 1; if(ACCESSIBLE(typ)) goto newpos; crm->typ = (typ == SCORR) ? CORR : DOOR; goto proceed; } nextnxy: ; } nx = x; ny = y; gx = EGD->gdx; gy = EGD->gdy; dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; if(abs(gx-x) >= abs(gy-y)) nx += dx; else ny += dy; while((typ = (crm = &levl[nx][ny])->typ) != 0) { /* in view of the above we must have IS_WALL(typ) or typ == POOL */ /* must be a wall here */ if(isok(nx+nx-x,ny+ny-y) && typ != POOL && ZAP_POS(levl[nx+nx-x][ny+ny-y].typ)){ crm->typ = DOOR; goto proceed; } if(dy && nx != x) { nx = x; ny = y+dy; continue; } if(dx && ny != y) { ny = y; nx = x+dx; dy = 0; continue; } /* I don't like this, but ... */ crm->typ = DOOR; goto proceed; } crm->typ = CORR; proceed: if(cansee(nx,ny)) { mnewsym(nx,ny); prl(nx,ny); } fcp = &(EGD->fakecorr[EGD->fcend]); if(EGD->fcend++ == FCSIZ) panic("fakecorr overflow"); fcp->fx = nx; fcp->fy = ny; fcp->ftyp = typ; newpos: if(EGD->gddone) nx = ny = 0; guard->mx = nx; guard->my = ny; pmon(guard); restfakecorr(); return(1); }