// 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;
}
Exemplo n.º 2
0
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));
 }