//find shortest path to nearest coin pile public static void findClosestCoinPile() { GameObject item, tempItem; int pos, x, y; int tempMotion, motion = -1; //clean history before start shortClose.Clear(); for (y = 0; y < Arena.size; y++) { for (x = 0; x < Arena.size; x++) { item = Arena.GetGameObject(x, y); if (item is Coin) { start = new Node(); start.f = 0; start.g = 0; start.h = 0; start.x = x; start.y = y; start.motion = -1; open.Add(start); while (true) { //remove first element from open list and add it to close list current = open[0]; closed.Add(current); open.RemoveAt(0); motion = current.motion; tempMotion = -1; for (int xT = current.x - 1; xT < current.x + 2; xT++) { if (xT < 0 || xT >= Arena.size) //out of bounds continue; for (int yT = current.y - 1; yT < current.y + 2; yT++) { //ignore current cell and diagonals if (!(xT == current.x ^ yT == current.y)) continue; if (yT < 0 || yT >= Arena.size) //out of bounds continue; tempItem = Arena.GetGameObject(xT, yT); if (tempItem is StoneWall || tempItem is BrickWall || tempItem is Water || (tempItem is Tank && ((Tank)tempItem).name != Tank.current_player_name)) //obstacle or another tank! ignore continue; temp = new Node(); temp.x = xT; temp.y = yT; temp.g = current.g + Math.Abs(xT - current.x) + Math.Abs(yT - current.y); //determine motion direction //add extra cost if direction must be changed if (xT > current.x) { if (motion != -1 && motion != RIGHT) temp.g++; tempMotion = RIGHT; } if (xT < current.x) { if (motion != -1 && motion != LEFT) temp.g++; tempMotion = LEFT; } if (yT > current.y) { if (motion != -1 && motion != DOWN) temp.g++; tempMotion = DOWN; } if (yT < current.y) { if (motion != -1 && motion != UP) temp.g++; tempMotion = UP; } temp.h = Math.Abs(xT - myself.x) + Math.Abs(yT - myself.y); temp.f = temp.g + temp.h; pos = open.IndexOf(temp); if (pos >= 0 && open[pos].g > temp.g) { open[pos].g = temp.g; open[pos].f = open[pos].g + open[pos].h; } else if (closed.IndexOf(temp) < 0) { temp.motion = tempMotion; open.Add(temp); } } } //quit if nothing found if (open.Count == 0) break; //sort open list open.Sort(CompareNodes); //exit condition if (closed[closed.Count - 1].x == myself.x && closed[closed.Count - 1].y == myself.y) break; } } //is current closed list the shortest? if (closed.Count > 0 && (shortClose.Count > closed.Count || shortClose.Count == 0)) { shortClose = new List<Node>(closed); } //clean up before next iteration open.Clear(); closed.Clear(); } } }
//comparator for non-increasing sort order private static int CompareNodes(Node n1, Node n2) { return n1.f - n2.f; }
//find and return my tank in Node form (for AI) public static void findMe() { GameObject item; myself = null; myTank = null; for (int y = 0; y < Arena.size; y++) { for (int x = 0; x < Arena.size; x++) { item = Arena.GetGameObject(x, y); if (item is Tank && ((Tank)item).name == Tank.current_player_name) { //Get Current Tank myTank = (Tank)item; myself = new Node(); myself.x = x; myself.y = y; myDirection = ((Tank)item).direction; return; } } } }