Package org.freerealm.map

Source Code of org.freerealm.map.AStarPathFinder$Node

package org.freerealm.map;

import java.util.ArrayList;
import java.util.Collections;

import java.util.Enumeration;
import org.freerealm.tile.Tile;
import org.freerealm.Realm;
import org.freerealm.Utility;
import org.freerealm.unit.Unit;
import org.freerealm.property.Move;
import org.freerealm.settlement.Settlement;
import org.freerealm.tile.improvement.TileImprovementType;

public class AStarPathFinder implements PathFinder {

    private Realm realm;
    private ArrayList<Node> closed = new ArrayList<Node>();
    private ArrayList<Node> open = new ArrayList<Node>();
    private int maxSearchDistance;
    private Node[][] nodes;

    public AStarPathFinder(Realm realm, int maxSearchDistance) {
        this.realm = realm;
        this.maxSearchDistance = maxSearchDistance;
        nodes = new Node[realm.getMapWidth()][realm.getMapHeight()];
        for (int x = 0; x < realm.getMapWidth(); x++) {
            for (int y = 0; y < realm.getMapHeight(); y++) {
                nodes[x][y] = new Node(x, y);
            }
        }
    }

    public Path findPath(Unit unit, Coordinate target, boolean ignoreOtherPlayers) {
        return findPath(unit, unit.getCoordinate(), target, ignoreOtherPlayers);
    }

    private Path findPath(Unit unit, Coordinate start, Coordinate target, boolean ignoreOtherPlayers) {
        if (!isValidLocation(unit, target, ignoreOtherPlayers)) {
            return null;
        }
        nodes[start.getAbscissa()][start.getOrdinate()].cost = 0;
        nodes[start.getAbscissa()][start.getOrdinate()].depth = 0;
        closed.clear();
        open.clear();
        open.add(nodes[start.getAbscissa()][start.getOrdinate()]);
        nodes[target.getAbscissa()][target.getOrdinate()].parent = null;
        int maxDepth = 0;
        while ((maxDepth < maxSearchDistance) && (open.size() != 0)) {
            Node current = open.get(0);
            if (current == nodes[target.getAbscissa()][target.getOrdinate()]) {
                break;
            }
            open.remove(current);
            closed.add(current);
            Coordinate currentCoordinate = new Coordinate(current.x, current.y);
            Enumeration<Coordinate> enumeration = Utility.getNeighborCoordinatesEnumeration(realm, currentCoordinate);
            while (enumeration.hasMoreElements()) {
                Coordinate coordinate = enumeration.nextElement();
                if (isValidLocation(unit, coordinate, ignoreOtherPlayers)) {
                    Tile tile = realm.getTile(coordinate);
                    float nextStepCost = current.cost + tile.getMovementCost();
                    Node neighbour = nodes[coordinate.getAbscissa()][coordinate.getOrdinate()];
                    if (nextStepCost < neighbour.cost) {
                        if (open.contains(neighbour)) {
                            open.remove(neighbour);
                        }
                        if (closed.contains(neighbour)) {
                            closed.remove(neighbour);
                        }
                    }
                    if (!open.contains(neighbour) && !(closed.contains(neighbour))) {
                        neighbour.cost = nextStepCost;
                        neighbour.heuristic = tile.getMovementCost();
                        maxDepth = Math.max(maxDepth, neighbour.setParent(current));
                        open.add(neighbour);
                        Collections.<Node>sort(open);
                    }
                }
            }
        }
        if (nodes[target.getAbscissa()][target.getOrdinate()].parent == null) {
            return null;
        }
        Path path = new Path();
        Node targetNode = nodes[target.getAbscissa()][target.getOrdinate()];
        while (targetNode != nodes[start.getAbscissa()][start.getOrdinate()]) {
            path.prependStep(targetNode.x, targetNode.y);
            targetNode = targetNode.parent;
        }
        return path;
    }

    private boolean isValidLocation(Unit unit, Coordinate coordinate, boolean ignoreOtherPlayers) {
        if (coordinate == null) {
            return false;
        }
        if (coordinate.getOrdinate() < 0) {
            return false;
        }
        Tile tile = realm.getTile(coordinate);
        if (tile == null) {
            return false;
        }

        if (!unit.getPlayer().isCoordinateExplored(coordinate)) {
            return false;
        }

        Move moveAbility = (Move) unit.getType().getAbility("Move");
        if (moveAbility == null) {
            return false;
        }

        if (!ignoreOtherPlayers && isTileBlockedByOtherPlayers(tile, unit)) {
            return false;
        }

        //TODO : Use set movement point instead of checking for roads
        TileImprovementType road = realm.getTileImprovementTypeManager().getImprovement("Road");
        if (tile.hasImprovement(road)) {
            return true;
        }

        if (!moveAbility.hasTileType(tile.getType())) {
            return false;
        }
        return true;
    }

    private boolean isTileBlockedByOtherPlayers(Tile tile, Unit unit) {
        if (tile.getSettlement() != null) {
            Settlement settlement = tile.getSettlement();
            if (!unit.getPlayer().equals(settlement.getPlayer())) {
                return true;
            }
        }
        if (tile.getNumberOfUnits() > 0) {
            Unit tileUnit = tile.getUnits().get(tile.getUnits().firstKey());
            if (!unit.getPlayer().equals(tileUnit.getPlayer())) {
                return true;
            }
        }
        return false;
    }

    private class Node implements Comparable {

        private int x;
        private int y;
        private float cost;
        private Node parent;
        private float heuristic;
        private int depth;

        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int setParent(Node parent) {
            depth = parent.depth + 1;
            this.parent = parent;
            return depth;
        }

        public int compareTo(Object other) {
            Node o = (Node) other;
            float f = heuristic + cost;
            float of = o.heuristic + o.cost;
            if (f < of) {
                return -1;
            } else if (f > of) {
                return 1;
            } else {
                return 0;
            }
        }

        @Override
        public String toString() {
            String string = new String();
            string = string + x + "," + y + " - " + cost;
            return string;
        }
    }
}
TOP

Related Classes of org.freerealm.map.AStarPathFinder$Node

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.