package search.game; import java.util.*; public abstract class GameSearch { public static final boolean DEBUG = false; /* * Note: the abstract Position also needs to be * subclassed to write a new game program. */ /* * Note: the abstract class Move also needs to be subclassed. * */ public static boolean PROGRAM = false; public static boolean HUMAN = true; /** * Notes: PROGRAM false -1, HUMAN true 1 */ /* * Abstract methods: */ public abstract boolean drawnPosition(Position p); public abstract boolean wonPosition(Position p, boolean player); public abstract float positionEvaluation(Position p, boolean player); public abstract void printPosition(Position p); public abstract Position [] possibleMoves(Position p, boolean player); public abstract Position makeMove(Position p, boolean player, Move move); public abstract boolean reachedMaxDepth(Position p, int depth); public abstract Move createMove(); /* * Search utility methods: */ protected Vector alphaBeta(int depth, Position p, boolean player) { Vector v = alphaBetaHelper(depth, p, player, 1000000.0f, -1000000.0f); //System.out.println("^^ v(0): " + v.elementAt(0) + ", v(1): " + v.elementAt(1)); return v; } protected Vector alphaBetaHelper(int depth, Position p, boolean player, float alpha, float beta) { if (GameSearch.DEBUG) System.out.println("alphaBetaHelper("+depth+","+p+","+alpha+","+beta+")"); if (reachedMaxDepth(p, depth)) { Vector v = new Vector(2); float value = positionEvaluation(p, player); v.addElement(new Float(value)); v.addElement(null); if(GameSearch.DEBUG) { System.out.println(" alphaBetaHelper: mx depth at " + depth+ ", value="+value); } return v; } Vector best = new Vector(); Position [] moves = possibleMoves(p, player); for (int i=0; i<moves.length; i++) { Vector v2 = alphaBetaHelper(depth + 1, moves[i], !player, -beta, -alpha); // if (v2 == null || v2.size() < 1) continue; float value = -((Float)v2.elementAt(0)).floatValue(); if (value > beta) { if(GameSearch.DEBUG) System.out.println(" ! ! ! value="+value+", beta="+beta); beta = value; best = new Vector(); best.addElement(moves[i]); Enumeration enum2 = v2.elements(); enum2.nextElement(); // skip previous value while (enum2.hasMoreElements()) { Object o = enum2.nextElement(); if (o != null) best.addElement(o); } } /** * Use the alpha-beta cutoff test to abort search if we * found a move that proves that the previous move in the * move chain was dubious */ if (beta >= alpha) { break; } } Vector v3 = new Vector(); v3.addElement(new Float(beta)); Enumeration enum2 = best.elements(); while (enum2.hasMoreElements()) { v3.addElement(enum2.nextElement()); } return v3; } public void playGame(Position startingPosition, boolean humanPlayFirst) { if (humanPlayFirst == false) { Vector v = alphaBeta(0, startingPosition, PROGRAM); startingPosition = (Position)v.elementAt(1); } while (true) { printPosition(startingPosition); if (wonPosition(startingPosition, PROGRAM)) { System.out.println("Program won"); break; } if (wonPosition(startingPosition, HUMAN)) { System.out.println("Human won"); break; } if (drawnPosition(startingPosition)) { System.out.println("Drawn game"); break; } System.out.println("Your move:"); Move move = createMove(); startingPosition = makeMove(startingPosition, HUMAN, move); printPosition(startingPosition); Vector v = alphaBeta(0, startingPosition, PROGRAM); Enumeration enum2 = v.elements(); while (enum2.hasMoreElements()) { System.out.println(" next element: " + enum2.nextElement()); } startingPosition = (Position)v.elementAt(1); } } }