public GameNode(IMCTSGame game, int parentsMove = -1) { if (game == null) { throw new ArgumentNullException("game"); } this.ParentsMove = parentsMove; this.Game = game; this._value = new Lazy <double>(this.ComputeValue); this._children = new Lazy <IList <ChildNode <double, GameNode> > >(this.CreateChildren); }
public static bool RandomMove(this IMCTSGame game) { if (game == null) { throw new ArgumentNullException("game"); } if (game.IsAutoMovePossible) { game.AutoMove(); return(true); } else { var possibleMoves = game.PossibleMoves; if (0 < possibleMoves) { var moveIndex = random.Next(possibleMoves); if (game.TryMove(moveIndex)) { return(true); } else { var moves = new List <int>(possibleMoves); int move; for (move = 0; move < possibleMoves; move++) { if (move != moveIndex) { moves.Add(move); } } bool moved = false; do { moveIndex = random.Next(moves.Count); move = moves[moveIndex]; moves[moveIndex] = moves[moves.Count - 1]; moves.RemoveAt(moves.Count - 1); moved = game.TryMove(move); } while (!moved && 0 < moves.Count); return(moved); } } else { return(false); } } }
public static int RandomFinish(this IMCTSGame game) { if (game == null) { throw new ArgumentNullException("game"); } int moves = 0; while (game.RandomMove()) { ++moves; } return(moves); }
/// <summary> /// Perform's move automatically by game model. This is prefered method /// over <see cref="TryMove"/> because there can be hidden probability /// distribution of different moves. /// </summary> /// <returns> /// Returns move index. If you passed this value as argument into /// <see cref="TryMove"/> it would perform the same action. /// </returns> /// <exception cref="InvalidOperationException"> /// if <see cref="IsAutoMovePossible"/> is false.</exception> public static int AutoMove(this IMCTSGame game) { if (game == null) { throw new ArgumentNullException("game"); } if (!game.IsAutoMovePossible) { throw new InvalidOperationException( "Auto-Move is not possible." ); } var move = game.GetAutoMoveIndex(); if (!game.TryMove(move)) { throw new InvalidOperationException("auto-move wasn't performed."); } return(move); }
/// <summary> /// "Start" button press event handler. This method starts the game. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void startButton_Click(object sender, EventArgs e) { /* set game type. */ int gameIdx = gameTypeComboBox.SelectedIndex; game = GameFactory <int> .Create(gameIdx, botOne, botTwo); game.Start(); pictureBox.Size = boardImage.Size; pictureBox.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox_Paint); Type a = game.GetType(), b = typeof(HHGame <int>), c = typeof(HCGame <int>); if (a.Equals(b) == true || a.Equals(c) == true) { pictureBox.MouseUp += new MouseEventHandler(this.pictureBox_MouseUp); } else { /* CCGame: launch a thread that will update the ui. */ // launch a worker thread that will get the bot's next move and update the UI. // this way the UI thread is not blocked and the operation is permitted (does not throw any exceptions). uiUpdaterWorker = new Thread( new ParameterizedThreadStart( (parameter) => { Form1 form = (Form1)parameter; while (game.IsFinished() == false && cancelToken.IsCancellationRequested == false) { form.Invoke((MethodInvoker) delegate { form.UpdateUI(); // runs on UI thread. }); Thread.Sleep(UI_REFRESH_RATE); } Console.WriteLine("[FORM] UI Updater thread exit."); }) ); uiUpdaterWorker.Start(this); } pictureBox.Refresh(); }
/// <summary> /// Method used to stop the worker game-worker threads and restart the game state. /// </summary> private void StopGame() { Thread stopper = new Thread( new ThreadStart(() => { // stop uiUpdaterWorker. cancelToken.Cancel(); // restart game. game.RestartGame(); // update the ui. this.Invoke((MethodInvoker) delegate { pictureBox.Refresh(); // re-initialize the game state. int gameIdx = gameTypeComboBox.SelectedIndex; game = GameFactory <int> .Create(gameIdx, botOne, botTwo); }); }) ); stopper.Start(); }