void GameResult(GameResultData g)
 {
     StartCoroutine(Coroutines.Lerp(0, 1, appearLength, (position) => {
         transform.localScale = Vector3.one * position;
     }));
     g.resultObject.SetActive(true);
     g.resultObject.GetComponentInChildren <TextMeshProUGUI>().text = g.response[_random.Next(0, g.response.Length - 1)];
 }
Exemplo n.º 2
0
        public async Task EndTurn()
        {
            lastMoveHighlight.Show(movesHistory.Actions.Last());
            DisplayEngineTurn = false;
            UpdateFEN();
            GameResultData resultData = gameState.GetResult();

            if (resultData.Result == GameResult.Ongoing)
            {
                await StartTurn();
            }
            else if (resultData.Result == GameResult.Win)
            {
                string color = resultData.Winner == 0 ? "White" : "Black";
                MessageBox.Show($"{color} won by checkmate!");
                GameEnded = true;
            }
            else
            {
                if (resultData.Reason == GameResultReason.Stalemate)
                {
                    MessageBox.Show($"Draw by stalemate");
                    GameEnded = true;
                }
                else if (!ignoreDraw)
                {
                    string drawMessage;
                    if (resultData.Reason == GameResultReason.ThreefoldRepetition)
                    {
                        drawMessage = "Draw by threefold repetition";
                    }
                    else
                    {
                        drawMessage = "Draw by 50-move rule";
                    }
                    MessageBoxResult result = MessageBox.Show($"{drawMessage}.\nDo you wish to continue?", "Draw", MessageBoxButton.YesNo);
                    if (result == MessageBoxResult.No)
                    {
                        GameEnded = true;
                    }
                    else
                    {
                        ignoreDraw = true;
                        await StartTurn();
                    }
                }
                else
                {
                    await StartTurn();
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// 棋譜の自動保存処理
        /// </summary>
        private void AutomaticSaveKifu(Move lastMove)
        {
            try
            {
                var lastColor = Position.sideToMove;

                // 1) 勝敗のカウンターを加算
                // (これは棋譜の自動保存が無効であってもなされなくてはならない)

                continuousGame.IncResult(lastMove, lastColor);

                // この対局棋譜を保存しなければならないなら保存する。
                var setting = TheApp.app.Config.GameResultSetting;
                if (!setting.AutomaticSaveKifu)
                {
                    return;
                }

                // 2) 棋譜ファイルを保存する。

                // プレイヤー名を棋譜上に反映させる。
                // → これは、DisplayName()と同等であればすでに設定されている。

                var kifu     = kifuManager.ToString(setting.KifuFileType);
                var filename = $"{continuousGame.GetKifuSubfolder()}{DefaultKifuFileName()}{setting.KifuFileType.ToExtensions()}";
                var filePath = Path.Combine(setting.KifuSaveFolder, filename);

                FileIO.WriteFile(filePath, kifu);

                // 3) csvファイルに情報をappendする。

                var table              = new GameResultTable();
                var csv_path           = setting.CsvFilePath();
                var handicapped        = Position.Handicapped;
                var timeSettingStrings = !handicapped ?
                                         $"先手:{TimeSettingString(Color.BLACK)},後手:{TimeSettingString(Color.WHITE)}" :
                                         $"下手:{TimeSettingString(Color.BLACK)},上手:{TimeSettingString(Color.WHITE)}";

                var result = new GameResultData()
                {
                    PlayerNames       = new[] { DisplayNameWithPreset(Color.BLACK), DisplayNameWithPreset(Color.WHITE) },
                    StartTime         = continuousGame.StartTime,
                    EndTime           = continuousGame.EndTime,
                    KifuFileName      = filename,
                    LastMove          = lastMove,
                    LastColor         = lastColor,
                    GamePly           = Position.gamePly - 1 /* 31手目で詰まされている場合、棋譜の手数としては30手であるため。 */,
                    BoardType         = kifuManager.Tree.rootBoardType,
                    TimeSettingString = timeSettingStrings,
                    Handicapped       = handicapped,
                    Comment           = null,
                };
                table.AppendLine(csv_path, result);

                // 連続対局の最終局であるなら、連続対局のトータルの結果を出力する。

                if (continuousGame.IsLastGame())
                {
                    // これが連続対局の最終局であったのなら、結果を書き出す。
                    result = new GameResultData()
                    {
                        Comment = continuousGame.GetGameResultString()
                    };
                    table.AppendLine(csv_path, result);
                }
            } catch (Exception ex)
            {
                // ファイルの書き出しに失敗などで例外が出て落ちるのはちょっと格好が悪いので捕捉しておく。
                TheApp.app.MessageShow(ex, false);
            }
        }
Exemplo n.º 4
0
        public int Evaluate(int depth, GameStage gameStage, int engineColor)
        {
            GameResultData resultData = gameState.GetResult();

            if (resultData.Result != GameResult.Ongoing)
            {
                if (resultData.Result == GameResult.Win)
                {
                    return(-CHECKMATE_SCORE - depth);
                }
                else
                {
                    return(GetDrawScore(engineColor));
                }
            }

            int score = 0;

            ulong[,] pieceAttacks = new ulong[2, 5];
            ulong[]  kingAttacks      = new ulong[2];
            int[]    kingAttacksScore = new int[2];
            ulong[]  kingSurrounding  = new ulong[2];
            int[]    kingFile         = { BitboardUtils.GetFile(BitboardUtils.BitScanForward(gameState.Pieces[0, (int)PieceType.King])),
                                          BitboardUtils.GetFile(BitboardUtils.BitScanForward(gameState.Pieces[1,            (int)PieceType.King])) };
            double[] kingAttackModifier = CalculateKingAttackModifier(kingFile);
            int[]    material           = new int[2];
            for (int pl = 0; pl <= 1; pl++)
            {
                if (gameStage != GameStage.Endgame)
                {
                    //rooks connected
                    int rooksConnectedScore = EvaluateRooksConnected(pl);
                    score += rooksConnectedScore;

                    //king safety
                    score += EvaluateKingFile(pl, kingFile[pl], rooksConnectedScore);

                    int startFile           = Math.Min(5, Math.Max(0, kingFile[pl] - 1));
                    int pawnProtectorsMoves = 0;
                    for (int f = startFile; f <= startFile + 2; f++)
                    {
                        ulong fileMask = BitboardUtils.GetFileMask(f);
                        //moved king pawns penalty
                        pawnProtectorsMoves += GetPawnMovesOfFile(pl, f, kingFile[pl]);

                        //pawn storm
                        ulong enemyPawnsOnFile = fileMask & gameState.Pieces[1 - pl, (int)PieceType.Pawn];
                        score += EvaluatePawnStorm(1 - pl, enemyPawnsOnFile, kingAttackModifier[1 - pl]);

                        //king open files penalty
                        score += EvaluateOpenKingFile(pl, enemyPawnsOnFile, kingAttackModifier[1 - pl]);
                    }
                    score += EvaluateKingPawnMoves(pl, pawnProtectorsMoves, kingAttackModifier[1 - pl]);
                }

                //pawn structure
                score += EvaluatePawnStructure(pl);

                ulong opKing = gameState.Pieces[1 - pl, (int)PieceType.King];
                int   file   = BitboardUtils.GetFile(BitboardUtils.BitScanForward(opKing));
                kingSurrounding[1 - pl] = opKing | gameState.MoveGenerators[(int)PieceType.King].GenerateAttacks(1 - pl);
                ulong opKingQuarter = GetKingQuarter(1 - pl, file);

                for (int i = 0; i < 5; i++)
                {
                    PieceType pieceType = (PieceType)i;
                    //material
                    score += EvaluateMaterial(pl, pieceType, material);

                    if (pieceType != PieceType.Pawn)
                    {
                        ulong piece = gameState.Pieces[pl, i];
                        while (piece > 0)
                        {
                            int   pieceSq = BitboardUtils.PopLSB(ref piece);
                            ulong attacks = gameState.MoveGenerators[i].GenerateAttacksFromSquare(pieceSq);

                            //mobility
                            score += EvaluateMobility(pl, pieceType, attacks, gameStage);

                            //center control
                            score += EvaluatePieceCenterControl(pl, pieceType, attacks);

                            if (pieceType == PieceType.Rook)
                            {
                                //rook on open file & 7th rank
                                score += EvaluateRookOpenFile(pl, pieceSq);
                                score += EvaluateRookRank(pl, pieceSq, gameStage);
                            }
                            else if (pieceType == PieceType.Knight)
                            {
                                //knight outpost
                                score += EvaluateKnightSquare(pl, pieceSq);
                            }

                            if (gameStage != GameStage.Endgame)
                            {
                                //king attack
                                ulong directKingAttacks  = kingSurrounding[1 - pl] & attacks;
                                ulong quarterKingAttacks = opKingQuarter & (attacks ^ directKingAttacks);
                                kingAttacks[pl] |= directKingAttacks | quarterKingAttacks;
                                CalculatePieceKingAttackScore(pl, pieceType, directKingAttacks, quarterKingAttacks, kingAttackModifier[pl], kingAttacksScore);
                                pieceAttacks[pl, i] |= attacks;
                            }
                        }
                    }
                }
            }

            if (gameStage != GameStage.Endgame)
            {
                //complete king attack analysis
                for (int pl = 0; pl <= 1; pl++)
                {
                    for (int i = 0; i < 5; i++)
                    {
                        CalculatePieceKingDefenseScore(pl, (PieceType)i, pieceAttacks[pl, i], kingAttacks[1 - pl], kingSurrounding[pl], kingAttacksScore);
                    }
                    score += EvaluateAttackVsDefense(1 - pl, kingAttacksScore);
                }
            }
            else
            {
                //endgame specific parameters
                for (int pl = 0; pl <= 1; pl++)
                {
                    //advanced king bonus
                    score += EvaluateEndgameKingSquare(pl);

                    //big material advantage
                    //march king towards enemy king, and push enemy king to the corner
                    score += EvaluateEndgameCornerMate(pl, material);

                    //King & Pawn vs King
                    score += EvaluateEndgameKPK(pl, material);
                }
            }
            return(score);
        }