/// <summary> /// Processes the estimate data and saves it to the database. /// </summary> private void RecordEstimateToDatabase() { //Validate and assign the job number before opening the file dialog window. Validation is //performed by the JobNumberValidation object upon instantiation. JobNumberValidation validationControl = new JobNumberValidation(txtJobNumber.Text, IsSaveOperation: true); if (validationControl.IsValidJobNumber) { if (!validationControl.IsDuplicateEstimate) { EstimateHelper estimateHelper = new EstimateHelper(Globals.ThisAddIn.Application); //Try to activate the 'Main Form' tab of the Estimate sheet. If the attempt is successful, then the process for saving estimate data //will move ahead. Otherwise, an error message will be shown to the user. if (estimateHelper.CalibratePosition()) { List <SystemEstimate> systemEstimateList = estimateHelper.PopulateSystemList(); if (systemEstimateList.Count > 0 && systemEstimateList != null) { try { EstimateRecordingService recordingService = new EstimateRecordingService(txtJobNumber.Text); recordingService.Commit(systemEstimateList); MessageBox.Show("The estimate for Job Number: " + txtJobNumber.Text + " was successfully saved.", "Estimate Saved"); } catch (Exception) { throw; } } } else { MessageBox.Show("To save Estimate data, the user must have the Estimate workbook open and be on the 'MainForm' tab."); } } else { MessageBox.Show("Sorry, but an estimate for this job already exists."); } } }
private void GetBestMoveImpl(Game game, int depth, out Move bestMove, out Estimate bestEstimate) { Player player = game.State.NextMovePlayer; bool isMaximizeStage = player == Player.Maximizing; Move curBestMove = null; Estimate curBestEstimate = isMaximizeStage ? Estimate.MinInf : Estimate.MaxInf; foreach (Move move in game.GetAllowedMoves()) { MovesChecked += 1; game.DoMove(move); Estimate estimate = game.State.StaticEstimate; // force AI to win faster if (game.State.IsTerminate && estimate != Estimate.Zero) { EstimateHelper.AdjustTerminalStateEstimate(depth, ref estimate); } if (depth < 3) { Trace.WriteLine($"{Tab(depth - 1)}Consider {move}"); } if (game.State.IsTerminate || depth == MaxDepth) { // no longer go deeper UpdateBestMove(isMaximizeStage, move, estimate, ref curBestMove, ref curBestEstimate); } else { // go deeper Move bestMoveInternal; Estimate bestEstimateInternal; GetBestMoveImpl(game, depth + 1, out bestMoveInternal, out bestEstimateInternal); UpdateBestMove(isMaximizeStage, move, bestEstimateInternal, ref curBestMove, ref curBestEstimate); } game.UndoMove(move); } if (curBestMove == null) { throw new InvalidOperationException("No moves found"); } bestMove = curBestMove; bestEstimate = curBestEstimate; #if DEBUG if (depth <= 3) { Trace.WriteLine($"{Tab(depth-1)}RET: {depth}; BM: {bestMove}; E: {bestEstimate} ({(isMaximizeStage ? "max" : "min")})"); } #endif }
private Estimate FindImpl(Game game, Estimate alpha, Estimate beta, int depth, int maxDepth, Metadata meta) { Player player = game.State.NextMovePlayer; bool isMax = player == Player.Maximizing; if (maxDepth - depth == 0) { return(game.State.StaticEstimate); } if (game.State.IsTerminate) { // make AI pick shortest path to terminate state // otherwise there will be funny situation then AI seeing that it won // w/o chances for other side will not purse the winning Estimate terminateEstimate = game.State.StaticEstimate; EstimateHelper.AdjustTerminalStateEstimate(depth, ref terminateEstimate); return(terminateEstimate); } Estimate v = isMax ? Estimate.MinInf : Estimate.MaxInf; List <Move> moves = game.GetAllowedMoves() .OrderByDescending(x => x.Priority) .ToList(); foreach (Move move in moves) { meta.MovesChecked += 1; using (DisposableMoveHandle.New(game, move)) { Estimate curEstimate = FindImpl(game, alpha, beta, depth + 1, maxDepth, meta); bool betterMoveFound = isMax ? curEstimate > v : curEstimate < v; if (betterMoveFound) { v = curEstimate; if (depth == 1) { meta.BestMove = move; } } if (isMax) { alpha = Estimate.Max(alpha, v); } else { beta = Estimate.Min(beta, v); } #if DEBUG if (depth <= 3) { Trace.WriteLine($"{ new string(' ', depth) } - Move {move} for {player} -- {curEstimate} -- Term? {game.State.IsTerminate}"); } #endif if (alpha >= beta) { // alpha/beta cut-off //Trace.WriteLine($"cut-off on depth {depth}"); break; } } } return(v); }