public static int pathCounter = int.MinValue + 1; // Incremented after every check #endregion Fields #region Methods // Yay C# has generators! /// <summary> /// A generator that produces positions by doing a breadth first iteration of tiles starting at a given position. /// </summary> /// <param name="engine">An engine object to get tiles from</param> /// <param name="position">The starting position.</param> /// <param name="distance">The maximum distance from the starting position. Or negative for no limit.</param> /// <param name="size">The maximum number of tiles traversed. Or negative for no limit.</param> public static IEnumerable<Position> BreadthFirst(Engine engine, Position position, int distance = -1, int size = -1) { // Reset ONE tile's pathIndex on the map to the minimum value to prevent integer rollover int index = pathCounter < 0 ? -pathCounter : pathCounter; engine.map.tiles[index % engine.map.width, (index / engine.map.width)%engine.map.height].pathIndex = int.MinValue; int localPathCounter = pathCounter++; LinkedList<Tile> perimeter = new LinkedList<Tile>(); perimeter.AddLast(engine.map.GetTileNearestTo(position)); perimeter.Last.Value.pathDistance = 0; while (size != 0 && perimeter.Count > 0) { Tile top = perimeter.First.Value; top.pathIndex = localPathCounter; perimeter.RemoveFirst(); if (distance >= 0 && top.pathDistance > distance) { yield break; } yield return top.position; foreach (var neighbor in top.neighbors) { if (neighbor.pathIndex < localPathCounter) { perimeter.AddLast(neighbor); neighbor.pathIndex = localPathCounter; neighbor.pathDistance = top.pathDistance + 1; } } size -= 1; } // This is not the place for cleanup code }
public Map(Vector2 startingPosition, int width, int height, ref Engine engine, GraphicsDevice graphicsDevice, int numberOfDreadlands, int numberOfDeserts, int numberOfPlains, int numberOfMountains, int numberOfTundras, int numberOfForests, int numberOfOceans, int numberOfResourceNodes) { tileIndex = startingPosition; this.width = width; this.height = height; this.engine = engine; this.graphicsDevice = graphicsDevice; this.numberOfDreadlands = numberOfDreadlands; this.numberOfDeserts = numberOfDeserts; this.numberOfPlains = numberOfPlains; this.numberOfMountains = numberOfMountains; this.numberOfTundras = numberOfTundras; this.numberOfForests = numberOfForests; this.numberOfOceans = numberOfOceans; this.numberOfResourceNodes = numberOfResourceNodes; // Generate map charmap = Generator.generate(width, height, numberOfDreadlands, numberOfDeserts, numberOfPlains, numberOfMountains, numberOfTundras, numberOfForests, numberOfOceans, numberOfResourceNodes); engine.map.UpdateTilesFromCharmap(charmap); // Generate map cache xCaches = (int) Math.Ceiling(width/214.0); yCaches = (int) Math.Ceiling(height/214.0); mapCaches = new RenderTarget2D[xCaches, yCaches]; for (int y = 0; y < yCaches; ++y) { for (int x = 0; x < xCaches; ++x) { mapCaches[x, y] = new RenderTarget2D(graphicsDevice, 214 * tilePxSize, 214 * tilePxSize); } } }
public static Position FindNextStep( Engine engine, Unit unit, Tile start, Tile end ) { List<Position> temp = FindPath(engine, unit, start, end); if (temp != null && temp.Count > 1) return temp[1]; else return null; }
public AI( Engine e, Player player, List<Position> g, List<Position> i, List<Position> m ) { engine = e; me = player; goldTiles = g; ironTiles = i; manaTiles = m; }
// handles context displays, selected units, resource counters, public Hud(ref Engine engine, ref Map map, Texture2D boxSelect, Texture2D HPbar) { this.engine = engine; this.map = map; this.boxSelect = boxSelect; this.HPbar = HPbar; this.currentPlayer = engine.players[0]; selectedUnits = new List<Unit>(); startRect = new Vector2(); endRect = new Vector2(); // initialize m = Mouse.GetState(); m2 = Mouse.GetState(); lastButtonPressed = "None"; }
public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; engine = new Engine(width, height); // Create initial players engine.AddPlayer("Frodo", teamIndex: 0); engine.AddPlayer("Sauron", teamIndex: 1); engine.ai1.me = engine.players[1]; engine.ai2.me = engine.players[0]; graphics.PreferredBackBufferWidth = 1280; graphics.PreferredBackBufferHeight = 720; IsMouseVisible = true; //graphics.ToggleFullScreen(); // activate full screen mode. toggle with alt + enter }
public Unit(int id, Engine engine, UnitType unitType, Position position, Player owner) { this.id = id; this.engine = engine; this.type = unitType; this.position = position; this.previousPosition = position; this.nextMove = -1; this.owner = owner; health = type.maxHealth; status = Status.Idle; orders = new List<Order>(); modifiers = new List<UnitModifier>(); animationStartTick = 0; direction = 0; currentPath = null; currentTargetPosition = null; }
public static List<Position> FindPath( Engine engine, Unit unit, Tile start, Tile end ) { List<Position> path = null; if (!unit.CanMove(end.position)) { foreach (Position pos in BreadthFirst(engine, end.position, -1, 500)) { if (unit.CanMove(pos)) { end = engine.map.tiles[pos.x, pos.y]; break; } } } if (!unit.CanMove(end.position)) { return null; } bool success = false; start.pathParent = null; start.pathDistance = 0; start.pathHeuristic = start.pathDistance + FValue(start, end); PriorityQueue<Tile> openSet = new PriorityQueue<Tile>(); openSet.Enqueue(start); int count = 0; //generate path while ( openSet.Count() > 0 ) { count += 1; Tile currentBest = openSet.Dequeue(); currentBest.pathIndex = pathCounter; // if we are at the goal end if (currentBest.position.Equals(end.position)) { success = true; break; } // Give up if we backtrack too far if ((currentBest.pathHeuristic >= start.pathHeuristic*14 && count > 2000) || count > 4000) { break; } // Take current best, generate all possible nodes, push them onto queue foreach (var neighbor in currentBest.neighbors) { if (!unit.CanMove(neighbor.position)) { continue; } double tentativeCost = currentBest.pathDistance + neighbor.tileType.movementCost; if (neighbor.pathIndex < pathCounter) { neighbor.pathIndex = pathCounter; neighbor.pathParent = currentBest; neighbor.pathDistance = tentativeCost; neighbor.pathHeuristic = neighbor.pathDistance + FValue(neighbor, end); openSet.Enqueue(neighbor); } else if (tentativeCost < neighbor.pathDistance) { // Update costs if the current path is better than the existing one neighbor.pathParent = currentBest; neighbor.pathDistance = tentativeCost; neighbor.pathHeuristic = neighbor.pathDistance + FValue(neighbor, end); openSet.HeapifyUp(neighbor); } } } if ( success ) { // Generate path by following parent from end to start path = new List<Position>(); Tile runner = end; while (runner != null) { path.Insert(0, runner.position); runner = runner.pathParent; } } pathCounter += 1; return path; }
public static Position FindNextStep( Engine engine, Unit unit, Position start, Position end) { return FindNextStep(engine, unit, engine.map.GetTileAt(start), engine.map.GetTileAt(end)); }
public EngineMap(Engine engine, int width, int height) { this.engine = engine; this.width = width; this.height = height; }