static public Ply CastlingQueenSide() { Ply newPly = new Ply(); newPly.castlingQueenSide = true; return(newPly); }
static public Ply PromoteBishop(Case from, Case to) { Ply newPly = Position(from, to); newPly.promotion = new BishopPromotion(); return(newPly); }
static public Ply PromoteKnight(Case from, Case to) { Ply newPly = Position(from, to); newPly.promotion = new KnightPromotion(); return(newPly); }
static public Ply PromoteQueen(Case from, Case to) { Ply newPly = Position(from, to); newPly.promotion = new QueenPromotion(); return(newPly); }
static public Ply EatKing(uint from, uint to) { Ply newPly = Position(from, to); newPly.lastPly = true; return(newPly); }
public Ply Run() { /*Console.WriteLine("Avant : B" + board.GetMailbox().countPieceBlanche + ", N " + board.GetMailbox().countPieceNoir); * foreach(int elmt in board.GetMailbox().etatPieceBlanche) * { * Console.Write(elmt + " "); * }*/ // Syzygy end-game table Ply ply = tableReader.getBestPly(); if (ply == null) // No results { // Iterative deepening search for (uint depth = 2; watch.ElapsedMilliseconds < timingMaxMs; depth++) { Ply tempPly = NegaScout(depth, int.MinValue, int.MaxValue); if (tempPly != null) { ply = tempPly; } //Console.WriteLine("Depth: " + depth + ", time: " + watch.ElapsedMilliseconds); } } Debug.Assert(ply != null, "ply is null"); /*Console.WriteLine("Apres : B" + board.GetMailbox().countPieceBlanche + ", N " + board.GetMailbox().countPieceNoir); * foreach (int elmt in board.GetMailbox().etatPieceBlanche) * { * Console.Write(elmt + " "); * } * Console.WriteLine("Ply : " + ply);*/ return(ply); }
static public Ply PromoteRook(Case from, Case to) { Ply newPly = Position(from, to); newPly.promotion = new RookPromotion(); return(newPly); }
static public Ply EnPassant(Case from, Case to, Case capturePossible, bool captureEffective) { Ply newPly = Position(from, to); newPly.captureEnPassant = capturePossible; newPly.captureEP = captureEffective; return(newPly); }
static public Ply Position(Case from, Case to) { Ply newPly = new Ply(); newPly.from = from; newPly.to = to; return(newPly); }
private Ply genMovePromotion(int depart, int arrivee, Color c) { string dp = Mailbox.tabCoord[depart]; Case from = Case.BuildCaseMailBox(depart, dp); string arr = Mailbox.tabCoord[arrivee]; Case to = Case.BuildCaseMailBox(depart, arr); return(Ply.PromoteQueen(from, to)); }
private int RecursiveNegaScout(uint depth, Ply parentPly, int alpha, int beta) { board.Push(parentPly); int best; int score2; WDL?wdl = tableReader.getWDL(); if (wdl.HasValue) { best = evaluator.EvaluateWDL(wdl.Value); } else { best = int.MinValue; if (depth == 0) { best = evaluator.Evaluate(); } else { foreach (Ply ply in ruler.GetPossiblePlies()) { if (watch.ElapsedMilliseconds >= timingMaxMs) { break; } int score = RecursiveNegaScout(depth - 1, ply, -beta, -alpha); score2 = score; if (score > alpha && score < beta && depth > 1) { score2 = RecursiveNegaScout(depth - 1, ply, -beta, -score); } if (score >= score2) { best = score; } else { best = score2; } } } } board.Pop(); return(best); }
public void Push(Ply ply) { // Backup the current chessboard stack.Push(pos); //Copy of pos Mailbox mailbox = new Mailbox(pos); mailbox.ply(ply); switchTurn(); pos = mailbox; }
public void testPly(Ply p) { Array.Copy(piece, savePiece, 64); Array.Copy(color, saveColor, 64); Array.Copy(etatPieceBlanche, saveEtatPieceBlanche, 6); Array.Copy(etatPieceNoir, saveEtatPieceNoir, 6); saveCountW = countPieceBlanche; saveCountB = countPieceNoir; if (ep.HasValue) { saveEp = ep.Value; } else { saveEp = null; } this.ply(p); }
private int RecursiveNegaMax(uint depth, Ply parentPly) { board.Push(parentPly); int best; WDL?wdl = tableReader.getWDL(); if (wdl.HasValue) { best = evaluator.EvaluateWDL(wdl.Value); } else // We need to explore only if the end game is unknown { best = int.MinValue; if (depth == 0) { best = evaluator.Evaluate(); } else { foreach (Ply ply in ruler.GetPossiblePlies()) { if (watch.ElapsedMilliseconds >= timingMaxMs) { break; } int score = -RecursiveNegaMax(depth - 1, ply); if (score > best) { best = score; } } } } board.Pop(); return(best); }
private Ply genMove(int depart, int arrivee, int v, int enPassant) { string dp = Mailbox.tabCoord[depart]; string arr = Mailbox.tabCoord[arrivee]; Ply p = null; //Generation d'une case EN_PASSANT car double saut if (enPassant != -1) { if (v == 0) { string ep = Mailbox.tabCoord[enPassant]; p = Ply.EnPassant(Case.BuildCaseMailBox(depart, dp), Case.BuildCaseMailBox(arrivee, arr), Case.BuildCaseMailBox(enPassant, ep), false); return(p); } //On mange un pion via la case en Passant else if (v == 1 && board.GetMailbox().getColor()[arrivee] == (int)Color.PAWN_EN_PASSANT) { string ep = Mailbox.tabCoord[enPassant]; p = Ply.EnPassant(Case.BuildCaseMailBox(depart, dp), Case.BuildCaseMailBox(arrivee, arr), Case.BuildCaseMailBox(enPassant, ep), true); return(p); } } //Generation d'un mouvement normal p = Ply.Position(Case.BuildCaseMailBox(depart, dp), Case.BuildCaseMailBox(arrivee, arr)); return(p); //return Ply.Position(Case.BuildCaseMailBox(depart, dp), Case.BuildCaseMailBox(arrivee, arr)); //int valeur = evaluateBoard(LIGHT); //Console.WriteLine("Mouvement possible {2} : {0}, {1}", dp, arr, piece[i]); }
private Ply NegaMax(uint depth) { Debug.Assert(depth >= 2); Ply bestPly = null; int bestScore = int.MinValue; foreach (Ply ply in ruler.GetPossiblePlies()) { if (watch.ElapsedMilliseconds >= timingMaxMs) { break; } int score = -RecursiveNegaMax(depth - 1, ply); if (score > bestScore) { bestPly = ply; bestScore = score; } } return(bestPly); }
static public Ply PromoteRook(Ply ply) { ply.promotion = new RookPromotion(); return(ply); }
// Castling is not supported public Ply getBestPly() { if (impl is null) { return(null); } if (board.CountMen > impl.Largest) { return(null); } Bitboard bitboard = board.ToBitboard(); uint res = impl.ProbeRoot( bitboard.white, bitboard.black, bitboard.kings, bitboard.queens, bitboard.rooks, bitboard.bishops, bitboard.knights, bitboard.pawns, 0, // 50-move clock bitboard.castling, bitboard.ep, // "En passant" bitboard.turn, UIntPtr.Zero // No more results ); if (res == Fathom.TB_RESULT_FAILED) { return(null); } uint from = Fathom.GetFrom(res); uint to = Fathom.GetTo(res); uint promote = Fathom.GetPromotes(res); uint ep = Fathom.GetEP(res); Ply ply; switch (promote) { case Fathom.TB_PROMOTES_ROOK: ply = Ply.PromoteRook(from, to); break; case Fathom.TB_PROMOTES_KNIGHT: ply = Ply.PromoteKnight(from, to); break; case Fathom.TB_PROMOTES_BISHOP: ply = Ply.PromoteBishop(from, to); break; case Fathom.TB_PROMOTES_QUEEN: ply = Ply.PromoteQueen(from, to); break; default: if (ep == 0) { ply = Ply.Position(from, to); } else { ply = Ply.EnPassant(from, to, ep, false); //TODO <----- Qu'est ce qu'il se passe la ? Si capture effective mettre true, si generation d'une case EP mettre false } break; } // From here, it is just printf debugging { String status; if (res == Fathom.TB_RESULT_CHECKMATE) { status = "Checkmate"; } else if (res == Fathom.TB_RESULT_STALEMATE) { status = "Stalemate"; } else if (res == Fathom.TB_RESULT_FAILED) { status = "Failed"; } else { status = "Normal"; } uint wdl = Fathom.GetWDL(res); String wdlStr; switch (wdl) { case Fathom.TB_WIN: wdlStr = "WIN"; break; case Fathom.TB_CURSED_WIN: wdlStr = "CURSED WIN"; break; case Fathom.TB_DRAW: wdlStr = "DRAW"; break; case Fathom.TB_BLESSED_LOSS: wdlStr = "BLESSED LOSS"; break; case Fathom.TB_LOSS: wdlStr = "LOSS"; break; default: wdlStr = "N/A"; break; } uint dtz = Fathom.GetDTZ(res); Console.Out.WriteLine( "Status: " + status + "\n" + "WDL: " + wdlStr + ", DTZ: " + dtz + "\n" + "ply: " + ply.ToString() + "\n" + "ep: " + ep + "\n" ); } return(ply); }
static public Ply PromoteKnight(Ply ply) { ply.promotion = new KnightPromotion(); return(ply); }
static public Ply PromoteQueen(Ply ply) { ply.promotion = new QueenPromotion(); return(ply); }
static public Ply PromoteBishop(Ply ply) { ply.promotion = new BishopPromotion(); return(ply); }
static void Main(string[] args) { #if DEBUG Debugger.Launch(); #endif if (args.Length != 1) { Console.WriteLine("Incorrect count of arguments."); Console.WriteLine("1 required and you have specified " + args.Length); Console.WriteLine("Did you forgot to specify 'white' or 'black' in the arguments?"); Console.WriteLine("Press enter to exit"); Console.ReadKey(); return; } Color agentColor; String fileSuffix; if (args[0] == "white") { fileSuffix = "AI1"; agentColor = Color.WHITE; } else if (args[0] == "black") { fileSuffix = "AI2"; agentColor = Color.BLACK; } else { Console.WriteLine("\'" + args[0] + "\' argument is unknown."); Console.WriteLine("Please choose between 'white' or 'black'"); Console.WriteLine("Press enter to exit"); Console.ReadKey(); return; } try { Init(); bool stop = false; int[] tabVal = new int[64]; String value; while (!stop) { using (var mmf = MemoryMappedFile.OpenExisting("plateau")) { using (var mmf2 = MemoryMappedFile.OpenExisting("rep" + fileSuffix)) { Mutex mutexStartAI = Mutex.OpenExisting("mutexStart" + fileSuffix); Mutex mutexAI = Mutex.OpenExisting("mutex" + fileSuffix); mutexAI.WaitOne(); mutexStartAI.WaitOne(); watch.Restart(); using (var accessor = mmf.CreateViewAccessor()) { ushort Size = accessor.ReadUInt16(0); byte[] Buffer = new byte[Size]; accessor.ReadArray(0 + 2, Buffer, 0, Buffer.Length); value = ASCIIEncoding.ASCII.GetString(Buffer); if (value == "stop") { stop = true; } else { //Console.WriteLine(value); String[] substrings = value.Split(','); for (int i = 0; i < substrings.Length; i++) { tabVal[i] = Convert.ToInt32(substrings[i]); } } } if (!stop) { /******************************************************************************************************/ /***************************************** ECRIRE LE CODE DE L'IA *************************************/ /******************************************************************************************************/ board.ResetFromPlatformRepresentation(tabVal, agentColor); Ply ply = strategist.Run(); value = ply.ToString(); /********************************************************************************************************/ /********************************************************************************************************/ /********************************************************************************************************/ using (var accessor = mmf2.CreateViewAccessor()) { byte[] Buffer = ASCIIEncoding.ASCII.GetBytes(value); accessor.Write(0, (ushort)Buffer.Length); accessor.WriteArray(0 + 2, Buffer, 0, Buffer.Length); }; } mutexAI.ReleaseMutex(); mutexStartAI.ReleaseMutex(); watch.Stop(); Debug.Assert( watch.ElapsedMilliseconds < 250, "IA took " + watch.ElapsedMilliseconds.ToString() + " which is more than 250ms to decide" ); } } } } catch (FileNotFoundException) { Console.WriteLine("Memory-mapped file does not exist. Run Process A first."); Console.ReadLine(); } #if DEBUG Console.ReadLine(); #endif }
public void ply(Ply p) { if (p.lastPly) { endGame = true; } int?testdep = p.from.getPosMailBox(); int?testarr = p.to.getPosMailBox(); int dep = 0; int arr = 0; if (testdep.HasValue && testarr.HasValue) { dep = p.from.getPosMailBox(); arr = p.to.getPosMailBox(); } else { for (int i = 0; i < tabCoord.Length; i++) { if (p.from.ToString().Equals(tabCoord[i])) { dep = i; } if (p.to.ToString().Equals(tabCoord[i])) { arr = i; } } } if (piece[arr] != (int)Piece.PAWN) { if (color[arr] == (int)Color.WHITE) { countPieceBlanche--; etatPieceBlanche[piece[arr]]--; } else if (color[arr] == (int)Color.BLACK) { countPieceNoir--; etatPieceNoir[piece[arr]]--; } } color[arr] = color[dep]; color[dep] = (int)Color.NONE; piece[arr] = piece[dep]; piece[dep] = (int)Color.NONE; //TODO //C'est un double saut qui genere une case en passant if (p.captureEnPassant != null && !p.captureEP) { //Si EP est deja set, c'est celui du tour d'avant donc on peut l'ecraser int caseEnPassant = p.captureEnPassant.getPosMailBox(); color[caseEnPassant] = (int)Color.PAWN_EN_PASSANT; ep = arr; } else if (p.captureEnPassant != null && p.captureEP) { Debug.Assert(ep.HasValue, "On mange un pion via EP mais aucuns pions associe à la piece"); //On mange un pion via la case en passant color[ep.Value] = (int)Color.NONE; piece[ep.Value] = (int)Color.NONE; ep = null; } if (p.captureEnPassant == null && this.ep.HasValue) { //Si on fait un mouvement et qu'il y a un EP alors on reset le EP (il est valable qu'un tour) int?caseEnPassant = null; //Il faut trouver le pion associé if (tabPos[ep.Value] >= 51 && tabPos[ep.Value] <= 58) { //Noir caseEnPassant = Mailbox.tab120[Mailbox.tabPos[ep.Value] + Mailbox.offset[0, 0]]; } else if (tabPos[ep.Value] >= 61 && tabPos[ep.Value] <= 68) { //blanc caseEnPassant = Mailbox.tab120[Mailbox.tabPos[ep.Value] - Mailbox.offset[0, 0]]; } Debug.Assert(caseEnPassant.HasValue, "Il y a une case en passant qui n'est pas au bon endroit " + tabCoord[ep.Value]); color[caseEnPassant.Value] = (int)Color.NONE; ep = null; } //Je sais pas trop l'impacte ici if (p.promotion != null) { piece[arr] = p.promotion.piece; } if (p.castlingKingSide) { //TODO -- qqch à faire la ? Vu qu'on a depart et arrivé ? } if (p.castlingQueenSide) { //TODO -- qqch à faire la ? Vu qu'on a depart et arrivé ? } }