/// <summary> /// Moves into a tile, and takes control. Assumes tile is unoccupied. /// </summary> /// <param name="hexTile"></param> public void Sieze(GameObject hexTile) { HexEntity entity = hexTile.GetComponent <HexEntity>(); Global.MapFlyWeight.TransferHexOwner(hexTile, this.Controller); entity.army = gameObject; }
/// <summary> /// Adds a supply line from this tile to a baseTile. /// </summary> /// <param name="baseTile">Tile to link a supply line to.</param> public void AddSupplyLine(GameObject baseTile) { //Add logic to check what the other is, and attempt to create a path to that location. HexEntity hex = baseTile.GetComponent <HexEntity>(); if (hex == null) { // do nothing. } else { //create a path between this tile and that one. if (pathObject != null) { Destroy(pathObject); pathObject = null; } GameObject armyTile = Global.MapFlyWeight.hexMap[Position]; pathObject = Instantiate(Global.MapFlyWeight.hexPathPrefab); HexPath path = pathObject.GetComponent <HexPath>(); path.Initialize(); List <GameObject> hexes = Global.MapFlyWeight.getPlayerAdjacencyMap(this.Controller).NearestAstar(armyTile, baseTile); path.AddHexes(hexes); supplyLines.Add(path); } }
public void UnRegisterOrder() { int finalIndex = hexEntities.Count - 1; GameObject baseTile = hexEntities[finalIndex]; HexEntity entity = baseTile.GetComponent <HexEntity>(); entity.DeleteOrder(this); }
// Simple logic to check adjacent based on cubic distance logic (two coordinates have Distance of 1) public bool Adjacent(HexEntity hex) { Vector3Int distance = this.CoordinateDistance(hex); return((distance.x == 1 && distance.y == 1 && distance.z == 0) || (distance.x == 1 && distance.y == 0 && distance.z == 1) || (distance.x == 0 && distance.y == 1 && distance.z == 1)); }
public void UnregisterAllMatchedOrders(HexEntity hex) { foreach (ArmyEntity army in armies) { foreach (HexPath path in army.supplyLines) { path.UnRegisterMatchedOrder(hex); } } }
/// <summary> /// Moves into a tile, and takes control. Assumes tile is unoccupied. /// </summary> /// <param name="hexTile"></param> public void Sieze(GameObject hexTile) { HexEntity entity = hexTile.GetComponent <HexEntity>(); Global.MapFlyWeight.TransferHexOwner(hexTile, Controller); entity.UpdateController(Controller); entity.army = gameObject; //Play the movement sound GameObject AudioObj = GameObject.Find("AudioManagerGame"); ArbitrarySounds sounds = AudioObj.GetComponentInChildren <ArbitrarySounds>(); sounds.OnArmyMove(); }
// A* search for finding shortest path. public List<GameObject> NearestAstar(GameObject root, GameObject target) { HexEntity rootEntity = root.GetComponent<HexEntity>(); HexEntity targetEntity = target.GetComponent<HexEntity>(); List<GameObject> closed = new List<GameObject>(); List<GameObject> open = new List<GameObject>(); Dictionary<GameObject, GameObject> cameFrom = new Dictionary<GameObject, GameObject>(); open.Add(root); Dictionary<GameObject, float> gScore = new Dictionary<GameObject, float>(); Dictionary<GameObject, float> fScore = new Dictionary<GameObject, float>(); gScore[root] = 0; fScore[root] = rootEntity.Distance(targetEntity); while (open.Count != 0) { GameObject current = _minFScore(fScore, open); HexEntity currentEntity = current.GetComponent<HexEntity>(); if (current == target) return _reconstructAstarPath(cameFrom, current); List<GameObject> neighbors = GetNeighbors(current); if (neighbors.Contains(target)) { cameFrom[target] = current; current = target; return _reconstructAstarPath(cameFrom, current); } open.Remove(current); closed.Remove(current); foreach (GameObject neighbor in neighbors) { if (!gScore.ContainsKey(neighbor)) gScore[neighbor] = Mathf.Infinity; if (!fScore.ContainsKey(neighbor)) fScore[neighbor] = Mathf.Infinity; HexEntity neighborEnt = neighbor.GetComponent<HexEntity>(); if (closed.Contains(neighbor)) continue; float tentativeGscore = gScore[current] + 1;//currentEntity.Distance(neighborEnt); if (tentativeGscore <= gScore[neighbor]) { cameFrom[neighbor] = current; gScore[neighbor] = tentativeGscore; float h = Vector3.Distance(neighbor.transform.position, target.transform.position); fScore[neighbor] = gScore[neighbor] + h; if (!open.Contains(neighbor)) open.Add(neighbor); } } } return open; }
// Update adjacency private void UpdateAdjacency(GameObject vertex1, GameObject vertex2) { HexEntity vertexEnt1 = vertex1.GetComponent<HexEntity>(); HexEntity vertexEnt2 = vertex2.GetComponent<HexEntity>(); if (vertexEnt1.Adjacent(vertexEnt2)) { if (!adjacencyMap.ContainsKey(vertex1)) adjacencyMap[vertex1] = new List<GameObject>(); if (!adjacencyMap.ContainsKey(vertex2)) adjacencyMap[vertex2] = new List<GameObject>(); adjacencyMap[vertex1].Add(vertex2); adjacencyMap[vertex2].Add(vertex1); } }
public void UnRegisterMatchedOrder(HexEntity matchObject) { int finalIndex = hexEntities.Count - 1; if (finalIndex < 1) { return; } GameObject baseTile = hexEntities[finalIndex]; if (matchObject == baseTile.GetComponent <HexEntity>()) { UnRegisterOrder(); } }
public void TransferHexOwner(GameObject hexObject, Player transferTo) { HexEntity hex = hexObject.GetComponent <HexEntity>(); Player transferFrom = hex.Controller; hex.Controller = transferTo; if (transferFrom != null && playerAdjacencyMaps.ContainsKey(transferFrom)) { playerAdjacencyMaps[transferFrom].RemoveVertex(hexObject); } if (!playerAdjacencyMaps.ContainsKey(hex.Controller)) { playerAdjacencyMaps[hex.Controller] = new AdjacencyMap(); } playerAdjacencyMaps[transferTo].AddVertex(hexObject); }
public bool IsConnected() { if (hexEntities.Count < 2) { return(false); } for (int i = 1; i < hexEntities.Count; i++) { HexEntity last = hexEntities[i - 1].GetComponent <HexEntity>(); HexEntity next = hexEntities[i].GetComponent <HexEntity>(); if (!last.Adjacent(next)) { return(false); } } return(true); }
public void InitPlayerAdjacencies() { playerAdjacencyMaps = new Dictionary <Player, AdjacencyMap>(); foreach (GameObject hexObject in hexMap.Values) { HexEntity hex = hexObject.GetComponent <HexEntity>(); if (hex.Controller == null) { continue; } if (!playerAdjacencyMaps.ContainsKey(hex.Controller)) { playerAdjacencyMaps[hex.Controller] = new AdjacencyMap(); } playerAdjacencyMaps[hex.Controller].AddVertex(hexObject); } }
/// <summary> /// Interface for an entity to request food from the hex path entity. /// TODO: Hook this up to the base of food production. /// It may be possible that this should instead be on another component... /// </summary> /// <param name="amountRequested">Amount of food requested</param> /// <returns>Amount of food transported.</returns> public int FoodRequest(int amountRequested) { if (amountRequested <= 0) { return(0); } int finalIndex = hexEntities.Count - 1; if (finalIndex < 0) { return(0); } GameObject baseTile = hexEntities[finalIndex]; HexEntity entity = baseTile.GetComponent <HexEntity>(); return(entity.FoodRequest(amountRequested, this.Length() - 1)); }
public void TransferHexOwner(GameObject hexObject, Player transferTo) { HexEntity hex = hexObject.GetComponent <HexEntity>(); Player transferFrom = hex.Controller; hex.Controller = transferTo; if (transferFrom != null && playerAdjacencyMaps.ContainsKey(transferFrom)) { transferFrom.UnregisterAllMatchedOrders(hex); playerAdjacencyMaps[transferFrom].RemoveVertex(hexObject); } if (!playerAdjacencyMaps.ContainsKey(transferTo)) { playerAdjacencyMaps[transferTo] = new AdjacencyMap(); } playerAdjacencyMaps[transferTo].AddVertex(hexObject); transferFrom.RefreshAllArmies(); }
/// <summary> /// Moves the unit across the board relative to current position. /// </summary> public void MoveAction(Vector3Int direction) { //Destroy(pathObject); Vector3 moveTo = Global.GetCubicVector(direction.x, direction.y, direction.z); Vector3Int nextPos = new Vector3Int(Position.x + direction.x, Position.y + direction.y, Position.z + direction.z); if (Global.MapFlyWeight.HasHexAtCubic(nextPos)) { //Get the tile for any operations that might be necessary. GameObject nextTile = Global.MapFlyWeight.hexMap[nextPos]; GameObject currentTile = Global.MapFlyWeight.hexMap[Position]; HexEntity nextHexEntity = nextTile.GetComponent <HexEntity>(); HexEntity currentHexEntity = currentTile.GetComponent <HexEntity>(); if (nextHexEntity.army != null && nextHexEntity.army.GetComponent <ArmyEntity>().Controller.PlayerId == Controller.PlayerId) { return; } if (nextHexEntity.army == null) { currentHexEntity.army = null; Sieze(nextTile); transform.Translate(moveTo); Position = nextPos; RefreshSupplyLines(); } else { Combat(nextHexEntity.army); if (nextHexEntity.army == null) { currentHexEntity.army = null; Sieze(nextTile); transform.Translate(moveTo); Position = nextPos; RefreshSupplyLines(); } } } }
/// <summary> /// Moves this army to another tile. /// </summary> /// <param name="targetTile"></param> public void Move(GameObject targetTile) { // Add logic to check what the other is, and attempt to create a path to that location. HexEntity TargetHex = targetTile.GetComponent <HexEntity>(); // Verify the action should be taken. // Did you know C# thinks & has higher priority then | ? Rediculous! if (TargetHex == null || hasMoved) { // Do nothing. } else { // checks to see if the tile can be moved to. HexEntity myHex = Global.MapFlyWeight.hexMap[Position].GetComponent <HexEntity>(); if (TargetHex.Adjacent(myHex)) { Vector3Int direction = TargetHex.Position - myHex.Position; MoveAction(direction); hasMoved = true; } } }
// "Ragged Walk". Tries to get on the same file as a target piece, with some heuristics and search once that's complete. // Extremely fast, because once we reach the file, we're basically just rule following. // TODO: implement search when file is not obvious. Using either wall clinging, or something different. public List <GameObject> RaggedWalk(GameObject root, GameObject target, Dictionary <Vector3Int, GameObject> map, int maxSteps = 1000) { List <GameObject> path = new List <GameObject>(); HexEntity targetEntity = target.GetComponent <HexEntity>(); int steps = 0; path.Add(root); while (!path.Contains(target)) { if (steps > maxSteps) { break; } HexEntity rootEntity = root.GetComponent <HexEntity>(); Vector3Int coordDist = rootEntity.Position - targetEntity.Position; Vector3Int nextPos = new Vector3Int(int.MinValue, int.MinValue, int.MinValue); List <GameObject> neighbors = GetNeighbors(root); if (neighbors.Contains(target)) { path.Add(target); return(path); } if (coordDist.x == 0) { if (coordDist.y > 0) { // Move north west Debug.Log("On-file NW"); nextPos = rootEntity.Position + new Vector3Int(0, 1, -1) * -1; } else { // Move south east Debug.Log("On-file SE"); nextPos = rootEntity.Position + new Vector3Int(0, -1, 1) * -1; } } else if (coordDist.y == 0) { if (coordDist.x > 0) { Debug.Log("On-file NE"); // Move north east nextPos = rootEntity.Position + new Vector3Int(1, 0, -1) * -1; } else { // Move south west Debug.Log("On-file SW"); nextPos = rootEntity.Position + new Vector3Int(-1, 0, 1) * -1; } } else if (coordDist.z == 0) { if (coordDist.y > 0) { // Move left Debug.Log("On-file E"); nextPos = rootEntity.Position + new Vector3Int(-1, 1, 0) * -1; } else { Debug.Log("On-file W"); nextPos = rootEntity.Position + new Vector3Int(1, -1, 0) * -1; // Move right } } else { if (coordDist.y > 0 && coordDist.z > 0) { // Move southwest Debug.Log("Off-file SW"); nextPos = rootEntity.Position + new Vector3Int(-1, 0, 1) * -1; } else if (coordDist.y > 0 && coordDist.z < 0) { // Move northwest Debug.Log("Off-file NW"); nextPos = rootEntity.Position + new Vector3Int(0, 1, -1) * -1; } else if (coordDist.x > 0 && coordDist.z > 0) { // Move southeast Debug.Log("Off-file SE"); nextPos = rootEntity.Position + new Vector3Int(0, -1, 1) * -1; } else if (coordDist.x > 0 && coordDist.z < 0) { // Move northeast Debug.Log("Off-file NE"); nextPos = rootEntity.Position + new Vector3Int(1, 0, -1) * -1; } else if (coordDist.z > 0 && coordDist.y < 0 && coordDist.x < 0) { // Move northeast? Debug.Log("Off-file SW"); nextPos = rootEntity.Position + new Vector3Int(-1, 0, 1) * -1; } else if (coordDist.z < 0 && coordDist.y > 0 && coordDist.x > 0) { // Move south? Debug.Log("Off-file NE"); nextPos = rootEntity.Position + new Vector3Int(1, 0, -1) * -1; } } Debug.Log("From position " + rootEntity.Position + " looking at target " + targetEntity.Position + " distance was " + (rootEntity.Position - targetEntity.Position) + " nextPos is " + nextPos); if (map.ContainsKey(nextPos)) { root = map[nextPos]; path.Add(root); } else { int index = (int)Random.Range(0, neighbors.Count); // TODO add heuristic path.Add(neighbors[index]); } steps++; } return(path); }
public List <GameObject> CreatePath(GameObject root, GameObject target, int maxAttempts = 100) { HexEntity rootEntity = root.GetComponent <HexEntity>(); HexEntity targetEntity = target.GetComponent <HexEntity>(); List <GameObject> closed = new List <GameObject>(); List <GameObject> open = new List <GameObject>(); Dictionary <GameObject, GameObject> cameFrom = new Dictionary <GameObject, GameObject>(); open.Add(root); Dictionary <GameObject, float> gScore = new Dictionary <GameObject, float>(); Dictionary <GameObject, float> fScore = new Dictionary <GameObject, float>(); gScore[root] = 0; fScore[root] = rootEntity.Distance(targetEntity); int attempts = 0; while (open.Count != 0) { if (attempts > maxAttempts) { break; } GameObject current = MinFScore(fScore, open); HexEntity currentEntity = current.GetComponent <HexEntity>(); if (current == target) { return(ReconstructPath(cameFrom, current)); } List <GameObject> neighbors = GetNeighbors(current); if (neighbors.Contains(target)) { cameFrom[target] = current; current = target; return(ReconstructPath(cameFrom, current)); } open.Remove(current); closed.Remove(current); foreach (GameObject neighbor in neighbors) { if (!gScore.ContainsKey(neighbor)) { gScore[neighbor] = Mathf.Infinity; } if (!fScore.ContainsKey(neighbor)) { fScore[neighbor] = Mathf.Infinity; } HexEntity neighborEnt = neighbor.GetComponent <HexEntity>(); if (closed.Contains(neighbor)) { continue; } float tentativeGscore = gScore[current] + 1;//currentEntity.Distance(neighborEnt); if (tentativeGscore <= gScore[neighbor]) { cameFrom[neighbor] = current; gScore[neighbor] = tentativeGscore; float h = Vector3.Distance(neighbor.transform.position, target.transform.position); fScore[neighbor] = gScore[neighbor] + h; if (!open.Contains(neighbor)) { open.Add(neighbor); } } } attempts += 1; } return(open); }
// Wraps Position distance function public float Distance(HexEntity hex) { return((this.Position - hex.Position).magnitude); }
// Return coordinate distance as magnitude. Divide by 2 for cubic public float CubicDistance(HexEntity hex) { return(CoordinateDistance(hex).magnitude / 2); }
// Wraps position vector operations. Returns distance in each coordinate. public Vector3Int CoordinateDistance(HexEntity hex) { Vector3Int distance = (this.Position - hex.Position); return(new Vector3Int(Mathf.Abs(distance.x), Mathf.Abs(distance.y), Mathf.Abs(distance.z))); }