private string MakeAnswer(SnakeAction snakeAction) { switch (snakeAction) { case SnakeAction.Down: return("DOWN"); case SnakeAction.Left: return("LEFT"); case SnakeAction.Right: return("RIGHT"); case SnakeAction.Up: return("UP"); case SnakeAction.ActDown: return("ACT,DOWN"); case SnakeAction.ActLeft: return("ACT,LEFT"); case SnakeAction.ActRight: return("ACT,RIGHT"); case SnakeAction.ActUp: return("ACT,UP"); default: break; } return(""); }
private static void TestMyMovement() { var gameBoard = new GameBoard(Boards.Current); SnakeAction lastmove = SnakeAction.Left; while (true) { Movement.MakeEnemyMove(gameBoard); Console.Clear(); Graphical.WriteField(gameBoard); Console.WriteLine($"{gameBoard.Head.X}:{gameBoard.Head.Y}:{gameBoard.HeadType}: {gameBoard.MyLength} {gameBoard.EvilTicks} {gameBoard.HasStone}"); bool possible = false; SnakeAction action = SnakeAction.ActDown; Element newHead = new Element(-1, -1); do { var key = Console.ReadKey(); switch (key.Key) { case ConsoleKey.UpArrow: action = SnakeAction.Up; break; case ConsoleKey.DownArrow: action = SnakeAction.Down; break; case ConsoleKey.LeftArrow: action = SnakeAction.Left; break; case ConsoleKey.RightArrow: action = SnakeAction.Right; break; default: continue; } if (!PossiblyFilter.IsMovePossible(gameBoard, action, lastmove, true, out newHead)) { Console.WriteLine("Impossible"); } else { possible = true; } }while (!possible); lastmove = action; gameBoard = new GameBoard(gameBoard); Movement.MakeMyMove(gameBoard, action, ref newHead); } }
public SnakeAction Move(GameStatus state) { var response = new SnakeAction(); var snake = state.Snakes.FirstOrDefault(s => s.Id == state.You); if (snake != null) { response.Move = snake.Update(state); } return(response); }
internal static bool IsDirectionBaff(SnakeAction action, ref Element head, ref Element tail) { switch ((SnakeAction)((int)action & 0x0F)) { case SnakeAction.Up: return(tail.Y > head.Y); case SnakeAction.Down: return(tail.Y < head.Y); case SnakeAction.Left: return(tail.X > head.X); case SnakeAction.Right: return(tail.X < head.X); } return(false); }
internal static bool IsNearNyamkaBaff(SnakeAction action, ref Element head, ref Element nyamka) { switch ((SnakeAction)((int)action & 0x0F)) { case SnakeAction.Up: return(nyamka.Y < head.Y); case SnakeAction.Down: return(nyamka.Y > head.Y); case SnakeAction.Left: return(nyamka.X < head.X); case SnakeAction.Right: return(nyamka.X > head.X); } return(false); }
public static void MakeMyMove(GameBoard gameBoard, SnakeAction action, ref Element newHead) { //Console.Clear(); //Graphical.WriteField(gameBoard); //-----rage----- if (newHead.type == BoardElement.FuryPill) { gameBoard.EvilTicks += 9; } //clean enemies EnemyEraser.CleanEnemyShake(gameBoard, newHead.X, newHead.Y); var dontMoveTail = MeEraser.CleanMe(gameBoard, newHead.X, newHead.Y); MoveMyHead(gameBoard, ref newHead); if (!dontMoveTail && newHead.type != BoardElement.Apple) { MoveMyTail(gameBoard, ref newHead, false); } if (newHead.type == BoardElement.Apple) { gameBoard.MyLength++; } if (newHead.type == BoardElement.Stone) { gameBoard.HasStone = true; if (gameBoard.EvilTicks == 0) { MoveMyTail(gameBoard, ref newHead, false); MoveMyTail(gameBoard, ref newHead, false); MoveMyTail(gameBoard, ref newHead, false); gameBoard.MyLength -= 3; } } if (gameBoard.EvilTicks != 0) { gameBoard.EvilTicks--; } }
internal static void SetState(BoardElement eatedElement, SnakeAction action) { if (eatedElement == BoardElement.FuryPill) { rageCount += 9; } else if (rageCount > 0) { rageCount--; } if ((int)action >= 0x10) { hasStone = false; } if (eatedElement == BoardElement.Stone) { hasStone = true; } LastMove = action; }
public static bool IsMovePossible(GameBoard gameBoard, SnakeAction actionS, SnakeAction lastMoveS, bool real, out Element newHead) { var action = (int)actionS & 0x0F; var lastMove = (int)lastMoveS & 0x0F; newHead = new Element(-1, -1); //180 degrees switch (gameBoard.HeadType) { case BoardElement.HeadUp: if (action == (int)SnakeAction.Down) { return(false); } break; case BoardElement.HeadLeft: if (action == (int)SnakeAction.Right) { return(false); } break; case BoardElement.HeadRight: if (action == (int)SnakeAction.Left) { return(false); } break; case BoardElement.HeadDown: if (action == (int)SnakeAction.Up) { return(false); } break; case BoardElement.HeadEvil: switch (lastMove & 0x0F) { case (int)SnakeAction.Up: if (action == (int)SnakeAction.Down) { return(false); } break; case (int)SnakeAction.Left: if (action == (int)SnakeAction.Right) { return(false); } break; case (int)SnakeAction.Right: if (action == (int)SnakeAction.Left) { return(false); } break; case (int)SnakeAction.Down: if (action == (int)SnakeAction.Up) { return(false); } break; } break; case BoardElement.HeadDead: return(false); } //over field newHead = gameBoard.Head.MakeMovement(actionS, gameBoard.Size); if (newHead.X == -1) { return(false); } //stones newHead.type = gameBoard.Board[newHead.X, newHead.Y]; if (newHead.type == BoardElement.StartFloor || newHead.type == BoardElement.Wall) { return(false); } if (gameBoard.EvilTicks == 0 && gameBoard.MyLength < 5 && newHead.type == BoardElement.Stone) { return(false); } //enemies if (Lists.IsEnemyHead(newHead.type) || (Lists.IsEnemyBody(newHead.type) && Helpers.IsNear(gameBoard, newHead.X, newHead.Y, Lists.enemyHeads))) { var enemyAgro = newHead.type == BoardElement.EnemyHeadEvil || Helpers.IsNear(gameBoard, newHead.X, newHead.Y, BoardElement.EnemyHeadEvil); //--правила для головы-- //Если текущая змейка не в ярости, а вражеская в ярости - то текущая змейка умирает. if (gameBoard.EvilTicks == 0 && enemyAgro) { return(false); } //Если обе змейки в ярости или обе не в ярости - то от каждой отрезаем длину другой змейки. //То есть, если столкнулись две змейки длиной в 5 и в 7 единиц, то змейка длиной в пять погибает, так как 5-7<2, а змейка длиной в 7 принимает длину 2 единицы. else if ((gameBoard.EvilTicks != 0) == enemyAgro) { var(headLength, tailLength, _) = EnemyDetector.GetEnemyShake(gameBoard, newHead.X, newHead.Y); if (gameBoard.MyLength - (headLength + tailLength + 1) < 2) { return(false); } } } else if (Lists.IsEnemyBody(newHead.type) || Lists.IsEnemyTail(newHead.type)) { if (gameBoard.EvilTicks == 0) { return(false); } } return(true); }
// Call recursively private static async Task <long> GetActionWeight(GameBoard gameBoard, Element newHead, SnakeAction action, int depth) { long currentRate = Rates.GetElementRate(gameBoard, ref newHead); if (currentRate == long.MinValue) { return(long.MinValue); } //investigate new position //if (gameBoard.EvilTicks == 0) //{ // var (_, _, isEvilNear) = MeDetector.GetMe(gameBoard, gameBoard.Head.X, gameBoard.Head.Y); // if (isEvilNear) // currentRate -= 10; //} currentRate *= (15 - depth); if (depth == maxDeep) { return(currentRate); } //move me #if DEBUG try { #endif Movement.MakeMyMove(gameBoard, action, ref newHead); //add enemy predictions #if DEBUG } catch (Exception) { Graphical.WriteToLog(gameBoard); throw; } #endif Movement.MakeEnemyMove(gameBoard); //calculate my variants var tasks = new List <Task <long> >(); for (int i = 0; i < 4; i++) { SnakeAction a = (SnakeAction)i; var newBoard = new GameBoard(gameBoard); if (PossiblyFilter.IsMovePossible(newBoard, a, action, false, out var newNewHead)) { tasks.Add(GetActionWeight(newBoard, newNewHead, a, depth + 1)); } } if (tasks.Count == 0) { return(long.MinValue); } var myVariantsScore = long.MinValue; do { var completedTask = await Task.WhenAny(tasks); tasks.Remove(completedTask); #if DEBUG if (completedTask.IsFaulted) { Graphical.WriteToLog(gameBoard); throw completedTask.Exception; } #endif if (!completedTask.IsFaulted && completedTask.Result != long.MinValue && myVariantsScore < completedTask.Result) { myVariantsScore = completedTask.Result; } } while (tasks.Count > 0); if (myVariantsScore == long.MinValue) { return(long.MinValue); } currentRate += myVariantsScore; return(currentRate); }
public static async Task <SnakeAction?> GetOptimalActionAsync(GameBoard gameBoard, SnakeAction lastMove) { var tasks = new Dictionary <Task <long>, SnakeAction>(); for (int i = 0; i < 4; i++) { SnakeAction action = (SnakeAction)i; var newBoard = new GameBoard(gameBoard); if (PossiblyFilter.IsMovePossible(newBoard, action, lastMove, true, out Element newHead)) { tasks.Add(GetActionWeight(newBoard, newHead, action, 0), action); } } if (tasks.Count == 0) { return(null); } bool first = true; SnakeAction result = SnakeAction.Down; long score = 0; do { var completedTask = await Task.WhenAny(tasks.Keys); var action = tasks[completedTask]; long weight; if (completedTask.IsFaulted) { weight = long.MinValue; #if DEBUG Graphical.WriteToLog(gameBoard); #endif } else { weight = completedTask.Result; } if (Helpers.IsDirectionBaff(action, ref gameBoard.Head, ref gameBoard.Tail)) { weight += 1; } if (Helpers.IsNearNyamkaBaff(action, ref gameBoard.Head, ref gameBoard.Nyamka)) { weight += 10; } if (first || score < weight) { first = false; result = action; score = weight; } tasks.Remove(completedTask); } while (tasks.Count > 0); return(result); }