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); }
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); }
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); }
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); }
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(); }
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)); } } }
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); }
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); }
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); }
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); }
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); }
public AI(GameboardImpl board) { this.currentBoard = board.MakeCopy(); }
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); }
public Routing(GameboardImpl gameboard) { this.gameboard = gameboard; }