void ResourcePool::Update() {
    //DebugLogger() << "ResourcePool::Update for type " << boost::lexical_cast<std::string>(m_type);
    // sum production from all ResourceCenters in each group, for resource point type appropriate for this pool
    MeterType meter_type = ResourceToMeter(m_type);
    MeterType target_meter_type = ResourceToTargetMeter(m_type);

    if (INVALID_METER_TYPE == meter_type || INVALID_METER_TYPE == target_meter_type)
        ErrorLogger() << "ResourcePool::Update() called when m_type can't be converted to a valid MeterType";

    // zero to start...
    m_connected_object_groups_resource_output.clear();
    m_connected_object_groups_resource_target_output.clear();

    // temporary storage: indexed by group of systems, which objects
    // are located in that system group?
    std::map<std::set<int>, std::set<std::shared_ptr<const UniverseObject>>> system_groups_to_object_groups;


    // for every object, find if a connected system group contains the object's
    // system.  If a group does, place the object into that system group's set
    // of objects.  If no group contains the object, place the object in its own
    // single-object group.
    for (std::shared_ptr<const UniverseObject> obj : Objects().FindObjects<const UniverseObject>(m_object_ids)) {
        int object_id = obj->ID();
        int object_system_id = obj->SystemID();
        // can't generate resources when not in a system
        if (object_system_id == INVALID_OBJECT_ID)
            continue;

        // is object's system in a system group?
        std::set<int> object_system_group;
        for (const std::set<int>& sys_group : m_connected_system_groups) {
            if (sys_group.find(object_system_id) != sys_group.end()) {
                object_system_group = sys_group;
                break;
            }
        }

        // if object's system is not in a system group, add it as its
        // own entry in m_connected_object_groups_resource_output and m_connected_object_groups_resource_target_output
        // this will allow the object to use its own locally produced
        // resource when, for instance, distributing pp
        if (object_system_group.empty()) {
            object_system_group.insert(object_id);  // just use this already-available set to store the object id, even though it is not likely actually a system

            float obj_output = obj->GetMeter(meter_type) ? obj->CurrentMeterValue(meter_type) : 0.0f;
            m_connected_object_groups_resource_output[object_system_group] = obj_output;

            float obj_target_output = obj->GetMeter(target_meter_type) ? obj->CurrentMeterValue(target_meter_type) : 0.0f;
            m_connected_object_groups_resource_target_output[object_system_group] = obj_target_output;
            continue;
        }

        // if resource center's system is in a system group, record which system
        // group that is for later
        system_groups_to_object_groups[object_system_group].insert(obj);
    }

    // sum the resource production for object groups, and store the total
    // group production, indexed by group of object ids
    for (std::map<std::set<int>, std::set<std::shared_ptr<const UniverseObject>>>::value_type& entry : system_groups_to_object_groups) {
        const std::set<std::shared_ptr<const UniverseObject>>& object_group = entry.second;
        std::set<int> object_group_ids;
        float total_group_output = 0.0f;
        float total_group_target_output = 0.0f;
        for (std::shared_ptr<const UniverseObject> obj : object_group) {
            if (obj->GetMeter(meter_type))
                total_group_output += obj->CurrentMeterValue(meter_type);
            if (obj->GetMeter(target_meter_type))
                total_group_target_output += obj->CurrentMeterValue(target_meter_type);
            object_group_ids.insert(obj->ID());
        }
        m_connected_object_groups_resource_output[object_group_ids] = total_group_output;
        m_connected_object_groups_resource_target_output[object_group_ids] = total_group_target_output;
    }

    ChangedSignal();
}
Exemple #2
0
void SupplyManager::Update() {
    m_supply_starlane_traversals.clear();
    m_supply_starlane_obstructed_traversals.clear();
    m_fleet_supplyable_system_ids.clear();
    m_resource_supply_groups.clear();
    m_propagated_supply_ranges.clear();

    // for each empire, need to get a set of sets of systems that can exchange
    // resources.  some sets may be just one system, in which resources can be
    // exchanged between UniverseObjects producing or consuming them, but which
    // can't exchange with any other systems.

    // which systems can share resources depends on system supply ranges, which
    // systems have obstructions to supply propagation for reach empire, and
    // the ranges and obstructions of other empires' supply, as only one empire
    // can supply each system or propagate along each starlane. one empire's
    // propagating supply can push back another's, if the pusher's range is
    // larger.

    // map from empire id to map from system id to range (in starlane jumps)
    // that supply can be propagated out of that system by that empire.
    std::map<int, std::map<int, float>> empire_system_supply_ranges;
    // map from empire id to which systems are obstructed for it for supply
    // propagation
    std::map<int, std::set<int>> empire_supply_unobstructed_systems;
    // map from empire id to map from system id to sum of supply source ranges
    // owned by empire in that in system
    std::map<int, std::map<int, float>> empire_system_supply_range_sums;

    for (const std::map<int, Empire*>::value_type& entry : Empires()) {
        const Empire* empire = entry.second;
        empire_system_supply_ranges[entry.first] = empire->SystemSupplyRanges();
        empire_supply_unobstructed_systems[entry.first] = empire->SupplyUnobstructedSystems();

        //std::stringstream ss;
        //for (int system_id : empire_supply_unobstructed_systems[entry.first])
        //{ ss << system_id << ", "; }
        //DebugLogger() << "Empire " << empire->EmpireID() << " unobstructed systems: " << ss.str();
    }
    for (auto empire_id_pair : empire_system_supply_ranges) {
        for (auto sys_id_pair : empire_id_pair.second) {
            empire_system_supply_range_sums[empire_id_pair.first][sys_id_pair.first] =
                EmpireTotalSupplyRangeSumInSystem(empire_id_pair.first, sys_id_pair.first);
        }
    }


    /////
    // probably temporary: additional restriction here for supply propagation
    // but not for general system obstruction as determind within Empire::UpdateSupplyUnobstructedSystems
    /////
    const std::vector<std::shared_ptr<Fleet>> fleets = GetUniverse().Objects().FindObjects<Fleet>();

    for (const std::map<int, Empire*>::value_type& entry : Empires()) {
        int empire_id = entry.first;
        const std::set<int>& known_destroyed_objects = GetUniverse().EmpireKnownDestroyedObjectIDs(empire_id);
        std::set<int> systems_containing_friendly_fleets;

        for (std::shared_ptr<const Fleet> fleet : fleets) {
            int system_id = fleet->SystemID();
            if (system_id == INVALID_OBJECT_ID) {
                continue;   // not in a system, so can't affect system obstruction
            } else if (known_destroyed_objects.find(fleet->ID()) != known_destroyed_objects.end()) {
                continue; //known to be destroyed so can't affect supply, important just in case being updated on client side
            }

            if ((fleet->HasArmedShips() || fleet->HasFighterShips()) && fleet->Aggressive()) {
                if (fleet->OwnedBy(empire_id)) {
                    if (fleet->NextSystemID() == INVALID_OBJECT_ID || fleet->NextSystemID() == fleet->SystemID()) {
                        systems_containing_friendly_fleets.insert(system_id);
                    }
                }
            }
        }

        std::set<int> systems_where_others_have_supply_sources_and_current_empire_doesnt;
        // add all systems where others have supply
        for (std::map<int, std::map<int, float>>::value_type& empire_supply : empire_system_supply_ranges) {
            if (empire_supply.first == empire_id || empire_supply.first == ALL_EMPIRES)
                continue;

            for (const std::map<int, float>::value_type& supply_range : empire_supply.second) {
                if (supply_range.second <= 0.0f)
                    continue;
                systems_where_others_have_supply_sources_and_current_empire_doesnt.insert(supply_range.first);
            }
        }
        // remove systems were this empire has supply
        std::map<int, std::map<int, float>>::const_iterator it = empire_system_supply_ranges.find(empire_id);
        if (it != empire_system_supply_ranges.end()) {
            for (const std::map<int, float>::value_type& supply_range : it->second) {
                if (supply_range.second <= 0.0f)
                    continue;
                systems_where_others_have_supply_sources_and_current_empire_doesnt.erase(supply_range.first);
            }
        }

        // for systems where others have supply sources and this empire doesn't
        // and where this empire has no fleets...
        // supply is obstructed
        for (int system_id : systems_where_others_have_supply_sources_and_current_empire_doesnt) {
            if (systems_containing_friendly_fleets.find(system_id) == systems_containing_friendly_fleets.end())
                empire_supply_unobstructed_systems[empire_id].erase(system_id);
        }
    }
    /////
    // end probably temporary...
    /////


    // system connections each empire can see / use for supply propagation
    std::map<int, std::map<int, std::set<int>>> empire_visible_starlanes;
    for (std::map<int, Empire*>::value_type& entry : Empires()) {
        const Empire* empire = entry.second;
        empire_visible_starlanes[entry.first] = empire->KnownStarlanes();//  VisibleStarlanes();
    }

    std::set<int> systems_with_supply_in_them;

    // store (supply range in jumps, and distance to supply source) of all
    // unobstructed systems before propagation, and add to list of systems
    // to propagate from.
    std::map<int, std::map<int, std::pair<float, float>>> empire_propagating_supply_ranges;
    float max_range = 0.0f;

    for (const auto& empire_supply : empire_system_supply_ranges) {
        int empire_id = empire_supply.first;
        const std::set<int>& unobstructed_systems = empire_supply_unobstructed_systems[empire_id];

        for (const std::map<int, float>::value_type& supply_range : empire_supply.second) {
            int system_id = supply_range.first;
            if (unobstructed_systems.find(system_id) != unobstructed_systems.end()) {
                // stored: first -> source supply range.  second -> distance to source (0 for the source itself)
                empire_propagating_supply_ranges[empire_id][system_id] = {supply_range.second, 0.0f};
                if (supply_range.second > max_range)
                    max_range = supply_range.second;
                systems_with_supply_in_them.insert(system_id);
            }
        }
    }


    // spread supply out from sources by "diffusion" like process, along unobstructed
    // starlanes, until the range is exhausted.
    for (float range_to_spread = max_range; range_to_spread >= 0;
         range_to_spread -= 1.0f)
    {
        //DebugLogger() << "!!!! Reduced spreading range to " << range_to_spread;

        // update systems that have supply in them
        for (const auto& empire_supply : empire_propagating_supply_ranges) {
            for (const std::map<int, std::pair<float, float>>::value_type& supply_range : empire_supply.second)
            { systems_with_supply_in_them.insert(supply_range.first); }
        }


        // resolve supply fights between multiple empires in one system.
        // pass over all empire-supplied systems, removing supply for all
        // but the empire with the highest supply range in each system
        for (int sys_id : systems_with_supply_in_them) {
            // sort empires by range in this system
            std::map<float, std::set<int>> empire_ranges_here;
            for (auto& empire_supply : empire_propagating_supply_ranges) {
                int empire_id = empire_supply.first;
                std::map<int, std::pair<float, float>>::const_iterator empire_supply_it = empire_supply.second.find(sys_id);
                // does this empire have any range in this system? if so, store it
                if (empire_supply_it == empire_supply.second.end())
                    continue;

                // stuff to break ties...
                float bonus = 0.0f;

                // empires with planets in system
                bool has_outpost = false, has_colony = false;
                if (std::shared_ptr<const System> sys = GetSystem(sys_id)) {
                    std::vector<int> obj_ids;
                    std::copy(sys->ContainedObjectIDs().begin(), sys->ContainedObjectIDs().end(), std::back_inserter(obj_ids));
                    for (std::shared_ptr<UniverseObject> obj : Objects().FindObjects(obj_ids)) {
                        if (!obj)
                            continue;
                        if (!obj->OwnedBy(empire_id))
                            continue;
                        if (obj->ObjectType() == OBJ_PLANET) {
                            if (std::shared_ptr<Planet> planet = std::dynamic_pointer_cast<Planet>(obj)) {
                                if (!planet->SpeciesName().empty())
                                    has_colony = true;
                                else
                                    has_outpost = true;
                                continue;
                            }
                        }
                    }
                }
                if (has_colony)
                    bonus += 0.5f;
                else if (has_outpost)
                    bonus += 0.3f;

                // sum of all supply sources in this system
                bonus += empire_system_supply_range_sums[empire_id][sys_id] / 1000.0f;

                // distance to supply source from here
                float propagated_distance_to_supply_source = std::max(1.0f, empire_supply_it->second.second);
                bonus += 0.0001f / propagated_distance_to_supply_source;

                // store ids of empires indexed by adjusted propgated range, in order to sort by range
                float propagated_range = empire_supply_it->second.first;
                empire_ranges_here[propagated_range + bonus].insert(empire_id);
            }

            if (empire_ranges_here.empty())
                continue;   // no empire has supply here?
            if (empire_ranges_here.size() == 1 && empire_ranges_here.begin()->second.size() < 2)
                continue;   // only one empire has supply here

            // at least two empires have supply sources here...
            // check if one is stronger

            // remove supply for all empires except the top-ranged empire here
            // if there is a tie for top-ranged, remove all
            std::map<float, std::set<int>>::reverse_iterator range_empire_it = empire_ranges_here.rbegin();
            int top_range_empire_id = ALL_EMPIRES;
            if (range_empire_it->second.size() == 1) {
                // if just one empire has the most range, it is the top empire
                top_range_empire_id = *(range_empire_it->second.begin());
            }
            //DebugLogger() << "top ranged empire here: " << top_range_empire_id;

            // remove range entries and traversals for all but the top empire
            // (or all empires if there is no single top empire)
            for (auto& empire_supply : empire_propagating_supply_ranges) {
                int empire_id = empire_supply.first;
                if (empire_id == top_range_empire_id)
                    continue;   // this is the top empire, so leave as the sole empire supplying here

                // remove from range entry...
                std::map<int, std::pair<float, float>>& empire_ranges = empire_supply.second;
                empire_ranges.erase(sys_id);

                //DebugLogger() << "... removed empire " << empire_id << " system " << sys_id << " supply.";

                // Remove from unobstructed systems
                empire_supply_unobstructed_systems[empire_id].erase(sys_id);

                std::set<std::pair<int, int>>& lane_traversals = m_supply_starlane_traversals[empire_id];
                std::set<std::pair<int, int>> lane_traversals_initial = lane_traversals;
                std::set<std::pair<int, int>>& obstructed_traversals = m_supply_starlane_obstructed_traversals[empire_id];
                std::set<std::pair<int, int>> obstrcuted_traversals_initial = obstructed_traversals;

                // remove from traversals departing from or going to this system for this empire,
                // and set any traversals going to this system as obstructed
                for (const auto& lane : lane_traversals_initial) {
                    if (lane.first == sys_id) {
                        lane_traversals.erase(std::make_pair(sys_id, lane.second));
                    }
                    if (lane.second == sys_id) {
                        lane_traversals.erase(std::make_pair(lane.first, sys_id));
                        obstructed_traversals.insert(std::make_pair(lane.first, sys_id));
                    }
                }

                // remove obstructed traverals departing from this system
                for (const auto& lane : obstrcuted_traversals_initial) {
                    if (lane.first == sys_id)
                        obstructed_traversals.erase(std::make_pair(lane.first, lane.second));
                }
            }

            //// DEBUG
            //DebugLogger() << "after culling empires ranges at system " << sys_id << ":";
            //for (std::map<int, std::map<int, float>>::value_type& empire_supply : empire_propagating_supply_ranges) {
            //    std::map<int, float>& system_ranges = empire_supply.second;
            //    std::map<int, float>::iterator range_it = system_ranges.find(sys_id);
            //    if (range_it != system_ranges.end())
            //        DebugLogger() << empire_supply.first << " : " << range_it->second;
            //}
            //// END DEBUG
        }

        if (range_to_spread <= 0)
            break;

        // initialize next iteration with current supply distribution
        auto empire_propagating_supply_ranges_next = empire_propagating_supply_ranges;


        // for sources of supply of at least the minimum range for this
        // iteration that are in the current map, give adjacent systems one
        // less supply in the next iteration (unless as much or more is already
        // there)
        for (const auto& empire_supply : empire_propagating_supply_ranges) {
            int empire_id = empire_supply.first;
            //DebugLogger() << ">-< Doing supply propagation for empire " << empire_id << " >-<";
            const std::map<int, std::pair<float, float>>& prev_sys_ranges = empire_supply.second;
            const std::set<int>& unobstructed_systems = empire_supply_unobstructed_systems[empire_id];

            for (const std::map<int, std::pair<float, float>>::value_type& supply_range : empire_supply.second) {
                // does the source system have enough supply range to propagate outwards?
                float range = supply_range.second.first;
                if (range != range_to_spread)
                    continue;
                float range_after_one_more_jump = range - 1.0f; // what to set adjacent systems' ranges to (at least)

                // how far is this system from a source of supply for this empire?
                float distance_to_supply_source = supply_range.second.second;

                // what starlanes can be used to propagate supply?
                int system_id = supply_range.first;

                //DebugLogger() << "propagating from system " << system_id << " which has range: " << range << " and distance: " << distance_to_supply_source;

                // attempt to propagate to all adjacent systems...
                for (int lane_end_sys_id : empire_visible_starlanes[empire_id][system_id]) {
                    // is propagation to the adjacent system obstructed?
                    if (unobstructed_systems.find(lane_end_sys_id) == unobstructed_systems.end()) {
                        // propagation obstructed!
                        //DebugLogger() << "Added obstructed traversal from " << system_id << " to " << lane_end_sys_id << " due to not being on unobstructed systems";
                        m_supply_starlane_obstructed_traversals[empire_id].insert({system_id, lane_end_sys_id});
                        continue;
                    }
                    // propagation not obstructed.


                    // does another empire already have as much or more supply here from a previous iteration?
                    float other_empire_biggest_range = -10000.0f;   // arbitrary big numbeer
                    for (const std::map<int, std::map<int, std::pair<float, float>>>::value_type& other_empire_supply : empire_propagating_supply_ranges) {
                        int other_empire_id = other_empire_supply.first;
                        if (other_empire_id == empire_id)
                            continue;
                        const std::map<int, std::pair<float, float>>& prev_other_empire_sys_ranges = other_empire_supply.second;
                        std::map<int, std::pair<float, float>>::const_iterator prev_other_empire_range_it = prev_other_empire_sys_ranges.find(lane_end_sys_id);
                        if (prev_other_empire_range_it == prev_other_empire_sys_ranges.end())
                            continue;
                        if (prev_other_empire_range_it->second.first > other_empire_biggest_range)
                            other_empire_biggest_range = prev_other_empire_range_it->second.first;
                    }

                    // if so, add a blocked traversal and continue
                    if (range_after_one_more_jump <= other_empire_biggest_range) {
                        m_supply_starlane_obstructed_traversals[empire_id].insert(std::make_pair(system_id, lane_end_sys_id));
                        //DebugLogger() << "Added obstructed traversal from " << system_id << " to " << lane_end_sys_id << " due to other empire biggest range being " << other_empire_biggest_range;
                        continue;
                    }

                    // otherwise, propagate into system...
                    float lane_length = DistanceBetweenObjects(system_id, lane_end_sys_id);
                    float distance_to_supply_source_after_next_lane = lane_length + distance_to_supply_source;

                    //DebugLogger() << "Attempting to propagate into system: " << lane_end_sys_id << " the new range: " << range_after_one_more_jump << " and distance: " << distance_to_supply_source_after_next_lane;

                    // if propagating supply would increase the range of the adjacent system,
                    // or decrease the distance to the adjacent system from a supply source...
                    std::map<int, std::pair<float, float>>::const_iterator prev_range_it = prev_sys_ranges.find(lane_end_sys_id);
                    if (prev_range_it == prev_sys_ranges.end()) {
                        empire_propagating_supply_ranges_next[empire_id][lane_end_sys_id] =
                            {range_after_one_more_jump, distance_to_supply_source_after_next_lane};
                        //DebugLogger() << " ... default case: no previous entry.";

                    } else {
                        //DebugLogger() << " ... previous entry values: " << prev_range_it->second.first << " and " << prev_range_it->second.second;

                        if (range_after_one_more_jump > prev_range_it->second.first) {
                            empire_propagating_supply_ranges_next[empire_id][lane_end_sys_id].first =
                                range_after_one_more_jump;
                            //DebugLogger() << " ... range increased!";
                        }
                        if (distance_to_supply_source_after_next_lane < prev_range_it->second.second) {
                            empire_propagating_supply_ranges_next[empire_id][lane_end_sys_id].second =
                                distance_to_supply_source_after_next_lane;
                            //DebugLogger() << " ... distance decreased!";
                        }
                    }
                    // always record a traversal, so connectivity is calculated properly
                    m_supply_starlane_traversals[empire_id].insert({system_id, lane_end_sys_id});
                    //DebugLogger() << "Added traversal from " << system_id << " to " << lane_end_sys_id;

                    // erase any previous obstructed traversal that just succeeded
                    if (m_supply_starlane_obstructed_traversals[empire_id].find(std::make_pair(system_id, lane_end_sys_id)) !=
                        m_supply_starlane_obstructed_traversals[empire_id].end())
                    {
                        //DebugLogger() << "Removed obstructed traversal from " << system_id << " to " << lane_end_sys_id;
                        m_supply_starlane_obstructed_traversals[empire_id].erase(std::make_pair(system_id, lane_end_sys_id));
                    }
                    if (m_supply_starlane_obstructed_traversals[empire_id].find(std::make_pair(lane_end_sys_id, system_id)) !=
                        m_supply_starlane_obstructed_traversals[empire_id].end())
                    {
                        //DebugLogger() << "Removed obstructed traversal from " << lane_end_sys_id << " to " << system_id;
                        m_supply_starlane_obstructed_traversals[empire_id].erase(std::make_pair(lane_end_sys_id, system_id));
                    }
                }
            }
        }

        // save propagated results for next iteration
        empire_propagating_supply_ranges = empire_propagating_supply_ranges_next;
    }

    //// DEBUG
    //DebugLogger() << "SuppolyManager::Update: after removing conflicts, empires can provide supply to the following system ids:";
    //for (std::map<int, std::map<int, float>>::value_type& empire_supply : empire_propagating_supply_ranges) {
    //    int empire_id = empire_supply.first;
    //    std::stringstream ss;
    //    for (std::map<int, float>::value_type& supply_range : empire_supply.second) {
    //        ss << supply_range.first << " (" << supply_range.second << "),  ";
    //    }
    //    DebugLogger() << "empire: " << empire_id << ":  " << ss.str();
    //}
    //// END DEBUG

    // record which systems are fleet supplyable by each empire (after resolving conflicts in each system)
    for (const auto& empire_supply : empire_propagating_supply_ranges) {
        int empire_id = empire_supply.first;
        for (const auto& supply_range : empire_supply.second) {
            if (supply_range.second.first < 0.0f)
                continue;   // negative supply doesn't count... zero does (it just reaches)
            m_fleet_supplyable_system_ids[empire_id].insert(supply_range.first);

            // should be only one empire per system at this point, but use max just to be safe...
            m_propagated_supply_ranges[supply_range.first] =
                std::max(supply_range.second.first, m_propagated_supply_ranges[supply_range.first]);
            m_empire_propagated_supply_ranges[empire_id][supply_range.first] =
                m_propagated_supply_ranges[supply_range.first];

            // should be only one empire per system at this point, but use max just to be safe...
            m_propagated_supply_distances[supply_range.first] =
                std::max(supply_range.second.second, m_propagated_supply_distances[supply_range.first]);
            m_empire_propagated_supply_distances[empire_id][supply_range.first] =
                m_propagated_supply_distances[supply_range.first];
        }

        //DebugLogger() << "For empire: " << empire_id << " system supply distances: ";
        //for (auto entry : m_empire_propagated_supply_distances[empire_id]) {
        //    DebugLogger() << entry.first << " : " << entry.second;
        //}
    }



    // TEST STUFF FOR INTER-EMPIRE-MERGING
    std::map<int, std::set<std::pair<int, int>>> ally_merged_supply_starlane_traversals = m_supply_starlane_traversals;

    // add connections into allied empire systems when their obstructed lane
    // traversals originate on either end of a starlane
    for (auto& empire_set : m_supply_starlane_obstructed_traversals) {
        // input:
        const std::set<std::pair<int, int>>& empire_obstructed_traversals = empire_set.second;
        // output:
        std::set<std::pair<int, int>>& empire_supply_traversals = ally_merged_supply_starlane_traversals[empire_set.first];


        std::set<int> allies_of_empire = Empires().GetEmpireIDsWithDiplomaticStatusWithEmpire(empire_set.first, DIPLO_ALLIED);
        for (int ally_id : allies_of_empire) {
            // input:
            auto const& ally_obstructed_traversals = m_supply_starlane_obstructed_traversals[ally_id];

            // find cases where outer loop empire has an obstructed traversal from A to B
            // and inner loop empire has an obstructed traversal from B to A
            for (auto const& empire_trav : empire_obstructed_traversals) {
                for (auto const& ally_trav : ally_obstructed_traversals) {
                    if (empire_trav.first == ally_trav.second && empire_trav.second == ally_trav.first) {
                        empire_supply_traversals.insert({empire_trav.first, empire_trav.second});
                        empire_supply_traversals.insert({empire_trav.second, empire_trav.first});
                    }
                }
            }
        }
    }

    // add allied supply starlane traversals to empires' traversals, so that
    // allies can use eachothers' supply networks
    for (auto& empire_set : ally_merged_supply_starlane_traversals) {
        std::set<std::pair<int, int>>& output_empire_traversals = empire_set.second;
        for (int ally_id : Empires().GetEmpireIDsWithDiplomaticStatusWithEmpire(empire_set.first, DIPLO_ALLIED)) {
            // copy ally traversals into the output empire traversals set
            for (const auto& traversal_pair : m_supply_starlane_traversals[ally_id])
                output_empire_traversals.insert(traversal_pair);
        }
    }

    // same for fleet supplyable system ids, as these are added to supplyable
    // groups in following code
    auto ally_merged_fleet_supplyable_system_ids = m_fleet_supplyable_system_ids;
    for (auto& empire_set : ally_merged_fleet_supplyable_system_ids) {
        std::set<int>& output_empire_ids = empire_set.second;
        for (int ally_id : Empires().GetEmpireIDsWithDiplomaticStatusWithEmpire(empire_set.first, DIPLO_ALLIED)) {
            // copy ally traversals into the output empire traversals set
            for (int sys_id : m_fleet_supplyable_system_ids[ally_id])
                output_empire_ids.insert(sys_id);
        }
    }

    // END TEST STUFF FOR INTER-EMPIRE-MERGING



    // determine supply-connected groups of systems for each empire.
    // need to merge interconnected supply groups into as few sets of mutually-
    // supply-exchanging systems as possible.  This requires finding the
    // connected components of an undirected graph, where the node
    // adjacency are the directly-connected systems determined above.
    for (const auto& empire_supply : empire_propagating_supply_ranges) {
        int empire_id = empire_supply.first;

        // assemble all direct connections between systems from remaining traversals
        std::map<int, std::set<int>> supply_groups_map;
        for (auto const& lane : ally_merged_supply_starlane_traversals[empire_id]) {
            supply_groups_map[lane.first].insert(lane.second);
            supply_groups_map[lane.second].insert(lane.first);
        }

        // also add connections from all fleet-supplyable systems to themselves, so that
        // any fleet supply able system with no connection to another system can still
        // have resource sharing within tiself
        for (int system_id : ally_merged_fleet_supplyable_system_ids[empire_id])
            supply_groups_map[system_id].insert(system_id);


        if (supply_groups_map.empty())
            continue;

        //DebugLogger() << "Empire " << empire_id << " supply groups map:";
        //for (auto const& q : supply_groups_map) {
        //    int source_id = q.first;

        //    std::stringstream other_ids;
        //    for (auto const& r : q.second)
        //    { other_ids << r << ", "; }

        //    DebugLogger() << " ... src: " << source_id << " to: " << other_ids.str();
        //}


        // create graph
        boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS> graph;

        // boost expects vertex labels to range from 0 to num vertices - 1, so need
        // to map from system id to graph id and back when accessing vertices
        std::vector<int> graph_id_to_sys_id;
        graph_id_to_sys_id.reserve(supply_groups_map.size());

        std::map<int, int> sys_id_to_graph_id;
        int graph_id = 0;
        for (std::map<int, std::set<int>>::value_type& supply_group : supply_groups_map) {
            int sys_id = supply_group.first;
            boost::add_vertex(graph);   // should add with index = graph_id

            graph_id_to_sys_id.push_back(sys_id);
            sys_id_to_graph_id[sys_id] = graph_id;
            ++graph_id;
        }

        // add edges for all direct connections between systems
        // and add edges from fleet supplyable systems to themselves
        for (std::map<int, std::set<int>>::value_type& supply_group : supply_groups_map) {
            int start_graph_id = sys_id_to_graph_id[supply_group.first];
            for (int system_id : supply_group.second) {
                int end_graph_id = sys_id_to_graph_id[system_id];
                boost::add_edge(start_graph_id, end_graph_id, graph);
            }
        }

        // declare storage and fill with the component id (group id of connected systems)
        // for each graph vertex
        std::vector<int> components(boost::num_vertices(graph));
        boost::connected_components(graph, &components[0]);

        // convert results back from graph id to system id, and into desired output format
        // output: std::map<int, std::set<std::set<int>>>& m_resource_supply_groups

        // first, sort into a map from component id to set of system ids in component
        std::map<int, std::set<int>> component_sets_map;
        for (std::size_t comp_graph_id = 0; comp_graph_id != components.size(); ++comp_graph_id) {
            int label = components[comp_graph_id];
            int sys_id = graph_id_to_sys_id[comp_graph_id];
            component_sets_map[label].insert(sys_id);
        }

        // copy sets in map into set of sets
        for (std::map<int, std::set<int>>::value_type& component_set : component_sets_map)
            m_resource_supply_groups[empire_id].insert(component_set.second);
    }
}
Exemple #3
0
void GenerateStarlanes(int max_jumps_between_systems, int max_starlane_length) {
    int num_systems, s1, s2, s3; // numbers of systems, indices in vec_sys
    int n; // loop counter

    std::vector<int> triVerts;  // indices of stars that form vertices of a triangle

    // array of set to store final, included starlanes for each star
    std::vector<std::set<int> > laneSetArray;

    // array of set to store possible starlanes for each star, as extracted form triangulation
    std::vector<std::set<int> > potential_lane_set_array;

    // iterators for traversing lists of starlanes
    std::set<int>::iterator laneSetIter, laneSetEnd, laneSetIter2, laneSetEnd2;

    // get systems
    std::vector<TemporaryPtr<System> > sys_vec = Objects().FindObjects<System>();
    num_systems = sys_vec.size();  // (actually = number of systems + 1)

    // pass systems to Delauney Triangulation routine, getting array of triangles back
    std::list<Delauney::DTTriangle>* triangle_list = Delauney::DelauneyTriangulate(sys_vec);
    if (!triangle_list ||triangle_list->empty()) {
        ErrorLogger() << "Got no list or blank list of triangles from Triangulation.";
        return;
    }

    Delauney::DTTriangle tri;
    // initialize arrays...
    potential_lane_set_array.resize(num_systems);
    for (n = 0; n < num_systems; n++) {
        potential_lane_set_array[n].clear();
    }
    laneSetArray.resize(num_systems);
    for (n = 0; n < num_systems; n++) {
        laneSetArray[n].clear();
    }

    // extract triangles from list, add edges to sets of potential starlanes for each star (in array)
    while (!triangle_list->empty()) {
        tri = triangle_list->front();

        triVerts = tri.Verts();
        s1 = triVerts[0];
        s2 = triVerts[1];
        s3 = triVerts[2];

        // add starlanes to list of potential starlanes for each star, making sure each pair involves
        // only stars that actually exist.  triangle generation uses three extra points which don't
        // represent actual systems and which need to be weeded out here.
        if ((s1 >= 0) && (s2 >= 0) && (s3 >= 0)) {
            if ((s1 < num_systems) && (s2 < num_systems)) {
                potential_lane_set_array[s1].insert(s2);
                potential_lane_set_array[s2].insert(s1);
            }
            if ((s1 < num_systems) && (s3 < num_systems)) {
                potential_lane_set_array[s1].insert(s3);
                potential_lane_set_array[s3].insert(s1);
            }
            if ((s2 < num_systems) && (s3 < num_systems)) {
                potential_lane_set_array[s2].insert(s3);
                potential_lane_set_array[s3].insert(s2);
            }
        }

        triangle_list->pop_front();
    }

    // cleanup
    delete triangle_list;

    //DebugLogger() << "Extracted Potential Starlanes from Triangulation";

    CullTooLongLanes(max_starlane_length, potential_lane_set_array, sys_vec);

    CullAngularlyTooCloseLanes(0.98, potential_lane_set_array, sys_vec);

    //DebugLogger() << "Culled Agularly Too Close Lanes";

    laneSetArray = potential_lane_set_array;

    // attempt removing lanes, but don't do so if it would make the systems
    // the lane connects too far apart
    for (n = 0; n < num_systems; ++n) {
        laneSetIter = potential_lane_set_array[n].begin();

        while (laneSetIter != potential_lane_set_array[n].end()) {
            s1 = *laneSetIter;

            // try removing lane
            laneSetArray[n].erase(s1);
            laneSetArray[s1].erase(n);

            if (!ConnectedWithin(n, s1, max_jumps_between_systems, laneSetArray)) {
                // lane removal was a bad idea.  restore it
                laneSetArray[n].insert(s1);
                laneSetArray[s1].insert(n);
            }

            ++laneSetIter;
        } // end while
    }

    // add the starlane to the stars
    for (n = 0; n < num_systems; ++n) {
        const std::set<int>& lanes = laneSetArray[n];
        for (std::set<int>::const_iterator it = lanes.begin(); it != lanes.end(); ++it)
            sys_vec[n]->AddStarlane(sys_vec[*it]->ID()); // System::AddStarlane() expects a system ID
    }

    DebugLogger() << "Initializing System Graph";
    GetUniverse().InitializeSystemGraph();
}
Exemple #4
0
void CMine::MoveOn (char axis,INT32 inc) 
{
int nSegment = Current ()->segment;
int nSide = Current ()->side;
int nPoint = Current ()->point;
int nLine = Current ()->line;
CDSegment *seg = Segments (nSegment);
INT16 i;

theApp.SetModified (TRUE);
switch (m_selectMode) {
	case POINT_MODE:
		switch (axis) {
			case 'X':
				Vertices (seg->verts [side_vert [nSide][nPoint]])->x += inc;
				break;
			case 'Y':
				Vertices (seg->verts [side_vert [nSide][nPoint]])->y += inc;
				break;
			case 'Z':
				Vertices (seg->verts [side_vert [nSide][nPoint]])->z += inc;
				break;
			}
		break;

	case LINE_MODE:
		switch (axis) {
			case 'X':
				Vertices (seg->verts [line_vert [side_line [nSide][nLine]][0]])->x += inc;
				Vertices (seg->verts [line_vert [side_line [nSide][nLine]][1]])->x += inc;
				break;
			case 'Y':
				Vertices (seg->verts [line_vert [side_line [nSide][nLine]][0]])->y += inc;
				Vertices (seg->verts [line_vert [side_line [nSide][nLine]][1]])->y += inc;
				break;
			case 'Z':
				Vertices (seg->verts [line_vert [side_line [nSide][nLine]][0]])->z += inc;
				Vertices (seg->verts [line_vert [side_line [nSide][nLine]][1]])->z += inc;
				break;
			}
		break;

	case SIDE_MODE:
		switch (axis) {
			case 'X':
			for (i = 0; i < 4; i++)
				Vertices (seg->verts [side_vert [nSide][i]])->x += inc;
			break;
		case 'Y':
			for (i = 0; i < 4; i++)
				Vertices (seg->verts [side_vert [nSide][i]])->y += inc;
			break;
		case 'Z':
			for (i = 0; i < 4; i++)
				Vertices (seg->verts [side_vert [nSide][i]])->z += inc;
			break;
		}
		break;

	case CUBE_MODE:
		switch (axis) {
			case 'X':
				for (i = 0; i < 8; i++)
					Vertices (seg->verts [i])->x += inc;
				for (i = 0; i < GameInfo ().objects.count; i++)
					if (Objects (i)->segnum == nSegment)
						Objects (i)->pos.x += inc;
				break;
			case 'Y':
				for (i = 0; i < 8; i++)
					Vertices (seg->verts [i])->y += inc;
				for (i = 0; i < GameInfo ().objects.count; i++) 
					if (Objects (i)->segnum == nSegment)
						Objects (i)->pos.y += inc;
				break;
			case 'Z':
				for (i = 0; i < 8; i++)
					Vertices (seg->verts [i])->z += inc;
				for (i = 0; i < GameInfo ().objects.count; i++) 
					if (Objects (i)->segnum == nSegment) 
						Objects (i)->pos.z += inc;
				break;
			}
	break;

	case OBJECT_MODE:
		switch (axis) {
			case 'X':
				CurrObj ()->pos.x += inc;
				break;
			case 'Y':
				CurrObj ()->pos.y += inc;
				break;
			case 'Z':
				CurrObj ()->pos.z += inc;
				break;
		}
	break;

	case BLOCK_MODE:
		CDObject *obj = Objects ();
		switch (axis) {
			case 'X':
				for (i = 0; i < MAX_VERTICES; i++)
					if (*VertStatus (i) & MARKED_MASK)
						Vertices (i)->x += inc;
				for (i = GameInfo ().objects.count; i; i--, obj++)
					if (obj->segnum >= 0)
						if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK)
							obj->pos.x += inc;
				break;
			case 'Y':
				for (i = 0; i < MAX_VERTICES; i++)
					if (*VertStatus (i) & MARKED_MASK)
						Vertices (i)->y += inc;
				for (i = GameInfo ().objects.count; i; i--, obj++)
					if (obj->segnum >= 0)
						if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK)
							obj->pos.y += inc;
				break;
			case 'Z':
				for (i = 0; i < MAX_VERTICES; i++)
					if (*VertStatus (i) & MARKED_MASK)
						Vertices (i)->z += inc;
				for (i = GameInfo ().objects.count; i; i--, obj++)
					if (obj->segnum >= 0)
						if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK)
							obj->pos.z += inc;
				break;
		}
	break;
	}
}
Exemple #5
0
void CMine::SpinSelection(double angle) 
{
	int nSegment = Current ()->segment;
	int nSide = Current ()->side;
	CDSegment *seg = Segments (nSegment);
	CDObject *obj;
	vms_vector center,opp_center;
	INT16 i;

#ifdef SPIN_RELATIVE
	double xspin,yspin,zspin;
	vms_vector rel [3];
#endif

/* calculate segment pointer */
switch (m_selectMode) {
	case POINT_MODE:
		ErrorMsg ("Cannot spin a point");
		break; /* can't spin a point */
	
	case LINE_MODE:
		ErrorMsg ("Cannot spin a line");
		break; /* line spinning not supported */
	
	case SIDE_MODE: // spin side around its center in the plane of the side
		// calculate center of current side
		theApp.SetModified (TRUE);
		center.x = center.y = center.z = 0;
		for (i = 0; i < 4; i++) {
			center.x += Vertices (seg->verts [side_vert [nSide][i]])->x;
			center.y += Vertices (seg->verts [side_vert [nSide][i]])->y;
			center.z += Vertices (seg->verts [side_vert [nSide][i]])->z;
			}
		center.x /= 4;
		center.y /= 4;
		center.z /= 4;
		// calculate orthogonal vector from lines which intersect point 0
		//       |x  y  z |
		// AxB = |ax ay az| = x(aybz-azby), y(azbx-axbz), z(axby-aybx)
		//       |bx by bz|
		struct vector {double x,y,z;};
		struct vector a,b,c;
		double length;
		INT16 vertnum1,vertnum2;

		vertnum1 = seg->verts [side_vert [nSide][0]];
		vertnum2 = seg->verts [side_vert [nSide][1]];
		a.x = (double)(Vertices (vertnum2)->x - Vertices (vertnum1)->x);
		a.y = (double)(Vertices (vertnum2)->y - Vertices (vertnum1)->y);
		a.z = (double)(Vertices (vertnum2)->z - Vertices (vertnum1)->z);
		vertnum1 = seg->verts [side_vert [nSide][0]];
		vertnum2 = seg->verts [side_vert [nSide][3]];
		b.x = (double)(Vertices (vertnum2)->x - Vertices (vertnum1)->x);
		b.y = (double)(Vertices (vertnum2)->y - Vertices (vertnum1)->y);
		b.z = (double)(Vertices (vertnum2)->z - Vertices (vertnum1)->z);
		c.x = a.y*b.z - a.z*b.y;
		c.y = a.z*b.x - a.x*b.z;
		c.z = a.x*b.y - a.y*b.x;
		// normalize the vector
		length = sqrt(c.x*c.x + c.y*c.y + c.z*c.z);
		c.x /= length;
		c.y /= length;
		c.z /= length;
		// set sign (since vert numbers for most sides don't follow right-handed convention)
		if (nSide!=1 && nSide!=5) {
			c.x = -c.x;
			c.y = -c.y;
			c.z = -c.z;
			}
		// set opposite center
		opp_center.x = center.x + (FIX)(0x10000L*c.x);
		opp_center.y = center.y + (FIX)(0x10000L*c.y);
		opp_center.z = center.z + (FIX)(0x10000L*c.z);
		/* rotate points around a line */
		for (i = 0; i < 4; i++) {
			RotateVertex(Vertices (seg->verts [side_vert [nSide][i]]),
			&center,&opp_center,angle);
			}
		break;


	case CUBE_MODE:	// spin cube around the center of the cube using screen's perspective
		// calculate center of current cube
		theApp.SetModified (TRUE);
		center.x = center.y = center.z = 0;
		for (i = 0; i < 8; i++) {
			center.x += Vertices (seg->verts [i])->x;
			center.y += Vertices (seg->verts [i])->y;
			center.z += Vertices (seg->verts [i])->z;
			}
		center.x /= 8;
		center.y /= 8;
		center.z /= 8;
		// calculate center of oppisite current side
		opp_center.x = opp_center.y = opp_center.z = 0;
		for (i = 0; i < 4; i++) {
			opp_center.x += Vertices (seg->verts [opp_side_vert [nSide][i]])->x;
			opp_center.y += Vertices (seg->verts [opp_side_vert [nSide][i]])->y;
			opp_center.z += Vertices (seg->verts [opp_side_vert [nSide][i]])->z;
			}
		opp_center.x /= 4;
		opp_center.y /= 4;
		opp_center.z /= 4;
		// rotate points about a point
		for (i = 0; i < 8; i++)
			RotateVertex(Vertices (seg->verts [i]),&center,&opp_center,angle);
		break;

	case OBJECT_MODE:	// spin object vector
		theApp.SetModified (TRUE);
		vms_matrix *orient;
		orient = (Current ()->object == GameInfo ().objects.count) ? &SecretOrient () : &CurrObj ()->orient;
		switch (nSide) {
			case 0:
				RotateVmsMatrix(orient,angle,'x');
				break;
			case 2:
				RotateVmsMatrix(orient,-angle,'x');
				break;
			case 1:
				RotateVmsMatrix(orient,-angle,'y');
				break;
			case 3:
				RotateVmsMatrix(orient,angle,'y');
				break;
			case 4:
				RotateVmsMatrix(orient,angle,'z');
				break;
			case 5:
				RotateVmsMatrix(orient,-angle,'z');
				break;
			}
#ifdef SPIN_RELATIVE
		// calculate angles to spin the side into the x-y plane
		// use points 0,1, and 2 of the side
		// make point0 the origin
		// and get coordinates of points 1 and 2 relative to point 0
		for (i=0;i<3;i++) {
			rel [i].x = vertices [seg->verts [side_vert [nSide][i]]].x - vertices [seg->verts [side_vert [nSide][0]]].x;
			rel [i].y = vertices [seg->verts [side_vert [nSide][i]]].y - vertices [seg->verts [side_vert [nSide][0]]].y;
			rel [i].z = vertices [seg->verts [side_vert [nSide][i]]].z - vertices [seg->verts [side_vert [nSide][0]]].z;
			}
		// calculate z-axis spin angle to rotate point1 so it lies in x-y plane
		zspin = (rel [1].x==rel [1].y) ? PI/4 : atan2(rel [1].y,rel [1].x);
		// spin all 3 points on z axis
		for (i=0;i<3;i++)
			RotateVmsVector(&rel [i],zspin,'z');
		// calculate y-axis spin angle to rotate point1 so it lies on x axis
		yspin = (rel [1].z==rel [1].x) ? PI/4 : atan2(rel [1].z,rel [1].x);
		// spin points 1 and 2 on y axis (don't need to spin point 0 since it is at 0,0,0)
		for (i=1;i<=2;i++)
			RotateVmsVector(&rel [i],yspin,'y');
		// calculate x-axis spin angle to rotate point2 so it lies in x-y plane
		xspin = (rel [2].z==rel [2].y) ? PI/4 : atan2(rel [2].z,rel [2].y);
		// spin points 2 on x axis (don't need to spin point 1 since it is on the x-axis
		RotateVmsVector(&rel [2],xspin,'x');
		RotateVmsMatrix(&obj->orient,zspin,'z');
		RotateVmsMatrix(&obj->orient,yspin,'y');
		RotateVmsMatrix(&obj->orient,xspin,'x');
		RotateVmsMatrix(&obj->orient,-xspin,'x');
		RotateVmsMatrix(&obj->orient,-yspin,'y');
		RotateVmsMatrix(&obj->orient,-zspin,'z');
#endif //SPIN_RELATIVE
		break;

	case BLOCK_MODE:
		theApp.SetModified (TRUE);
		// calculate center of current cube
		center.x = center.y = center.z = 0;
		for (i = 0; i < 8; i++) {
			center.x += Vertices (seg->verts [i])->x;
			center.y += Vertices (seg->verts [i])->y;
			center.z += Vertices (seg->verts [i])->z;
			}
		center.x /= 8;
		center.y /= 8;
		center.z /= 8;
		// calculate center of oppisite current side
		opp_center.x = opp_center.y = opp_center.z = 0;
		for (i = 0; i < 4; i++) {
			opp_center.x += Vertices (seg->verts [opp_side_vert [nSide][i]])->x;
			opp_center.y += Vertices (seg->verts [opp_side_vert [nSide][i]])->y;
			opp_center.z += Vertices (seg->verts [opp_side_vert [nSide][i]])->z;
			}
		opp_center.x /= 4;
		opp_center.y /= 4;
		opp_center.z /= 4;
		// rotate points about a point
		for (i=0;i<VertCount ();i++)
			if (*VertStatus (i) & MARKED_MASK)
				RotateVertex(Vertices (i),&center,&opp_center,angle);
		// rotate Objects () within marked cubes
		obj = Objects ();
		for (i = GameInfo ().objects.count; i; i--, obj++)
			if (Segments (obj->segnum)->wall_bitmask & MARKED_MASK)
				RotateVertex(&obj->pos, &center, &opp_center, angle);
		break;
	}
}
Exemple #6
0
bool Planet::Colonize(int empire_id, const std::string& species_name, double population) {
    const Species* species = 0;

    // if desired pop > 0, we want a colony, not an outpost, so we need to do some checks
    if (population > 0.0) {
        // check if specified species exists and get reference
        species = GetSpecies(species_name);
        if (!species) {
            ErrorLogger() << "Planet::Colonize couldn't get species already on planet with name: " << species_name;
            return false;
        }
        // check if specified species can colonize this planet
        if (EnvironmentForSpecies(species_name) < PE_HOSTILE) {
            ErrorLogger() << "Planet::Colonize: can't colonize planet already populated by species " << species_name;
            return false;
        }
    }

    // reset the planet to unowned/unpopulated
    if (!OwnedBy(empire_id)) {
        Reset();
    } else {
        PopCenter::Reset();
        for (std::set<int>::const_iterator it = m_buildings.begin(); it != m_buildings.end(); ++it)
            if (TemporaryPtr<Building> building = GetBuilding(*it))
                building->Reset();
        m_just_conquered = false;
        m_is_about_to_be_colonized = false;
        m_is_about_to_be_invaded = false;
        m_is_about_to_be_bombarded = false;
        SetOwner(ALL_EMPIRES);
    }

    // if desired pop > 0, we want a colony, not an outpost, so we have to set the colony species
    if (population > 0.0)
        SetSpecies(species_name);

    // find a default focus. use first defined available focus.
    // AvailableFoci function should return a vector of all names of
    // available foci.
    std::vector<std::string> available_foci = AvailableFoci();
    if (species && !available_foci.empty()) {
        bool found_preference = false;
        for (std::vector<std::string>::const_iterator it = available_foci.begin();
             it != available_foci.end(); ++it)
        {
            if (!it->empty() && *it == species->PreferredFocus()) {
                SetFocus(*it);
                found_preference = true;
                break;
            }
        }

        if (!found_preference)
            SetFocus(*available_foci.begin());
    } else {
        DebugLogger() << "Planet::Colonize unable to find a focus to set for species " << species_name;
    }

    // set colony population
    GetMeter(METER_POPULATION)->SetCurrent(population);
    GetMeter(METER_TARGET_POPULATION)->SetCurrent(population);
    BackPropagateMeters();


    // set specified empire as owner
    SetOwner(empire_id);

    // if there are buildings on the planet, set the specified empire as their owner too
    std::vector<TemporaryPtr<Building> > buildings = Objects().FindObjects<Building>(BuildingIDs());
    for (std::vector<TemporaryPtr<Building> >::iterator building_it = buildings.begin();
         building_it != buildings.end(); ++building_it)
    { (*building_it)->SetOwner(empire_id); }

    return true;
}
void RoadPositionSystem::Update(float dt) {
    for(auto o : Objects()) {
        PositionChanged(o);
    }
}
Exemple #8
0
void FleetTransferOrder::ExecuteImpl() const {
    ValidateEmpireID();

    // look up the destination fleet
    TemporaryPtr<Fleet> target_fleet = GetFleet(DestinationFleet());
    if (!target_fleet) {
        ErrorLogger() << "Empire attempted to move ships to a nonexistant fleet";
        return;
    }
    // check that destination fleet is owned by empire
    if (!target_fleet->OwnedBy(EmpireID())) {
        ErrorLogger() << "Empire attempted to move ships to a fleet it does not own";
        return;
    }
    // verify that fleet is in a system
    if (target_fleet->SystemID() == INVALID_OBJECT_ID) {
        ErrorLogger() << "Empire attempted to transfer ships to/from fleet(s) not in a system";
        return;
    }

    // check that all ships are in the same system
    std::vector<TemporaryPtr<Ship> > ships = Objects().FindObjects<Ship>(m_add_ships);

    std::vector<TemporaryPtr<Ship> > validated_ships;
    validated_ships.reserve(m_add_ships.size());
    std::vector<int>                 validated_ship_ids;
    validated_ship_ids.reserve(m_add_ships.size());

    for (std::vector<TemporaryPtr<Ship> >::const_iterator it = ships.begin();
         it != ships.end(); ++it)
    {
        TemporaryPtr<Ship> ship = *it;
        if (!ship->OwnedBy(EmpireID()))
            continue;
        if (ship->SystemID() != target_fleet->SystemID())
            continue;
        if (ship->FleetID() == target_fleet->ID())
            continue;
        validated_ships.push_back(ship);
        validated_ship_ids.push_back(ship->ID());
    }
    if (validated_ships.empty())
        return;

    GetUniverse().InhibitUniverseObjectSignals(true);

    // remove from old fleet(s)
    std::set<TemporaryPtr<Fleet> > modified_fleets;
    for (std::vector<TemporaryPtr<Ship> >::iterator it = validated_ships.begin();
         it != validated_ships.end(); ++it)
    {
        TemporaryPtr<Ship> ship = *it;
        if (TemporaryPtr<Fleet> source_fleet = GetFleet(ship->FleetID())) {
            source_fleet->RemoveShip(ship->ID());
            modified_fleets.insert(source_fleet);
        }
        ship->SetFleetID(target_fleet->ID());
    }

    // add to new fleet
    target_fleet->AddShips(validated_ship_ids);

    GetUniverse().InhibitUniverseObjectSignals(false);

    // signal change to fleet states
    modified_fleets.insert(target_fleet);

    for (std::set<TemporaryPtr<Fleet> >::iterator it = modified_fleets.begin();
         it != modified_fleets.end(); ++it)
    {
        TemporaryPtr<Fleet> modified_fleet = *it;
        if (!modified_fleet->Empty())
            modified_fleet->StateChangedSignal();
        // if modified fleet is empty, it should be immently destroyed, so that updating it now is redundant
    }
}
Exemple #9
0
CombatInfo::CombatInfo(int system_id_, int turn_) :
    turn(turn_),
    system_id(system_id_)
{
    TemporaryPtr<System> system = ::GetSystem(system_id);
    if (!system) {
        Logger().errorStream() << "CombatInfo constructed with invalid system id: " << system_id;
        return;
    }

    // add system to full / complete objects in combat - NOTE: changed from copy of system
    objects.Insert(system);


    // find ships and their owners in system
    std::vector<TemporaryPtr<Ship> > ships =
        Objects().FindObjects<Ship>(system->ShipIDs());

    for (std::vector<TemporaryPtr<Ship> >::const_iterator ship_it = ships.begin();
         ship_it != ships.end(); ++ship_it)
    {
        TemporaryPtr<Ship> ship = *ship_it;
        // add owner to empires that have assets in this battle
        empire_ids.insert(ship->Owner());

        objects.Insert(ship);
    }

    // find planets and their owners in system
    std::vector<TemporaryPtr<Planet> > planets =
        Objects().FindObjects<Planet>(system->PlanetIDs());

    for (std::vector<TemporaryPtr<Planet> >::const_iterator planet_it = planets.begin();
         planet_it != planets.end(); ++planet_it)
    {
        TemporaryPtr<Planet> planet = *planet_it;
        // if planet is populated, add owner to empires that have assets in this battle
        if (planet->CurrentMeterValue(METER_POPULATION) > 0.0)
            empire_ids.insert(planet->Owner());

        objects.Insert(planet);
    }

    // TODO: should buildings be considered separately?

    // now that all participants in the battle have been found, loop through
    // objects again to assemble each participant empire's latest
    // known information about all objects in this battle

    // system
    for (std::set<int>::const_iterator empire_it = empire_ids.begin();
         empire_it != empire_ids.end(); ++empire_it)
    {
        int empire_id = *empire_it;
        if (empire_id == ALL_EMPIRES)
            continue;
        empire_known_objects[empire_id].Insert(GetEmpireKnownSystem(system->ID(), empire_id));
    }

    // ships
    for (std::vector<TemporaryPtr<Ship> >::const_iterator it = ships.begin();
         it != ships.end(); ++it)
    {
        TemporaryPtr<Ship> ship = *it;
        int ship_id = ship->ID();
        TemporaryPtr<const Fleet> fleet = GetFleet(ship->FleetID());
        if (!fleet) {
            Logger().errorStream() << "CombatInfo::CombatInfo couldn't get fleet with id "
                                   << ship->FleetID() << " in system " << system->Name() << " (" << system_id << ")";
            continue;
        }

        for (std::set<int>::const_iterator empire_it = empire_ids.begin();
             empire_it != empire_ids.end(); ++empire_it)
        {
            int empire_id = *empire_it;
            if (empire_id == ALL_EMPIRES)
                continue;
            if (GetUniverse().GetObjectVisibilityByEmpire(ship_id, empire_id) >= VIS_BASIC_VISIBILITY ||
                   (fleet->Aggressive() &&
                       (empire_id == ALL_EMPIRES ||
                        fleet->Unowned() ||
                        Empires().GetDiplomaticStatus(empire_id, fleet->Owner()) == DIPLO_WAR)))
            { empire_known_objects[empire_id].Insert(GetEmpireKnownShip(ship->ID(), empire_id));}
        }
    }

    // planets
    for (std::vector<TemporaryPtr<Planet> >::const_iterator it = planets.begin();
         it != planets.end(); ++it)
    {
        TemporaryPtr<Planet> planet = *it;
        int planet_id = planet->ID();

        for (std::set<int>::const_iterator empire_it = empire_ids.begin(); empire_it != empire_ids.end(); ++empire_it) {
            int empire_id = *empire_it;
            if (empire_id == ALL_EMPIRES)
                continue;
            if (GetUniverse().GetObjectVisibilityByEmpire(planet_id, empire_id) >= VIS_BASIC_VISIBILITY) {
                empire_known_objects[empire_id].Insert(GetEmpireKnownPlanet(planet->ID(), empire_id));
            }
        }
    }

    // after battle is simulated, any changes to latest known or actual objects
    // will be copied back to the main Universe's ObjectMap and the Universe's
    // empire latest known objects ObjectMap - NOTE: Using the real thing now
}
void HydralicMeshSystem::Update(float dt) {

    
    for (GameObject* object : Objects()) {
        const Atlas::Node& housing = object->GetComponent<Atlas>()->GetNode("HydralicHousing");
        const Atlas::Node& cylinder = object->GetComponent<Atlas>()->GetNode("HydralicMetal");
        
        auto& mesh = object->GetComponent<Mesh>()->GetMesh<Vertex>();
        Spring* spring = object->GetComponent<Spring>();
        
        float houseWidth = object->GetComponent<Hydralic>()->minLength;
        float houseEdgeWidth = 0.02f;
        float houseThickness = 1.2f;
        float houseTex = 0.05f;
        
        float cylinderEdgeWidth = 0.02f;
        float cylinderWidth = spring->length - houseWidth;
        float cylinderThickness = 0.80f;
        float cylinderTex = 0.05f;
        
        mesh.vertices.resize(6 + 8);
        
        mesh.vertices[0].Position = {cylinderThickness, houseWidth,0};
        mesh.vertices[0].TextureCoords = {cylinder.outer.left +cylinderTex,cylinder.outer.top};
        
        mesh.vertices[1].Position = {-cylinderThickness, houseWidth,0};
        mesh.vertices[1].TextureCoords = {cylinder.outer.left +cylinderTex,cylinder.outer.bottom};
        
        mesh.vertices[2].Position = {cylinderThickness, houseWidth+cylinderWidth-cylinderEdgeWidth,0};
        mesh.vertices[2].TextureCoords = {cylinder.outer.right - cylinderTex, cylinder.outer.top};
        
        mesh.vertices[3].Position = {-cylinderThickness,houseWidth+cylinderWidth-cylinderEdgeWidth,0};
        mesh.vertices[3].TextureCoords = {cylinder.outer.right - cylinderTex, cylinder.outer.bottom};
        
        mesh.vertices[4].Position = {cylinderThickness,houseWidth+cylinderWidth,0};
        mesh.vertices[4].TextureCoords = {cylinder.outer.right, cylinder.outer.top};
        
        mesh.vertices[5].Position = {-cylinderThickness,houseWidth+cylinderWidth,0};
        mesh.vertices[5].TextureCoords = {cylinder.outer.right, cylinder.outer.bottom};
       
        mesh.triangles.clear();
        
        for (int i=0; i<2; i++) {
            int index = i * 2;
            mesh.triangles.push_back(index + 0);
            mesh.triangles.push_back(index + 2);
            mesh.triangles.push_back(index + 3);
            
            mesh.triangles.push_back(index + 0);
            mesh.triangles.push_back(index + 3);
            mesh.triangles.push_back(index + 1);
        }
        
        mesh.vertices[6].Position = {houseThickness,0,0};
        mesh.vertices[6].TextureCoords = {housing.outer.left, housing.outer.top};
        
        mesh.vertices[7].Position = {-houseThickness,0,0};
        mesh.vertices[7].TextureCoords = {housing.outer.left, housing.outer.bottom};
        
        mesh.vertices[8].Position = {houseThickness,houseEdgeWidth,0};
        mesh.vertices[8].TextureCoords = {housing.outer.left+houseTex, housing.outer.top};
        
        mesh.vertices[9].Position = {-houseThickness, houseEdgeWidth,0};
        mesh.vertices[9].TextureCoords = {housing.outer.left+houseTex, housing.outer.bottom};
        
        mesh.vertices[10].Position = {houseThickness, houseWidth - houseEdgeWidth,0};
        mesh.vertices[10].TextureCoords = {housing.outer.right-houseTex, housing.outer.top};
        
        mesh.vertices[11].Position = {-houseThickness,houseWidth - houseEdgeWidth,0};
        mesh.vertices[11].TextureCoords = {housing.outer.right-houseTex, housing.outer.bottom};
        
        mesh.vertices[12].Position = {houseThickness, houseWidth,0};
        mesh.vertices[12].TextureCoords = {housing.outer.right, housing.outer.top};
        
        mesh.vertices[13].Position = {-houseThickness, houseWidth,0};
        mesh.vertices[13].TextureCoords = {housing.outer.right, housing.outer.bottom};
        
        for (int i=0; i<3; i++) {
            int index = 6 + i * 2;
            mesh.triangles.push_back(index + 0);
            mesh.triangles.push_back(index + 2);
            mesh.triangles.push_back(index + 3);
            
            mesh.triangles.push_back(index + 0);
            mesh.triangles.push_back(index + 3);
            mesh.triangles.push_back(index + 1);
        }
        
        
    }
}
Exemple #11
0
void CreateWorld()
{
	Objects TownUpObjects[9] = {Objects(375, 300, 50, 150), Objects(185, 325, 80, 130), Objects(85, 195, 50, 155), Objects(0, -1, 101, 210), Objects(100, -1, 135, 185),
	Objects(245, -1, 75, 100), Objects(310, -1, 50, 150), Objects(380, -1, 100, 150), Objects(400, -1, 100, 175)};
	places.InsertTop("TownUP.bmp", NULL, NULL, NULL, 9, TownUpObjects, 0, NULL, 0, NULL);
	Objects TownExitObjects[11] = {Objects(-1, -1, 140, 100), Objects(85, -1, 50, 155), Objects(160, -1, 40, 155), Objects(240, -1, 90, 155), Objects(340, -1, 150, 155),
	Objects(370, -1, 175, 175), Objects(-1, 360, 125, 150), Objects(315, 300, 300, 300), Objects(400, 240, 100, 100), Objects(30, 210, 50, 50), Objects(270, 210, 50, 50)};
	places.InsertBottom("TownExit.bmp", NULL, NULL, NULL, 11, TownExitObjects, 0, NULL, 2, NPCs);
	Objects TownLeftObjects[9] = {Objects(240, 290, 75, 85), Objects(-1, -1, 100, 175), Objects(90, -1, 50, 210), Objects(150, 0, 90, 210), Objects(210, 0, 30, 260),
	Objects(-1, 290, 70, 200), Objects(210, 0, 50, 75), Objects(285, 0, 177, 75), Objects(400, 75, 60, 125)};
	places.InsertLeft("TownLeft.bmp", NULL, NULL, NULL, 9, TownLeftObjects, 0, NULL, 0, NULL);
	currentLocation = currentLocation->left;
	Objects LeftUpObjects[8] = {Objects(0, 0, 235, 210), Objects(0, 209, 100, 200), Objects(0, 280, 230, 200), Objects(170, 250, 50, 200), Objects(245, 0, 200, 210),
	Objects(365, 209, 100, 200), Objects(250, 290, 300, 160), Objects(250, 250, 60, 100)};
	currentLocation->InsertTop("TownLeftUp.bmp", NULL, NULL, NULL, 8, LeftUpObjects, 0, NULL, 0, NULL);
	currentLocation = places.bottom;
	Objects FirstForest[9] = {Objects(0, 0, 190, 275), Objects(0, 199, 165, 100), Objects(0, 298, 110, 150), Objects(0, 370, 140, 75), Objects(190, 270, 75, 180),
	Objects(250, 0, 250, 150), Objects(280, 0, 250, 200), Objects(330, 189, 250, 150), Objects(380, 300, 100, 150)};
	currentLocation->InsertBottom("FirstForest.bmp", NULL, NULL, NULL, 9, FirstForest, 0, NULL, 0, NULL);
	currentLocation = currentLocation->bottom;
	Objects SecondForest[6] = {Objects(0, 0, 170, 200), Objects(215, 0, 85, 200), Objects(170, 120, 45, 160), Objects(330, 0, 100, 465), Objects(220, 250, 45, 160),
	Objects(0, 300, 250, 250)};
	currentLocation->InsertBottom("SecondForest.bmp", NULL, NULL, NULL, 6, SecondForest, 0, NULL, 0, NULL);
	currentLocation = currentLocation->bottom;
	Objects caveObjects[4] = {Objects(-1, -1, 200, 500), Objects(100, 200, 130, 500), Objects(300, -1, 500, 500), Objects(250, 200, 500, 500)};
	Interior Cave[1] = {Interior(new Location("FirstCave.bmp", NULL, NULL, NULL, NULL, 4, caveObjects, 0, NULL, 0, NULL), 215, 150, 240, 60, SetFront)};
	Objects ThirdForest[5] = {Objects(0, 0, 200, 500), Objects(230, -1, 220, 200), Objects(250, 199, 140, 160), Objects(390, 300, 50, 150), Objects(199, 325, 35, 30)};
	currentLocation->InsertLeft("ThirdForest.bmp", NULL, NULL, NULL, 5, ThirdForest, 1, Cave, 0, NULL);
	currentLocation = currentLocation->left;
	Objects SecondCaveObjects[5] = {Objects(-1, -1, 200, 300), Objects(-1, -1, 231, 200), Objects(0, 298, 255, 200), Objects(250, -1, 500, 200),
	Objects(280, 100, 500, 500)};
	currentLocation->interiors[0].getLocation()->InsertBottom("SecondCave.bmp", NULL, NULL, NULL, 5, SecondCaveObjects, 0, NULL, 0, NULL);
	currentLocation = &places;
}
Exemple #12
0
int current_frame=0;
bool w = false, a = false, s = false, d = false, InInterior = false, InMenu = false, topInterior = false, text1 = false, text2 = false;
void *font2;
float color[3];

CTimer StopTime;
int last_time, StoppedTime, currentInterior, walkTimer;
CTimer *Timer=new CTimer();
Inventory inventory;

CObject *NPCs = NULL;
CObject Textbox;
Character Gerad;
BMPClass background; 
CBaseSprite *mario1sprite=NULL, *InventorySprite=NULL, *NPC1Sprite = NULL, *NPC2Sprite = NULL, *TextboxSprite = NULL;
Objects objects[9] = {Objects(0, 190, 40, 300), Objects(0, 0, 50, 100), Objects(0, 260, 200, 215), Objects(240, 390, 215, 215), Objects(285, 350, 45, 50),
Objects(80, 150, 60, 300), Objects(375, 300, 200, 200), Objects(250, 0, 75, 110), Objects(435, 0, 75,50)};
Location places("StartingPoint.bmp", NULL, NULL, NULL, NULL, 9, objects, 0, NULL, 0, NULL);
Location *currentLocation = &places;
Location *exitLocation = NULL;


void CreateObjects()
{
  int x=50, y=250, xspeed=-4, yspeed=0;
	Gerad.person.create(x, y, xspeed, yspeed, mario1sprite, Timer);
	inventory.box.create(50, 50, 0, 0, InventorySprite, Timer);
	NPCs = new CObject[2];
	NPCs[0].create(x, y, xspeed, yspeed, NPC1Sprite, Timer);
	NPCs[1].create(x + 250, y, xspeed, yspeed, NPC2Sprite, Timer);
	Textbox.create(50, 50, 0, 0, TextboxSprite, Timer);