示例#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++;
                }
            }
        }
    }
}
示例#2
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;
    }
    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++;
                }
            }
        }
    }
}
示例#3
0
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++;
                    }
                }
            }
        }
    }
}