Esempio n. 1
0
    /* This method calculates the movement range of the given unit based on the unit's maximum movement and the movement costs
     * of terrian for the give unit. It also sets the focus value of all hexes in the unit's movement to the value of set_focus.
     * A HashSet of all hexes that the unit can move to is returned. */
    public HashSet<HexScript> unit_move_range(UnitScript unit, bool set_focus)
    {
        HashSet<HexScript> reachable_hexes = new HashSet<HexScript>();

        if (unit != null) {
            Queue<HexScript> potential_hexes = new Queue<HexScript>();
            SortedDictionary<HexScript, int> cur_values = new SortedDictionary<HexScript, int>();
            // Initialize queue and dictionary entries
            potential_hexes.Enqueue( hex_of(unit) );
            cur_values.Add( hex_of(unit), unit.getMovement() );
            // Only search hexes that are new, or that have a new path, from a different hex, with a greater movement value
            while (potential_hexes.Count > 0) {
                HexScript hex = potential_hexes.Dequeue();

                int cur_val = -1;
                // Find hex's current cost
                cur_values.TryGetValue(hex, out cur_val);

                // Possibility to move to adjacent hexes
                if (cur_val > 0) {
                    // Sift through all valid adjacent hexes
                    for (int adj_idx = 0; adj_idx < 6; ++adj_idx) {
                        HexScript adj_hex = adjacentHexTo(hex, adj_idx);

                        if (adj_hex != null) {
                            // Find a movement value for moving through this hex via a different path, if one exists
                            int old_val = -1;
                            bool exists = cur_values.TryGetValue(adj_hex, out old_val);
                            // Calculate the new excess movement value after moving through the adjacent hex
                            int new_val = cur_val - UnitScript.move_cost(unit.unitType(), adj_hex.getType());

                            if (new_val >= 0) {
                                // check if the current hex is occupied by an enemy unit
                                if (adj_hex.getOccupied() > 0 && adj_hex.getOccupied() != unit.getPlayer()) {
                                    new_val = 0;
                                } else {
                                    // check if the current adj_hex is adjacent to a hex occupied by an enemy unit
                                    for (int idx = 0; idx < 6; ++idx) {
                                        HexScript adj_hex_2 = adjacentHexTo(adj_hex, idx);
                                        // reduce the new movement value to 0, when the hex is adjacent to an enemy
                                        if (adj_hex_2 != null && adj_hex_2.getOccupied() > 0 && adj_hex_2.getOccupied() != unit.getPlayer()) {
                                            new_val = 0;
                                            break;
                                        }
                                    }
                                }

                                /* Only add hexes for which the cost of moving through subtracted from the current movement value yields a non-negative result.
                                 * Also, the space cannot already be occupied. */
                                if (!exists && (adj_hex.getOccupied() == 0 || adj_hex.getOccupied() == unit.getPlayer())) {
                                    //Debug.Log(adj_hex.position + " : " + new_val + " ");
                                    // Set the hex focus value of hexes within the units movement range and add them to the list of reachable hexes
                                    if (adj_hex.getOccupied() == 0) {
                                        reachable_hexes.Add(adj_hex);
                                        adj_hex.setFocus(set_focus);
                                    }

                                    potential_hexes.Enqueue(adj_hex);
                                    cur_values.Add(adj_hex, new_val);
                                } else if (old_val >= 0 && new_val > old_val) {
                                    //Debug.Log(adj_hex.position + " : " + old_val + " -> " + new_val + " ");
                                    potential_hexes.Enqueue(adj_hex);
                                    cur_values [adj_hex] = new_val;
                                }
                            }
                        }

                    }

                    //Debug.Log("\n");
                }
            }
        }

        return reachable_hexes;
    }