private void ponderingWorker_DoWork(object sender, DoWorkEventArgs e) { //TODO: Kolla så ställningen inte förändrats. //TODO: Bli av med denna worker? //Flytta motorn hit? blobFish.cancelFlag.setValue(0); EvalResult resultPlace = new EvalResult(); resultPlace.bestMove = null; if (depthAutoToolStripMenuItem.Checked) { minDepth = -1; } Thread thread = new Thread(delegate() { engineStart(minDepth, game.currentPosition.boardCopy(), resultPlace); }); thread.Name = "engineThread"; thread.Start(); while (thread.IsAlive) { if (ponderingWorker.CancellationPending) { blobFish.cancelFlag.setValue(1); e.Cancel = true; break; } Thread.Sleep(50); } e.Result = resultPlace; }
private void engineStart(int minDepth, Position pos, EvalResult resultPlace) { //TODO: Hitta något bättre sätt att göra detta på. EvalResult res = blobFish.eval(pos, minDepth); resultPlace.bestMove = res.bestMove; resultPlace.allMoves = res.allMoves; resultPlace.allEvals = res.allEvals; resultPlace.evaluation = res.evaluation; return; }
private void ponderingWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show(e.Error.Message); } else if (e.Cancelled) { //Vidtag lämplig åtgärd } else { try { EvalResult res = (EvalResult)e.Result; if (res.bestMove == null) { //blobFish.cancelFlag.setValue(0); //takeback(1); setPonderingMode(false); //throw new Exception("Inget bästa drag!"); } else { setPonderingMode(false); printEval(res); if (engineIsToMove()) { this.playMove(res.bestMove); } } } catch (Exception exc) { MessageBox.Show(exc.Message); scoresheetBox.Text = "Ett fel inträffade."; takeback(1); setPonderingMode(false); } //Samlar upp skräp då UI väntar på att användaren skall dra. if (!engineIsToMove()) { GC.Collect(); GC.WaitForPendingFinalizers(); } } }
static private string testForcedMates() { string testName = "Forcerad matt-tester"; string detailedResult = testName + ": " + Environment.NewLine; int testCounter = 1; bool testFailed = false; Engine blobfish = new Engine(); bool makeTest(string FEN, int movesToMate) { Position pos = new Position(FEN); EvalResult result = blobfish.eval(pos, movesToMate + 1); int plysToMate = (movesToMate * 2) - 1; bool success = result.evaluation == (pos.whiteToMove ? (2001 - plysToMate) : (-2001 + plysToMate)); if (success) { detailedResult += " Test " + testCounter.ToString() + ": Lyckades" + Environment.NewLine; } else { detailedResult += " Test " + testCounter.ToString() + ": Misslyckades" + Environment.NewLine; testFailed = true; } testCounter++; return(success); } makeTest("r1bqkb1r/pppp1ppp/2n2n2/4p2Q/2B1P3/8/PPPP1PPP/RNB1K1NR w KQkq - 4 4", 1); //Skolmatt makeTest("r1b1k2r/ppppqppp/2n5/4n3/1PP2B2/5N2/1P1NPPPP/R2QKB1R b KQkq - 0 8", 1); //Budapestmatten makeTest("8/8/8/8/8/8/6R1/1k2K2R w K - 0 1", 1); //Matt genom rockad makeTest("3r4/8/8/8/8/8/6R1/k3K2R w K - 0 1", 2); //Matt genom rockad makeTest("8/5P1k/5K2/8/8/8/8/8 w - - 0 1", 2); //Underpromotering //5 makeTest("8/6k1/R7/1R6/8/8/8/4K3 w - - 0 1", 2); //Trappstegsmatt makeTest("r7/ppp2kpp/2nb4/5K2/2PP1P1q/2N5/PP1Q2PP/R4BNR b - - 0 16", 2); //Portugisiskt makeTest("r4rk1/pp3Npp/1b6/8/2Q5/P6P/1q3PP1/R4RK1 w - - 0 1", 3); //Kvävmatt makeTest("6k1/ppp3pp/6r1/8/4nP1K/N1Pr4/PP5P/R4R2 b - - 8 26", 3); //Inte lika forcerande matt i tre. makeTest("8/8/8/5B2/8/6K1/6N1/5k2 w - - 0 1", 5); //Matt med springare och löpare. if (testFailed) { return(detailedResult); } else { return(testName + ": Felfritt!"); } }
private void printEval(EvalResult result) { int decisiveResult = blobFish.decisiveResult(game.currentPosition, currentMoves); if (decisiveResult != -2) { resultPopUp(decisiveResult); } else if (!blobFish.mateableMaterial(game.currentPosition.board)) { resultPopUp(-1); } else if (result.bestMove != null) { float eval = result.evaluation; string textEval; if (eval > 1000) { int plysToMate = (int)(2002 - eval); textEval = "M" + (plysToMate / 2).ToString(); } else if (eval < -1000) { int plysToMate = (int)(2002 + eval); textEval = "m-" + (plysToMate / 2).ToString(); } else { textEval = Math.Round(eval, 2).ToString(); } computerMoveStatusLabel.Text = "Datorn spelade: " + result.bestMove.toString(game.currentPosition); evalStatusLabel.Text = "Datorns evaluering: " + textEval; timeSpentStatusLabel.Text = "Förbrukad tid: " + ponderingTime.ToString(@"mm\:ss"); } else { throw new Exception("Odefinierat bästa drag."); } }
public EvalResult eval(Position pos, int minDepth) { //Om minDepth är -1, skall datorn själv bestämma djup. if (minDepth == -1) { minDepth = automaticDepth(pos); } List <Move> moves = allValidMoves(pos, true); EvalResult result = new EvalResult(); int gameResult = decisiveResult(pos, moves); if (gameResult != -2) { result.evaluation = gameResult; result.allMoves = new List <Move>(); result.allEvals = null; return(result); //Ställningen är avgjord. } else { List <SecureFloat> allEvals = new List <SecureFloat>(); float bestValue = pos.whiteToMove ? float.NegativeInfinity : float.PositiveInfinity; if (moves.Count == 1) { //Spela forcerande drag omedelbart? EvalResult res = eval(moves[0].execute(pos), minDepth - 1); result.evaluation = evaluationStep(res.evaluation); result.allMoves = moves; result.bestMove = moves[0]; return(result); } // Ökar minimum-djupet om antalet tillgängliga drag är färre än de som anges // i moveIncreaseLimits, vilka återfinns i EngineData. foreach (int item in moveIncreaseLimits) { if (moves.Count <= item) { minDepth++; } else { break; } } SecureFloat globalAlpha = new SecureFloat(); globalAlpha.setValue(float.NegativeInfinity); SecureFloat globalBeta = new SecureFloat(); globalBeta.setValue(float.PositiveInfinity); List <Thread> threadList = new List <Thread>(); SecureFloat bestMove = new SecureFloat(0); for (int i = 0; i < moves.Count; i++) //foreach (Move currentMove in moves) { Move currentMove = moves[i]; SecureFloat newFloat = new SecureFloat(); int iCopy = i; allEvals.Add(newFloat); Thread thread = new Thread(delegate() { threadStart(currentMove.execute(pos), (sbyte)(minDepth - 1), iCopy, bestMove, newFloat, globalAlpha, globalBeta); }); thread.Name = currentMove.toString(pos); thread.Start(); threadList.Add(thread); } //result.bestMove = moves[0]; Thread.Sleep(sleepTime); for (int i = 0; i < allEvals.Count; i++) { SecureFloat threadResult = allEvals[i]; float value = threadResult.getValue(); #pragma warning disable CS1718 // Comparison made to same variable if (value != value) //Kollar om talet är odefinierat. #pragma warning restore CS1718 // Comparison made to same variable { //Om resultatet inte hunnit beräknas. if (cancelFlag.getValue() != 0) { abortAll(threadList); result.bestMove = null; result.evaluation = float.NaN; result.allEvals = null; Thread.Sleep(10); //För att ge övriga trådar chans att stanna. return(result); } else if (this.moveNowFlag.getValue() != 0) { abortAll(threadList); Thread.Sleep(10); //För att ge övriga trådar chans att stanna. result.bestMove = moves[(int)bestMove.getValue()]; return(result); } Thread.Sleep(sleepTime); i--; } else { //Om resultatet är klart. result.bestMove = moves[(int)bestMove.getValue()]; } } if (pos.whiteToMove) { result.evaluation = globalAlpha.getValue(); } else { result.evaluation = globalBeta.getValue(); } result.allEvals = allEvals; } result.allMoves = moves; return(result); }