/** * 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++; } } } } }
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; } } }