public PathFinder(Grid graph, Cell start, Cell goal) { // Priority Queue which contains cells that are candidates for examining, lowest priority to the node with the lowest f value var frontier = new PriorityQueue<Cell>(); frontier.Enqueue(start, 0); cameFrom[start] = start; costSoFar[start] = 0; while (frontier.Count > 0) { var current = frontier.Dequeue(); // Exit the search if goal have discovered if (current.Equals(goal)) { break; } // discovers the neighbours foreach (var next in graph.Neighbors(current)) { int newCost = costSoFar[current] + graph.Cost(current, next); if (!costSoFar.ContainsKey(next) || newCost < costSoFar[next]) { costSoFar[next] = newCost; // f = g + h int priority = newCost + Heuristic(next, goal); frontier.Enqueue(next, priority); cameFrom[next] = current; } } } }
public void move(ConnectionToServer conn, Cell nextMove, int currentX, int currentY) { if (nextMove.x == currentX + 1) { conn.sendData("RIGHT#"); } else if (nextMove.x == currentX - 1) { conn.sendData("LEFT#"); } else if (nextMove.y == currentY + 1) { conn.sendData("DOWN#"); } else if (nextMove.y == currentY - 1) { conn.sendData("UP#"); } Thread.Sleep(1000); }
// Note: a generic version of A* would abstract over Cell and // also Heuristic public static int Heuristic(Cell a, Cell b) { return Math.Abs(a.x - b.x) + Math.Abs(a.y - b.y); }
public Cell findPath(Game2 game) { lowestTimeCostToCoinPile = 1000; lowestTimeCostToLifePack = 1000; String[,] board = game.board; var grid = new Grid(10, 10); // set the obstacles to the Grid from the game for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { // set bricks if (board[i, j] == "B") { grid.brickWalls.Add(new Cell(j, i)); } // set stones else if (board[i, j] == "S") { grid.stone.Add(new Cell(j, i)); } // set water else if (board[i, j] == "W") { grid.water.Add(new Cell(j, i)); } } } var gridWithoutWater = new Grid(10, 10); // set the obstacles to the Grid from the game without water for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { // set bricks if (board[i, j] == "B") { gridWithoutWater.brickWalls.Add(new Cell(j, i)); } // set stones else if (board[i, j] == "S") { gridWithoutWater.stone.Add(new Cell(j, i)); } } } //remove coin piles that have been accuired by other players. foreach (var p in game.player) { if (p.health == 0) { continue; } //ignore enemy who has just died!!! :v if (p.playerNumber == game.myPlayerNumber) { continue; } // ignore me foreach (var c in game.Coin) { // catch whether another player is on a coin pile if (p.playerLocationX == c.locationX && p.playerLocationY == c.locationY) { game.Coin.Remove(c); break; } } } //remove life packs that have been accuired by other players. foreach (var p in game.player) { if (p.playerNumber == game.myPlayerNumber) { continue; } // ignore me foreach (var life in game.Lifepacket) { // catch whether another player is on a lifepacket if (p.playerLocationX == life.locationX && p.playerLocationY == life.locationY) { game.Lifepacket.Remove(life); break; } } } // get my Player's current position foreach (var p in game.player) { if (p.playerNumber == game.myPlayerNumber) { game.me = p; } } var start = new Cell(game.me.playerLocationX, game.me.playerLocationY); //Console.WriteLine("my current location is "+ game.me.playerLocationX + game.me.playerLocationY); //#################### Begins the Procedure to Get the proper goal to follow. ##################################### /* tips... value of the coin, lifetime, whether an enemy is also targetting the coin - if he can get it soon,.... if my health is low, high priority to health pack */ /* STEPS 1. apply A* for every pack on the board - store each path (stacks), time cost to goal (in s) 2. for each goal, time to goal > life time of goal ? ignore; (3) pro step - if enemy is goalting this and he can reach it before me ? ignore; ( this will be implemented at the final stage of the development) (4) now I have reachable goals. if my health is low? lifepack: coin 5. if coin: select the most valuable coin -- to be implemented!!! 6. now you have a precise goal ! /* TO DO go to the most valuable coin pile from the reachable coinPile list */ // ######### Enemy search ############### for (int i = 0; i < game.totalPlayers; i++) { var enemy = game.player[i]; if (enemy.health == 0) { continue; } // ignore dead players // TO DO :- if enemy die, remove it and gain coin pile (spoil). // Console.WriteLine("Total number of players " + game.totalPlayers); // Console.WriteLine("Enemy Number " + enemy.playerNumber + " my Num " + game.myPlayerNumber); if (enemy.playerNumber == game.myPlayerNumber) { // Console.WriteLine("In the if,,..Enemy Number " + enemy.playerNumber + " my Num " +game.myPlayerNumber); continue; } Cell goal = new Cell(enemy.playerLocationX, enemy.playerLocationY); // Console.WriteLine(game.myPlayerNumber+" Enemy Loc "+ goal.x + ","+ goal.y + "Enemy NO " + enemy.playerNumber + " -----------------------------------------------------"); var pathFinder = new PathFinder(gridWithoutWater, start, goal); //if the enemy is straight to me ( Now I have a life threat ) if (FilterStraightPath(start, goal, pathFinder.cameFrom)) { game.enemyPresents = true; if (path.Count != 0) { Cell nextCell = path.Pop(); path.Clear(); return nextCell; } } } // ######### Life Packs search ########## foreach (var lifePack in game.Lifepacket) { // Console.WriteLine("lowestTimeCost= " + lowestTimeCostToLifePack + " timeCostToTarget= " + timeCostToTarget + " lifeTime" + lifePack.lifeTime); Cell goal = new Cell(lifePack.locationX, lifePack.locationY); if (start.x == goal.x && start.y == goal.y) // otherwise pathfinder will break { // Console.WriteLine("Life Pack Accuired!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); accuiredLifePacket = lifePack; continue; } var pathFinder = new PathFinder(grid, start, goal); BuildPath(start, goal, pathFinder.cameFrom); // filter the reachable life packs in time if (timeCostToTarget <= lifePack.lifeTime && timeCostToTarget < lowestTimeCostToLifePack) // < or <= { // Console.WriteLine("New lowest time cost = " + timeCostToTarget); lowestTimeCostToLifePack = timeCostToTarget; // keep the backup of the nearest path sequence for now if (path.Count != 0) { pathToNearestLifePack = new Stack<Cell>(path.Reverse()); } } } if (game.Lifepacket.Count != 0) { // Console.WriteLine("Life Pack removed!"); game.Lifepacket.Remove(accuiredLifePacket); } // ######### Coin Piles search ########## foreach (var coinPile in game.Coin) { // Console.WriteLine("lowestTimeCost= " + lowestTimeCostToCoinPile + " timeCostToTarget= " + timeCostToTarget + " lifeTime" + coinPile.lifeTime); Cell goal = new Cell(coinPile.locationX, coinPile.locationY); if (start.x == goal.x && start.y == goal.y) // otherwise pathfinder will break { // Console.WriteLine("Coin Accuired!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); accuiredCoin = coinPile; continue; } var pathFinder = new PathFinder(grid, start, goal); BuildPath(start, goal, pathFinder.cameFrom); // filter the reachable coins in time if (timeCostToTarget <= coinPile.lifeTime && timeCostToTarget <= lowestTimeCostToCoinPile) // < or <= { // Console.WriteLine("New lowest time cost = " + timeCostToTarget); lowestTimeCostToCoinPile = timeCostToTarget; // keep the backup of the nearestpath sequence for now if (path.Count != 0) { pathToNearestCoinPile = new Stack<Cell>(path.Reverse()); } } } if (game.Coin.Count != 0) { // Console.WriteLine("Coin removed!"); game.Coin.Remove(accuiredCoin); } // ####### take decission to go to the Life pack or the Coin pile /* if (game.me.health < 100 ) { Console.WriteLine("my health is low"); if (pathToNearestLifePack.Count != 0) { //get the next cell address to move var nextCell = pathToNearestLifePack.Pop(); // clear stacks pathToNearestLifePack.Clear(); path.Clear(); return nextCell; } }*/ if (lowestTimeCostToCoinPile < lowestTimeCostToLifePack) { if (pathToNearestCoinPile.Count != 0) { //get the next cell address to move var nextCell = pathToNearestCoinPile.Pop(); // clear stacks pathToNearestCoinPile.Clear(); path.Clear(); return nextCell; } else { // if there aren't any coins on the board path.Clear(); return start; } } if (pathToNearestLifePack.Count != 0) { //get the next cell address to move var nextCell = pathToNearestLifePack.Pop(); // clear stacks pathToNearestLifePack.Clear(); path.Clear(); return nextCell; } else { // if there aren't any life packs on the board path.Clear(); return start; } }
private bool FilterStraightPath(Cell start, Cell goal, Dictionary<Cell, Cell> cameFrom) { if (start.x != goal.x && start.y != goal.y) { return false; } if (start.x == goal.x && start.y == goal.y) { return false; } if (start.x == goal.x) { Cell current = goal; path.Push(current); while (current.x != start.x || current.y != start.y) { current = cameFrom[current]; if (current.x != start.x) { return false; } path.Push(current); } } else { Cell current = goal; path.Push(current); while (current.x != start.x || current.y != start.y) { current = cameFrom[current]; if (current.y != start.y) { return false; } path.Push(current); } } path.Pop(); // to remove the current cell, bcs we want the next cell return true; }
void BuildPath(Cell start, Cell goal, Dictionary<Cell, Cell> cameFrom) { int timeCostToTarget = 0; Cell current = goal; path.Push(current); while (current.x != start.x || current.y != start.y) { current = cameFrom[current]; path.Push(current); timeCostToTarget += 1; } path.Pop(); this.timeCostToTarget = timeCostToTarget; }
/// <summary> /// To fetch data from server /// </summary> public void receiveData() { try { // Console.WriteLine("recieving"); //Creating listening Socket this.listener = new TcpListener(IPAddress.Any, 7000); // Console.WriteLine("waiting for server response"); String messageFromServer; //Establish connection upon server request while (true) { //Starts listening listener.Start(); reciever = listener.AcceptTcpClient(); r_stream = reciever.GetStream(); Byte[] bytes = new Byte[256]; int i; messageFromServer = null; // Console.WriteLine("recieving1"); while ((i = r_stream.Read(bytes, 0, bytes.Length)) != 0) { messageFromServer = System.Text.Encoding.ASCII.GetString(bytes, 0, i); } // Print the raw message from the server Console.WriteLine("\nServer messege:- " + messageFromServer + "\n"); parser.parse(messageFromServer); // game.addPacksToBoard(); // path finding starts here if (messageFromServer != null) { if (messageFromServer.StartsWith("G")) { // Console.WriteLine("inide G"); // to keep syn the game clock with server clock game.gameClock += 1; Console.WriteLine("Game Clock is " + game.gameClock); try { game.addPacksToBoard(); game.updatePacks(game.gameClock); Console.WriteLine("\n"); // Print the map (Game board) on the Console parser.tokenizer.printBoard(); Console.WriteLine("\n"); //path finding starts ( The whole ai business happens here..... ) nextMove = ai.findPath(game); /* //solution to the exception (if me and an enemy tries to jump to a cell simultaniously String gameCell = game.board[nextMove.x, nextMove.y]; if (gameCell == "0" || gameCell == "1" || gameCell == "2" || gameCell == "3" || gameCell == "4") { continue; } */ int currentX = game.me.playerLocationX; int currentY = game.me.playerLocationY; // Console.WriteLine("\nNextX:- " + nextMove.x + " NextY:- " + nextMove.y + "\n"); // no movements if there isn't a reachable goal on the board if (nextMove.x != currentX || nextMove.y != currentY) { packPresents = true; } // #### Detect an Enemy who can be shoot out #### /* STEPS 1. A* search other players 2. filter the straight paths (enemy can see mee - I can see enemy) - using a new method in Ai class 3. cancel the other tasks 4. if health is low? don't engage (hide) : engage (shoot) face to face */ if (game.enemyPresents) { // Console.WriteLine("I can see an enemy !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); int myDirection = game.me.direction; // Console.WriteLine("My direction is " + myDirection); // shoot if (nextMove.x == currentX + 1) { if (myDirection == 1) { shoot(); } // if Im gonna shoot, instead of protecting myself else { sendData("RIGHT#"); } r_stream.Close(); listener.Stop(); reciever.Close(); game.enemyPresents = false; continue; } else if (nextMove.x == currentX - 1) { if (myDirection == 3) { shoot(); } // if Im gonna shoot, instead of protecting myself else { sendData("LEFT#"); } r_stream.Close(); listener.Stop(); reciever.Close(); game.enemyPresents = false; continue; } else if (nextMove.y == currentY + 1) { if (myDirection == 2) { shoot(); } // if Im gonna shoot, instead of protecting myself else { sendData("DOWN#"); } r_stream.Close(); listener.Stop(); reciever.Close(); game.enemyPresents = false; continue; } else if (nextMove.y == currentY - 1) { if (myDirection == 0) { shoot(); } // if Im gonna shoot, instead of protecting myself else { sendData("UP#"); } r_stream.Close(); listener.Stop(); reciever.Close(); game.enemyPresents = false; continue; } game.enemyPresents = false; } // TO DO:- initialy tank direction is up, it wants to go right... timeCostToTarget is lack of the time to turn right... has to fix this. if (packPresents) { // Console.WriteLine("inside pack presents"); // Console.WriteLine(currentX+","+ currentY+ " next move:- " + nextMove.x+ "," + nextMove.y); // move the tank if (nextMove.x == currentX + 1) { sendData("RIGHT#"); } else if (nextMove.x == currentX - 1) { sendData("LEFT#"); } else if (nextMove.y == currentY + 1) { sendData("DOWN#"); } else if (nextMove.y == currentY - 1) { sendData("UP#"); } packPresents = false; } else { shoot(); } } catch (Exception ex) { Console.WriteLine("me and an enemy tries to jump to a cell simultaniously%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); Console.WriteLine("inside catch-------"+ex.ToString()); shoot(); continue; } } } r_stream.Close(); listener.Stop(); reciever.Close(); } } catch (Exception e) { Console.WriteLine("Communication (RECEIVING) Failed! " + e.Message + "\n" + e.Source + "\n" + e.Data); errorOcurred = true; } finally { /*if (reciever != null) if (reciever.Connected) reciever.Close();*/ // if (errorOcurred) Console.WriteLine("restarting receiving ;)"); receiveData(); } }