public bool PlaceShape(Dungeon room_to_be_placed,bool force_connection,bool force_cardinal_direction_connection,bool allow_room_placement_under_features,params CellType[] allowed_to_overwrite) { int first_row = H+1; int first_col = W+1; //todo: this doesn't respect the map boundaries yet - it can overwrite the edge walls with the room. int last_row = -1; int last_col = -1; for(int i=0;i<room_to_be_placed.H;++i){ for(int j=0;j<room_to_be_placed.W;++j){ if(!room_to_be_placed[i,j].IsWall()){ if(i < first_row){ first_row = i; } if(i > last_row){ last_row = i; } if(j < first_col){ first_col = j; } if(j > last_col){ last_col = j; } } } } Dungeon room = new Dungeon((last_row - first_row) + 1,(last_col - first_col) + 1); int rh = room.H; int rw = room.W; //'force connection' means that the added room must connect somehow to the existing passable tiles of the map. for(int i=0;i<rh;++i){ for(int j=0;j<rw;++j){ room[i,j] = room_to_be_placed[i+first_row,j+first_col]; } } List<pos> positions = map.AllPositions().Where(x=>x.row < H-rh && x.col < W-rw).Randomize(); //'allow room placement under features' means, if the room has a floor and the map has a feature in the same location, that won't disqualify placement - instead, if the room passes, the feature will appear instead of the floor. Dungeon connected = new Dungeon(rh,rw); for(int num=0;num<positions.Count;++num){ pos p = positions[num]; bool bad_connection = force_connection; for(int i=0;i<rh;++i){ for(int j=0;j<rw;++j){ if(room[i,j].IsPassable()){ foreach(pos neighbor in new pos(i,j).PositionsWithinDistance(1)){ pos neighbor_offset = new pos(p.row + neighbor.row,p.col + neighbor.col); if(!force_cardinal_direction_connection){ //if this bool is set, check later. if(map.BoundsCheck(neighbor_offset) && map[neighbor_offset].IsPassable()){ bad_connection = false; } } if(connected.BoundsCheck(neighbor)){ connected[neighbor] = map[neighbor_offset]; } } if(force_cardinal_direction_connection){ foreach(pos neighbor in new pos(i,j).CardinalAdjacentPositions()){ if(connected.BoundsCheck(neighbor) && map[p.row+neighbor.row,p.col+neighbor.col].IsPassable()){ bad_connection = false; } } } } } } if(!bad_connection && connected.IsFullyConnected()){ bool valid = true; for(int i=0;i<rh && valid;++i){ for(int j=0;j<rw && valid;++j){ if(room[i,j] != CellType.Wall){ bool this_position_valid = false; if(map[p.row+i,p.col+j].IsWall()){ this_position_valid = true; } if(map[p.row+i,p.col+j].Is(allowed_to_overwrite)){ this_position_valid = true; } if(map[p.row+i,p.col+j] == room[i,j]){ this_position_valid = true; } if(map[p.row+i,p.col+j].IsFloor() && room[i,j].IsFloor()){ this_position_valid = true; } if(room[i,j].IsFloor() && allow_room_placement_under_features){ this_position_valid = true; } if(!this_position_valid){ valid = false; } } } } if(valid){ for(int i=0;i<rh;++i){ for(int j=0;j<rw;++j){ if(room[i,j] != CellType.Wall){ if(map[p.row+i,p.col+j].IsWall() || map[p.row+i,p.col+j].Is(allowed_to_overwrite)){ map[p.row+i,p.col+j] = room[i,j]; } } } } return true; } } } return false; }