Exemplo n.º 1
0
/**
 * Add charge(s) of rain to given container, possibly contaminating it.
 */
void item::add_rain_to_container(bool acid, int charges)
{
    if( charges <= 0) {
        return;
    }
    item ret( acid ? "water_acid" : "water", calendar::turn );
    const long capa = get_remaining_capacity_for_liquid( ret );
    if (contents.empty()) {
        // This is easy. Just add 1 charge of the rain liquid to the container.
        if (!acid) {
            // Funnels aren't always clean enough for water. // todo; disinfectant squeegie->funnel
            ret.poison = one_in(10) ? 1 : 0;
        }
        ret.charges = std::min<long>( charges, capa );
        put_in(ret);
    } else {
        // The container already has a liquid.
        item &liq = contents[0];
        long orig = liq.charges;
        long added = std::min<long>( charges, capa );
        if (capa > 0 ) {
            liq.charges += added;
        }

        if (liq.typeId() == ret.typeId() || liq.typeId() == "water_acid_weak") {
            // The container already contains this liquid or weakly acidic water.
            // Don't do anything special -- we already added liquid.
        } else {
            // The rain is different from what's in the container.
            // Turn the container's liquid into weak acid with a probability
            // based on its current volume.

            // If it's raining acid and this container started with 7
            // charges of water, the liquid will now be 1/8th acid or,
            // equivalently, 1/4th weak acid (the rest being water). A
            // stochastic approach gives the liquid a 1 in 4 (or 2 in
            // liquid.charges) chance of becoming weak acid.
            const bool transmute = x_in_y(2 * added, liq.charges);

            if (transmute) {
                item transmuted("water_acid_weak", 0);
                transmuted.charges = liq.charges;
                contents[0] = transmuted;
            } else if (liq.typeId() == "water") {
                // The container has water, and the acid rain didn't turn it
                // into weak acid. Poison the water instead, assuming 1
                // charge of acid would act like a charge of water with poison 5.
                long total_poison = liq.poison * (orig) + (5 * added);
                liq.poison = total_poison / liq.charges;
                long leftover_poison = total_poison - liq.poison * liq.charges;
                if (leftover_poison > rng(0, liq.charges)) {
                    liq.poison++;
                }
            }
        }
    }
}
Exemplo n.º 2
0
item *game::inv_map_for_liquid(const item &liquid, const std::string title)
{
    std::vector <item> &here = m.i_at(g->u.posx, g->u.posy);
    typedef std::vector< std::list<item> > pseudo_inventory;
    pseudo_inventory grounditems;
    indexed_invslice grounditems_slice;
    std::vector<item *> ground_containers;

    LIQUID_FILL_ERROR error;

    std::set<std::string> dups;
    for( auto item_iter = here.begin(); item_iter != here.end(); ++item_iter ) {
        if( item_iter->get_remaining_capacity_for_liquid(liquid, error) > 0 ) {
            if( dups.count( item_iter->tname()) == 0 ) {
                grounditems.push_back( std::list<item>(1, *item_iter) );

                if( grounditems.size() <= 10 ) {
                    grounditems.back().front().invlet = '0' + grounditems.size() - 1;
                } else {
                    grounditems.back().front().invlet = ' ';
                }
                dups.insert( item_iter->tname() );

                ground_containers.push_back( &*item_iter );
            }
        }
    }

    for (size_t a = 0; a < grounditems.size(); a++) {
        // avoid INT_MIN, as it can be confused with "no item at all"
        grounditems_slice.push_back(indexed_invslice::value_type(&grounditems[a], INT_MIN + a + 1));
    }
    static const item_category category_on_ground(
        "GROUND:",
        _("GROUND:"),
        -1000
    );

    u.inv.restack(&u);
    u.inv.sort();
    const indexed_invslice stacks = u.inv.slice_filter_by_capacity_for_liquid(liquid);

    inventory_selector inv_s(false, true, title);
    inv_s.make_item_list(grounditems_slice, &category_on_ground);
    inv_s.make_item_list(stacks);
    inv_s.prepare_paging();

    inventory_selector::drop_map prev_droppings;
    while (true) {
        inv_s.display();
        const std::string action = inv_s.ctxt.handle_input();
        const long ch = inv_s.ctxt.get_raw_input().get_first_input();
        const int item_pos = g->u.invlet_to_position(static_cast<char>(ch));

        if (item_pos != INT_MIN) {
            inv_s.set_to_drop(item_pos, 0);
            return inv_s.first_item;
        } else if (ch >= '0' && ch <= '9' && (size_t)(ch - '0') < grounditems_slice.size()) {
            const int ip = ch - '0';
            return ground_containers[ip];
        } else if (inv_s.handle_movement(action)) {
            // continue with comparison below
        } else if (action == "QUIT") {
            return NULL;
        } else if (action == "RIGHT" || action == "CONFIRM") {

            inv_s.set_selected_to_drop(0);

            for( size_t i = 0; i < grounditems_slice.size(); i++) {
                if( &grounditems_slice[i].first->front() == inv_s.first_item ) {
                    return ground_containers[i];
                }
            }

            return inv_s.first_item;
        }
    }
}