package generator;
import java.util.Random;
import engine.Board;
/**
* Class is used to generate a outline of the board.
*/
public final class OutlineGenerator {
/**
* Generates a outline of the board.
*
* @param width - width of the board
* @param height - height of the board
* @param pbbSolid - probability of insertion of solid
* @param pbbIce - probability of insertion of ice
* @param pbbLava - probability of insertion of lava
* @param pbbElevator - probability of insertion of elevator
* @param pbbSolidConcrete - probability of insertion of a solid_concrete
* @return new outline of the board
*/
public static Board generateOutline(
int width, int height,
double pbbSolid, double pbbIce, double pbbLava, double pbbElevator,
double pbbPainter, double pbbSolidConcrete) {
assert (pbbSolid>=0 && pbbSolid<=1 && pbbIce>=0 && pbbIce<=1 &&
pbbElevator>=0 && pbbElevator<=1 && pbbLava>=0 && pbbLava<=1 &&
pbbSolidConcrete>=0 && pbbSolidConcrete<=1);
Board board = new Board(width,height);
Random rand = new Random();
if (width < 1 || height < 1) return board;
int[] types = new int[] {Board.SOLID, Board.CONCRETE, Board.ELEVATOR,
Board.PAINTER, Board.LAVA, Board.ICE};
double[] pbbs = new double[] {pbbSolid, pbbSolidConcrete, pbbElevator,
pbbPainter, pbbLava, pbbIce};
int[] factors = new int[] {8, 8, 1, 1, 8, 8};
for (int k = 0; k < types.length; k++) {
int[][] goodPositions = new int[width][height];
double total = getAllPositions(types[k], board, goodPositions);
double left = (int)(pbbs[k]*total+0.5);
int[] perm = MixGenerator.randomPermutation(width*height);
for (int i = 0; i < width*height; i++) {
int x = perm[i] % width;
int y = perm[i] / width;
if (goodPositions[x][y] > 0) {
double pbb = ((double)left*goodPositions[x][y]/total);
if (board.getType(x-1, y) == types[k]) pbb*=factors[k];
if (board.getType(x+1, y) == types[k]) pbb*=factors[k];
if (board.getType(x, y+1) == types[k]) pbb*=factors[k]/2;
if (rand.nextDouble() < pbb) {
if (types[k] == Board.CONCRETE) {
int color;
if (board.getType(x-1,y) == Board.CONCRETE)
color = board.getColor(x-1,y); else
if (board.getType(x+1,y) == Board.CONCRETE)
color = board.getColor(x+1,y); else
if (board.getType(x,y+1) == Board.CONCRETE)
color = board.getColor(x,y+1); else
color = rand.nextInt(Board.NUM_COLORS);
board.setElement(x,y,Board.CONCRETE,color);
} else
if (types[k] == Board.PAINTER) {
int color = rand.nextInt(Board.NUM_COLORS);
board.setElement(x, y, types[k], color);
} else
board.setElement(x,y,types[k]);
// Increment total weight
if (x > 0 && goodPositions[x-1][y] > 0) {
int inc = goodPositions[x-1][y]*(factors[k]-1);
left += pbbs[k]*inc;
total += inc;
goodPositions[x-1][y] += inc;
}
if (x < width-1 && goodPositions[x+1][y] > 0) {
int inc = goodPositions[x+1][y]*(factors[k]-1);
left += pbbs[k]*inc;
total += inc;
goodPositions[x+1][y] += inc;
}
left -= goodPositions[x][y];
}
total -= goodPositions[x][y];
goodPositions[x][y] = 0;
}
}
}
// Repairing lava
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++)
if (board.getType(i, j) == Board.LAVA) {
if (board.getType(i-1, j) != Board.LAVA)
board.setElement(i-1, j, Board.SOLID);
if (board.getType(i+1, j) != Board.LAVA)
board.setElement(i+1, j, Board.SOLID);
}
return board;
}
/*
* Finds all fields of the board, where can be inserted a element of given type.
*
* @param type - type of a element
* @param board
* @param positions - contains the coordinates of the found fields
* @return number of the fields
*/
private static int getAllPositions(int type, Board board, int[][] positions) {
int total = 0;
switch (type) {
case Board.SOLID:
for (int i = 0; i < board.width; i++)
for (int j = 0; j < board.height; j++)
positions[i][j] = 1;
return board.width * board.height;
case Board.CONCRETE:
for (int i = 0; i < board.width; i++)
for (int j = 0; j < board.height; j++)
if (board.isSolid(i, j)) {
positions[i][j] = 1; total++;
}
return total;
case Board.ELEVATOR:
for (int i = 0; i < board.width; i++)
for (int j = 0; j < board.height; j++)
if (board.isEmpty(i, j) && board.isSolid(i, j+1) && !board.isSolid(i, j-1)) {
positions[i][j] = 1; total++;
}
return total;
case Board.PAINTER:
for (int i = 0; i < board.width; i++)
for (int j = 0; j < board.height; j++)
if (board.isEmpty(i, j) && board.isSolid(i, j+1) && !board.isSolid(i, j-1)) {
positions[i][j] = 1; total++;
}
return total;
case Board.LAVA:
for (int i = 0; i < board.width; i++)
for (int j = 0; j < board.height; j++)
if (board.isEmpty(i, j) && board.isSolid(i, j+1) && !board.isSolid(i, j-1)
&& (board.getType(i-1, j) == Board.EMPTY || board.getType(i-1, j) == Board.SOLID)
&& (board.getType(i+1, j) == Board.EMPTY || board.getType(i+1, j) == Board.SOLID)) {
positions[i][j] = 1; total++;
}
return total;
case Board.ICE:
for (int i = 0; i < board.width; i++)
for (int j = 0; j < board.height; j++)
if (board.isEmpty(i, j) &&
!(board.getType(i-1, j) == Board.LAVA) &&
!(board.getType(i+1, j) == Board.LAVA) &&
!(board.getType(i, j-1) == Board.LAVA) &&
!(board.getType(i, j+1) == Board.LAVA)) {
positions[i][j] = 1; total++;
}
return total;
}
assert false;
return 0;
}
}