in Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/ClassroomDecoratorImplementation.java [102:219]
public void buildOnWorld(MissionInit missionInit, World world) throws DecoratorException {
this.drawContext = new BlockDrawingHelper();
if(this.buildingWidth == 0){
// We are using complexity so these need to be sampled from the Gaussian
this.buildingWidth = Math.max((int)(rand.nextGaussian()*2 + this.buildingComplexity*MAX_BUILDING_SIZE + MIN_ROOM_SIZE), MIN_ROOM_SIZE);
this.buildingLength = Math.max((int)(rand.nextGaussian()*2 + this.buildingComplexity*MAX_BUILDING_SIZE + MIN_ROOM_SIZE), MIN_ROOM_SIZE);
this.buildingHeight = Math.max(Math.max(this.buildingWidth, this.buildingLength) * ROOM_HEIGHT / MIN_ROOM_SIZE, ROOM_HEIGHT);
}
// create the room grid
ArrayList<Room> rooms = this.createRooms();
// randomize the indices used to query different divisions. This has the effect of making
// the path to the goal random each time.
this.shuffleIndices();
// determine how long the path to the goal should be
if(this.pathLength == 0){
this.pathLength = (int)((1 - 0.25 * this.pathComplexity)*rooms.size()) - 1;
}else{
this.pathLength = Math.min(this.pathLength, rooms.size() - 1);
}
// find a path to the goal
ArrayList<Divider> path = new ArrayList<Divider>();
Room startRoom, goalRoom;
if(this.pathLength > 0){
for(Room room : rooms){
for(Room markRoom : rooms){
markRoom.mark = false;
}
if(findPath(path, room, this.pathLength)){
break;
}
}
if(path.size() < this.pathLength){
// error
throw new DecoratorException("Unable to find path to goal");
}
startRoom = path.get(0).getIn();
goalRoom = path.get(path.size() - 1).getOut();
for(Divider divider : path){
divider.setHint(this.rand.nextDouble() < this.hintLikelihood);
}
// create all of the obstacles along the path
createObstacles(path);
}else{
startRoom = goalRoom = rooms.get(0);
startRoom.isComplete = true;
}
// find orphan rooms
for(Room room : rooms){
if(room.isComplete){
continue;
}
for(Room markRoom : rooms){
markRoom.mark = false;
}
path.clear();
if(findPath(path, room, rooms.size())){
// reverse the directions (the algorithm finds a path from the start room
// to the end room, so we will reverse it so it goes from the completed
// portion of the building back to the orphan room.
for(Divider obstacle : path){
obstacle.reverse();
}
// create all of the obstacles along the path
createObstacles(path);
}else{
throw new DecoratorException("Unable to join orphan room to goal path");
}
}
// carve out the building
this.drawContext.beginDrawing(world);
for(int x=START_X; x<START_X + this.buildingWidth; x++){
for(int y=START_Y; y<START_Y + this.buildingHeight; y++){
for(int z=START_Z; z<START_Z + this.buildingLength; z++){
world.setBlockToAir(new BlockPos(x, y, z));
}
}
}
// this should clear all of the torches and levers left over from last time. It doesn't.
drawContext.clearEntities(world, START_X - 1, START_Y - 1, START_Z - 1, START_X + this.buildingWidth, START_Y + this.buildingHeight, START_Z + this.buildingLength);
// draw the rooms
for(Room room : rooms){
room.draw(world, this.rand, this.palette);
}
// place goal
setBlockState(world, new BlockPos(goalRoom.x+this.rand.nextInt(goalRoom.width-4) + 2, goalRoom.y, goalRoom.z + goalRoom.length - 2), this.palette.goal);
this.drawContext.endDrawing(world);
// set the agent positions
PosAndDirection p2 = new PosAndDirection();
p2.setX(new BigDecimal(startRoom.x + this.rand.nextInt(goalRoom.width-2) + 0.5));
p2.setY(new BigDecimal(1 + startRoom.y));
p2.setZ(new BigDecimal(startRoom.z + 0.5));
// TODO - for the moment, force all players to being at the maze start point - but this needs to be optional.
for (AgentSection as : missionInit.getMission().getAgentSection())
{
p2.setPitch(as.getAgentStart().getPlacement().getPitch());
p2.setYaw(as.getAgentStart().getPlacement().getYaw());
as.getAgentStart().setPlacement(p2);
}
}