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