/* This file is part of Eternity II Editor.
*
* Eternity II Editor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Eternity II Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Eternity II Editor. If not, see <http://www.gnu.org/licenses/>.
*
* Eternity II Editor project is hosted on SourceForge:
* http://sourceforge.net/projects/eternityii/
* and maintained by Yannick Kirschhoffer <alcibiade@alcibiade.org>
*/
package org.alcibiade.eternity.editor.model.operation;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import org.alcibiade.eternity.editor.model.GridModel;
import org.alcibiade.eternity.editor.model.Pattern;
import org.alcibiade.eternity.editor.model.QuadModel;
import org.alcibiade.eternity.editor.solver.RandomFactory;
public class GridFiller extends GridOperation {
private Random rand;
public GridFiller(GridModel gridModel) {
super(gridModel);
rand = RandomFactory.getRandom();
}
public void fillRandom(int nbPatterns) {
assert nbPatterns > 0;
do {
Set<Pattern> patterns = selectRandomPatterns(nbPatterns);
fillBorder(patterns);
fillCenter(patterns);
} while (getModel().getPatternStats().getPatterns().size() != nbPatterns);
}
public void FillRandomAsymetric(int nbPatterns) {
assert nbPatterns > 1;
boolean valid;
do {
fillRandom(nbPatterns);
valid = true;
valid = valid && !getModel().isHSymetric();
valid = valid && !getModel().isVSymetric();
valid = valid && !getModel().isRSymetric();
} while (!valid);
}
public void FillBorderRandom(int nbPatterns) {
do {
fillBorder(selectRandomPatterns(nbPatterns, getModel().getPatternStats()
.getInnerPatterns()));
} while (getModel().getPatternStats().getOuterPatterns().size() != nbPatterns);
}
public void FillCenterRandom(int nbPatterns) {
do {
fillCenter(selectRandomPatterns(nbPatterns, getModel().getPatternStats()
.getOuterPatterns()));
} while (getModel().getPatternStats().getInnerPatterns().size() != nbPatterns);
}
public void fillBorder(Set<Pattern> patterns) {
assert !patterns.isEmpty();
Pattern defaultPattern = Pattern.getDefaultPattern();
int gridSize = getModel().getSize();
for (int y = 0; y < gridSize; y++) {
for (int x = 0; x < gridSize; x++) {
QuadModel quad = getModel().getQuad(x, y);
for (int d = 0; d < 4; d++) {
if (x == 0 && d == QuadModel.DIR_WEST) {
quad.setPattern(d, defaultPattern);
} else if (y == 0 && d == QuadModel.DIR_NORTH) {
quad.setPattern(d, defaultPattern);
} else if (x == gridSize - 1 && d == QuadModel.DIR_EAST) {
quad.setPattern(d, defaultPattern);
} else if (y == gridSize - 1 && d == QuadModel.DIR_SOUTH) {
quad.setPattern(d, defaultPattern);
}
if (x == 0 || x == gridSize - 1) {
if (d == QuadModel.DIR_NORTH) {
if (y == 0) {
quad.setPattern(d, defaultPattern);
} else {
quad.setPattern(d, getModel().getQuad(x, y - 1).getPattern(
QuadModel.DIR_SOUTH));
}
} else if (d == QuadModel.DIR_SOUTH) {
if (y < gridSize - 1) {
quad.setPattern(d, selectRandomPattern(patterns));
}
}
}
if (y == 0 || y == gridSize - 1) {
if (d == QuadModel.DIR_WEST) {
if (x == 0) {
quad.setPattern(d, defaultPattern);
} else {
quad.setPattern(d, getModel().getQuad(x - 1, y).getPattern(
QuadModel.DIR_EAST));
}
} else if (d == QuadModel.DIR_EAST) {
if (x < gridSize - 1) {
quad.setPattern(d, selectRandomPattern(patterns));
}
}
}
}
}
}
}
public void fillCenter(Set<Pattern> patterns) {
assert !patterns.isEmpty();
Pattern defaultPattern = Pattern.getDefaultPattern();
int gridSize = getModel().getSize();
for (int y = 0; y < gridSize; y++) {
for (int x = 0; x < gridSize; x++) {
QuadModel quad = getModel().getQuad(x, y);
for (int d = 0; d < 4; d++) {
if (x > 0 && x < gridSize - 1) {
if (d == QuadModel.DIR_NORTH) {
if (y == 0) {
quad.setPattern(d, defaultPattern);
} else {
quad.setPattern(d, getModel().getQuad(x, y - 1).getPattern(
QuadModel.DIR_SOUTH));
}
} else if (d == QuadModel.DIR_SOUTH) {
if (y < gridSize - 1) {
quad.setPattern(d, selectRandomPattern(patterns));
}
}
}
if (y > 0 && y < gridSize - 1) {
if (d == QuadModel.DIR_WEST) {
if (x == 0) {
quad.setPattern(d, defaultPattern);
} else {
quad.setPattern(d, getModel().getQuad(x - 1, y).getPattern(
QuadModel.DIR_EAST));
}
} else if (d == QuadModel.DIR_EAST) {
if (x < gridSize - 1) {
quad.setPattern(d, selectRandomPattern(patterns));
}
}
}
}
}
}
}
/*
* Pattern(s) selection methods
*/
private Pattern selectRandomPattern(Set<Pattern> patterns) {
int randIndex = rand.nextInt(patterns.size());
Pattern result = null;
Iterator<Pattern> itPatterns = patterns.iterator();
while (itPatterns.hasNext() && randIndex >= 0) {
Pattern pattern = itPatterns.next();
if (randIndex == 0) {
result = pattern;
}
randIndex--;
}
assert result != null;
return result;
}
private Set<Pattern> selectRandomPatterns(int nbPatterns) {
return selectRandomPatterns(nbPatterns, new HashSet<Pattern>());
}
private Set<Pattern> selectRandomPatterns(int nbPatterns, Set<Pattern> excluded) {
List<Pattern> patterns = new LinkedList<Pattern>();
patterns.addAll(Pattern.getAllPatterns());
patterns.remove(Pattern.getDefaultPattern());
patterns.removeAll(excluded);
while (patterns.size() > nbPatterns) {
int rndix = rand.nextInt(patterns.size());
patterns.remove(rndix);
}
return new HashSet<Pattern>(patterns);
}
}