org/homelinux/largo/schach/KIBoard.java
changeset 0 e0dbaef72362
child 3 673c7ef3411e
equal deleted inserted replaced
-1:000000000000 0:e0dbaef72362
       
     1 /**
       
     2  *   $Id: KIBoard.java 139 2008-04-25 05:02:55Z mbroeker $
       
     3  *  $URL: http://localhost/svn/eclipse/Schachspiel/trunk/org/homelinux/largo/schach/KIBoard.java $
       
     4  */
       
     5 
       
     6 package org.homelinux.largo.schach;
       
     7 
       
     8 import org.homelinux.largo.games.board.Move;
       
     9 import org.homelinux.largo.games.board.chessboard.ChessBoard;
       
    10 
       
    11 public class KIBoard extends ChessBoard {
       
    12 	static final long serialVersionUID = 200208;
       
    13 	static final int game_const = 500;
       
    14 
       
    15 	protected boolean SIMU_DEBUG  = false;
       
    16 	private boolean negate_estimation = false;
       
    17 
       
    18 	private Move bestMove;
       
    19 	private int desired_depth;
       
    20 
       
    21 	public KIBoard(int w, int h) {
       
    22 		super(w, h);
       
    23 		desired_depth = -1;
       
    24 	}
       
    25 
       
    26 	/**
       
    27 	 * Set the current DEBUG-Level:
       
    28 	 * simu: print all valid, simulated moves
       
    29 	 * undo: print all undos
       
    30 	 */
       
    31 	public void setDebug(boolean simu, boolean undo) {
       
    32 		SIMU_DEBUG = simu;
       
    33 		UNDO_DEBUG = undo;
       
    34 	}
       
    35 
       
    36 	public boolean simu_debug() {
       
    37 		return SIMU_DEBUG;
       
    38 	}
       
    39 
       
    40 	public boolean undo_debug() {
       
    41 		return UNDO_DEBUG;
       
    42 	}
       
    43 
       
    44 	/**
       
    45 	 * This function flips the sides: Player A maximizes and Player B minimizes
       
    46 	 */
       
    47 	public void negateEstimation(boolean b) {
       
    48 		negate_estimation = b;
       
    49 	}
       
    50 
       
    51 	/**
       
    52 	 * The Minimax-Algorithm works for TWO-PLAYER Games
       
    53 	 * Player A minimizes, Player B maximizes
       
    54 	 */
       
    55 	public int estimateFunction() {
       
    56 		int i;
       
    57 		int white = 0;
       
    58 		int black = 0;
       
    59 
       
    60 		for(i=0;i<64;i++) {
       
    61 			if (isWhite(i))
       
    62 				white+=getValue(i);
       
    63 			if (isBlack(i))
       
    64 				black+=getValue(i);
       
    65 		}
       
    66 
       
    67 		white+=controls("white");
       
    68 		black+=controls("black");
       
    69 
       
    70 		/**
       
    71 		 * solves ticket #3
       
    72 		 */
       
    73 		if ( negate_estimation )
       
    74 			return white-black;
       
    75 
       
    76 		return black-white;
       
    77 	}
       
    78 
       
    79 	/**
       
    80 	 * simulates and returns the next possible move for a Player or null, when no more moves are possible.
       
    81 	 * The Turn is flipped automatically if "simulate(...)" will find a valid move.
       
    82 	 */
       
    83 	Move simulate(int t, int o) {
       
    84 		Move move = null;
       
    85 		int value;
       
    86 
       
    87 		if ( validTurn(o) ) {
       
    88 			while ( t < 64 ) {
       
    89 				if (!simulateMove(t, o) ) {
       
    90 					t++;
       
    91 					continue;
       
    92 				}
       
    93 
       
    94 				value = estimateFunction();
       
    95 				if(SIMU_DEBUG)
       
    96 					print("SIMU", t, o, value);
       
    97 
       
    98 				move = new Move(value, t, o);
       
    99 
       
   100 				/* Flip Sides */
       
   101 				setBlacksTurn(!isBlacksTurn());
       
   102 				return move;
       
   103 			}
       
   104 		}
       
   105 		return null;
       
   106 	}
       
   107 
       
   108 	/**
       
   109 	 * AlphaBeta-Algorithm: the Maximizer
       
   110 	 */
       
   111 	int max_alpha_beta (int depth, int alpha, int beta) {
       
   112 		int moveValue;
       
   113 		int o, t;
       
   114 		Move move = null;
       
   115 
       
   116 		if ( desired_depth == -1 )
       
   117 			desired_depth = depth;
       
   118 
       
   119 		for (o = 0; o < 64; o++) {
       
   120 			t=0;
       
   121 			while ( (move=simulate(t, o)) != null ) {
       
   122 				/* particular move from black */
       
   123 				t = move.target;
       
   124 
       
   125 				if ( depth == 0 || Math.abs(move.value) > game_const )
       
   126 					moveValue = move.value;
       
   127 				else /* best next move */
       
   128 					moveValue = min_alpha_beta(depth-1, alpha, beta);
       
   129 
       
   130 				undo();
       
   131 				t++;
       
   132 
       
   133 				if ( moveValue >= beta )
       
   134 					return beta;
       
   135 
       
   136 				if ( moveValue > alpha ) {
       
   137 					alpha = moveValue;
       
   138 					if ( depth == desired_depth )
       
   139 						bestMove = move;
       
   140 				}
       
   141 			}
       
   142 		}
       
   143 
       
   144 		return alpha;
       
   145 	}
       
   146 
       
   147 	/**
       
   148 	 * AlphaBeta-Algorithm: the Minimizer
       
   149 	 */
       
   150 	int min_alpha_beta(int depth, int alpha, int beta) {
       
   151 		int moveValue;
       
   152 		int o, t;
       
   153 		Move move = null;
       
   154 
       
   155 		for (o = 0; o < 64; o++) {
       
   156 			t=0;
       
   157 			while ( (move=simulate(t, o)) != null ) {
       
   158 				/* particular move from white */
       
   159 				t = move.target;
       
   160 
       
   161 				if ( depth == 0 || Math.abs(move.value) > game_const )
       
   162 					moveValue = move.value;
       
   163 				else /* best next move */
       
   164 					moveValue = max_alpha_beta(depth-1, alpha, beta);
       
   165 
       
   166 				undo();
       
   167 				t++;
       
   168 
       
   169 				if ( moveValue <= alpha )
       
   170 					return alpha;
       
   171 
       
   172 				if ( moveValue < beta )
       
   173 					beta = moveValue;
       
   174 			}
       
   175 		}
       
   176 
       
   177 		return beta;
       
   178 	}
       
   179 
       
   180 	/**
       
   181 	 * Evaluates the next, best Move after search_depth half-moves.
       
   182 	 * When the Machine has Black, set negateEstimation(false);
       
   183 	 * When the Machine has White, set negateEstimation(true);
       
   184 	 */
       
   185 	public boolean doBestMove(int search_depth) {
       
   186 		int value;
       
   187 
       
   188 		desired_depth = -1;
       
   189 		bestMove = null;
       
   190 		value = max_alpha_beta(search_depth, Integer.MIN_VALUE, Integer.MAX_VALUE);
       
   191 
       
   192 		if ( bestMove == null ) {
       
   193 			System.err.println("Computing once more...");
       
   194 			value = max_alpha_beta(1, Integer.MIN_VALUE, Integer.MAX_VALUE);
       
   195 			if (bestMove == null) {
       
   196 				System.out.println("Check Mate");
       
   197 				return false;
       
   198 			}
       
   199 		}
       
   200 
       
   201 		if (doMove(bestMove.target, bestMove.origin)) {
       
   202 			print(getColor(bestMove.target), bestMove.target, bestMove.origin, bestMove.value);
       
   203 			return true;
       
   204 		}
       
   205 
       
   206 		print("Check Mate", bestMove.target, bestMove.origin, bestMove.value);
       
   207 		return false;
       
   208 	}
       
   209 }