Exemplo n.º 1
0
/** Sort karts and update the m_gp_rank KartStatus member, in preparation
 *  for future calls to RaceManager::getKartGPRank or
 *  RaceManager::getKartWithGPRank
 */
void RaceManager::computeGPRanks()
{
    // calculate the rank of each kart
    const unsigned int NUM_KARTS = getNumberOfKarts();
    PtrVector<computeGPRanksData::SortData> sort_data;

    // Ignore the first kart if it's a follow-the-leader race.
    int start=(race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER);
    if (start)
    {
        // fill values for leader
        computeGPRanksData::SortData *sd = new computeGPRanksData::SortData();

        sd->m_position  = -1;
        sd->m_score     = -1;
        sd->m_race_time = -1;
        sort_data.push_back(sd);
        m_kart_status[0].m_gp_rank = -1;
        if(UserConfigParams::m_ftl_debug)
        {
            Log::debug("Race Manager","[ftl] kart '%s' has position %d.",
                       World::getWorld()->getKart(0)->getIdent().c_str(),
                       sd->m_position);
        }
    }
    for (unsigned int kart_id = start; kart_id < NUM_KARTS; ++kart_id)
    {
        computeGPRanksData::SortData *sd = new computeGPRanksData::SortData();
        sd->m_position  = kart_id;
        sd->m_score     = getKartScore(kart_id);
        sd->m_race_time = getOverallTime(kart_id);
        sort_data.push_back(sd);
        if(UserConfigParams::m_ftl_debug)
        {
            Log::debug("Race Manager",
                       "[ftl] kart '%s' has position %d score %d.",
                       World::getWorld()->getKart(kart_id)->getIdent().c_str(),
                       sd->m_position, sd->m_score);
        }
    }

    sort_data.insertionSort(start);
    for (unsigned int i=start; i < NUM_KARTS; ++i)
    {
        if(UserConfigParams::m_ftl_debug)
        {
            const AbstractKart *kart =
                World::getWorld()->getKart(sort_data[i].m_position);
            Log::debug("Race Manager","[ftl] kart '%s' has now position %d.",
                kart->getIdent().c_str(),
                i-start);
        }

        m_kart_status[sort_data[i].m_position].m_gp_rank = i - start;
    }
}   // computeGPRanks
/** Returns a list of randomly selected karts. This list firstly contains
 *  karts in the currently selected group, but which are not in the list
 *  of 'existing karts'. If not enough karts are available in the current
 *  group, karts from all other groups are used to fill up the list.
 *  This is used by the race manager to select the AI karts.
 *  \param count          Number of karts to select randomly.
 *  \param existing_karts List of karts that should not be used. This is the
 *                        list of karts selected by the players.
 *  \param ai_list        List of AI karts already selected (eg through the
 *                        command line). The random AIs will also be added
 *                        to this list.
 */
void KartPropertiesManager::getRandomKartList(int count,
                                            RemoteKartInfoList& existing_karts,
                                            std::vector<std::string> *ai_list)
{
    // First: set up flags (based on global kart
    // index) for which karts are already used
    // -----------------------------------------
    std::vector<bool> used;
    used.resize(getNumberOfKarts(), false);

    std::vector<std::string> random_kart_queue;
    for (unsigned int i=0; i<existing_karts.size(); i++)
    {
        try
        {
            int id = getKartId(existing_karts[i].getKartName());
            used[id] = true;
        }
        catch (std::runtime_error& ex)
        {
            (void)ex;
            Log::error("[KartPropertiesManager]", "getRandomKartList : WARNING, "
                "can't find kart '%s'", existing_karts[i].getKartName().c_str());
        }
    }
    for(unsigned int i=0; i<ai_list->size(); i++)
    {
        try
        {
            int id=getKartId((*ai_list)[i]);
            used[id] = true;
        }
        catch (std::runtime_error &ex)
        {
            (void)ex;
            Log::error("[KartPropertiesManager]", "getRandomKartList : WARNING, "
                "can't find kart '%s'",(*ai_list)[i].c_str());
        }
    }

    do
    {
        // if we have no karts left in our queue, re-fill it
        if (count > 0 && random_kart_queue.size() == 0)
        {
            random_kart_queue.clear();
            std::vector<int> karts_in_group =
                getKartsInGroup(UserConfigParams::m_last_used_kart_group);

            assert(karts_in_group.size() > 0);

            // first try not to use a kart already used by a player
            for (unsigned int i=0; i<karts_in_group.size(); i++)
            {
                const KartProperties &kp=m_karts_properties[karts_in_group[i]];
                if (!used[karts_in_group[i]]                 &&
                    m_kart_available[karts_in_group[i]]      &&
                    !PlayerManager::get()->getCurrentPlayer()->isLocked(kp.getIdent())   )
                {
                    random_kart_queue.push_back(kp.getIdent());
                }
            }

            // if we really need to, reuse the same kart as the player
            if (random_kart_queue.size() == 0)
            {
                for (unsigned int i=0; i<karts_in_group.size(); i++)
                {
                    const KartProperties &kp =
                        m_karts_properties[karts_in_group[i]];
                    random_kart_queue.push_back(kp.getIdent());
                }
            }

            assert(random_kart_queue.size() > 0);

            std::random_shuffle(random_kart_queue.begin(),
                                random_kart_queue.end()   );
        }

        while (count > 0 && random_kart_queue.size() > 0)
        {
            ai_list->push_back(random_kart_queue.back());
            random_kart_queue.pop_back();
            count --;
        }

    } while (count > 0);

    // There should always be enough karts
    assert(count==0);
}   // getRandomKartList