158 lines
4.6 KiB
Java
158 lines
4.6 KiB
Java
package uulm.teamname.marvelous.gamelibrary.ai;
|
|
|
|
import uulm.teamname.marvelous.gamelibrary.entities.EntityID;
|
|
import uulm.teamname.marvelous.gamelibrary.entities.EntityType;
|
|
import uulm.teamname.marvelous.gamelibrary.gamelogic.GameStateView;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
|
|
class BoardAnalyzer {
|
|
private final Board origin;
|
|
private final EntityType player;
|
|
private final HashMap<Integer, Float> scoreCache = new HashMap<>();
|
|
private final HashMap<Integer, ArrayList<Action>> actionCache = new HashMap<>();
|
|
private Action bestAction = null;
|
|
|
|
public BoardAnalyzer(GameStateView state, EntityID turn) {
|
|
this.origin = Board.generate(state, turn);
|
|
this.player = turn.type;
|
|
}
|
|
|
|
public Action analyze(GameStateView state) {
|
|
Node tree = new Node(origin, new Action(ActionType.None));
|
|
|
|
int maxDepth = 2;
|
|
int depth = 0;
|
|
long startTime = System.nanoTime();
|
|
while(System.nanoTime() - startTime <= 1000 * 1000 * 1000) {
|
|
expandTree(tree, state);
|
|
depth++;
|
|
if(depth > maxDepth) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
alphaBetaMax(tree, Float.MIN_VALUE, Float.MAX_VALUE, true);
|
|
|
|
if(bestAction != null) {
|
|
return bestAction;
|
|
}
|
|
|
|
return new Action(ActionType.None);
|
|
}
|
|
|
|
private Float alphaBetaMax(Node root, Float a, Float b, boolean main) {
|
|
if(!root.hasChildren()) {
|
|
return calculateScore(root.board);
|
|
}
|
|
Float w = a;
|
|
for(Node child: root.getChildren()) {
|
|
Float v;
|
|
if(child.board.turn.type == child.board.origin) {
|
|
v = alphaBetaMax(child, a, w, false);
|
|
}else {
|
|
v = alphaBetaMin(child, w, b);
|
|
}
|
|
if(v > w) {
|
|
w = v;
|
|
}
|
|
if(w >= b) {
|
|
if(main) {
|
|
bestAction = child.action;
|
|
}
|
|
return w;
|
|
}
|
|
if(main) {
|
|
bestAction = child.action;
|
|
}
|
|
}
|
|
return w;
|
|
}
|
|
|
|
private Float alphaBetaMin(Node root, Float a, Float b) {
|
|
if(!root.hasChildren()) {
|
|
return calculateScore(root.board);
|
|
}
|
|
Float w = b;
|
|
for(Node child: root.getChildren()) {
|
|
Float v;
|
|
if(child.board.turn.type == child.board.origin) {
|
|
v = alphaBetaMax(child, a, w, false);
|
|
}else {
|
|
v = alphaBetaMin(child, w, b);
|
|
}
|
|
if(v < w) {
|
|
w = v;
|
|
}
|
|
if(w <= a) {
|
|
return w;
|
|
}
|
|
}
|
|
return w;
|
|
}
|
|
|
|
private ArrayList<Node> getLeaves(Node root) {
|
|
return getLeaves(root, new ArrayList<>());
|
|
}
|
|
|
|
private ArrayList<Node> getLeaves(Node root, ArrayList<Node> accumulator) {
|
|
for(Node child: root.getChildren()) {
|
|
if(child.hasChildren()) {
|
|
getLeaves(child, accumulator);
|
|
}else {
|
|
accumulator.add(child);
|
|
}
|
|
}
|
|
return accumulator;
|
|
}
|
|
|
|
private void expandTree(Node root, GameStateView state) {
|
|
if(!root.hasChildren()) {
|
|
expandNode(root, state);
|
|
return;
|
|
}
|
|
for(Node child: root.getChildren()) {
|
|
if(child.board.ended) {
|
|
continue;
|
|
}
|
|
if(child.hasChildren()) {
|
|
expandTree(child, state);
|
|
}else {
|
|
expandNode(child, state);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void expandNode(Node origin, GameStateView state) {
|
|
ArrayList<Action> actions = generateActions(origin.board, state);
|
|
for(Action action: actions) {
|
|
Board result = origin.board.applyAction(state, action);
|
|
scoreCache.put(result.hashCode(), result.calculateScore());
|
|
origin.addChild(result, action, result.calculateScore());
|
|
}
|
|
}
|
|
|
|
private ArrayList<Action> generateActions(Board board, GameStateView state) {
|
|
int hash = board.hashCode();
|
|
if(actionCache.containsKey(hash)) {
|
|
return actionCache.get(hash);
|
|
}else {
|
|
ArrayList<Action> result = board.generateActions(state);
|
|
actionCache.put(hash, result);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
private Float calculateScore(Board board) {
|
|
int hash = board.hashCode();
|
|
if(scoreCache.containsKey(hash)) {
|
|
return scoreCache.get(hash);
|
|
}else {
|
|
Float result = board.calculateScore();
|
|
scoreCache.put(hash, result);
|
|
return result;
|
|
}
|
|
}
|
|
}
|