- Updated the PlayerModel to fix a bug in the high score tracking. - Created HighScoreDialog.java, which displays the high scores from a PlayerModel. In the future, it will have a "New Game" button so that it can be used to transition between games.
160 lines
3.8 KiB
Java
160 lines
3.8 KiB
Java
package model.playerModel;
|
|
|
|
import java.util.Random;
|
|
|
|
import model.Board;
|
|
import model.playerModel.node.InputNode;
|
|
import model.playerModel.node.SigmoidNode;
|
|
|
|
public class PlayerModel {
|
|
|
|
public static final Random rand = new Random();
|
|
|
|
private final SigmoidNode[] hiddenLayer;
|
|
private final int[] highScore = new int[10];
|
|
|
|
private int highScoresAchieved = 0;
|
|
// One node for each tile-color combination, plus one for each upcoming
|
|
// tile-color combination.
|
|
private final InputNode[] inputNode = new InputNode[(Board.NUM_COLS
|
|
* Board.NUM_ROWS * (Board.TileColor.values().length - 1))];
|
|
|
|
private int nextHighInGames = 0;
|
|
|
|
// One node for each tile plus four for the colors to be selected.
|
|
// outputNode[0] is blue.
|
|
// outputNode[1] is green.
|
|
// outputNode[2] is red.
|
|
// outputNode[3] is yellow.
|
|
// outputNode[4] through outputNode[n] represent grid spaces. A true means
|
|
// that the player is predicted to place on that tile.
|
|
// They should be read from the top-left to bottom-right, across rows.
|
|
// Ideally, the network should return only one true between 0 and 3 and only
|
|
// one true between 4 and n, representing one color and the tile in which it
|
|
// should be placed.
|
|
private final SigmoidNode[] outputNode = new SigmoidNode[(Board.NUM_COLS * Board.NUM_ROWS) + 4];
|
|
|
|
public PlayerModel() {
|
|
for (int i = 0; i < highScore.length; i++) {
|
|
highScore[i] = -1;
|
|
}
|
|
|
|
hiddenLayer = new SigmoidNode[inputNode.length
|
|
+ ((inputNode.length * 2) / 3)];
|
|
|
|
for (int i = 0; i < inputNode.length; i++) {
|
|
inputNode[i] = new InputNode();
|
|
}
|
|
|
|
for (int i = 0; i < hiddenLayer.length; i++) {
|
|
hiddenLayer[i] = new SigmoidNode();
|
|
|
|
for (int j = 0; j < inputNode.length; j++) {
|
|
hiddenLayer[i].addNode(inputNode[j], 1);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < outputNode.length; i++) {
|
|
outputNode[i] = new SigmoidNode();
|
|
|
|
for (int j = 0; j < hiddenLayer.length; j++) {
|
|
outputNode[i].addNode(hiddenLayer[j], 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
public int[] getHighScores() {
|
|
return highScore;
|
|
}
|
|
|
|
public boolean[] getPrediction(boolean[] input) {
|
|
if (input.length == inputNode.length) {
|
|
boolean[] prediction = new boolean[outputNode.length];
|
|
|
|
for (int i = 0; i < input.length; i++) {
|
|
inputNode[i].setStimulation(input[i]);
|
|
}
|
|
|
|
for (int i = 0; i < prediction.length; i++) {
|
|
prediction[i] = outputNode[i].axon();
|
|
}
|
|
|
|
return prediction;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public GameGoal getTargetScore() {
|
|
GameGoal goal;
|
|
int targetScore;
|
|
int highScore = getHighScore();
|
|
|
|
if (highScoresAchieved == 0) {
|
|
goal = new GameGoal(0, true);
|
|
nextHighInGames = 1;
|
|
}
|
|
|
|
else if (nextHighInGames == 0) {
|
|
// Set next game for high score.
|
|
nextHighInGames = (int) (Math.pow(highScoresAchieved + 1, 2) / 2);
|
|
|
|
// Return high score times increase percentage.
|
|
targetScore = highScore / (2 * (highScoresAchieved + 1));
|
|
|
|
if (targetScore <= highScore) {
|
|
targetScore = highScore + 1;
|
|
}
|
|
|
|
goal = new GameGoal(targetScore, true);
|
|
}
|
|
|
|
else {
|
|
double scoreReduction = .1 * rand.nextDouble();
|
|
targetScore = (int) (highScore - (highScore * scoreReduction));
|
|
|
|
if (targetScore >= highScore) {
|
|
targetScore = highScore - 1;
|
|
}
|
|
|
|
goal = new GameGoal(targetScore, false);
|
|
}
|
|
|
|
return goal;
|
|
}
|
|
|
|
public void logGame(int score) {
|
|
if (highScore[0] == -1) {
|
|
highScore[0] = score;
|
|
}
|
|
|
|
else {
|
|
loop: for (int i = 0; i < highScore.length; i++) {
|
|
if (score > highScore[i]) {
|
|
for (int j = highScore.length - 2; j >= i; j--) {
|
|
highScore[j + 1] = highScore[j];
|
|
}
|
|
|
|
highScore[i] = score;
|
|
break loop;
|
|
}
|
|
}
|
|
}
|
|
|
|
highScoresAchieved += (score == highScore[0]) ? 1 : 0;
|
|
nextHighInGames--;
|
|
}
|
|
|
|
public void train(boolean[] example) {
|
|
if (example.length == outputNode.length) {
|
|
for (int i = 0; i < outputNode.length; i++) {
|
|
outputNode[i].learn(example[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
private int getHighScore() {
|
|
return highScore[0];
|
|
}
|
|
}
|