Esempio n. 1
0
        /// <summary>
        /// Writes <see cref="AIResult"/> and <see cref="Bitboard"/> objects as new line to the csv file.
        /// </summary>
        /// <param name="aiResult">The AI result.</param>
        /// <param name="bitboard">The bitboard.</param>
        public void WriteLine(AIResult aiResult, Bitboard bitboard)
        {
            using (var csvLogger = OpenOrCreateFile(FileExtension))
            {
                if (csvLogger.BaseStream.Length == 0)
                {
                    WriteValues(csvLogger, _header);
                }

                var values = new List <string>
                {
                    GetCurrentTime(),
                    aiResult.PVNodes.ToString(),
                    aiResult.Stats.TotalNodes.ToString(),
                    aiResult.Stats.EndNodes.ToString(),
                    aiResult.Stats.AlphaBetaCutoffs.ToString(),
                    aiResult.Stats.TranspositionTableHits.ToString(),
                    aiResult.Stats.BranchingFactor.ToString(),
                    aiResult.NodesPerSecond.ToString(),
                    aiResult.TimePerNode.ToString(),
                    aiResult.Depth.ToString(),
                    aiResult.Score.ToString(),
                    aiResult.PreferredTime.ToString(AITimeFormat),
                    aiResult.Time.ToString(AITimeFormat),
                    bitboard.Occupancy[0].ToString(),
                    bitboard.Occupancy[1].ToString(),
                    bitboard.GamePhase.ToString()
                };

                WriteValues(csvLogger, values);
            }
        }
Esempio n. 2
0
 private void AICallback(AIResult result)
 {
     if (result == null)
     {
         return;
     }
     Controls.Find(result.LabelName, false).First().Text = result.Content;
 }
Esempio n. 3
0
    /// <summary>
    /// 原地休息
    /// </summary>
    /// <param name="sprite">Sprite.</param>
    public AIResult Rest(RoleInstance sprite)
    {
        AIResult rst = new AIResult
        {
            MoveX  = sprite.Pos.X,
            MoveY  = sprite.Pos.Y,
            IsRest = true
        };

        return(rst);
    }
Esempio n. 4
0
    private IEnumerator OnMove()
    {
        while (!isDone && moveRound == GameManager.Instance.GetCurRound())
        {
            yield return(0);
        }
        if (moveRound != GameManager.Instance.GetCurRound())
        {
            moveThread.Abort();
            EndMove();
            yield break;
        }

        for (int i = 0; i < result.Count; ++i)
        {
            AIResult v = result[i];
            if (timer.GameTurnStatus == GameTurnStatus.WaitingForDrop)
            {
                if (timer.waitingTime > intervalSecond * result.Count)
                {
                    float maxRandSec = timer.waitingTime - intervalSecond * result.Count;
                    float minRandSec = 1f;
                    maxRandSec = maxRandSec > 5 ? 5 : maxRandSec;
                    minRandSec = maxRandSec > minRandSec ? minRandSec : maxRandSec;
                    float randSec = UnityEngine.Random.Range(minRandSec, maxRandSec);
                    yield return(new WaitForSeconds(randSec));
                }
            }
            else if (timer.GameTurnStatus == GameTurnStatus.DropingMore)
            {
                if (timer.selectTime > intervalSecond * (result.Count - i))
                {
                    yield return(new WaitForSeconds(intervalSecond));
                }
            }

            if (moveRound != GameManager.Instance.GetCurRound())
            {
                break;
            }
            boardManager.SelectPiece(v.x, v.y);
            if (isBeSkilled)
            {
                isBeSkilled = false;
                break;
            }
        }

        EndMove();
    }
Esempio n. 5
0
 private void Update()
 {
     if (executionTree != null)
     {
         if (executionTree.MoveNext())
         {
             lastResult = executionTree.Current;
         }
         else
         {
             result.TrySetResult(lastResult);
             Destroy(this);
         }
     }
 }
Esempio n. 6
0
    void TurnEnd()
    {
        CurrentTurn = (CurrentTurn + 1) % 2;
        CheckCellEnable();
        if (CurrentTurn == 0)
        {
            // 4つ目引数は何手先までを読むか
            AIResult result = Recursive(OthelloCells, CurrentTurn, false, 7);
            if (result.cell == null)
            {
                // null の場合は、CPUの番はパス
                return;
            }

            PutCell(result.cell, false);
        }
    }
Esempio n. 7
0
    /// <summary>
    /// 靠近自己最近的敌人
    /// </summary>
    /// <returns>The to nearest enemy.</returns>
    /// <param name="sprite">Sprite.</param>
    /// <param name="moverange">Moverange.</param>
    public AIResult MoveToNearestEnemy(RoleInstance sprite, List <BattleBlockVector> range)
    {
        var tmp = GetNearestEnemyBlock(sprite, range);

        if (tmp == null)
        {
            return(null);
        }

        AIResult rst = new AIResult
        {
            Zhaoshi = null,
            MoveX   = tmp.X,
            MoveY   = tmp.Y,
            IsRest  = true //靠近对手
        };

        return(rst);
    }
Esempio n. 8
0
    public static AIResult FindBestMove(bool side, Board board, int depth)
    {
        DateTime inicio = DateTime.Now;

        AIResult    result    = new AIResult();
        int         bestValue = side ? -100000 : 100000;
        List <Move> bestMoves = new List <Move>();
        int         alpha     = -100000;
        int         beta      = 100000;

        result.leaves = 0;
        board.side    = side;
        for (int i = 0; i < board.Count(); i++)
        {
            List <Move> moves = board.GetAllMovements(i);
            for (int j = 0; j < moves.Count; j++)
            {
                Board newBoard = board.Clone();
                newBoard.MovePiece(moves[j].piece, moves[j].position);

                int value = EvaluateNode(newBoard, 1, !side, ref result.leaves, alpha, beta) + newBoard.EvaluateBoard() / 10;
                if ((!side && value <= bestValue) || (side && value >= bestValue))
                {
                    if (bestValue != value)
                    {
                        bestMoves.Clear();
                    }
                    bestValue = value;
                    bestMoves.Add(moves[j]);
                }
            }
        }
        result.bestValue = bestValue;
        var random = new System.Random(DateTime.Now.Second + alpha + beta + result.leaves);

        result.move = bestMoves[random.Next() % bestMoves.Count];
        board.Initialize();
        result.time = DateTime.Now.Subtract(inicio);

        return(result);
    }
Esempio n. 9
0
    public override void OnEnterState()
    {
        BattleboxHelper.Instance.HideAllBlocks();
        BattleStateMechine.Instance.BindBattleAction(null);

        m_currentRole = BattleStateMechine.Instance.CurrentRole;
        if (m_currentRole == null)
        {
            GameUtil.LogError("ai当前角色为空");
            return;
        }
        AIManager.Instance.GetAIResult(BattleStateMechine.Instance.CurrentRole, (result) =>
        {
            m_aiResult = result;
            BattleBlockVector MoveTo    = new BattleBlockVector(result.MoveX, result.MoveY);
            BattleBlockVector SkillTo   = new BattleBlockVector(result.AttackX, result.AttackY);
            BattleZhaoshiInstance Skill = result.Zhaoshi;
            Jyx2Item Item = result.Item;
            DoAIAction(MoveTo, SkillTo, Skill, Item);
        });
    }
Esempio n. 10
0
    public void GetAIResultClassic(RoleInstance role, Action <AIResult> callback)
    {
        //初始化范围逻辑
        //rangeLogic = new RangeLogic(BattleboxHelper.Instance.IsBlockExists, BattleModel.BlockHasRole);

        //获得角色移动能力
        int moveAbility = role.GetMoveAbility();

        //行动范围
        var range = rangeLogic.GetMoveRange(role.Pos.X, role.Pos.Y, moveAbility);

        //可使用招式
        var zhaoshis = role.GetZhaoshis(false);

        //TODO:攻击计算缓存 by Cherubinxxx
        //AttackResultCache cache = new AttackResultCache(currentSprite, Field);

        //AI算法:穷举每个点,使用招式,取最大收益
        AIResult result   = null;
        double   maxscore = 0;

        foreach (var zhaoshi in zhaoshis)
        {
            if (zhaoshi.GetStatus() != BattleZhaoshiInstance.ZhaoshiStatus.OK)
            {
                continue;
            }

            GetMoveAndCastPos(role, zhaoshi, range);

            BattleBlockVector[] tmp = m_GetMoveAndCastPosResult;
            if (tmp != null && tmp.Length == 2 && tmp[0] != null)
            {
                BattleBlockVector movePos = tmp[0];
                BattleBlockVector castPos = tmp[1];
                double            score   = GetSkillCastResultScore(role, zhaoshi, movePos.X, movePos.Y, castPos.X, castPos.Y, true);
                // yield return 0; //分帧
                //if (score <= 0 && rst.HitEnemyCount > 0)
                //{
                //    score = ToolsShared.GetRandom(0, 1);
                //}
                if (score > maxscore)
                {
                    maxscore = score;
                    result   = new AIResult
                    {
                        AttackX = castPos.X,
                        AttackY = castPos.Y,
                        MoveX   = movePos.X,
                        MoveY   = movePos.Y,
                        Zhaoshi = zhaoshi,
                        IsRest  = false
                    };
                }
            }
        }

        //考虑吃药
        if (role.Items.Count > 0 && (role.Hp < 0.2 * role.MaxHp || role.Mp < 0.2 * role.MaxMp || role.Tili < 0.2 * Jyx2Consts.MaxTili))
        {
            List <Jyx2Item> items = GetAvailableItems(role, 3); //只使用药物
            foreach (var item in items)
            {
                double score = 0;
                //尽量吃刚刚好的药
                if (item.AddHp > 0)
                {
                    score += Mathf.Min(item.AddHp, role.MaxHp - role.Hp) - item.AddHp / 10;
                }
                if (item.AddMp > 0)
                {
                    score += Mathf.Min(item.AddMp, role.MaxMp - role.Mp) / 2 - item.AddMp / 10;
                }
                if (item.AddTili > 0)
                {
                    score += Mathf.Min(item.AddTili, Jyx2Consts.MaxTili - role.Tili) - item.AddTili / 10;
                }

                if (score > 0)
                {
                    score *= 1.5;//自保系数大
                }

                if (score > maxscore)
                {
                    maxscore = score;
                    var tmp = GetFarestEnemyBlock(role, range);
                    result = new AIResult
                    {
                        MoveX  = tmp.X,
                        MoveY  = tmp.Y,
                        IsRest = false,
                        Item   = item
                    };
                }
            }
        }

        List <Jyx2Item> anqis = GetAvailableItems(role, 4); //获取暗器

        //使用暗器
        if (anqis.Count > 0)
        {
            foreach (var anqi in anqis)
            {
                BattleZhaoshiInstance anqizhaoshi = new AnqiZhaoshiInstance(role.Anqi, anqi);

                if (anqizhaoshi.GetStatus() != BattleZhaoshiInstance.ZhaoshiStatus.OK)
                {
                    continue;
                }

                GetMoveAndCastPos(role, anqizhaoshi, range);

                BattleBlockVector[] tmp = m_GetMoveAndCastPosResult;
                if (tmp != null && tmp.Length == 2 && tmp[0] != null)
                {
                    BattleBlockVector movePos = tmp[0];
                    BattleBlockVector castPos = tmp[1];
                    double            score   = GetSkillCastResultScore(role, anqizhaoshi, movePos.X, movePos.Y, castPos.X, castPos.Y, true);

                    if (score > maxscore)
                    {
                        maxscore = score;
                        result   = new AIResult
                        {
                            AttackX = castPos.X,
                            AttackY = castPos.Y,
                            MoveX   = movePos.X,
                            MoveY   = movePos.Y,
                            Zhaoshi = anqizhaoshi,
                            IsRest  = false
                        };
                    }
                }
            }
        }

        //Debug.Log(Time.realtimeSinceStartup);

        if (result != null)
        {
            callback(result);
            return;
        }

        //否则靠近自己最近的敌人
        result = MoveToNearestEnemy(role, range);
        if (result != null)
        {
            callback(result);
            return;
        }

        //否则原地休息
        callback(Rest(role));
        return;
    }
Esempio n. 11
0
 public override void OnLeaveState()
 {
     m_aiResult    = null;
     m_currentRole = null;
 }
Esempio n. 12
0
    // 引数の組み合わせで、そのときのturnから見たときの点数が戻り値
    AIResult Recursive(OthelloCell[,] aiField, int turn, bool prevPass, int depth)
    {
        List <OthelloCell> cells = GetEnableCells(aiField, turn);

        if (cells.Count == 0)
        {
            // 打てるところがない
            if (prevPass)
            {
                // 前回パスしていたら、連続パスなのでゲーム終了 (AIが思考上でゲームが終わったときの判定も含む)
                // 白と黒の数をカウントする
                int white = 0;
                int black = 0;
                for (int i = 0; i < BoardSize; i++)
                {
                    for (int j = 0; j < BoardSize; j++)
                    {
                        if (aiField[i, j].OwnerID == 0)
                        {
                            white++;
                        }
                        else if (aiField[i, j].OwnerID == 1)
                        {
                            black++;
                        }
                    }
                }

                if ((turn == 0 && white > black) ||
                    (turn == 1 && white < black))
                {
                    return(new AIResult {
                        point = 99999
                    });                                  // 勝ちなのでスコアとしてはでかい数を返す
                }

                return(new AIResult {
                    point = -99999
                });                                   // 負けなのでスコアとして小さい数を返す
            }
            else
            {
                // 前回パスしていなかったら 普通にパスする(ターンを変えて関数を呼ぶ)
                // 相手のターンでの点数が自分の逆なのでマイナスにする
                // 一旦AIResult型で受け取ってポイント部分をマイナスにして新しく返す
                AIResult result = Recursive(aiField, (turn + 1) % 2, true, depth);
                return(new AIResult {
                    point = -result.point
                });
            }
        }
        else
        {
            // 打てるところがあるので打っていく
            // 一番点数が高いものを選ぶ
            int maxPoint = int.MinValue;
            int maxIndex = 0;


            for (int index = 0; index < cells.Count; index++)
            {
                // 引数で与えられた盤面をコピーする
                for (int i = 0; i < BoardSize; i++)
                {
                    for (int j = 0; j < BoardSize; j++)
                    {
                        currentField[i, j].OwnerID = aiField[i, j].OwnerID;
                    }
                }

                // その選択でひっくり返えす
                CheckAndReverse(currentField, cells[index], turn, true);
                // 打った場所の点数
                int point = points[(int)cells[index].Location.y, (int)cells[index].Location.x];
                // 1手先、打つ処理に渡す depthを1引いているのがポイント
                // Recursiveの呼び出しでは相手の点数によって自分の点数が下がるので 引く
                // 例えば、今、黒なら ターンが変わって白が打つ → 戻り値は白が打ったときの点数→ 黒から見ると逆の点数になるので引いている
                if (depth > 0)
                {
                    point -= Recursive(currentField, (turn + 1) % 2, false, depth - 1).point;
                }

                if (maxPoint < point)
                {
                    // 点数の更新をする、その時、何番目を選んだかも保持する
                    maxPoint = point;
                    maxIndex = index;
                }
            }

            // 計算した点数と、そのときに選ぶセル返すようにする
            return(new AIResult {
                point = maxPoint, cell = cells[maxIndex]
            });
        }
    }
Esempio n. 13
0
 public AILesson(int segIdx, AIInputBuffer inputBuffer, AIResult result)
 {
     _segIdx      = segIdx;
     _inputBuffer = inputBuffer;
     Result       = result;
 }