public static List <PositionNode> GetNextSteps(this Ship ship, PositionNode current) { PositionNode shipNode = new PositionNode(ship.pos, ship.rotation, ship.speed); List <PositionNode> path = new List <PositionNode>(); int count = 0; while (current != null && !current.Equals(shipNode) && current.parent != null && count < 30) { path.Add(current); current = current.parent; count++; } if (count >= 30) { Console.Error.WriteLine("Can't find shipNode"); return(null); } if (current != null && current.Equals(shipNode)) { path.Reverse(); return(path); } return(null); }
public static void InitializeNeighbours() { List <MoveType> validMoves = new List <MoveType> { MoveType.Wait, MoveType.Left, MoveType.Right, MoveType.Faster, MoveType.Slower, }; foreach (var current in nodeTable.Values) { foreach (MoveType move in validMoves) { int speed = current.speed; int rotation = current.rotation; switch (move) { case MoveType.Faster: speed += 1; break; case MoveType.Slower: speed -= 1; break; case MoveType.Right: rotation = (current.rotation + 5) % 6; break; case MoveType.Left: rotation = (current.rotation + 1) % 6; break; default: break; } if (speed > 2 || speed < 0 || (speed == 0 && move == MoveType.Wait)) { continue; } Vector pos = current.pos + Vector.directions[current.rotation] * speed; PositionNode newNode = new PositionNode(pos, rotation, speed); if (pos.isInBound()) { current.neighbours.Add(nodeTable[newNode], move); } } } }
public ShipPositionInfo(Vector pos, int rotation, int speed) { this.pos = pos; this.rotation = rotation; this.speed = speed; this.shipFront = this.pos + Vector.directions[this.rotation]; this.shipRight = this.pos + Vector.directions[(this.rotation + 5) % 6]; this.shipLeft = this.pos + Vector.directions[(this.rotation + 1) % 6]; this.shipBack = this.pos - Vector.directions[this.rotation]; this.minePos = this.pos - Vector.directions[this.rotation] * 2; this.positionNode = PositionNode.GetPositionNode(pos, rotation, speed); }
public static void InitializeNodes() { for (int x = 0; x <= 22; x++) { for (int y = 0; y <= 20; y++) { for (int speed = 0; speed <= 2; speed++) { for (int rotation = 0; rotation < Vector.directions.Count; rotation++) { Hex hexPos = new Hex(x, y); Vector pos = hexPos.ConvertCube(); PositionNode newNode = new PositionNode(pos, rotation, speed); nodeTable.Add(newNode, newNode); } } } } }
public static bool isPositionSafe(PositionNode node, Ship ship, int step) { foreach (var cannon in ship.dodgeableCannons) { foreach (var check in node.checkList) { if (cannon.turns == step && cannon.hexPos == check) { return(false); } } } foreach (var check in node.checkList) { if (Mine.minePos.Contains(check)) { return(false); } if (ship.enemyShipCollisionCheck.Contains(check)) { return(false); } } if (node.rotation != node.prevRotation) { if (Mine.minePos.Contains(node.extraCheckList[node.prevRotation])) { return(false); } if (ship.enemyShipCollisionCheck.Contains(node.extraCheckList[node.prevRotation])) { return(false); } } return(true); }
public static void ShipMakeMove(Ship ship) { bool waitMove = false; if (ship.isShipStuck()) { waitMove = true; if (ship.firedLastRound == false) { foreach (var enemy in Ship.ships.Values.OrderBy(s => s.pos.Distance(ship.pos))) { if (enemy.team == Team.Enemy && enemy.isAlive) { //Console.Error.WriteLine("ATK " + enemy.id + ":" + enemy.pos.toStr()); var predictedPos = ship.GetPredictedFirePos(enemy); if (predictedPos.Distance(ship.currentPositionInfo.shipFront) <= 11) { var action = new Action(MoveType.Fire, ship, predictedPos); Action.AddAction(action); return; } } } } } foreach (var cannon in Cannon.cannons) { //var shipPredictedPos = ship.GetPredictedPos(cannon.turns); if (cannon.turns <= 3 && ship.WillCannonHitShip(cannon)) { if (false)//(ship.speed == 0 && ship.lastMoveCommand.Distance(ship.pos) > 4) { var action = new Action(MoveType.Faster, ship); Action.AddAction(action); return; } else { int randX = random.Next(0, 22); int randY = random.Next(0, 20); Hex hex = new Hex(randX, randY); Vector randomPos = hex.ConvertCube(); Console.Error.WriteLine("Dodging"); Action action = ship.Dodge(cannon); if (action != null) { Action.AddAction(action); return; } } } } if (ship.speed == 2) //check ramming into mines { var forwardPos = ship.pos + 3 * Vector.directions[ship.rotation]; if (Mine.minePos.Contains(forwardPos.ConvertHex())) { ship.targetPosition = Vector.Undefined; } } if (Game.gameTurn >= ship.nextMineTurn) { foreach (var enemy in Ship.ships.Values) { if (enemy.isAlive && enemy.team == Team.Enemy) { if (enemy.nextPositionInfo.pos == ship.currentPositionInfo.minePos || enemy.nextPositionInfo.shipFront == ship.currentPositionInfo.minePos || enemy.nextPositionInfo.shipBack == ship.currentPositionInfo.minePos) { var action = new Action(MoveType.Mine, ship); Action.AddAction(action); return; } } } } foreach (var barrel in Barrel.barrels.OrderBy(b => ship.nextPositionInfo.pos.Distance(b.pos) - Convert.ToInt32(ship.targetPosition == b.pos) * 100)) { bool sameTarget = false; foreach (var ally in Ship.ships.Values) { if (ally.team == Team.Ally && ally.isAlive && ally != ship && ally.nextPositionInfo.pos.Distance(barrel.pos) < ship.nextPositionInfo.pos.Distance(barrel.pos)) { sameTarget = true; break; } } if (sameTarget) { continue; } if (ship.nextPositionInfo.shipFront == barrel.pos || ship.nextPositionInfo.pos == barrel.pos) { continue; } if (Ship.ships.Values.Any(enemy => enemy.isAlive && enemy.team == Team.Enemy && enemy.nextPositionInfo.pos.Distance(barrel.pos) <= 5 && enemy.nextPositionInfo.pos.Distance(barrel.pos) < ship.nextPositionInfo.pos.Distance(barrel.pos))) { continue; } Console.Error.WriteLine("Target: " + barrel.pos.ConvertHex().toStr()); Action action = ship.MoveShip(barrel.pos); if (action != null) { if (action.move != MoveType.Wait) { Action.AddAction(action); return; } else { waitMove = true; break; } } else { waitMove = true; break; } } if (waitMove)//ship.speed >= 1 && ship.lastMoveCommand != Vector.Undefined) { } else { Console.Error.WriteLine("Searching Random Position..."); PositionNode target = null; target = Pathfinding.GetLongestPath(ship, 6); /*var shipWithMostRum = Ship.ships.Values.OrderByDescending(s => s.rum).FirstOrDefault(); * if (ship == shipWithMostRum) * { * target = Pathfinding.GetLongestPath(ship, 6, true); * } * else * { * target = Pathfinding.GetLongestPath(ship, 6); * }*/ var path = ship.GetNextSteps(target); if (path != null && path.Count > 1) { var next = path[0]; foreach (var node in path) { Console.Error.WriteLine(node.step + ": S: " + node.speed + " R: " + node.rotation + " " + node.moveType + " " + node.pos.toStr()); } Action action = new Action(next.moveType, ship); if (action.move != MoveType.Wait) { Action.AddAction(action); return; } else { waitMove = true; } } } /*else * { * foreach (var enemy in Ship.ships.Values.OrderBy(s => s.pos.Distance(ship.pos))) * { * if (enemy.team == Team.Enemy && enemy.isAlive) * { * * Vector pos = ship.RandomPosition(enemy.nextPositionInfo.shipFront, 3, 7); * Console.Error.WriteLine("Random enemy: " + pos.toStr()); * * if (pos == Vector.Undefined) * { * continue; * } * * * Action action = ship.MoveShip(pos); * if (action != null) * { * if (action.move != MoveType.Wait) * { * Action.AddAction(action); * return; * } * else * { * waitMove = true; * break; * } * } * else * { * break; * } * } * } * }*/ if (ship.firedLastRound == false) { foreach (var enemy in Ship.ships.Values.OrderBy(s => s.pos.Distance(ship.pos))) { if (enemy.team == Team.Enemy && enemy.isAlive) { //Console.Error.WriteLine("ATK " + enemy.id + ":" + enemy.pos.toStr()); var predictedPos = ship.GetPredictedFirePos(enemy); if (predictedPos != Vector.Undefined && predictedPos.Distance(ship.currentPositionInfo.shipFront) <= 10) { var action = new Action(MoveType.Fire, ship, predictedPos); Action.AddAction(action); return; } } } } if (Game.gameTurn >= ship.nextMineTurn) { /*foreach (var enemy in Ship.ships.Values) * { * if (enemy.isAlive && enemy.team == Team.Enemy) * { * if (ship.currentPositionInfo.minePos.Distance(enemy.nextPositionInfo.shipFront) <= 2) * { * var action = new Action(MoveType.Mine, ship); * Action.AddAction(action); * return; * } * } * }*/ /*foreach (var ally in Ship.ships.Values) * { * if (ally.isAlive && ally.team == Team.Ally && ally != ship) * { * if (ship.currentPositionInfo.minePos.Distance(ally.nextPositionInfo.shipFront) > 3) * { * var action = new Action(MoveType.Mine, ship); * Action.AddAction(action); * return; * } * } * }*/ } Action.AddAction(new Action(ship)); }
public static PositionNode GetLongestPath(Ship ship, int radius, bool fleeing = false) { HashSet <PositionNode> set = new HashSet <PositionNode>(); Queue <PositionNode> q = new Queue <PositionNode>(); List <PositionNode> nextExpand = new List <PositionNode>(); PositionNode shipNode = PositionNode.GetPositionNode(ship.pos, ship.rotation, ship.speed); //shipNode.distance = 0; shipNode.step = 0; shipNode.parent = null; set.Add(shipNode); q.Enqueue(shipNode); int step = 0; int loops = 0; PositionNode current = null; // bfs loop while (q.Count != 0) { current = q.Dequeue(); foreach (var pair in current.neighbours) { var neighbour = pair.Key; var move = pair.Value; int neighbourStep = step + 1;//current.step + 1; neighbour.prevRotation = current.rotation; if (!set.Contains(neighbour) && isPositionSafe(neighbour, ship, neighbourStep)) { set.Add(neighbour); neighbour.parent = current; neighbour.moveType = move; neighbour.step = neighbourStep; nextExpand.Add(neighbour); } } if (q.Count == 0 && nextExpand.Count > 0) //if bfs is done expanding current step and next expand has items { if (step >= radius) { break; } nextExpand.ForEach(n => q.Enqueue(n)); //put all list items into queue nextExpand.Clear(); step++; //add 1 more step to count the distance } loops++; } if (step >= radius && nextExpand.Count > 0) { PositionNode first = null; if (fleeing) { first = nextExpand.OrderByDescending(n => CombinedDistanceFromEnemy(n.pos)).FirstOrDefault(); } else { first = nextExpand.OrderByDescending(n => n.pos.Distance(ship.pos)).FirstOrDefault(); } return(first); } return(null); }
public static PositionNode CalculateShortestPaths(Ship ship, Vector targetPosition) { float loopStartTime = Timer.TickCount; HashSet <PositionNode> closedSet = new HashSet <PositionNode>(); HashSet <PositionNode> openSet = new HashSet <PositionNode>(); foreach (var node in Pathfinding.nodeTable.Values) { node.gScore = 9999; node.fScore = 9999; node.parent = null; //prev.Add(stop, null); } List <PositionNode> nextExpand = new List <PositionNode>(); PositionNode shipNode = PositionNode.GetPositionNode(ship.pos, ship.rotation, ship.speed); shipNode.gScore = 0; shipNode.fScore = shipNode.pos.Distance(targetPosition); shipNode.step = 0; shipNode.parent = null; openSet.Add(shipNode); PositionNode current = null; int step = 0; int loops = 0; while (openSet.Count > 0) { current = openSet.OrderBy(n => n.fScore).FirstOrDefault(); if (current.pos == targetPosition) { break; } openSet.Remove(current); closedSet.Add(current); foreach (var pair in current.neighbours) { var neighbour = pair.Key; var move = pair.Value; var distance = move == 0 ? 0 : 1; distance += neighbour.speed; var neighbourStep = current.step + 1; if (closedSet.Contains(neighbour) || !isPositionSafe(neighbour, ship, neighbourStep)) { continue; } var alternativeDistance = current.gScore + distance; if (!openSet.Contains(neighbour)) { //nextExpand.Add(neighbour); openSet.Add(neighbour); } else if (alternativeDistance >= neighbour.gScore) { continue; } neighbour.parent = current; neighbour.gScore = alternativeDistance; neighbour.fScore = alternativeDistance + neighbour.pos.Distance(targetPosition); neighbour.moveType = move; neighbour.step = neighbourStep; } /*if (openSet.Count == 0 && nextExpand.Count > 0) * { * nextExpand.ForEach(n => openSet.Add(n)); //put all list items into queue * nextExpand.Clear(); * * step++; //add 1 more step to count the distance * Console.Error.WriteLine("Loops: " + loops + " Steps: " + step); * }*/ loops++; } //float loopTime = Timer.TickCount - loopStartTime; //Console.Error.WriteLine("LoopTime: " + loopTime); Console.Error.WriteLine("Loops: " + loops + " Steps: " + step); return(current); }
public static List <PositionNode> GetNextSteps(this Ship ship, Vector targetPosition) { PositionNode result = Pathfinding.CalculateShortestPaths(ship, targetPosition); return(GetNextSteps(ship, result)); }