// Prepares items for dropping by reordering them so that the drop // cost is minimal and "dependent" items get taken off first. // Implements the "backpack" logic. std::list<act_item> reorder_for_dropping( const player &p, const drop_indexes &drop ) { auto res = convert_to_items( p, drop, -1, -1 ); auto inv = convert_to_items( p, drop, 0, INT_MAX ); auto worn = convert_to_items( p, drop, INT_MIN, -2 ); // Sort inventory items by volume in ascending order inv.sort( []( const act_item & first, const act_item & second ) { return first.it->volume() < second.it->volume(); } ); // Add missing dependent worn items (if any). for( const auto &wait : worn ) { for( const auto dit : p.get_dependent_worn_items( *wait.it ) ) { const auto iter = std::find_if( worn.begin(), worn.end(), [ dit ]( const act_item & ait ) { return ait.it == dit; } ); if( iter == worn.end() ) { worn.emplace_front( dit, dit->count_by_charges() ? dit->charges : 1, 100 ); // @todo: Use a calculated cost } } } // Sort worn items by storage in descending order, but dependent items always go first. worn.sort( []( const act_item & first, const act_item & second ) { return first.it->is_worn_only_with( *second.it ) || ( ( first.it->get_storage() > second.it->get_storage() ) && !second.it->is_worn_only_with( *first.it ) ); } ); units::volume storage_loss = 0; // Cumulatively increases units::volume remaining_storage = p.volume_capacity(); // Cumulatively decreases while( !worn.empty() && !inv.empty() ) { storage_loss += worn.front().it->get_storage(); remaining_storage -= p.volume_capacity_reduced_by( storage_loss ); if( remaining_storage < inv.front().it->volume() ) { break; // Does not fit } while( !inv.empty() && remaining_storage >= inv.front().it->volume() ) { remaining_storage -= inv.front().it->volume(); res.push_back( inv.front() ); res.back().consumed_moves = 0; // Free of charge inv.pop_front(); } res.push_back( worn.front() ); worn.pop_front(); } // Now insert everything that remains std::copy( inv.begin(), inv.end(), std::back_inserter( res ) ); std::copy( worn.begin(), worn.end(), std::back_inserter( res ) ); return res; }
MovingPath MovingPathScript::MovingPathScriptImpl::createPath(const MovingPath & oldPath, const GridIndex & destination, const MovingArea & area) const { auto newPath = oldPath; //Init the path if it's empty. if (newPath.isEmpty()) { auto startingIndex = area.getStartingIndex(); auto startingInfo = area.getMovingInfo(startingIndex); newPath.init(MovingPath::PathNode(startingIndex, startingInfo.m_MaxRemainingMovementRange)); } //If the destination is in the path already, cut the path and return. if (newPath.hasIndex(destination)) { newPath.tryFindAndCut(destination); return newPath; } //The destination is not in the path. Try extending the path to destination. Return the new path if succeed. if (newPath.tryExtend(destination, area.getMovingInfo(destination).m_MovingCost)) return newPath; //The path can't be extended (because the remaining movement range is not big enough). //Generate a new shortest path. auto pathNodeList = std::list<MovingPath::PathNode>(); auto currentIndex = destination; auto currentInfo = area.getMovingInfo(currentIndex); auto previousIndex = currentInfo.m_PreviousIndex; auto startingIndex = area.getStartingIndex(); while (currentIndex != startingIndex) { pathNodeList.emplace_front(MovingPath::PathNode(currentIndex, currentInfo.m_MaxRemainingMovementRange)); currentIndex = previousIndex; currentInfo = area.getMovingInfo(currentIndex); previousIndex = currentInfo.m_PreviousIndex; } pathNodeList.emplace_front(MovingPath::PathNode(startingIndex, area.getMovingInfo(startingIndex).m_MaxRemainingMovementRange)); newPath.init(std::move(pathNodeList)); return newPath; }
TEST(PriorityQueues, Top10Hits) { auto hits = std::forward_list<Hit>{}; for (char c = 'a'; c <= 'z'; ++c) { hits.emplace_front(generate_random_hit(std::string{c})); } auto top_ten_hits = sort_hits(hits.begin(), hits.end(), 10); for (const auto& hit : top_ten_hits) { std::cout << hit.rank_ << " " << hit.document_->title() << '\n'; } // Check order of hints for (size_t i = 1; i < top_ten_hits.size(); ++i) { ASSERT_TRUE(top_ten_hits[i-1].rank_ > top_ten_hits[i].rank_); } }
/// \b Complexity: O(1) void push_front(const value_type& v) { emplace_front(v); }
/// \b Complexity: O(1) void push_front(value_type&& v) { emplace_front(std::move(v)); }