public void AddHop(int x, int y, int victimX, int victimY, Piece.Type victimType) { // for (int i = 0; i < hops.Count; i++) // if (hops[i].victimX == victimX && hops[i].victimY == victimY) // throw new Exception("Cant jump same piece twice!"); hops.Add(new Hop{targetX = x, targetY = y,victimX = victimX, victimY = victimY, victimType = victimType}); numTaken++; }
public override ulong Apply(Board b, ulong hash = 0) { #if CHECK_APPLY_UNDO for (int q = 0; q < 10; q++) for (int j = 0; j < 10; j++) if (b.pieces[q,j] != null) pieces2[q,j] = new Piece(q,j,b.pieces[q,j].color, b.pieces[q,j].type); #endif typePriorToApply = b.pieces [x, y].type; int len = hops.Count; // remove origin hash ^= AI.zobristPieceMask[b.pieces[x, y].squareNumIndex, b.pieces [x, y].HashCode]; // update origin and destination // required to do in steps for the case when begin == end Color c = b.pieces [x, y].color; b.pieces [x, y].color = Color.None; // dont care what the type is if it in not occupied b.pieces [hops [len - 1].targetX, hops [len - 1].targetY].color = c; b.pieces [hops [len - 1].targetX, hops [len - 1].targetY].type = typePriorToApply; // Promotion: if (hops [len - 1].targetY == (c == Color.White ? 9 : 0)) b.pieces [hops [len - 1].targetX, hops [len - 1].targetY].type = Piece.Type.Dam; // add destination hash ^= AI.zobristPieceMask[b.pieces[hops [len - 1].targetX, hops [len - 1].targetY].squareNumIndex, b.pieces [hops [len - 1].targetX, hops [len - 1].targetY].HashCode]; // remove victims for (int i = 0; i < len; i++) { #if DEBUG if (b.pieces [hops [i].victimX, hops [i].victimY].color == Color.None) throw new Exception(); #endif hash ^= AI.zobristPieceMask[b.pieces[hops [i].victimX, hops [i].victimY].squareNumIndex, b.pieces [hops [i].victimX, hops [i].victimY].HashCode]; b.pieces [hops [i].victimX, hops [i].victimY].color = Color.None; } #if CHECK_APPLY_UNDO for (int q = 0; q < 10; q++) for (int j = 0; j < 10; j++) if (b.pieces[q,j] != null) pieces4[q,j] = new Piece(q, j, b.pieces[q,j].color, b.pieces[q,j].type); #endif return hash; }
public void SetupTestBoard1() { for (int i = 0; i < 40; i += 2) { pieces[i%10 + ((i/10)%2 != 0 ? 1 : 0), i/10] = new Piece(i%10 + ((i/10)%2 != 0 ? 1 : 0), i/10, Color.White, Piece.Type.Normal); pieces[i%10 + ((i/10)%2 != 0 ? 1 : 0), i/10 + 6] = new Piece(i%10 + ((i/10)%2 != 0 ? 1 : 0), i/10 + 6, Color.Black, Piece.Type.Normal); //pieces[9 - (i%10), 9 - i/10] = new Piece(Color.Black, Piece.Type.Normal); } for (int i = 0; i < 20; i += 2) { pieces [i % 10 + ((i / 10) % 2 != 0 ? 1 : 0), i / 10 + 4] = new Piece (i % 10 + ((i / 10) % 2 != 0 ? 1 : 0), i / 10 + 4, Color.None, Piece.Type.Normal); } pieces [0, 4].color = Color.White; pieces [2, 4].color = Color.White; pieces [3, 7].color = Color.None; }
public Board () { for (int i = 0; i < 20; i++) { pieces[squareIndexToX(49 - i), squareIndexToY(49 - i)] = new Piece(squareIndexToX(49 - i), squareIndexToY(49 - i), Color.White, Piece.Type.Normal); pieces[squareIndexToX(i), squareIndexToY(i)] = new Piece(squareIndexToX(i), squareIndexToY(i), Color.Black, Piece.Type.Normal); //pieces[9 - (i%10), 9 - i/10] = new Piece(Color.Black, Piece.Type.Normal); } for (int i = 0; i < 20; i += 2) { pieces [i % 10 + ((i / 10) % 2 != 0 ? 1 : 0), i / 10 + 4] = new Piece (i % 10 + ((i / 10) % 2 != 0 ? 1 : 0), i / 10 + 4, Color.None, Piece.Type.Normal); } for (int i = 0; i < 50; i++) { pieces1D [i] = pieces [squareIndexToX(i), squareIndexToY (i)]; pieces1D[i].squareNumIndex = i; } currentColor = Color.White; }
private float MiniMax(int depth, bool maximizing, bool isRootNode, float alpha, float beta, ulong hash) { if (this.stop) return (maximizing ? float.PositiveInfinity : float.NegativeInfinity); // #if USE_HASHES int hashIndex = (int)(hash % ((ulong)HASH_TABLE_SIZE)); if (depth <= 0) return b.RateBoard(); int bestBet = 0; List<Move> moves; if (hashCollection [hashIndex].hash == hash) { moves = b.GetAllAllowedMoves(hashCollection [hashIndex].numTaken); bestBet = hashCollection [hashIndex].bestMoveIndex; } else moves = b.GetAllAllowedMoves(); // #if USE_HASHES int length = moves.Count; if (length == 0) return b.RateBoard(); hash ^= AI.zobristColorMask; // invert for recursed calls // #endif float bestScore = (maximizing? float.NegativeInfinity : float.PositiveInfinity); int bestIndex = 0; Color c = b.currentColor; // no need to think if there's only one option if (isRootNode && length == 1) return 0; // import to do AFTER one-move checking b.currentColor = (b.currentColor == Color.Black ? Color.White : Color.Black); int i = bestBet; do { Move m = moves[i]; ulong newHash = m.Apply(b, hash); #if CHECK_APPLY_UNDO Piece[,] pieces2 = new Piece[10,10]; for (int q = 0; q < 10; q++) for (int j = 0; j < 10; j++) if (pieces[q,j] != null) pieces2[q,j] = new Piece(pieces[q,j].color, pieces[q,j].type); #endif m.score = MiniMax(depth - 1, !maximizing, false, alpha, beta, newHash); #if CHECK_APPLY_UNDO for (int q = 0; q < 10; q++) for (int j = 0; j < 10; j++) if (pieces [q, j] != null) if (pieces2 [q, j].color != pieces [q, j].color || (pieces2 [q, j].color != Color.None && pieces [q, j].type != pieces2 [q, j].type)) { PrintBoard(); int qewqwe = 5; } #endif if (maximizing && m.score > alpha) alpha = m.score; else if (!maximizing && m.score < beta) beta = m.score; if ((maximizing && m.score > bestScore) || (!maximizing && m.score < bestScore)) { bestScore = m.score; bestIndex = i; } m.Undo(b, hash); if (beta <= alpha) break; i++; if (i == length) i = 0; } while (i != bestBet); b.currentColor = c; #if USE_HASHES if (bestIndex != 0/* && hashCollection [hashIndex].hash == 0*/) { hashCollection [hashIndex].bestMoveIndex = bestIndex; hashCollection [hashIndex].numTaken = (char)moves[bestIndex].numTaken; if (bestIndex >= length) throw new Exception("can not add items that do not exist!"); hashCollection [hashIndex].hash = hash ^ AI.zobristColorMask; // #if DEBUG // b.hashCollection[hashIndex].perfectHash = b.PerfectHash(); // #endif } #endif tempBestMoveIndex = bestIndex; return bestScore; }
/// <summary> /// Undo the move /// </summary> /// <param name="b">the board.</param> /// <param name="hash">Hash.</param> public override void Undo(Board b, ulong hash = 0) { #if CHECK_APPLY_UNDO Piece[,] pieces3 = new Piece[10,10]; for (int q = 0; q < 10; q++) for (int j = 0; j < 10; j++) if (b.pieces[q,j] != null) pieces3[q,j] = new Piece(q, j, b.pieces[q,j].color, b.pieces[q,j].type); for (int q = 0; q < 10; q++) for (int j = 0; j < 10; j++) if (b.pieces [q, j] != null) if (pieces4 [q, j].color != b.pieces [q, j].color || (pieces4 [q, j].color != Color.None && b.pieces [q, j].type != pieces4 [q, j].type)) { b.PrintBoard(); int qewqwe = 5; } #endif int len = hops.Count; // required to do in steps for the case when begin == end Color c = b.pieces [hops [len - 1].targetX, hops [len - 1].targetY].color; b.pieces [hops [len - 1].targetX, hops [len - 1].targetY].color = Color.None; b.pieces [x, y].color = c; b.pieces [x, y].type = typePriorToApply; Color victimColor = (c == Color.Black ? Color.White : Color.Black); for (int i = 0; i < len; i++) { b.pieces [hops [i].victimX, hops [i].victimY].color = victimColor; b.pieces [hops [i].victimX, hops [i].victimY].type = hops[i].victimType; } #if CHECK_APPLY_UNDO for (int q = 0; q < 10; q++) for (int j = 0; j < 10; j++) if (b.pieces [q, j] != null) if (pieces2 [q, j].color != b.pieces [q, j].color || (pieces2 [q, j].color != Color.None && b.pieces [q, j].type != pieces2 [q, j].type)) { b.PrintBoard(); int qewqwe = 5; } #endif }