/** * 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++; } } } } }
// 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; } const char *typeId = acid ? "water_acid" : "water"; int max = dynamic_cast<it_container*>(type)->contains; int orig = 0; int added = charges; if (contents.empty()) { // This is easy. Just add 1 charge of the rain liquid to the container. item ret(item_controller->find_template(typeId), 0); if (!acid) { // Funnels aren't always clean enough for water. // todo; disinfectant squeegie->funnel ret.poison = one_in(10) ? 1 : 0; } ret.charges = ( charges > max ? max : charges ); put_in(ret); } else { // The container already has a liquid. item &liq = contents[0]; orig = liq.charges; max -= liq.charges; added = ( charges > max ? max : charges ); if (max > 0 ) { liq.charges += added; } if (liq.typeId() == 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(item_controller->find_template("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. int total_poison = liq.poison * (orig) + (5*added); liq.poison = total_poison / liq.charges; int leftover_poison = total_poison - liq.poison * liq.charges; if (leftover_poison > rng(0, liq.charges)) { liq.poison++; } } } } }
void fill_funnels(game *g, int rain_depth_mm_per_hour, bool acid, trap_id t) { int funnel_radius_mm = 0; switch (t) { case tr_funnel: funnel_radius_mm = 380; break; case tr_makeshift_funnel: funnel_radius_mm = 85; break; default: return; } // How many turns should it take for us to collect 1 charge of rainwater? item water(item_controller->find_template("water"), 0); const double charge_ml = (double) (water.weight()) / water.charges; const double PI = 3.14159265358979f; const double surface_area_mm2 = PI * (funnel_radius_mm * funnel_radius_mm); const double vol_mm3_per_hour = surface_area_mm2 * rain_depth_mm_per_hour; const double vol_mm3_per_turn = vol_mm3_per_hour / 600; const double ml_to_mm3 = 1000; const double turns_per_charge = charge_ml * ml_to_mm3 / vol_mm3_per_turn; item *c = NULL; char maxcontains = 0; // Give each funnel on the map a chance to collect the rain. std::set<point> funnel_locs = g->m.trap_locations(t); std::set<point>::iterator i; for (i = funnel_locs.begin(); i != funnel_locs.end(); ++i) { point loc = *i; std::vector<item>& items = g->m.i_at(loc.x, loc.y); if (one_in(turns_per_charge)) { // This funnel has collected some rain! Put the rain in the largest // container here which is either empty or contains some mixture of // impure water and acid. for (int j = 0; j < items.size(); j++) { item *it = &(items[j]); if (it->is_container() && it->has_flag("WATERTIGHT") && it->has_flag("SEALS")) { it_container* ct = dynamic_cast<it_container*>(it->type); if (ct->contains > maxcontains && ( it->contents.empty() || it->contents[0].typeId() == "water" || it->contents[0].typeId() == "water_acid" || it->contents[0].typeId() == "water_acid_weak")) { c = it; maxcontains = ct->contains; } } } } } // If we found an eligible container, add some rain to it (or consider // contaminating its current liquid). if (c != NULL) { const char *typeId = acid ? "water_acid" : "water"; if (c->contents.empty()) { // This is easy. Just add 1 charge of the rain liquid to the container. item ret(item_controller->find_template(typeId), 0); if (!acid) { // Funnels aren't always clean enough for water. ret.poison = one_in(10) ? 1 : 0; } c->put_in(ret); } else { // The container already has a liquid. item &liq = c->contents[0]; it_container* ct = dynamic_cast<it_container*>(c->type); if (liq.charges < ct->contains) { liq.charges++; } if (liq.typeId() == 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, liq.charges); if (transmute) { item transmuted(item_controller->find_template("water_acid_weak"), 0); transmuted.charges = liq.charges; c->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. int total_poison = liq.poison * (liq.charges - 1) + 5; liq.poison = total_poison / liq.charges; int leftover_poison = total_poison - liq.poison * liq.charges; if (leftover_poison > rng(0, liq.charges)) { liq.poison++; } } } } } }