public float Evaluate(Board Current, int Move) { int Value = 0; // value of move for (int Plays = 0; Plays < NumberOfPlayouts; Plays++) { Board MCPlayout = Current.Clone(); MCPlayout.Move(Move); State Winner = Expand(MCPlayout); if (Winner == Current.CurrentPlayer) Value++; // win means +1 else if (Winner == Current.CurrentOpponent) Value--; // loss means -1 } return (Value / (float)NumberOfPlayouts); // project into [-1,1] }
public static List<int> PreprocessMoves(Board Current, List<int> TestCandidates) { List<int> CandidateMoves = new List<int> { }; foreach (int Move in TestCandidates) { Board CheckWin = Current.Clone(); // test if immediate win possible CheckWin.Move(Move); if (CheckWin.TestVictory() == Current.CurrentPlayer) { CandidateMoves.Add(Move); return CandidateMoves; } else { // test if we make an assist for our opponent List<int> OpponentMoves = CheckWin.GetValidMoves(); bool IsBad = false; foreach (int OMove in OpponentMoves) { Board Tmp = CheckWin.Clone(); Tmp.Move(OMove); // did we make an assist? if (Tmp.TestVictory() == Current.CurrentOpponent) { // forget the move! IsBad = true; break; } } if (!IsBad) { CandidateMoves.Add(Move); } } } return CandidateMoves; }
/// <summary> /// returns a move by minimax and deep cuts /// </summary> /// <remarks> /// THIS IS STILL BUGGY!!! /// </remarks> /// <param name="CurrentSituation">current game situation</param> /// <returns>move to play</returns> public override int Play(Board CurrentSituation) { Scores.SetStrength(100); CP = CurrentSituation.CurrentPlayer; List<int> CandidateMoves = CurrentSituation.GetValidMoves(); TProcess.Maximum = CandidateMoves.Count; TProcess.Value = 0; float value = float.MinValue; int ColumnToPlay = -1; WorkingBoard = CurrentSituation.Clone(); foreach (int M in CandidateMoves) { TProcess.PerformStep(); float eval = ScoreMove(M, 0, float.MinValue, float.MaxValue); //MessageBox.Show(value.ToString()); if (eval > value) { value = eval; ColumnToPlay = M; } } return ColumnToPlay; }