/** 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