/** remove a building from the region.
 * remove_building lets units leave the building
 */
void remove_building(building ** blist, building * b)
{
    unit *u;
    const struct building_type *bt_caravan, *bt_dam, *bt_tunnel;

    assert(bfindhash(b->no));

    bt_caravan = bt_find("caravan");
    bt_dam = bt_find("dam");
    bt_tunnel = bt_find("tunnel");

    handle_event(b->attribs, "destroy", b);
    for (u = b->region->units; u; u = u->next) {
        if (u->building == b) leave(u, true);
    }

    b->size = 0;
    update_lighthouse(b);
    bunhash(b);

    /* Falls Karawanserei, Damm oder Tunnel einstürzen, wird die schon
     * gebaute Straße zur Hälfte vernichtet */
    if (b->type == bt_caravan || b->type == bt_dam || b->type == bt_tunnel) {
        region *r = b->region;
        int d;
        for (d = 0; d != MAXDIRECTIONS; ++d) {
            direction_t dir = (direction_t)d;
            if (rroad(r, dir) > 0) {
                rsetroad(r, dir, rroad(r, dir) / 2);
            }
        }
    }

    /* Stattdessen nur aus Liste entfernen, aber im Speicher halten. */
    while (*blist && *blist != b) {
        blist = &(*blist)->next;
    }
    *blist = b->next;
    b->region = NULL;
    b->next = deleted_buildings;
    deleted_buildings = b;
}
Exemple #2
0
static void destroy_road(unit * u, int nmax, struct order *ord)
{
    char token[128];
    const char *s = gettoken(token, sizeof(token));
    direction_t d = s ? get_direction(s, u->faction->locale) : NODIRECTION;
    if (d == NODIRECTION) {
        /* Die Richtung wurde nicht erkannt */
        cmistake(u, ord, 71, MSG_PRODUCE);
    }
    else {
        unit *u2;
        region *r = u->region;
        short road, n = (short)nmax;

        if (nmax > SHRT_MAX) {
            n = SHRT_MAX;
        }
        else if (nmax < 0) {
            n = 0;
        }

        for (u2 = r->units; u2; u2 = u2->next) {
            if (u2->faction != u->faction && is_guard(u2, GUARD_TAX)
                && cansee(u2->faction, u->region, u, 0)
                && !alliedunit(u, u2->faction, HELP_GUARD)) {
                cmistake(u, ord, 70, MSG_EVENT);
                return;
            }
        }

        road = rroad(r, d);
        n = _min(n, road);
        if (n != 0) {
            region *r2 = rconnect(r, d);
            int willdo = eff_skill(u, SK_ROAD_BUILDING, r) * u->number;
            willdo = _min(willdo, n);
            if (willdo == 0) {
                /* TODO: error message */
            }
            if (willdo > SHRT_MAX)
                road = 0;
            else
                road = road - (short)willdo;
            rsetroad(r, d, road);
            ADDMSG(&u->faction->msgs, msg_message("destroy_road",
                "unit from to", u, r, r2));
        }
    }
}
Exemple #3
0
void build_road(region * r, unit * u, int size, direction_t d)
{
    int n, left;
    region *rn = rconnect(r, d);

    assert(u->number);
    if (!eff_skill(u, SK_ROAD_BUILDING, r)) {
        cmistake(u, u->thisorder, 103, MSG_PRODUCE);
        return;
    }
    if (besieged(u)) {
        cmistake(u, u->thisorder, 60, MSG_PRODUCE);
        return;
    }

    if (rn == NULL || rn->terrain->max_road < 0) {
        cmistake(u, u->thisorder, 94, MSG_PRODUCE);
        return;
    }

    if (r->terrain->max_road < 0) {
        cmistake(u, u->thisorder, 94, MSG_PRODUCE);
        return;
    }

    if (r->terrain == newterrain(T_SWAMP)) {
        /* wenn kein Damm existiert */
        const struct building_type *bt_dam = bt_find("dam");
        if (!bt_dam || !buildingtype_exists(r, bt_dam, true)) {
            cmistake(u, u->thisorder, 132, MSG_PRODUCE);
            return;
        }
    }
    else if (r->terrain == newterrain(T_DESERT)) {
        const struct building_type *bt_caravan = bt_find("caravan");
        /* wenn keine Karawanserei existiert */
        if (!bt_caravan || !buildingtype_exists(r, bt_caravan, true)) {
            cmistake(u, u->thisorder, 133, MSG_PRODUCE);
            return;
        }
    }
    else if (r->terrain == newterrain(T_GLACIER)) {
        const struct building_type *bt_tunnel = bt_find("tunnel");
        /* wenn kein Tunnel existiert */
        if (!bt_tunnel || !buildingtype_exists(r, bt_tunnel, true)) {
            cmistake(u, u->thisorder, 131, MSG_PRODUCE);
            return;
        }
    }

    /* left kann man noch bauen */
    left = r->terrain->max_road - rroad(r, d);

    /* hoffentlich ist r->road <= r->terrain->max_road, n also >= 0 */
    if (left <= 0) {
        ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder,
            "error_roads_finished", ""));
        return;
    }

    if (size > 0)
        left = _min(size, left);
    /* baumaximum anhand der rohstoffe */
    if (u_race(u) == get_race(RC_STONEGOLEM)) {
        n = u->number * GOLEM_STONE;
    }
    else {
        n = get_pooled(u, get_resourcetype(R_STONE), GET_DEFAULT, left);
        if (n == 0) {
            cmistake(u, u->thisorder, 151, MSG_PRODUCE);
            return;
        }
    }
    left = _min(n, left);

    /* n = maximum by skill. try to maximize it */
    n = u->number * eff_skill(u, SK_ROAD_BUILDING, r);
    if (n < left) {
        const resource_type *ring = get_resourcetype(R_RING_OF_NIMBLEFINGER);
        item *itm = ring ? *i_find(&u->items, ring->itype) : 0;
        if (itm != NULL && itm->number > 0) {
            int rings = _min(u->number, itm->number);
            n = n * ((roqf_factor() - 1) * rings + u->number) / u->number;
        }
    }
    if (n < left) {
        int dm = get_effect(u, oldpotiontype[P_DOMORE]);
        if (dm != 0) {
            int sk = eff_skill(u, SK_ROAD_BUILDING, r);
            int todo = (left - n + sk - 1) / sk;
            todo = _min(todo, u->number);
            dm = _min(dm, todo);
            change_effect(u, oldpotiontype[P_DOMORE], -dm);
            n += dm * sk;
        }                           /* Auswirkung Schaffenstrunk */
    }

    /* make minimum of possible and available: */
    n = _min(left, n);

    /* n is now modified by several special effects, so we have to
     * minimize it again to make sure the road will not grow beyond
     * maximum. */
    rsetroad(r, d, rroad(r, d) + (short)n);

    if (u_race(u) == get_race(RC_STONEGOLEM)) {
        int golemsused = n / GOLEM_STONE;
        if (n % GOLEM_STONE != 0) {
            ++golemsused;
        }
        scale_number(u, u->number - golemsused);
    }
    else {
        use_pooled(u, get_resourcetype(R_STONE), GET_DEFAULT, n);
        /* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */
        produceexp(u, SK_ROAD_BUILDING, _min(n, u->number));
    }
    ADDMSG(&u->faction->msgs, msg_message("buildroad",
        "region unit size", r, u, n));
}