예제 #1
0
파일: AI.cs 프로젝트: DKirikov/Unity3D_CFG
        private List <MoveInfo> GetAvailableCardMoves(GameboardImpl board)       //Todo: change it on GetBestMoves
        {
            List <MoveInfo> res = new List <MoveInfo>();

            CommandInfo command = board.commands[board.cur_command_idx];

            List <CardImpl> cards = command.hand;

            foreach (CardImpl card in cards)
            {
                List <Move> moves = card.GetMoves(board);

                //foreach (Move move in moves)
                //res.Add(new MoveInfo(move));

                if (moves.Count > 0)
                {
                    Random rand  = new Random();
                    int    index = rand.Next(moves.Count);
                    res.Add(new MoveInfo(moves[index]));
                }
            }

            return(res);
        }
예제 #2
0
        public static double GetBoardWeight(GameboardImpl board, bool isMax)        //ToDo: improve it
        {
            double res = 0;

            for (int j = 0; j < board.commands.Length; j++)
            {
                double      weight  = 0;
                CommandInfo command = board.commands[j];

                foreach (UnitImpl unit in command.staff)
                {
                    weight += unit.CalculateWeight();
                }

                if (j == board.cur_command_idx)
                {
                    res += weight;
                }
                else
                {
                    res -= weight;
                }
            }

            res += board.commands[board.cur_command_idx].crystals_count * 0.9;

            if (!isMax)             // is Min
            {
                res *= -1;
            }

            return(res);
        }
예제 #3
0
        public List <Move> GetMoves(GameboardImpl gameboard_ref)
        {
            List <Move> ret = new List <Move>();

            var command = gameboard_ref.commands [gameboard_ref.cur_command_idx];

            if (command.crystals_count >= cost)
            {
                if (isMagic)
                {
                    List <GameboardCell> target_cell = gameboard_ref.AddRangedMoves(gameboard_ref.cur_command_idx, healing > 0, strength > 0);
                    foreach (var cell in target_cell)
                    {
                        ret.Add(new MagicMoveImpl(cell, command.hand.FindIndex(x => x == this), cell.unit.command_idx == gameboard_ref.cur_command_idx));
                    }
                }
                else
                {
                    List <OrientedCell> available_cells = gameboard_ref.CalcAvailableCellsForCard(isGiant);

                    foreach (var cell in available_cells)
                    {
                        ret.Add(new CardMoveImpl(cell.cell, cell.orientation, command.hand.FindIndex(x => x == this)));
                    }
                }
            }

            return(ret);
        }
예제 #4
0
        public List <Move> GetMoves(GameboardImpl gameboard_ref)
        {
            List <Move> ret         = new List <Move>();
            List <Move> simpleMoves = new List <Move>();

            if (!made_move)
            {
                List <Routing.CAvailableCells> available_cells = new List <Routing.CAvailableCells>();

                if (isTeleport)                 //ToDo fill available_cells in case of giant teleport
                {
                    foreach (var cell in gameboard_ref.cells)
                    {
                        if (cell.active && cell.unit == null)                         //ToDo move to GameboardImpl
                        {
                            available_cells.Add(new Routing.CAvailableCells(new OrientedCell {
                                cell = cell
                            }, 0));
                        }
                    }
                }
                else
                {
                    available_cells = new Routing(gameboard_ref).CalcAvailableCells(oriented_cell, isGiant ? speed * 2 : speed);
                }

                if (isRangedAttack)
                {
                    List <GameboardCell> target_cell = gameboard_ref.AddRangedMoves(command_idx, healing > 0, strength > 0);
                    foreach (var cell in target_cell)
                    {
                        ret.Add(new KillMoveImpl(oriented_cell.cell, oriented_cell.orientation, oriented_cell.cell, cell, 0, cell.unit.command_idx == command_idx));
                    }
                }

                if (!isRangedAttack)
                {
                    AddNeighborKills(gameboard_ref, oriented_cell, ret, 0);
                }

                foreach (var cell in available_cells)
                {
                    simpleMoves.Add(new MoveImpl(cell.cell, cell.orientation, oriented_cell.cell, cell.steps));

                    if (!isRangedAttack)
                    {
                        AddNeighborKills(gameboard_ref, cell, ret, cell.steps);
                    }
                }

                ret.Sort((x, y) => x.Steps - y.Steps);
                simpleMoves.Sort((x, y) => y.Steps - x.Steps);

                ret.AddRange(simpleMoves);

                ret.Add(new SkipMoveImpl(oriented_cell.cell));
            }

            return(ret);
        }
예제 #5
0
파일: AI.cs 프로젝트: DKirikov/Unity3D_CFG
        private void CalculateAllCardMoves()
        {
            MoveInfo move = null;

            DateTime t0 = DateTime.Now;

            c = 0;

            List <MoveInfo> cardMoves = GetAvailableCardMoves(currentBoard);

            c++;
            double        bestWeight = AIHelper.GetBoardWeight(currentBoard, true);
            GameboardImpl bestBoard  = currentBoard;

            foreach (MoveInfo cardMove in cardMoves)
            {
                GameboardImpl newBoard = currentBoard.MakeCopy();
                cardMove.move.MakeMove(newBoard);

                c++;
                double newWeight = AIHelper.GetBoardWeight(newBoard, true);
                if (newWeight > bestWeight)
                {
                    bestWeight = newWeight;
                    bestBoard  = newBoard;
                    move       = cardMove;
                }
            }

            currentBoard = bestBoard;

            if (move == null)
            {
                return;
            }

            if (onCalculateMove != null)
            {
                onCalculateMove(move.move);
            }

            move.c                     = c;
            move.dt                    = (DateTime.Now - t0).TotalMilliseconds;
            move.makeMoveCount         = makeMoveCount;
            move.makeMoves             = makeMoves;
            move.getMovesCount         = getMovesCount;
            move.getMoves              = getMoves;
            move.calcRouteToMultyCount = calcRouteToMultyCount;
            move.calcRouteToMulty      = calcRouteToMulty;

            AIHelper.ShowLogForMove(move);

            CalculateAllCardMoves();
        }
예제 #6
0
        private void AddNeighborKills(GameboardImpl gameboard_ref, OrientedCell cell, List <Move> ret, int steps)
        {
            List <GameboardCell> neighbor_cells = gameboard_ref.GetNeighborCells(cell);

            foreach (GameboardCell neighbor_cell in neighbor_cells)
            {
                if (neighbor_cell.unit != null && neighbor_cell.unit.command_idx != command_idx)//Frendly fire
                {
                    ret.Add(new KillMoveImpl(cell.cell, cell.orientation, oriented_cell.cell, neighbor_cell, steps, false));
                }
            }
        }
예제 #7
0
파일: AI.cs 프로젝트: DKirikov/Unity3D_CFG
        private bool CheckBoard(GameboardImpl board, List <GameboardImpl> uniqueBoards)
        {
            foreach (GameboardImpl b in uniqueBoards)
            {
                if (b.commands[0].staff.Count != b.commands[0].staff.Count || b.commands[1].staff.Count != b.commands[1].staff.Count)
                {
                    continue;
                }

                bool isBreak = false;
                for (int n = 0; n < 2; n++)
                {
                    for (int i = 0; i < b.commands[n].staff.Count; i++)
                    {
                        UnitImpl unit0 = b.commands[n].staff[i];
                        UnitImpl unit1 = board.commands[n].staff[i];

                        if (unit0.id == unit1.id && unit0.hp == unit1.hp &&
                            unit0.oriented_cell.orientation == unit1.oriented_cell.orientation &&
                            Math.Abs(unit0.oriented_cell.cell.board_x - unit1.oriented_cell.cell.board_x) < 1 &&
                            Math.Abs(unit0.oriented_cell.cell.board_y - unit1.oriented_cell.cell.board_y) < 1)
                        {
                            continue;
                        }

                        isBreak = true;
                        break;
                    }

                    if (isBreak)
                    {
                        break;
                    }
                }

                if (!isBreak)
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #8
0
파일: AI.cs 프로젝트: DKirikov/Unity3D_CFG
        private GameboardImpl MakeEndOfTurn(GameboardImpl board)//ToDo: remove it
        {
            GameboardImpl newBoard = board.MakeCopy();

            if (newBoard.cur_command_idx == 0)
            {
                newBoard.cur_command_idx = 1;
            }
            else
            {
                newBoard.cur_command_idx = 0;
            }

            CommandInfo command = newBoard.commands[newBoard.cur_command_idx];

            foreach (UnitImpl unit in command.staff)
            {
                unit.made_move = false;
            }

            return(newBoard);
        }
예제 #9
0
        public GameboardImpl MakeCopy()
        {
            GameboardImpl ret = new GameboardImpl();

            for (int player_idx = 0; player_idx < players_qty; ++player_idx)
            {
                ret.commands[player_idx] = new CommandInfo();

                foreach (UnitImpl unit in commands[player_idx].staff)
                {
                    UnitImpl new_unit = new UnitImpl(unit);

                    new_unit.oriented_cell.orientation = unit.oriented_cell.orientation;
                    new_unit.oriented_cell.cell        = ret.cells[unit.oriented_cell.cell.board_x, unit.oriented_cell.cell.board_y];
                    SetUnitPlace(new_unit.oriented_cell, new_unit);

                    //ToDo check for something else

                    ret.commands[player_idx].staff.Add(new_unit);
                }

                ret.commands[player_idx].crystals_count = commands[player_idx].crystals_count;
                ret.commands[player_idx].crystals_inc   = commands[player_idx].crystals_inc;

                foreach (CardImpl cardImpl in commands[player_idx].hand)
                {
                    ret.commands[player_idx].hand.Add(new CardImpl(cardImpl));
                }

                foreach (CardImpl cardImpl in commands[player_idx].deck)
                {
                    ret.commands[player_idx].deck.Add(new CardImpl(cardImpl));
                }
            }

            ret.cur_command_idx = cur_command_idx;

            return(ret);
        }
예제 #10
0
파일: AI.cs 프로젝트: DKirikov/Unity3D_CFG
        private List <MoveInfo>[] GetMovesByDistForWalkerMode(GameboardImpl board, UnitImpl unit, bool isMax)   //ToDo: move it to AIHelper
        {
            //1:
            int oldSpeed = unit.speed;

            unit.speed = 100;

            DateTime    t0          = DateTime.Now;
            List <Move> simpleMoves = unit.GetMoves(board);

            getMovesCount++;
            getMoves  += (DateTime.Now - t0).TotalMilliseconds;
            unit.speed = oldSpeed;

            List <MoveInfo> moves = new List <MoveInfo>();
            //2:
            int maxDist = 0;

            foreach (Move move in simpleMoves)
            {
                MoveInfo moveInfo = new MoveInfo(move);
                moves.Add(moveInfo);

                t0 = DateTime.Now;
                //2.1:
                moveInfo.board = board.MakeCopy();
                move.MakeMove(moveInfo.board);
                makeMoveCount++;
                makeMoves += (DateTime.Now - t0).TotalMilliseconds;

                //2.1:
                c++;
                moveInfo.weight = AIHelper.GetBoardWeight(moveInfo.board, isMax);

                //2.2:
                moveInfo.distance = (int)Math.Ceiling(move.Steps / (double)oldSpeed);
                if (moveInfo.distance == 0)
                {
                    moveInfo.distance = 1;
                }

                if (moveInfo.distance > maxDist)
                {
                    maxDist = moveInfo.distance;
                }
            }

            maxDist++;            //it because array size will be count + 1

            //3:
            List <MoveInfo>[] movesByDist = new List <MoveInfo> [maxDist];
            for (int i = 0; i < maxDist; i++)
            {
                movesByDist[i] = new List <MoveInfo>();
            }

            foreach (MoveInfo move in moves)
            {
                movesByDist[move.distance].Add(move);
            }

            return(movesByDist);
        }
예제 #11
0
파일: AI.cs 프로젝트: DKirikov/Unity3D_CFG
        private List <MoveInfo> GetBestMoves(GameboardImpl board, UnitImpl unit, bool isMax)
        {
            List <MoveInfo>[] movesByDist = GetMovesByDistForWalkerMode(board, unit, isMax);

            //3:
            int maxDist = movesByDist.Length;

            List <MoveInfo>[] bestMovesByDist = new List <MoveInfo> [maxDist];
            for (int i = 1; i < maxDist; i++)
            {
                bestMovesByDist[i] = new List <MoveInfo>();
                double bestW = isMax ? double.MinValue : double.MaxValue;

                foreach (MoveInfo move in movesByDist[i])
                {
                    if ((isMax && move.weight > bestW) ||
                        (!isMax && move.weight < bestW))
                    {
                        bestW = move.weight;
                    }
                }

                foreach (MoveInfo move in movesByDist[i])
                {
                    if (move.weight == bestW)
                    {
                        bestMovesByDist[i].Add(move);
                    }
                }
            }

            //4:
            //and 5 and 6:
            c++;
            double bestWeight           = AIHelper.GetBoardWeight(board, isMax);
            int    bestNearestDistIndex = 1;
            int    bestDistIndex        = 1;

            for (int i = 1; i < maxDist; i++)
            {
                double w = bestMovesByDist[i][0].weight;
                if ((isMax && w > bestWeight) ||
                    (!isMax && w < bestWeight))
                {
                    bestWeight    = w;
                    bestDistIndex = i;
                    if (bestNearestDistIndex == 1)
                    {
                        bestNearestDistIndex = i;
                    }
                }
            }

            List <MoveInfo> res = new List <MoveInfo>();

            if (bestNearestDistIndex == 1)
            {
                //Random rand = new Random();
                //int index = rand.Next(bestMovesByDist[1].Count);
                res.Add(bestMovesByDist[1][bestMovesByDist[1].Count - 1]);
            }
            else
            {
                MoveInfo moveInfo = BestMoveForGoToTargetCell(movesByDist[1], bestMovesByDist[bestNearestDistIndex], bestNearestDistIndex - 1, unit.speed);
                res.Add(moveInfo);
            }

            if (bestNearestDistIndex != bestDistIndex)
            {
                MoveInfo moveInfo = BestMoveForGoToTargetCell(movesByDist[1], bestMovesByDist[bestDistIndex], bestDistIndex - 1, unit.speed);

                if (res[0] != moveInfo)
                {
                    res.Add(moveInfo);
                }
            }

            return(res);
        }
예제 #12
0
파일: AI.cs 프로젝트: DKirikov/Unity3D_CFG
 public AI(GameboardImpl board)
 {
     this.currentBoard = board.MakeCopy();
 }
예제 #13
0
파일: AI.cs 프로젝트: DKirikov/Unity3D_CFG
        private MoveInfo CalculateBoardWeight(GameboardImpl board, out double bestWeight, int depth, bool isMax, double alpha, double beta)
        {
            DateTime time0        = DateTime.Now;
            MoveInfo bestMoveInfo = null;

            bestWeight = isMax ? alpha : beta;

            CommandInfo command = board.commands[board.cur_command_idx];

            foreach (UnitImpl unit in command.staff)
            {
                if (unit.made_move)
                {
                    continue;
                }

                double candidateWeight;

                List <MoveInfo> moves = GetBestMoves(board, unit, isMax);

                bool allUnitsMoved = NoActiveUnitsCount(command.staff) == 1;
                foreach (MoveInfo move in moves)
                {
                    DateTime      t0       = DateTime.Now;
                    GameboardImpl newBoard = board.MakeCopy();
                    move.move.MakeMove(newBoard);
                    makeMoveCount++;
                    makeMoves += (DateTime.Now - t0).TotalMilliseconds;

                    MoveInfo nextMove = null;

                    if (newBoard.is_game_finished)
                    {
                        c++;
                        candidateWeight = AIHelper.GetBoardWeight(newBoard, isMax);
                    }
                    else
                    {
                        if (allUnitsMoved)
                        {
                            if (depth > 1)                            // && !newBoard.is_game_finished
                            {
                                newBoard = MakeEndOfTurn(newBoard);
                                if (isMax)
                                {
                                    CalculateBoardWeight(newBoard, out candidateWeight, depth - 1, !isMax, bestWeight, beta);
                                }
                                else
                                {
                                    CalculateBoardWeight(newBoard, out candidateWeight, depth - 1, !isMax, alpha, bestWeight);
                                }
                            }
                            else
                            {
                                c++;
                                candidateWeight = AIHelper.GetBoardWeight(newBoard, isMax);
                            }
                        }
                        else
                        {
                            if (isMax)
                            {
                                nextMove = CalculateBoardWeight(newBoard, out candidateWeight, depth, isMax, bestWeight, beta);
                            }
                            else
                            {
                                nextMove = CalculateBoardWeight(newBoard, out candidateWeight, depth, isMax, alpha, bestWeight);
                            }
                        }
                    }

                    //if (UpdateWeight(move, ref bestWeight, ref bestMoveInfo, isMax, candidateWeight) && depth == maxDepth)
                    //bestMoveInfo.nextMove = nextMove;

                    if (isMax && candidateWeight > bestWeight ||
                        !isMax && candidateWeight < bestWeight)
                    {
                        bestWeight   = candidateWeight;
                        bestMoveInfo = move;

                        if (depth == maxDepth)
                        {
                            bestMoveInfo.nextMove = nextMove;
                        }
                    }

                    if ((!isMax && candidateWeight <= alpha) || (isMax && candidateWeight >= beta))
                    {
                        break;
                    }
                }

                break;                 //for remove unnecessary moves
            }

            if (bestMoveInfo != null)
            {
                bestMoveInfo.dt = (DateTime.Now - time0).TotalMilliseconds;
            }

            return(bestMoveInfo);
        }
예제 #14
0
 public Routing(GameboardImpl gameboard)
 {
     this.gameboard = gameboard;
 }