Пример #1
0
        private int evaluationPlayer(LatrunculiApp latrunculi)
        {
            var evaluation = latrunculi.HistoryManager.Steps.TakeLast(depth + 1).Reverse().Select((step, index) =>
                                                                                                  step.CapturedCount * (index + 1) * (index % 2 == 0 ? 1 : -1)
                                                                                                  ).Sum();

            if (latrunculi.Debug && evaluation != 0)
            {
                string steps = string.Join(", ", latrunculi.HistoryManager.Steps.TakeLast(depth + 1).Select(step => step.Move));
                Console.WriteLine($"{steps}: {evaluation}");
                DebugPrintDesk?.Invoke(this, null);
            }
            return(depth % 2 == 0 ? evaluation : -evaluation);
        }
Пример #2
0
 public CommandManager(LatrunculiApp app, HistoryPrinter historyPrinter, DeskPrinter deskPrinter)
 {
     this.app            = app;
     this.historyPrinter = historyPrinter;
     this.deskPrinter    = deskPrinter;
     this.playerTypes    = new Dictionary <string, Func <IPlayer> >()
     {
         ["human"]    = () => createHumanPlayer(),
         ["random"]   = () => createRandomPlayer(),
         ["minimax2"] = () => createMiniMaxPlayer(2),
         ["minimax4"] = () => createMiniMaxPlayer(4),
         ["minimax3"] = () => createMiniMaxPlayer(3)
     };
     this.helpPlayer = createMiniMaxPlayer(3);
 }
Пример #3
0
 private (Move move, int evaluation, int bestMovesCount) minMaxRecursive(LatrunculiApp latrunculi, int depth, Move move, CancellationToken ct = default)
 {
     ct.ThrowIfCancellationRequested();
     try
     {
         latrunculi.Rules.Move(latrunculi.HistoryManager.ActualPlayer, move);
         var indentation = this.depth - depth;
         var moves       = string.Join(';', latrunculi.HistoryManager.Steps.TakeLast(this.depth - depth + 1)
                                       .Select(step => step.Move.ToString()));
         if (latrunculi.Debug)
         {
             deskLogger.WriteLine($"{latrunculi.HistoryManager.ActualPlayer} {moves}");
             deskLogger.WriteLine(deskToString.GetDeskAsString(latrunculi));
         }
         (Move move, int evaluation, int bestMovesCount)? evaluation = null;
         if (depth == 0 || latrunculi.IsEnded)
         {
             evaluation = (move, evaluationPlayer(latrunculi), 1);
             if (latrunculi.Debug && evaluation.Value.evaluation != 0)
             {
                 logger.WriteLine($"{latrunculi.HistoryManager.ActualPlayer} {moves} ({evaluation})", indentation);
             }
         }
         else
         {
             //logger.WriteLine($"Start {app.HistoryManager.ActualPlayer} {moves}", indentation);
             var evaluations = latrunculi.Rules.GetAllValidMoves(latrunculi.HistoryManager.ActualPlayer)
                               .ToArray()
                               .Select(nextMove => minMaxRecursive(latrunculi, depth - 1, nextMove, ct))
                               .ToArray();
             var maxEvaluation = evaluations.Max(move => move.evaluation);
             var maxCount      = evaluations
                                 .Where(eval => eval.evaluation == maxEvaluation)
                                 .Sum(eval => eval.bestMovesCount);
             if (latrunculi.Debug && maxEvaluation != 0)
             {
                 logger.WriteLine($"End {latrunculi.HistoryManager.ActualPlayer} {moves} ({maxEvaluation}, count: {maxCount})", indentation);
             }
             evaluation = (move, maxEvaluation, maxCount);
         }
         return(evaluation.Value);
     }
     finally
     {
         latrunculi.HistoryManager.Back();
     }
 }
Пример #4
0
        private Move getBestMove(LatrunculiApp latrunculi, ChessBoxState player, CancellationToken ct = default)
        {
            ct.ThrowIfCancellationRequested();
            logger?.Dispose();
            deskLogger?.Dispose();
            logger     = new FileLogger($"{latrunculi.HistoryManager.ActualRound} - {player} - minimax {depth}");
            deskLogger = new FileLogger($"{latrunculi.HistoryManager.ActualRound} - {player} - minimax {depth} - desk");

            var validMoves = latrunculi.Rules.GetAllValidMoves(player).ToArray();
            IEnumerable <(Move move, int evaluation, int bestMovesCount)> moves = validMoves.Select(move => (minMaxRecursive(latrunculi, depth, move, ct))).ToArray();

            if (latrunculi.Debug)
            {
                logger.WriteLine("############################# Result");
                foreach (var moveInfo in moves)
                {
                    logger.WriteLine($"{moveInfo.evaluation} {moveInfo.move}, count: {moveInfo.bestMovesCount}");
                }
            }
            if (latrunculi.BestMovesDebug)
            {
                Console.WriteLine();
                foreach (var moveInfo in moves)
                {
                    Console.WriteLine($"{moveInfo.evaluation} {moveInfo.move}, count: {moveInfo.bestMovesCount}");
                }
                Console.WriteLine($"--------------------------------");
            }
            var maxEvaluation        = moves.Max(move => move.evaluation);
            var maxMoves             = moves.Where(move => move.evaluation == maxEvaluation).ToArray();
            var maxBestCount         = maxMoves.Max(move => move.bestMovesCount);
            var bestMoves            = maxMoves.Where(move => move.bestMovesCount == maxBestCount).Select(move => move.move).ToArray();
            var moveForwardDirection = player == ChessBoxState.Black ? -1 : 1;
            var bestForwardMoves     = bestMoves.Where(move => move.To.Y - move.From.Y == moveForwardDirection).ToArray();

            if (bestForwardMoves.Length == 0)
            {
                bestForwardMoves = bestMoves.Where(move => move.From.Y == move.To.Y).ToArray();
            }
            if (bestForwardMoves.Length == 0)
            {
                bestForwardMoves = bestMoves;
            }
            logger.Dispose();
            return(bestForwardMoves.Skip(random.Next(bestForwardMoves.Count()) - 1).First());
        }
Пример #5
0
        public string GetDeskAsString(LatrunculiApp latrunculi)
        {
            var           desk = latrunculi.Desk;
            StringBuilder sb   = new StringBuilder(2 * desk.Size.Width * desk.Size.Height);

            sb.Append(getLineSeparator(desk));
            for (int y = desk.Size.Height - 1; y >= 0; y--)
            {
                string inner = string.Join(" | ",
                                           Enumerable.Range(0, desk.Size.Width)
                                           .Select(x => getCheckBox(latrunculi, new ChessBoxPosition(desk.Size, x, y)))
                                           );
                sb.Append($"{y + 1} | {inner} |\n");
                sb.Append(getLineSeparator(desk));
            }
            sb.Append(getLetters(desk));
            return(sb.ToString());
        }
Пример #6
0
        public GameContext(LatrunculiApp latrunculi)
        {
            Latrunculi = latrunculi;
            latrunculi.PropertyChanged += (_, e) =>
            {
                switch (e.PropertyName)
                {
                case nameof(latrunculi.Desk):
                    helpCts?.Cancel();
                    HelpMove = null;
                    break;

                case nameof(latrunculi.ActualPlayer):
                    turnCts?.Cancel();
                    helpCts?.Cancel();
                    TryTurn();
                    break;
                }
                ;
            };
            latrunculi.HistoryManager.PropertyChanged += (_, e) =>
            {
                if (e.PropertyName == nameof(latrunculi.HistoryManager.IsLastIndexSelected))
                {
                    if (latrunculi.HistoryManager.IsLastIndexSelected && !latrunculi.IsEnded)
                    {
                        TryTurn();
                    }
                    else
                    {
                        turnCts?.Cancel();
                        helpCts?.Cancel();
                    }
                }
            };
            turnWorker = createMoveWorker(handlePlayerTurn);
            helpWorker = createMoveWorker(handleHelped);
            ActualizeStatus();
            TryTurn();
        }
Пример #7
0
        public Move Turn(LatrunculiApp latrunculi, ChessBoxState player, CancellationToken ct = default)
        {
            Console.Write("Váš tah (start cíl): ");
            string line = Console.ReadLine().Trim().ToLower();

            if (commandManager.CheckCommand(line))
            {
                return(null);
            }
            var moveMatch = Regex.Match(line, @"^(?<from>[a-zA-Z][1-9])\s*(?<to>[a-zA-Z][1-9])$");

            if (moveMatch.Success)
            {
                ChessBoxPosition from = ChessBoxPosition.FromString(deskSize, moveMatch.Groups["from"].Value);
                ChessBoxPosition to   = ChessBoxPosition.FromString(deskSize, moveMatch.Groups["to"].Value);
                return(new Move(from, to));
            }
            else
            {
                throw new InvalidCastException("Je vyžadován tah ve formátu start cíl, např. E4 E5");
            }
        }
Пример #8
0
        private string getCheckBox(LatrunculiApp latrunculi, ChessBoxPosition position)
        {
            var    lastChange = latrunculi.HistoryManager.LastStep?.Changes.Find(change => change.Position.Index == position.Index);
            var    state      = latrunculi.Desk.PlayingDesk[position.X, position.Y];
            string symbol;

            switch (state)
            {
            case ChessBoxState.Black:
                symbol = "b";
                break;

            case ChessBoxState.White:
                symbol = "w";
                break;

            case ChessBoxState.Empty:
            default:
                symbol = " ";
                break;
            }
            if (lastChange != null)
            {
                if (lastChange.IsCaptured == true)
                {
                    symbol = "X";
                }
                else if (lastChange.NewState == ChessBoxState.Empty)
                {
                    symbol = "_";
                }
                else if (lastChange.NewState == state)
                {
                    symbol = symbol.ToUpper();
                }
            }
            return(symbol);
        }
Пример #9
0
 public Move Turn(LatrunculiApp latrunculi, ChessBoxState player, CancellationToken ct = default)
 {
     return(getBestMove(latrunculi, player, ct));
 }
Пример #10
0
 public void Dispose()
 {
     app = null;
 }
Пример #11
0
 public SaveGameManager(LatrunculiApp app)
 {
     this.app = app;
 }
Пример #12
0
        static void Main(string[] args)
        {
            Console.WriteLine("========================================");
            Console.WriteLine("Latrunculi - @author: František Pospíšil");
            Console.WriteLine("========================================");
            Console.WriteLine();

            var            latrunculi     = new LatrunculiApp();
            HistoryPrinter historyPrinter = new HistoryPrinter(latrunculi.HistoryManager);
            DeskPrinter    deskPrinter    = new DeskPrinter(latrunculi.Desk, latrunculi.HistoryManager);
            var            commandManager = new CommandManager(latrunculi, historyPrinter, deskPrinter);

            latrunculi.WhitePlayer =
                commandManager.createPlayerByType(args.FirstOrDefault()) ??
                commandManager.GetPlayerType(ChessBoxState.White);

            latrunculi.BlackPlayer =
                commandManager.createPlayerByType(args.Skip(1).FirstOrDefault()) ??
                commandManager.GetPlayerType(ChessBoxState.Black);

            while (true)
            {
                try
                {
                    while (true)
                    {
                        try
                        {
                            if (!latrunculi.IsEnded)
                            {
                                Console.WriteLine();
                                deskPrinter.PrintDesk();
                                string actualPlayer = latrunculi.HistoryManager.ActualPlayer == ChessBoxState.Black ? "černý" : "bílý";
                                Console.WriteLine();
                                WriteColoredMulti(
                                    TextSegment($"Tah "),
                                    TextSegment($"@{latrunculi.HistoryManager.ActualRound}", ConsoleColor.Yellow),
                                    TextSegment($", hraje "),
                                    TextSegment($"{actualPlayer} ", ConsoleColor.Yellow),
                                    TextSegment($"hráč ({latrunculi.ActualPlayer.ToString()}). "));
                                var move = latrunculi.Turn();
                                if (move != null)
                                {
                                    WriteColoredMulti(TextSegment("Zahrán tah "), TextSegment($"{move}", ConsoleColor.Green), TextSegment("."));
                                }
                                latrunculi.Rules.CheckEndOfGame();
                            }
                            else
                            {
                                Console.Write("Zadejte příkaz: ");
                                var line = Console.ReadLine();
                                commandManager.CheckCommand(line);
                            }
                        }
                        catch (EndOfGameException e)
                        {
                            Console.WriteLine();
                            deskPrinter.PrintDesk();
                            WriteColoredLine(e.Message, ConsoleColor.Green);
                            WriteColoredLine("Engine: " + (e.Winner == ChessBoxState.Black ? latrunculi.BlackPlayer : latrunculi.WhitePlayer).ToString(), ConsoleColor.Gray);
                            break;
                        }
                        catch (AbortGameException)
                        {
                            return;
                        }
                        catch (Exception e)
                        {
                            WriteColoredLine(e.Message, ConsoleColor.Red);
                        }
                    }
                }
                catch (Exception)
                {
                    return;
                }
            }
        }
Пример #13
0
        public Move Turn(LatrunculiApp latrunculi, ChessBoxState player, CancellationToken ct = default)
        {
            var validMoves = latrunculi.Rules.GetAllValidMoves(player);

            return(validMoves.Skip(random.Next(validMoves.Count()) - 1).First());
        }