int check_availability(int curr_pit) { int i; //printf("%s %d Checking Availability for %d\n",SELF,id,curr_pit); for(i = 0; i < N_PITS; i++) { //Mutex down(sem_mut,0); printf("%s %d requesting food from meat-pit %d\n",SELF,id,curr_pit); if(!occupied(sem_rival,curr_pit) && !occupied(sem_ranger,curr_pit) && semctl(sem_self,curr_pit,GETVAL,0) < semctl(sem_pit,curr_pit,GETVAL,0)) { up(sem_mut,0); return curr_pit; } if(semctl(sem_pit,curr_pit,GETVAL,0) == 0) printf("Meat-pit %d empty\n",curr_pit); else printf("%s %d denied access\n",SELF,id); up(sem_mut,0); // Change curr_pit curr_pit = curr_pit%N_PITS + 1; } // No pit available return -1; }
void DiplomacyRegion::display() { if (!occupied() && attacking_pieces.empty() && attacking_support.empty() && attacking_convoys.empty() && defending_support.empty()) { return; } printf("Region: %s (%s)\n",names[0],names[1]); if (occupied()) { printf("\tThe region itself has %d occupiers.\n",occupiers.size()); for (int i = 0; i < occupiers.size(); ++i) { occupiers[i]->display(); } for (int i = 0; i < coasts.size(); ++i) { printf("------<coast>------\n"); coasts[i]->display(); printf("------</coast>-----\n"); } } if (!attacking_pieces.empty()) { printf("\tThe region is under attack by %d pieces.\n",attacking_pieces.size()); for (int i = 0; i < attacking_pieces.size(); ++i) { attacking_pieces[i]->display(); } } if (!attacking_support.empty()) { printf("\tAttackers are being supported by %d pieces.\n",attacking_support.size()); for (int i = 0; i < attacking_support.size(); ++i) { printf("\tThe piece: "); attacking_support[i]->supporter->display(); printf("\tIs supporting: "); attacking_support[i]->supported->display(); } } }
void RingBuffer::readWithPad(double *data, unsigned int frames) { if (frames <= occupied()) { read(data, frames); } else { std::cout << "Underrun" << std::endl; // Not enough in the buffer so pad with zeros unsigned int padSize = frames - occupied(); read(data, occupied()); for (unsigned int i=0; i<padSize; i++) { data[frames - i - 1] = 0; } } }
BOOL LASoccupancyGrid::write_asc_grid(const char* file_name) const { FILE* file = fopen(file_name, "w"); if (file == 0) return FALSE; fprintf(file, "ncols %d\012", max_x-min_x+1); fprintf(file, "nrows %d\012", max_y-min_y+1); fprintf(file, "xllcorner %f\012", grid_spacing*min_x); fprintf(file, "yllcorner %f\012", grid_spacing*min_y); fprintf(file, "cellsize %lf\012", grid_spacing); fprintf(file, "NODATA_value %d\012", 0); fprintf(file, "\012"); I32 pos_x, pos_y; for (pos_y = min_y; pos_y <= max_y; pos_y++) { for (pos_x = min_x; pos_x <= max_x; pos_x++) { if (occupied(pos_x, pos_y)) { fprintf(file, "1 "); } else { fprintf(file, "0 "); } } fprintf(file, "\012"); } fclose(file); return TRUE; }
/* * Returns true if a move is legal for the given side; false otherwise. */ bool Board::checkMove(Move *m, Side side) { // Passing is only legal if you have no moves. if (m == NULL) return !hasMoves(side); int X = m->getX(); int Y = m->getY(); // Make sure the square hasn't already been taken. if (occupied(X, Y)) return false; Side other = (side == BLACK) ? WHITE : BLACK; for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { if (dy == 0 && dx == 0) continue; // Is there a capture in that direction? int x = X + dx; int y = Y + dy; if (onBoard(x, y) && get(other, x, y)) { do { x += dx; y += dy; } while (onBoard(x, y) && get(other, x, y)); if (onBoard(x, y) && get(side, x, y)) return true; } } } return false; }
int Board::value(Side side) { int cost[8][8] = { {99, -8, 8, 6, 6, 8, -8, 99}, {-8, -24, -4, -3, -3, -4, -24, -8}, {8, -4, 7, 4, 4, 7, -4, 8}, {6, -3, 4, 0, 0, 4, -3, 6}, {6, -3, 4, 0, 0, 4, -3, 6}, {8, -4, 7, 4, 4, 7, -4, 8}, {-8, -24, -4, -3, -3, -4, -24, -8}, {99, -8, 8, 6, 6, 8, -8, 99} }; int value = 0; for (int i = 0; i < 8; i++){ for (int j = 0; j < 8; j++){ if (occupied(i, j)){ if (get(side, i, j)){ value = value + cost[i][j]; } else { value = value - cost[i][j]; } } } } return value; }
bool validate_move_no_conflict(board_t * board, piece_info_t * move){ uintptr_t i; if (!valid_coord(move->x, move->y)){ return false; } piece_cell_t * cells; uintptr_t sz; cells = piece_info_points(move, &sz); for (i = 1;i < sz;i++){ int8_t x,y; x = cells[i].x; y = cells[i].y; if (!valid_coord(x, y) || occupied(board, x, y)){ free(cells); return false; } } free(cells); return true; }
/* void Dstar::getSucc(state u,list<state> &s) * -------------------------- * Returns a list of successor states for state u, since this is an * 8-way graph this list contains all of a cells neighbours. Unless * the cell is occupied in which case it has no successors. */ void Dstar::getSucc(state u,list<state> &s) { s.clear(); u.k.first = -1; u.k.second = -1; if (occupied(u)) return; u.x += 1; s.push_front(u); u.y += 1; s.push_front(u); u.x -= 1; s.push_front(u); u.x -= 1; s.push_front(u); u.y -= 1; s.push_front(u); u.y -= 1; s.push_front(u); u.x += 1; s.push_front(u); u.x += 1; s.push_front(u); }
Shape Shape::rotateCW(int pivotX, int pivotY) const { Shape out { cols(), rows() }; int dx, dy; int w = static_cast<int>(cols()), h = static_cast<int>(rows()); int xmax = w - 1, ymax = h - 1; for (int sy = 0; sy < h; sy++) for (int sx = 0; sx < w; ++sx) { // px, py == 0, 0 means rotate around center if (pivotX == 0 && pivotY == 0) { dx = ymax - sy; dy = sx; } else { dx = ymax - sy - (ymax - (pivotX + pivotY)); dy = sx - (pivotX - pivotY); } if (dx < 0 || dx > xmax || dy < 0 || dy > ymax) continue; auto tile = at(sx, sy); if (tile.occupied()) { tile.setRotation(tile.rotation() + 1); out.at(dx, dy) = tile; } } return out; }
void set_color_scooch(burger* b, double dx, double dy, char* color, int direction) { int x = get_norm_x(b, dx); int y = get_norm_y(b, dy); if (occupied(b, x, y)) x += direction; b->color_matrix[y+(x*b->w)] = color; }
void put_burger_scooch(burger* b, double dx, double dy, char c, int direction) { int x = get_norm_x(b, dx); int y = get_norm_y(b, dy); if (occupied(b, x, y)) x += direction; update_frame(b,x,y); b->burger_matrix[y+(x*b->w)] = c; }
bool RoombotBuildPlan::getConnector(size_t index, size_t connectorIndex) const { int* xMods; int* zMods; int hxMods[NR_OF_CONNECTORS]; int hyMods[NR_OF_CONNECTORS]; int vxMods[NR_OF_CONNECTORS]; int vyMods[NR_OF_CONNECTORS]; vxMods[SOUTH_CONNECTOR] = 0; vxMods[SOUTH_EAST_CONNECTOR] = -1; vxMods[SOUTH_WEST_CONNECTOR] = 1; vxMods[NORTH_EAST_CONNECTOR] = -1; vxMods[NORTH_WEST_CONNECTOR] = 1; vxMods[NORTH_CONNECTOR] = 0; vyMods[SOUTH_CONNECTOR] = -1; vyMods[SOUTH_EAST_CONNECTOR] = 0; vyMods[SOUTH_WEST_CONNECTOR] = 0; vyMods[NORTH_EAST_CONNECTOR] = 1; vyMods[NORTH_WEST_CONNECTOR] = 1; vyMods[NORTH_CONNECTOR] = 2; hxMods[SOUTH_CONNECTOR] = -1; hxMods[SOUTH_EAST_CONNECTOR] = 0; hxMods[SOUTH_WEST_CONNECTOR] = 0; hxMods[NORTH_EAST_CONNECTOR] = 1; hxMods[NORTH_WEST_CONNECTOR] = 1; hxMods[NORTH_CONNECTOR] = 2; hyMods[SOUTH_CONNECTOR] = 0; hyMods[SOUTH_EAST_CONNECTOR] = 1; hyMods[SOUTH_WEST_CONNECTOR] = -1; hyMods[NORTH_EAST_CONNECTOR] = 1; hyMods[NORTH_WEST_CONNECTOR] = -1; hyMods[NORTH_CONNECTOR] = 0; if(positions[index].isHorizontal){ xMods = hxMods; zMods = hyMods; } else { xMods = vxMods; zMods = vyMods; } if(connectorIndex == SOUTH_BOT_CONNECTOR || connectorIndex == SOUTH_TOP_CONNECTOR || connectorIndex == NORTH_BOT_CONNECTOR || connectorIndex == NORTH_TOP_CONNECTOR) { return false; } int x = positions[index].getX() + xMods[connectorIndex]; int z = positions[index].getZ() + zMods[connectorIndex]; return occupied(x, z); }
bool Map::seize(unsigned tilePos) { bool retVal = false; if (!occupied(tilePos) && at(tilePos) != mi_WallValue) { mba_Occupied[tilePos] = true; retVal = true; } return retVal; }
bool can_castle(string input, unordered_map< string, string > *board, struct PlayerStatus &player_ps) //if can successfully castle, updates board and returns true; returns false otherwise { char player = piece_at(board, to_cart(player_ps.k_pos))[0]; int row = (player == 'W')? 1:8; vector<int> king_start {5,row}; vector<int> rook_start, rook_end, king_end; if (input == "0-0"){ //king-side castling if (!player_ps.castle_k_side) return false; vector<int> rook_start {8,row}; vector<int> rook_end {6,row}; vector<int> king_end {7,row}; } else{ //queen-side castling vector<int> queen_spot {4, row}; if (!player_ps.castle_q_side || occupied(board, queen_spot)) return false; vector<int> rook_start {1,row}; vector<int> rook_end {4,row}; vector<int> king_end {3,row}; } if (!occupied(board,king_end) && !occupied(board,rook_end)){ unordered_map<string,string> board2 = unordered_map<string,string>(*board); //make copy of board update_board(rook_start, rook_end, &board2); update_board(king_start, king_end, &board2); if (is_king_safe(&board2, player_ps)){ update_board(rook_start, rook_end, board); update_board(king_start, king_end, board); player_ps.k_pos = to_str(king_end); player_ps.castle_k_side = false; player_ps.castle_q_side = false; return true; } } return false; }
bool validate_move_check_no_cross_edge(board_t * board , role_t role, int8_t x, int8_t y){ piece_cell_t NG_cells[4] = {{x+1,y}, {x,y+1}, {x-1,y}, {x,y-1}}; uintptr_t i; if (occupied(board, x, y)){ return false; } for (i = 0;i < 4;i++){ piece_cell_t * cell = &NG_cells[i]; if (occupied(board, cell->x, cell->y) && role == occupied_by(board, cell->x, cell->y)){ return false; } } return true; }
void RingBuffer::read(double *data, unsigned int frames) { if (frames <= occupied()) { for (unsigned int i=0; i<frames; i++) { data[i] = _buffer[_readPos]; std::cout << data[i] << std::endl; _readPos = _readPos + 1; if (_readPos == _size) { _readPos = 0; } } _occupied = _occupied - frames; } }
bool validate_move_check_cross_corner(board_t * board , role_t role, int8_t x, int8_t y){ piece_cell_t required_cells[4] = {{x+1,y+1}, {x+1,y-1}, {x-1,y+1}, {x-1,y-1}}; uintptr_t i; for (i = 0;i < 4;i++){ piece_cell_t * cell = &required_cells[i]; if (occupied(board, cell->x, cell->y) && role == occupied_by(board, cell->x, cell->y)){ return true; } } return false; }
role_t occupied_by(board_t * board, int8_t x, int8_t y){ if (!valid_coord(x,y)){ return ROLE_NONE; } if (!occupied(board, x, y)){ return ROLE_NONE; } uint32_t mask; mask = 1 << x; if (board->cellcolors[y] & mask){ return ROLE_BLACK; } return ROLE_WHITE; }
Permutation Permutation_interleave (Permutation me, long from, long to, long blocksize, long offset) { try { long n = Permutation_checkRange (me, &from, &to); long nblocks = n / blocksize; long nrest = n % blocksize; if (nrest != 0) Melder_throw ("There is not an integer number of blocks in the range.\n" "(The last block is only of size ", nrest, L" instead of ", blocksize, ")."); if (offset >= blocksize) { Melder_throw (L"Offset must be smaller than blocksize."); } autoPermutation thee = Data_copy (me); if (nblocks == 1) { return thee.transfer(); } autoNUMvector<long> occupied (1, blocksize); long posinblock = 1 - offset; for (long i = 1; i <= n; i++) { long index, rblock = (i - 1) % nblocks + 1; posinblock += offset; if (posinblock > blocksize) { posinblock -= blocksize; } if (i % nblocks == 1) { long count = blocksize; while (occupied[posinblock] == 1 && count > 0) { posinblock++; count--; if (posinblock > blocksize) { posinblock -= blocksize; } } occupied[posinblock] = 1; } index = from - 1 + (rblock - 1) * blocksize + posinblock; thy p[from - 1 + i] = my p[index]; } return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": not interleaved."); } }
/** * Counts score using the naive values for squares. For Testing minimax */ int Board::getScoreNaive(Side side) { int score = 0; for(int i = 0; i < 8; i++) { for(int j = 0; j < 8; j++) { if(occupied(i, j)) { // if ours if(get(side, i, j)) { score += naiveVal[i][j]; } else { score -= naiveVal[i][j]; } } } } return score; }
// Display the Square's contents. void Square::display(ostream& outStream) const { // Output whitespace. outStream << " "; // If the Square is occupied, then display the occupier of the Square. if (occupied()) { // Display the occupier of the Square. occupiedBy().display(outStream); } // If the Square is not occupied, then display whitespace instead. else { // Display whitespace instead. outStream << " "; } // Output whitespace followed by a bar to delineate the verticals on // the Square. outStream << " |"; }
/* void Dstar::getPred(state u,list<state> &s) * -------------------------- * Returns a list of all the predecessor states for state u. Since * this is for an 8-way connected graph the list contails all the * neighbours for state u. Occupied neighbours are not added to the * list. */ void Dstar::getPred(state u,list<state> &s) { s.clear(); u.k.first = -1; u.k.second = -1; u.x += 1; if (!occupied(u)) s.push_front(u); u.y += 1; if (!occupied(u)) s.push_front(u); u.x -= 1; if (!occupied(u)) s.push_front(u); u.x -= 1; if (!occupied(u)) s.push_front(u); u.y -= 1; if (!occupied(u)) s.push_front(u); u.y -= 1; if (!occupied(u)) s.push_front(u); u.x += 1; if (!occupied(u)) s.push_front(u); u.x += 1; if (!occupied(u)) s.push_front(u); }
bool Board::move(Pieces_t::iterator source, Movements_t::const_iterator target) { if(source == pieces.end()) { std::cerr << "source iterator of piece to move is invalid" << std::endl; return false; } if(target == trajectories.end() && target == capturings.end()) { std::cerr << "target iterator of piece to move to is invalid" << std::endl; return false; } if(source != target->first) { std::cerr << "target iterator does not match source iterator, source{" << **source << "}, target {" << **(target->first) << "}" << std::endl; return false; } if(occupied(target->second)) { std::cerr << "target iterator to move to is occupied:" << std::endl; for(auto &p : pieces) { if(p->pos == target->second) { std::cerr << "\t" << *p << std::endl; } } return false; } std::clog << "Moved piece at " << (*source)->pos << std::flush; (*source)->move(target->second); update(target->second); std::clog << " to " << target->second << std::endl; return true; }
/* bool Dstar::replan() * -------------------------- * Updates the costs for all cells and computes the shortest path to * goal. Returns true if a path is found, false otherwise. The path is * computed by doing a greedy search over the cost+g values in each * cells. In order to get around the problem of the robot taking a * path that is near a 45 degree angle to goal we break ties based on * the metric euclidean(state, goal) + euclidean(state,start). */ bool Dstar::replan() { path.clear(); int res = computeShortestPath(); // printf("res: %d ols: %d ohs: %d tk: [%f %f] sk: [%f %f] sgr: (%f,%f)\n",res,openList.size(),openHash.size(),openList.top().k.first,openList.top().k.second, s_start.k.first, s_start.k.second,getRHS(s_start),getG(s_start)); if (res < 0) { //fprintf(stderr, "NO PATH TO GOAL\n"); path.cost = INFINITY; return false; } list<state> n; list<state>::iterator i; state cur = s_start; state prev = s_start; if (isinf(getG(s_start))) { //fprintf(stderr, "NO PATH TO GOAL\n"); path.cost = INFINITY; return false; } // constructs the path while(cur != s_goal) { path.path.push_back(cur); path.cost += cost(prev,cur); getSucc(cur, n); if (n.empty()) { //fprintf(stderr, "NO PATH TO GOAL\n"); path.cost = INFINITY; return false; } // choose the next node in the path by selecting the one with smallest // g() + cost. Break ties by choosing the neighbour that is closest // to the line between start and goal (i.e. smallest sum of Euclidean // distances to start and goal). double cmin = INFINITY; double tmin = INFINITY; state smin = cur; for (i=n.begin(); i!=n.end(); i++) { if (occupied(*i)) continue; double val = cost(cur,*i); double val2 = trueDist(*i,s_goal) + trueDist(s_start,*i); // (Euclidean) cost to goal + cost to pred double val3 = getG(*i); val += val3; // tiebreak if curent neighbour is equal to current best // choose the neighbour that has the smallest tmin value if (!isinf(val) && near(val,cmin)) { if (val2 < tmin) { tmin = val2; cmin = val; smin = *i; } } // if next neighbour (*i) is scrictly lower cost than the // current best, then set it to be the current best. else if (val < cmin) { tmin = val2; cmin = val; smin = *i; } } // end for loop n.clear(); if( isinf(cmin) ) break; prev = cur; cur = smin; } // end while loop path.path.push_back(s_goal); path.cost += cost(prev,s_goal); return true; }
bool Board::get(Side side, int x, int y) { return occupied(x, y) && (black[x + 8*y] == (side == BLACK)); }
void fill_zoo (struct mkroom *sroom) { struct monst *mon; int sx,sy,i; int sh, tx, ty, goldlim, type = sroom->rtype; int rmno = (sroom - rooms) + ROOMOFFSET; coord mm; sh = sroom->fdoor; switch(type) { case COURT: if(level.flags.is_maze_lev) { for(tx = sroom->lx; tx <= sroom->hx; tx++) for(ty = sroom->ly; ty <= sroom->hy; ty++) if(IS_THRONE(levl[tx][ty].typ)) goto throne_placed; } i = 100; do { /* don't place throne on top of stairs */ (void) somexy(sroom, &mm); tx = mm.x; ty = mm.y; } while (occupied((signed char)tx, (signed char)ty) && --i > 0); throne_placed: /* TODO: try to ensure the enthroned monster is an M2_PRINCE */ break; case BEEHIVE: tx = sroom->lx + (sroom->hx - sroom->lx + 1)/2; ty = sroom->ly + (sroom->hy - sroom->ly + 1)/2; if(sroom->irregular) { /* center might not be valid, so put queen elsewhere */ if ((int) levl[tx][ty].roomno != rmno || levl[tx][ty].edge) { (void) somexy(sroom, &mm); tx = mm.x; ty = mm.y; } } break; case ZOO: case LEPREHALL: goldlim = 500 * level_difficulty(); break; } for(sx = sroom->lx; sx <= sroom->hx; sx++) for(sy = sroom->ly; sy <= sroom->hy; sy++) { if(sroom->irregular) { if ((int) levl[sx][sy].roomno != rmno || levl[sx][sy].edge || (sroom->doorct && distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)) continue; } else if(!SPACE_POS(levl[sx][sy].typ) || (sroom->doorct && ((sx == sroom->lx && doors[sh].x == sx-1) || (sx == sroom->hx && doors[sh].x == sx+1) || (sy == sroom->ly && doors[sh].y == sy-1) || (sy == sroom->hy && doors[sh].y == sy+1)))) continue; /* don't place monster on explicitly placed throne */ if(type == COURT && IS_THRONE(levl[sx][sy].typ)) continue; mon = makemon( (type == COURT) ? courtmon() : (type == BARRACKS) ? squadmon() : (type == MORGUE) ? morguemon() : (type == BEEHIVE) ? (sx == tx && sy == ty ? &mons[PM_QUEEN_BEE] : &mons[PM_KILLER_BEE]) : (type == LEPREHALL) ? &mons[PM_LEPRECHAUN] : (type == COCKNEST) ? &mons[PM_COCKATRICE] : (type == ANTHOLE) ? antholemon() : (struct permonst *) 0, sx, sy, NO_MM_FLAGS); if(mon) { mon->msleeping = 1; if (type==COURT && mon->mpeaceful) { mon->mpeaceful = 0; set_malign(mon); } } switch(type) { case ZOO: case LEPREHALL: if(sroom->doorct) { int distval = dist2(sx,sy,doors[sh].x,doors[sh].y); i = sq(distval); } else i = goldlim; if(i >= goldlim) i = 5*level_difficulty(); goldlim -= i; (void) mkgold((long) rn1(i, 10), sx, sy); break; case MORGUE: if(!rn2(5)) (void) mk_tt_object(CORPSE, sx, sy); if(!rn2(10)) /* lots of treasure buried with dead */ (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy, true, false); if (!rn2(5)) make_grave(sx, sy, (char *)0); break; case BEEHIVE: if(!rn2(3)) (void) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy, true, false); break; case BARRACKS: if(!rn2(20)) /* the payroll and some loot */ (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy, true, false); break; case COCKNEST: if(!rn2(3)) { struct obj *sobj = mk_tt_object(STATUE, sx, sy); if (sobj) { for (i = rn2(5); i; i--) (void) add_to_container(sobj, mkobj(RANDOM_CLASS, false)); sobj->owt = weight(sobj); } } break; case ANTHOLE: if(!rn2(3)) (void) mkobj_at(FOOD_CLASS, sx, sy, false); break; } } switch (type) { case COURT: { struct obj *chest; levl[tx][ty].typ = THRONE; (void) somexy(sroom, &mm); (void) mkgold((long) rn1(50 * level_difficulty(),10), mm.x, mm.y); /* the royal coffers */ chest = mksobj_at(CHEST, mm.x, mm.y, true, false); chest->spe = 2; /* so it can be found later */ level.flags.has_court = 1; break; } case BARRACKS: level.flags.has_barracks = 1; break; case ZOO: level.flags.has_zoo = 1; break; case MORGUE: level.flags.has_morgue = 1; break; case SWAMP: level.flags.has_swamp = 1; break; case BEEHIVE: level.flags.has_beehive = 1; break; } }
Path Map::findPath(int startX, int startY, int destX, int destY, unsigned char walkmask, int maxCost) { // Path to be built up (empty by default) Path path; // Declare open list, a list with open tiles sorted on F cost std::priority_queue<Location> openList; // Return when destination not walkable if (!getWalk(destX, destY, walkmask)) return path; // Reset starting tile's G cost to 0 MetaTile *startTile = getMetaTile(startX, startY); startTile->Gcost = 0; // Add the start point to the open list openList.push(Location(startX, startY, startTile)); bool foundPath = false; // Keep trying new open tiles until no more tiles to try or target found while (!openList.empty() && !foundPath) { // Take the location with the lowest F cost from the open list. Location curr = openList.top(); openList.pop(); // If the tile is already on the closed list, this means it has already // been processed with a shorter path to the start point (lower G cost) if (curr.tile->whichList == mOnClosedList) { continue; } // Put the current tile on the closed list curr.tile->whichList = mOnClosedList; // Check the adjacent tiles for (int dy = -1; dy <= 1; dy++) { for (int dx = -1; dx <= 1; dx++) { // Calculate location of tile to check const int x = curr.x + dx; const int y = curr.y + dy; // Skip if if we're checking the same tile we're leaving from, // or if the new location falls outside of the map boundaries if ((dx == 0 && dy == 0) || !contains(x, y)) { continue; } MetaTile *newTile = getMetaTile(x, y); // Skip if the tile is on the closed list or is not walkable // unless its the destination tile if (newTile->whichList == mOnClosedList || ((newTile->blockmask & walkmask) && !(x == destX && y == destY))) { continue; } // When taking a diagonal step, verify that we can skip the // corner. if (dx != 0 && dy != 0) { MetaTile *t1 = getMetaTile(curr.x, curr.y + dy); MetaTile *t2 = getMetaTile(curr.x + dx, curr.y); if ((t1->blockmask | t2->blockmask) & BLOCKMASK_WALL) continue; } // Calculate G cost for this route, ~sqrt(2) for moving diagonal int Gcost = curr.tile->Gcost + (dx == 0 || dy == 0 ? basicCost : basicCost * 362 / 256); /* Demote an arbitrary direction to speed pathfinding by adding a defect (TODO: change depending on the desired visual effect, e.g. a cross-product defect toward destination). Important: as long as the total defect along any path is less than the basicCost, the pathfinder will still find one of the shortest paths! */ if (dx == 0 || dy == 0) { // Demote horizontal and vertical directions, so that two // consecutive directions cannot have the same Fcost. ++Gcost; } // It costs extra to walk through a being (needs to be enough // to make it more attractive to walk around). if (occupied(x, y)) { Gcost += 3 * basicCost; } // Skip if Gcost becomes too much // Warning: probably not entirely accurate if (Gcost > maxCost * basicCost) { continue; } if (newTile->whichList != mOnOpenList) { // Found a new tile (not on open nor on closed list) /* Update Hcost of the new tile. The pathfinder does not work reliably if the heuristic cost is higher than the real cost. In particular, using Manhattan distance is forbidden here. */ int dx = std::abs(x - destX), dy = std::abs(y - destY); newTile->Hcost = std::abs(dx - dy) * basicCost + std::min(dx, dy) * (basicCost * 362 / 256); // Set the current tile as the parent of the new tile newTile->parentX = curr.x; newTile->parentY = curr.y; // Update Gcost and Fcost of new tile newTile->Gcost = Gcost; newTile->Fcost = Gcost + newTile->Hcost; if (x != destX || y != destY) { // Add this tile to the open list newTile->whichList = mOnOpenList; openList.push(Location(x, y, newTile)); } else { // Target location was found foundPath = true; } } else if (Gcost < newTile->Gcost) { // Found a shorter route. // Update Gcost and Fcost of the new tile newTile->Gcost = Gcost; newTile->Fcost = Gcost + newTile->Hcost; // Set the current tile as the parent of the new tile newTile->parentX = curr.x; newTile->parentY = curr.y; // Add this tile to the open list (it's already // there, but this instance has a lower F score) openList.push(Location(x, y, newTile)); } } } } // Two new values to indicate whether a tile is on the open or closed list, // this way we don't have to clear all the values between each pathfinding. mOnClosedList += 2; mOnOpenList += 2; // If a path has been found, iterate backwards using the parent locations // to extract it. if (foundPath) { int pathX = destX; int pathY = destY; while (pathX != startX || pathY != startY) { // Add the new path node to the start of the path list path.push_front(Position(pathX, pathY)); // Find out the next parent MetaTile *tile = getMetaTile(pathX, pathY); pathX = tile->parentX; pathY = tile->parentY; } } return path; }
bool Map::occupied(unsigned tileX, unsigned tileY) { return occupied(tileY * width() + tileX); }
void wsSolve(Array2D<char> const& wsArray, //Wordsearch array to solve. StrLocMap& matchMap) //List of words and their locations { /** * @brief Given the array (wsArray) and the list of words to find (domain of * matchMap), wsSolve will fill the range of matchMap with the locations * of the words to find. For instance, if matchMap contains * (string1, locationData), wsSolve() fills in locationData * with the location of the string. If the word is not found, * locationData will remain unmodified. * * The algorithm itself is quite complex. See wsSolveDoc.h for more * information. * * @author MPW * @date 7/19/2008 * @version 1 * */ typedef std::vector<Coord> CoordVec; //Declare the array of vectors of strings and set them all to empty vectors. Array2D<VecStr> occupied(wsArray.getWidth(), wsArray.getHeight()); for (unsigned y = 0; y != wsArray.getHeight(); ++y) { for (unsigned x = 0; x != wsArray.getWidth(); ++x) occupied(x, y) = std::vector<std::string>(); } //Find the list of letters to make a location list for, and for each letter, //pair the letter with a vector containing the coordinates of each occurrence //of that letter. //We go through the list, finding each letter to cache. std::map<char, CoordVec> cacheList; char prevChar = 0; char currentChar = 0; for (StrLocMap::iterator itr = matchMap.begin(); itr != matchMap.end();) { //currentChar is still from the previous loop! Hence, we set prevChar to //currentChar and update currentChar. prevChar = currentChar; currentChar = itr->first[0]; //If the letter here is the same as the one before, it repeats (since //maps sort their elements in alphabetical order) (if this is //the first loop, this will never happen; prevChar will be nul, and no first //letter of a string can be nul; therefore, we don't count the first element //as appearing twice). if (currentChar == prevChar) { cacheList.insert(std::make_pair(currentChar, CoordVec())); //This trasverses the map until we get to a different character. while ((++itr != matchMap.end()) && (itr->first[0] == currentChar)); //This is so the ++itr below does not execute. continue; } ++itr; } //Copy each of the strings into a multimap; this will sort the strings by //length. std::multimap<unsigned, std::string> strList; for (StrLocMap::iterator itr = matchMap.begin(); itr != matchMap.end(); ++itr) strList.insert(std::make_pair(itr->first.size(), itr->first)); //Start the find. for (std::multimap<unsigned, std::string>::reverse_iterator itr = strList.rbegin(); itr != strList.rend(); ++itr) { std::string& str = itr->second; bool isCached = !(cacheList.find(str[0]) == cacheList.end()); //Whether or not //the first letter //of the current //string is //cached. Coord startLocation(0, 0); //Location to start searching at; if the first //letter of the word's locations have been cached, //and none of the cached positions are the //location where str is found, startLocation is //set to the spot one after the last cached //position. if (isCached) { CoordVec& coordVec = cacheList[str[0]]; if (coordVec.size() != 0) { //We assert here that the cached locations are in "ascending order"; //see wsSolveDoc.h for more information. for (unsigned i = 0; i != coordVec.size(); ++i) { //Contains the list of all possible directions the word can have //at the given coordinates; see wsSolveDoc.h for more information. std::vector<Direction> possibleDirList; findWordAt(wsArray, str, coordVec[i], possibleDirList); //Go through the vector, either until we find a valid direction //the word can have, or until there are no possible directions //the word can have left. (There's a chance possibleDir.empty() is //already true, so in that case, just skip over that part.) for (std::vector<Direction>::iterator itr2 = possibleDirList.begin(); itr2 != possibleDirList.end(); ++itr2) { if (!areAllOccupiedBySuperstring(occupied, str, coordVec[i], *itr2)) { //You found the word! matchMap[str] = LocationData(coordVec[i], *itr2); setOccupied(occupied, str, coordVec[i], *itr2); goto lblContinue; } } } } } //If the word was found in a cache, we skip over to lblContinue; however, we //would then be skipping over some variable declarations in the current //scope. This is banned by C++ syntax, so we wrap the following code in //another block. { Coord const endLocation(wsArray.getWidth(), wsArray.getHeight()); Coord location(startLocation); //Find the next occurrence of the character you're searching for. while ((location = searchForLetter(wsArray, str[0], location)) != endLocation) { //Cache this position (if relevant). if (isCached) cacheList[str[0]].push_back(location); //Contains the list of all possible directions the word can have //at the given coordinates; see wsSolveDoc.h for more information. std::vector<Direction> possibleDirList; findWordAt(wsArray, str, location, possibleDirList); for (std::vector<Direction>::iterator itr2 = possibleDirList.begin(); itr2 != possibleDirList.end(); ++itr2) { if (!areAllOccupiedBySuperstring(occupied, str, location, *itr2)) { //You found the word! matchMap[str] = LocationData(location, *itr2); setOccupied(occupied, str, location, *itr2); //You're done with this loop; you then enter the next loop //(i.e., you search for the next string.) goto lblContinue; } } //Increase the location's position by 1; if it goes past the end of //the row, go down another row. if (location.pX < wsArray.getWidth()) ++location.pX; else { if (location.pY < wsArray.getHeight()) { //This code executes if you're on the last position on the //last row; in that case, you're done. ++location.pY; location.pX = 0; } else break; } } } lblContinue: continue; } }
bool is_legal_move(vector<int> start, vector<int> end, const unordered_map< string, string > *board) { int x1 = start[0], y1= start[1]; // 'start' coordinates int x2 = end[0], y2 = end[1]; // 'end' coordinates int devX = (x2 - x1 >= 0)? x2-x1: x1-x2; //absolute column deviation int devY = (y2 - y1 >= 0)? y2-y1: y1-y2; //absolute row deviation bool start_in_range = (x1 >= 1) && (x1 <= 8) && (y1 >= 1) && (y1 <= 8); // is valid starting point bool end_in_range = (x2 >= 1) && (x2 <= 8) && (y2 >= 1) && (y2 <= 8); // is valid ending point if (!(start_in_range && end_in_range)) // position(s) are off the board! return false; char colour = piece_at(board, start)[0]; char piece = piece_at(board, start)[1]; vector<int> intermediate; if (piece_at(board, end)[0] != colour){ //ending point is not already occupied by you if (piece == 'P'){ //PAWN int sign = (colour == 'W')? 1: -1; if( !occupied(board,end) && y2 == y1 + sign && devX == 0){ //standard jump return true; } else if (colour == 'W' && y1 == 2 && y2 == 4 && devX == 0){ //if white's first move, double jump allowed vector<int> intermediate {x1,3}; //intermediate position if (!occupied(board, end) && !occupied(board,intermediate)) return true; } else if (colour == 'B' && y1 == 7 && y2 == 5 && devX == 0){ //if black's first move, double jump allowed vector<int> intermediate {x1,6}; //intermediate position if (!occupied(board, end) && !occupied(board,intermediate)) return true; } else if (occupied(board,end) && y2 == y1 + sign && devX == 1) //pawn makes a kill return true; } else if (piece == 'R' || piece == 'Q'){ //ROOK/QUEEN int sign; if (devY == 0) //no row deviation; moves along row sign = (x2 - x1) > 0? 1: -1; int j; for(j = 1; j < devX; ++j) { vector<int> intermediate {x1 + sign*j, y1}; //jth intermediate space if (occupied(board, intermediate)) return false; } return true; if (devX == 0) //no column deviation; moves along column sign = (y2 - y1) > 0? 1: -1; int i; for(i = 1; i < devY; ++i) { vector<int> intermediate {x1,y1 + sign*i}; //jth intermediate space if (occupied(board, intermediate)) return false; } return true; } else if (piece == 'N'){ //KNIGHT if ( (devY == 2 && devX == 1) || (devY == 1 && devX == 2)) return true; } else if (piece == 'B' || piece == 'Q'){ //BISHOP/QUEEN if (devX == devY) {//absolute row deviation = absolute column deviation int y_sign = (y2 - y1) > 0? 1: -1; int x_sign = (x2 - x1) > 0? 1: -1; int k; for (k=1; k < devX; ++k){ vector<int> intermediate {x1 + (x_sign)*k,y1 + (y_sign)*k}; //kth intermediate space if (occupied(board,intermediate)) return false; } return true; } } else if (piece == 'K'){ //KING if ( devX <= 1 && devY <= 1) //ensures that 'end' is only one move away from 'start' return true; } return false; } else return false; }