/// <summary> /// find next move by direct score /// </summary> /// <param name="x">current board</param> /// <returns>next move</returns> static public int DirectScoreMove(Board x) { double maxScore = 0; int maxi = -1; for (int k = 0; k < 4; k++) { if (BoardControl.ExecuteMove(x, k) == x) { continue; } if (PreScore.DirectScore(BoardControl.ExecuteMove(x, k)) > maxScore) { maxScore = PreScore.DirectScore(BoardControl.ExecuteMove(x, k)); maxi = k; } } if (maxi == -1) { return(new Random(DateTime.Now.Millisecond).Next() % 4); } else { return(maxi); } }
/// <summary> /// play game for monte carlo method /// </summary> /// <param name="Str">play strategy</param> /// <param name="board">current board</param> /// <param name="nmove">monte carlo steps</param> /// <param name="move">pre-pointed next step</param> /// <returns>score by monte carlo</returns> public static double MontePlay(Strategy Str, Board board, int nmove, int move = -1) { bool first = true; while (true) { UInt64 newboard; if (first && (move != -1)) { if (BoardControl.ExecuteMove(board, move) == board) { return(0); } first = false; } else { for (move = 0; move < 4; move++) { if (BoardControl.ExecuteMove(board, move) != board) { break; } } if (move == 4) { break; } move = Str(board); if (move < 0) { break; } } newboard = BoardControl.ExecuteMove(board, move); if (newboard == board) { continue; } UInt64 tile = BoardControl.RandomTile(); board = BoardControl.InsertTileRand(newboard, tile); nmove--; if (nmove <= 0) { return(PreScore.DirectScore(board)); } } return(0); }
/// <summary> /// play game by pointed strategy /// </summary> /// <param name="Str">play strategy</param> public static void Play(Strategy Str) { Board board = BoardControl.InitBoard(); int moveno = 0; int scorepenalty = 0; while (true) { int move; Board newboard; for (move = 0; move < 4; move++) { if (BoardControl.ExecuteMove(board, move) != board) { break; } } if (move == 4) { break; } BoardControl.Print(board); System.Console.WriteLine("Move:" + (++moveno).ToString() + ", score:" + (BoardControl.Score(board) - scorepenalty).ToString() + '\n'); move = Str(board); if (move < 0) { break; } newboard = BoardControl.ExecuteMove(board, move); if (newboard == board) { System.Console.WriteLine("Illegal move!\n"); moveno--; continue; } Board tile = BoardControl.RandomTile(); if (tile == 2) { scorepenalty += 4; } board = BoardControl.InsertTileRand(newboard, tile); } BoardControl.Print(board); System.Console.WriteLine("\nGame over.\nScore:" + (BoardControl.Score(board) - scorepenalty).ToString() + ".\n"); }
/// <summary> /// score while next process is move /// </summary> /// <param name="x">current board</param> /// <param name="prob">current board probability</param> /// <param name="para">parameters of search</param> /// <returns>score</returns> static double ScoreNextMove(UInt64 x, float prob, Param para) { double best = 0.0f; UInt64 newboard; para.depth++; for (int d = 0; d < 4; ++d) { newboard = BoardControl.ExecuteMove(x, d); if (x != newboard) { best = Math.Max(best, ScoreNextInsert(newboard, prob, para)); } } para.depth--; return(best); }
/// <summary> /// score board while pointed the next move /// </summary> /// <param name="x">current board</param> /// <param name="d">pre-pointed next move</param> /// <returns>score</returns> public static double ScoreFirstMove(Board x, int d) { double res; Param para = new Param(); para.scoreTable = new Dictionary <ulong, double>(); para.depthLimit = Math.Max(3, BoardControl.CountDistinctTiles(x) - 2); UInt64 newboard = BoardControl.ExecuteMove(x, d); if (x == newboard) { res = 0; } else { res = ScoreNextInsert(newboard, 1.0f, para) + 1e-6; } return(res); }
/// <summary> /// find next move by monte carlo method /// </summary> /// <param name="x">current board</param> /// <returns>next move</returns> static public int MonteCarloMove(Board x) { int iterN = 2000; double[] score = new double[4] { 0, 0, 0, 0 }; double maxScore = 0; int maxi = 0; Parallel.For(0, 4, (i, loopState) => { if (BoardControl.ExecuteMove(x, i) != x) { for (int j = 0; j < iterN; j++) { score[i] = score[i] + PlayGame.MontePlay(DirectScoreMove, x, 10, i); } } }); for (int k = 0; k < 4; k++) { if (score[k] > maxScore) { maxScore = score[k]; maxi = k; } } if (BoardControl.ExecuteMove(x, maxi) == x) { return(new Random(DateTime.Now.Millisecond).Next() % 4); } Console.WriteLine("Predict average score:" + (maxScore / iterN).ToString()); Console.WriteLine(); return(maxi); }