void get_neighbours(const region * r, region ** list) { int dir; for (dir = 0; dir != MAXDIRECTIONS; ++dir) { list[dir] = rconnect(r, (direction_t)dir); } }
region *rrandneighbour(region * r) { direction_t i; region *rc = NULL; int rr, c = 0; /* Nachsehen, wieviele Regionen in Frage kommen */ for (i = 0; i != MAXDIRECTIONS; i++) { c++; } /* Zufällig eine auswählen */ rr = rng_int() % c; /* Durchzählen */ c = -1; for (i = 0; i != MAXDIRECTIONS; i++) { rc = rconnect(r, i); c++; if (c == rr) break; } assert(i != MAXDIRECTIONS); return rc; }
static void frame_regions(int age, const terrain_type * terrain) { plane *hplane = get_homeplane(); region *r = regions; for (r = regions; r; r = r->next) { plane *pl = rplane(r); direction_t d; if (r->age < age) continue; if (pl != hplane) continue; /* only do this on the main world */ if (r->terrain == terrain) continue; for (d = 0; d != MAXDIRECTIONS; ++d) { region *rn = rconnect(r, d); if (rn == NULL) { int x = r->x + delta_x[d]; int y = r->y + delta_y[d]; pnormalize(&x, &y, pl); rn = new_region(x, y, pl, 0); terraform_region(rn, terrain); rn->age = r->age; } } } }
static int scareaway(region * r, int anzahl) { int n, p, diff = 0, emigrants[MAXDIRECTIONS]; direction_t d; anzahl = _min(_max(1, anzahl), rpeasants(r)); /* Wandern am Ende der Woche (normal) oder wegen Monster. Die * Wanderung wird erst am Ende von demographics () ausgefuehrt. * emigrants[] ist local, weil r->newpeasants durch die Monster * vielleicht schon hochgezaehlt worden ist. */ for (d = 0; d != MAXDIRECTIONS; d++) emigrants[d] = 0; p = rpeasants(r); assert(p >= 0 && anzahl >= 0); for (n = _min(p, anzahl); n; n--) { direction_t dir = (direction_t) (rng_int() % MAXDIRECTIONS); region *rc = rconnect(r, dir); if (rc && fval(rc->terrain, LAND_REGION)) { ++diff; rc->land->newpeasants++; emigrants[dir]++; } } rsetpeasants(r, p - diff); assert(p >= diff); return diff; }
static order *monster_seeks_target(region * r, unit * u) { direction_t d; unit *target = NULL; int dist, dist2; direction_t i; region *nr; /* Das Monster sucht ein bestimmtes Opfer. Welches, steht * in einer Referenz/attribut * derzeit gibt es nur den alp */ switch (old_race(u_race(u))) { case RC_ALP: target = alp_target(u); break; default: assert(!"Seeker-Monster gibt kein Ziel an"); } /* TODO: prüfen, ob target überhaupt noch existiert... */ if (!target) { log_error("Monster '%s' hat kein Ziel!\n", unitname(u)); return NULL; /* this is a bug workaround! remove!! */ } if (r == target->region) { /* Wir haben ihn! */ if (u_race(u) == get_race(RC_ALP)) { alp_findet_opfer(u, r); } else { assert(!"Seeker-Monster hat keine Aktion fuer Ziel"); } return NULL; } /* Simpler Ansatz: Nachbarregion mit gerinster Distanz suchen. * Sinnvoll momentan nur bei Monstern, die sich nicht um das * Terrain kümmern. Nebelwände & Co machen derzeit auch nix... */ dist2 = distance(r, target->region); d = NODIRECTION; for (i = 0; i < MAXDIRECTIONS; i++) { nr = rconnect(r, i); assert(nr); dist = distance(nr, target->region); if (dist < dist2) { dist2 = dist; d = i; } } assert(d != NODIRECTION); return create_order(K_MOVE, u->faction->locale, "%s", LOC(u->faction->locale, directions[d])); }
static int client_connect(void) { struct addrinfo *res; struct pollfd fds; int ret, err; socklen_t len; ret = getaddrinfo(dst_addr, port, NULL, &res); if (ret) { perror("getaddrinfo"); return ret; } rs = rsocket(res->ai_family, res->ai_socktype, res->ai_protocol); if (rs < 0) { perror("rsocket"); ret = rs; goto free; } set_options(rs); /* TODO: bind client to src_addr */ ret = rconnect(rs, res->ai_addr, res->ai_addrlen); if (ret && (errno != EINPROGRESS)) { perror("rconnect"); goto close; } if (ret && (errno == EINPROGRESS)) { fds.fd = rs; fds.events = POLLOUT; ret = do_poll(&fds, poll_timeout); if (ret) goto close; len = sizeof err; ret = rgetsockopt(rs, SOL_SOCKET, SO_ERROR, &err, &len); if (ret) goto close; if (err) { ret = -1; errno = err; perror("async rconnect"); } } close: if (ret) rclose(rs); free: freeaddrinfo(res); return ret; }
bool is_coastregion(region * r) { direction_t i; int res = 0; for (i = 0; !res && i < MAXDIRECTIONS; i++) { region *rn = rconnect(r, i); if (rn && fval(rn->terrain, SEA_REGION)) res++; } return res != 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)); } } }
RsocketsTransmitter::RsocketsTransmitter(const size_t i, const std::string &address, const size_t port, TransmitterPool &pool) : Transmitter(i, address, port, pool) { cout << "Connecting Rsockets Transmitter to " << serverIP << ", port " << serverPort << endl; int rc; servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = inet_addr(serverIP.c_str()); servAddr.sin_port = htons(serverPort); cout << "Thread " << index << ": Connecting to " << endPoint.str() << "..." << endl; sock = rsocket(AF_INET, SOCK_STREAM, 0); assert(sock); rc = rconnect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)); assert(rc == 0); }
short rroad(const region * r, direction_t d) { connection *b; region *r2 = rconnect(r, d); if (!r2) { return 0; } b = get_borders(r, r2); while (b && b->type != &bt_road) { b = b->next; } if (!b) { return 0; } return (r == b->from) ? b->data.sa[0] : b->data.sa[1]; }
/* * We can't fork RDMA connections and pass them from the parent to the child * process. Instead, we need to establish the RDMA connection after calling * fork. To do this, we delay establishing the RDMA connection until we try * to send/receive on the server side. */ static void fork_active(int socket) { struct sockaddr_storage addr; int sfd, dfd, ret; socklen_t len; uint32_t msg; long flags; sfd = fd_getd(socket); flags = real.fcntl(sfd, F_GETFL); real.fcntl(sfd, F_SETFL, 0); ret = real.recv(sfd, &msg, sizeof msg, MSG_PEEK); real.fcntl(sfd, F_SETFL, flags); if ((ret != sizeof msg) || msg) goto err1; len = sizeof addr; ret = real.getpeername(sfd, (struct sockaddr *) &addr, &len); if (ret) goto err1; dfd = rsocket(addr.ss_family, SOCK_STREAM, 0); if (dfd < 0) goto err1; ret = rconnect(dfd, (struct sockaddr *) &addr, len); if (ret) goto err2; set_rsocket_options(dfd); copysockopts(dfd, sfd, &rs, &real); real.shutdown(sfd, SHUT_RDWR); real.close(sfd); fd_store(socket, dfd, fd_rsocket, fd_ready); return; err2: rclose(dfd); err1: fd_store(socket, sfd, fd_normal, fd_ready); }
static void get_island_info(region * root, int *size_p, int *inhabited_p, int *maxage_p) { int qi, size = 0, maxage = 0, inhabited = 0; quicklist *ql, *island = NULL; ql_push(&island, root); fset(root, RF_MARK); for (ql = island, qi = 0; ql; ql_advance(&ql, &qi, 1)) { int d; region *r = (region *)ql_get(ql, qi); if (r->units) { unit *u; for (u = r->units; u; u = u->next) { if (!fval(u->faction, FFL_NOIDLEOUT) && u->faction->age > maxage) { maxage = u->faction->age; } } ++inhabited; } ++size; for (d = 0; d != MAXDIRECTIONS; ++d) { region *rn = rconnect(r, d); if (rn && !fval(rn, RF_MARK) && rn->land) { ql_push(&island, rn); fset(rn, RF_MARK); } } } for (ql = island, qi = 0; ql; ql_advance(&ql, &qi, 1)) { region *r = (region *)ql_get(ql, qi); freset(r, RF_MARK); } ql_free(island); if (size_p) *size_p = size; if (inhabited_p) *inhabited_p = inhabited; if (maxage_p) *maxage_p = maxage; }
int connect(int socket, const struct sockaddr *addr, socklen_t addrlen) { int fd, ret; if (fd_get(socket, &fd) == fd_rsocket) { ret = rconnect(fd, addr, addrlen); if (!ret || errno == EINPROGRESS) return ret; ret = transpose_socket(socket, fd_normal); if (ret < 0) return ret; rclose(fd); fd = ret; } else if (fd_gets(socket) == fd_fork) { fd_store(socket, fd, fd_normal, fd_fork_active); } return real.connect(fd, addr, addrlen); }
struct quicklist *regions_in_range(struct region *start, int maxdist, bool(*allowed) (const struct region *, const struct region *)) { quicklist * rlist = NULL; node *root = new_node(start, 0, NULL); node **end = &root->next; node *n = root; while (n != NULL) { region *r = n->r; int depth = n->distance + 1; int d; if (n->distance >= maxdist) break; for (d = 0; d != MAXDIRECTIONS; ++d) { region *rn = rconnect(r, d); if (rn == NULL) continue; if (fval(rn, RF_MARK)) continue; /* already been there */ if (allowed && !allowed(r, rn)) continue; /* can't go there */ /* add the region to the list of available ones. */ ql_push(&rlist, rn); /* make sure we don't go here again, and put the region into the set for further BFS'ing */ fset(rn, RF_MARK); *end = new_node(rn, depth, n); end = &(*end)->next; } n = n->next; } free_nodes(root); return rlist; }
void create_icebergs(void) { region *r; for (r = regions; r; r = r->next) { if (r->terrain == newterrain(T_ICEBERG_SLEEP) && chance(0.05)) { bool has_ocean_neighbour = false; direction_t dir; region *rc; unit *u; freset(r, RF_SELECT); for (dir = 0; dir < MAXDIRECTIONS; dir++) { rc = rconnect(r, dir); if (rc && fval(rc->terrain, SEA_REGION)) { has_ocean_neighbour = true; break; } } if (!has_ocean_neighbour) continue; rsetterrain(r, T_ICEBERG); fset(r, RF_SELECT); move_iceberg(r); for (u = r->units; u; u = u->next) { freset(u->faction, FFL_SELECT); } for (u = r->units; u; u = u->next) { if (!fval(u->faction, FFL_SELECT)) { fset(u->faction, FFL_SELECT); ADDMSG(&u->faction->msgs, msg_message("iceberg_create", "region", r)); } } } } }
static int recurse_regions(region * r, region_list ** rlist, bool(*fun) (const region * r)) { if (!fun(r)) return 0; else { int len = 0; direction_t d; region_list *rl = calloc(sizeof(region_list), 1); rl->next = *rlist; rl->data = r; (*rlist) = rl; fset(r, RF_MARK); for (d = 0; d != MAXDIRECTIONS; ++d) { region *nr = rconnect(r, d); if (nr && !fval(nr, RF_MARK)) len += recurse_regions(nr, rlist, fun); } return len + 1; } }
void rsetroad(region * r, direction_t d, short val) { connection *b; region *r2 = rconnect(r, d); if (!r2) { return; } b = get_borders(r, r2); while (b && b->type != &bt_road) { b = b->next; } if (!b) { if (!val) return; b = new_border(&bt_road, r, r2); } if (r == b->from) { b->data.sa[0] = val; } else { b->data.sa[1] = val; } }
static bool virgin_region(const region * r) { direction_t d; if (r == NULL) return true; if (fval(r->terrain, FORBIDDEN_REGION)) return false; if (r->units) return false; for (d = 0; d != MAXDIRECTIONS; ++d) { const region *rn = rconnect(r, d); if (rn) { if (rn->age > r->age + 1) return false; if (rn->units) return false; if (fval(rn->terrain, FORBIDDEN_REGION)) { /* because it kinda sucks to have islands that are adjacent to a firewall */ return false; } } } return true; }
static direction_t richest_neighbour(region * r, faction * f, int absolut) { /* m - maximum an Geld, d - Richtung, i - index, t = Geld hier */ double m; double t; direction_t d = NODIRECTION, i; if (absolut == 1 || rpeasants(r) == 0) { m = (double)all_money(r, f); } else { m = (double)all_money(r, f) / (double)rpeasants(r); } /* finde die region mit dem meisten geld */ for (i = 0; i != MAXDIRECTIONS; i++) { region *rn = rconnect(r, i); if (rn != NULL && fval(rn->terrain, LAND_REGION)) { if (absolut == 1 || rpeasants(rn) == 0) { t = (double)all_money(rn, f); } else { t = (double)all_money(rn, f) / (double)rpeasants(rn); } if (t > m) { m = t; d = i; } } } return d; }
int random_neighbours(region * r, region_list ** rlist, const terrain_type * (*terraformer) (direction_t)) { int nsize = 0; direction_t dir; for (dir = 0; dir != MAXDIRECTIONS; ++dir) { region *rn = rconnect(r, dir); if (rn == NULL) { const terrain_type *terrain = terraformer(dir); plane *pl = rplane(r); int x = r->x + delta_x[dir]; int y = r->y + delta_y[dir]; pnormalize(&x, &y, pl); rn = new_region(x, y, pl, 0); terraform_region(rn, terrain); regionqueue_push(rlist, rn); if (rn->land) { ++nsize; } } } return nsize; }
static void move_iceberg(region * r) { attrib *a; direction_t dir; region *rc; a = a_find(r->attribs, &at_iceberg); if (!a) { dir = (direction_t) (rng_int() % MAXDIRECTIONS); a = a_add(&r->attribs, make_iceberg(dir)); } else { if (rng_int() % 100 < 20) { dir = (direction_t) (rng_int() % MAXDIRECTIONS); a->data.i = dir; } else { dir = (direction_t) a->data.i; } } rc = rconnect(r, dir); if (rc && !fval(rc->terrain, ARCTIC_REGION)) { if (fval(rc->terrain, SEA_REGION)) { /* Eisberg treibt */ ship *sh, *shn; unit *u; int x, y; for (u = r->units; u; u = u->next) freset(u->faction, FFL_SELECT); for (u = r->units; u; u = u->next) if (!fval(u->faction, FFL_SELECT)) { fset(u->faction, FFL_SELECT); ADDMSG(&u->faction->msgs, msg_message("iceberg_drift", "region dir", r, dir)); } x = r->x; y = r->y; runhash(r); runhash(rc); r->x = rc->x; r->y = rc->y; rc->x = x; rc->y = y; rhash(rc); rhash(r); /* rc ist der Ozean (Ex-Eisberg), r der Eisberg (Ex-Ozean) */ /* Schiffe aus dem Zielozean werden in den Eisberg transferiert * und nehmen Schaden. */ for (sh = r->ships; sh; sh = sh->next) freset(sh, SF_SELECT); for (sh = r->ships; sh; sh = sh->next) { /* Meldung an Kapitän */ float dmg = get_param_flt(global.parameters, "rules.ship.damage.intoiceberg", 0.10F); damage_ship(sh, dmg); fset(sh, SF_SELECT); } /* Personen, Schiffe und Gebäude verschieben */ while (rc->buildings) { rc->buildings->region = r; translist(&rc->buildings, &r->buildings, rc->buildings); } while (rc->ships) { float dmg = get_param_flt(global.parameters, "rules.ship.damage.withiceberg", 0.10F); fset(rc->ships, SF_SELECT); damage_ship(rc->ships, dmg); move_ship(rc->ships, rc, r, NULL); } while (rc->units) { building *b = rc->units->building; u = rc->units; u->building = 0; /* prevent leaving in move_unit */ move_unit(rc->units, r, NULL); u_set_building(u, b); /* undo leave-prevention */ } /* Beschädigte Schiffe können sinken */ for (sh = r->ships; sh;) { shn = sh->next; if (fval(sh, SF_SELECT)) { u = ship_owner(sh); if (sh->damage >= sh->size * DAMAGE_SCALE) { if (u != NULL) { ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg_des", "ship", sh)); } remove_ship(&sh->region->ships, sh); } else if (u != NULL) { ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg", "ship", sh)); } } sh = shn; } } else if (rng_int() % 100 < 20) { /* Eisberg bleibt als Gletscher liegen */ unit *u; rsetterrain(r, T_GLACIER); a_remove(&r->attribs, a); for (u = r->units; u; u = u->next) freset(u->faction, FFL_SELECT); for (u = r->units; u; u = u->next) if (!fval(u->faction, FFL_SELECT)) { fset(u->faction, FFL_SELECT); ADDMSG(&u->faction->msgs, msg_message("iceberg_land", "region", r)); } } } }
void do_markets(void) { quicklist *traders = 0; unit *markets[MAX_MARKETS]; region *r; for (r = regions; r; r = r->next) { if (r->land) { faction *f = region_get_owner(r); const struct race *rc = f ? f->race : NULL; int p = rpeasants(r); int numlux = rc_luxury_trade(rc), numherbs = rc_herb_trade(rc); numlux = (p + numlux - MIN_PEASANTS) / numlux; numherbs = (p + numherbs - MIN_PEASANTS) / numherbs; if (numlux > 0 || numherbs > 0) { int d, nmarkets = 0; const item_type *lux = r_luxury(r); const item_type *herb = r->land->herbtype; nmarkets += get_markets(r, markets + nmarkets, MAX_MARKETS - nmarkets); for (d = 0; d != MAXDIRECTIONS; ++d) { region *r2 = rconnect(r, d); if (r2 && r2->buildings) { nmarkets += get_markets(r2, markets + nmarkets, MAX_MARKETS - nmarkets); } } if (nmarkets) { while (lux && numlux--) { int n = rng_int() % nmarkets; unit *u = markets[n]; item *items; attrib *a = a_find(u->attribs, &at_market); if (a == NULL) { a = a_add(&u->attribs, a_new(&at_market)); ql_push(&traders, u); } items = (item *)a->data.v; i_change(&items, lux, 1); a->data.v = items; /* give 1 luxury */ } while (herb && numherbs--) { int n = rng_int() % nmarkets; unit *u = markets[n]; item *items; attrib *a = a_find(u->attribs, &at_market); if (a == NULL) { a = a_add(&u->attribs, a_new(&at_market)); ql_push(&traders, u); } items = (item *)a->data.v; i_change(&items, herb, 1); a->data.v = items; /* give 1 herb */ } } } } } if (traders) { quicklist *qliter = traders; int qli = 0; for (qli = 0; qliter; ql_advance(&qliter, &qli, 1)) { unit *u = (unit *)ql_get(qliter, qli); attrib *a = a_find(u->attribs, &at_market); item *items = (item *)a->data.v; a->data.v = NULL; while (items) { item *itm = items; items = itm->next; if (itm->number) { ADDMSG(&u->faction->msgs, msg_message("buyamount", "unit amount resource", u, itm->number, itm->type->rtype)); itm->next = NULL; i_add(&u->items, itm); } else { i_free(itm); } } a_remove(&u->attribs, a); } ql_free(traders); } }
void randomevents(void) { region *r; faction *monsters = get_monsters(); icebergs(); godcurse(); orc_growth(); demon_skillchanges(); /* Orkifizierte Regionen mutieren und mutieren zurück */ for (r = regions; r; r = r->next) { if (fval(r, RF_ORCIFIED)) { direction_t dir; double probability = 0.0; for (dir = 0; dir < MAXDIRECTIONS; dir++) { region *rc = rconnect(r, dir); if (rc && rpeasants(rc) > 0 && !fval(rc, RF_ORCIFIED)) probability += 0.02; } if (chance(probability)) { ADDMSG(&r->msgs, msg_message("deorcified", "region", r)); freset(r, RF_ORCIFIED); } } else { attrib *a = a_find(r->attribs, &at_orcification); if (a != NULL) { double probability = 0.0; if (rpeasants(r) <= 0) continue; probability = a->data.i / (double)rpeasants(r); if (chance(probability)) { fset(r, RF_ORCIFIED); a_remove(&r->attribs, a); ADDMSG(&r->msgs, msg_message("orcified", "region", r)); } else { a->data.i -= _max(10, a->data.i / 10); if (a->data.i <= 0) a_remove(&r->attribs, a); } } } } /* Vulkane qualmen, brechen aus ... */ for (r = regions; r; r = r->next) { if (r->terrain == newterrain(T_VOLCANO_SMOKING)) { if (a_find(r->attribs, &at_reduceproduction)) { ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r)); rsetterrain(r, T_VOLCANO); } else { if (rng_int() % 100 < 12) { ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r)); rsetterrain(r, T_VOLCANO); } else if (r->age > 20 && rng_int() % 100 < 8) { volcano_outbreak(r); } } } else if (r->terrain == newterrain(T_VOLCANO)) { if (rng_int() % 100 < 4) { ADDMSG(&r->msgs, msg_message("volcanostartsmoke", "region", r)); rsetterrain(r, T_VOLCANO_SMOKING); } } } /* Monumente zerfallen, Schiffe verfaulen */ for (r = regions; r; r = r->next) { building **blist = &r->buildings; while (*blist) { building *b = *blist; if (fval(b->type, BTF_DECAY) && !building_owner(b)) { b->size -= _max(1, (b->size * 20) / 100); if (b->size == 0) { remove_building(blist, r->buildings); } } if (*blist == b) blist = &b->next; } } /* monster-einheiten desertieren */ if (monsters) { for (r = regions; r; r = r->next) { unit *u; for (u = r->units; u; u = u->next) { if (u->faction && !is_monsters(u->faction) && (u_race(u)->flags & RCF_DESERT)) { if (fval(u, UFL_ISNEW)) continue; if (rng_int() % 100 < 5) { ADDMSG(&u->faction->msgs, msg_message("desertion", "unit region", u, r)); u_setfaction(u, monsters); } } } } } /* Chaos */ for (r = regions; r; r = r->next) { int i; if (fval(r, RF_CHAOTIC)) { chaos(r); } i = chaoscount(r); if (i) { chaoscounts(r, -(int)(i * ((double)(rng_int() % 10)) / 100.0)); } } #ifdef HERBS_ROT rotting_herbs(); #endif dissolve_units(); }
void terraform_region(region * r, const terrain_type * terrain) { /* Resourcen, die nicht mehr vorkommen können, löschen */ const terrain_type *oldterrain = r->terrain; rawmaterial **lrm = &r->resources; assert(terrain); while (*lrm) { rawmaterial *rm = *lrm; const resource_type *rtype = NULL; if (terrain->production != NULL) { int i; for (i = 0; terrain->production[i].type; ++i) { if (rm->type->rtype == terrain->production[i].type) { rtype = rm->type->rtype; break; } } } if (rtype == NULL) { *lrm = rm->next; free(rm); } else { lrm = &rm->next; } } r->terrain = terrain; terraform_resources(r); if (!fval(terrain, LAND_REGION)) { region_setinfo(r, NULL); if (r->land != NULL) { i_freeall(&r->land->items); freeland(r->land); r->land = NULL; } rsettrees(r, 0, 0); rsettrees(r, 1, 0); rsettrees(r, 2, 0); rsethorses(r, 0); rsetpeasants(r, 0); rsetmoney(r, 0); freset(r, RF_ENCOUNTER); freset(r, RF_MALLORN); /* Beschreibung und Namen löschen */ return; } if (r->land) { int d; for (d = 0; d != MAXDIRECTIONS; ++d) { rsetroad(r, d, 0); } i_freeall(&r->land->items); } else { static struct surround { struct surround *next; const luxury_type *type; int value; } *trash = NULL, *nb = NULL; const luxury_type *ltype = NULL; direction_t d; int mnr = 0; r->land = calloc(1, sizeof(land_region)); r->land->ownership = NULL; region_set_morale(r, MORALE_DEFAULT, -1); region_setname(r, makename()); for (d = 0; d != MAXDIRECTIONS; ++d) { region *nr = rconnect(r, d); if (nr && nr->land) { struct demand *sale = r->land->demands; while (sale && sale->value != 0) sale = sale->next; if (sale) { struct surround *sr = nb; while (sr && sr->type != sale->type) sr = sr->next; if (!sr) { if (trash) { sr = trash; trash = trash->next; } else { sr = calloc(1, sizeof(struct surround)); } sr->next = nb; sr->type = sale->type; sr->value = 1; nb = sr; } else sr->value++; ++mnr; } } } if (!nb) { // TODO: this is really lame int i = get_maxluxuries(); if (i > 0) { i = rng_int() % i; ltype = luxurytypes; while (i--) ltype = ltype->next; } } else { int i = rng_int() % mnr; struct surround *srd = nb; while (i > srd->value) { i -= srd->value; srd = srd->next; } if (srd->type) setluxuries(r, srd->type); while (srd->next != NULL) srd = srd->next; srd->next = trash; trash = nb; nb = NULL; } } if (fval(terrain, LAND_REGION)) { const item_type *itype = NULL; char equip_hash[64]; /* TODO: put the equipment in struct terrain, faster */ sprintf(equip_hash, "terrain_%s", terrain->_name); equip_items(&r->land->items, get_equipment(equip_hash)); if (r->terrain->herbs) { int len = 0; while (r->terrain->herbs[len]) ++len; if (len) itype = r->terrain->herbs[rng_int() % len]; } if (itype != NULL) { rsetherbtype(r, itype); rsetherbs(r, (short)(50 + rng_int() % 31)); } else { rsetherbtype(r, NULL); } if (oldterrain == NULL || !fval(oldterrain, LAND_REGION)) { if (rng_int() % 100 < 3) fset(r, RF_MALLORN); else freset(r, RF_MALLORN); if (rng_int() % 100 < ENCCHANCE) { fset(r, RF_ENCOUNTER); } } } if (oldterrain == NULL || terrain->size != oldterrain->size) { if (terrain == newterrain(T_PLAIN)) { rsethorses(r, rng_int() % (terrain->size / 50)); if (rng_int() % 100 < 40) { rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000); } } else if (chance(0.2)) { rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000); } else { rsettrees(r, 2, 0); } rsettrees(r, 1, rtrees(r, 2) / 4); rsettrees(r, 0, rtrees(r, 2) / 8); if (!fval(r, RF_CHAOTIC)) { int peasants; peasants = (maxworkingpeasants(r) * (20 + dice_rand("6d10"))) / 100; rsetpeasants(r, _max(100, peasants)); rsetmoney(r, rpeasants(r) * ((wage(r, NULL, NULL, INT_MAX) + 1) + rng_int() % 5)); } } }
int read_borders(gamedata *data) { struct storage *store = data->store; for (;;) { int bid = 0; char zText[32]; region *from, *to; border_type *type; READ_TOK(store, zText, sizeof(zText)); if (!strcmp(zText, "end")) break; READ_INT(store, &bid); if (data->version < UIDHASH_VERSION) { int fx, fy, tx, ty; READ_INT(store, &fx); READ_INT(store, &fy); READ_INT(store, &tx); READ_INT(store, &ty); from = findregion(fx, fy); to = findregion(tx, ty); } else { int fid, tid; READ_INT(store, &fid); READ_INT(store, &tid); from = findregionbyid(fid); to = findregionbyid(tid); if (!to || !from) { log_warning("%s connection between incomplete regions %d and %d", zText, fid, tid); continue; } } type = find_bordertype(zText); if (type == NULL) { log_error("[read_borders] unknown connection type '%s' in %s\n", zText, regionname(from, NULL)); assert(type || !"connection type not registered"); } if (to == from && type && from) { direction_t dir = (direction_t)(rng_int() % MAXDIRECTIONS); region *r = rconnect(from, dir); log_error("[read_borders] invalid %s in %s\n", type->__name, regionname(from, NULL)); if (r != NULL) to = r; } if ((type->read && !type->write)) { log_warning("ignore invalid border '%s' between '%s' and '%s'\n", zText, regionname(from, 0), regionname(to, 0)); } else { connection *b = new_border(type, from, to); nextborder--; /* new_border erhöht den Wert */ b->id = bid; assert(bid <= nextborder); if (type->read) { type->read(b, data); } if (data->version < NOBORDERATTRIBS_VERSION) { attrib *a = NULL; int result = read_attribs(data, &a, b); if (border_convert_cb) { border_convert_cb(b, a); } while (a) { a_remove(&a, a); } if (result < 0) { return result; } } } } return 0; }
static int muse_connect( const char* host, int port ) { int rsrv = INVALID_SOCKET; struct sockaddr_in rsrvINETAddress; struct sockaddr *rsrvSockAddrPtr = NULL; int selret, conret; struct timeval tval = {5, 0}; fd_set rset, wset; rsrvSockAddrPtr = (struct sockaddr*)&rsrvINETAddress; memset( (char*)&rsrvINETAddress, 0, sizeof(rsrvINETAddress) ); rsrvINETAddress.sin_family = AF_INET; rsrvINETAddress.sin_addr.s_addr = host_to_ip( host ); rsrvINETAddress.sin_port = htons( port ); rsrv = socket( AF_INET, SOCK_STREAM, 0 ); if ( !socket_nonblock(rsrv) ) { close( rsrv ); return INVALID_SOCKET; } conret = rconnect( rsrv, (struct sockaddr*)rsrvSockAddrPtr, sizeof(rsrvINETAddress) ); if ( conret == 0 ) goto ok; if ( conret < 0 && errno != EINPROGRESS ) { close( rsrv ); return INVALID_SOCKET; } errno = 0; /* * Else wait for connection. Cannot use cfgst_microsleep */ FD_ZERO( &rset ); FD_SET( rsrv, &rset ); wset = rset; selret = rselect( rsrv+1, &rset, &wset, NULL, &tval ); if ( selret == 0 ) { close( rsrv ); /* timeout */ errno = ETIMEDOUT; return INVALID_SOCKET; } if ( FD_ISSET(rsrv, &rset) || FD_ISSET(rsrv, &wset) ) { int error=0, optret, len=sizeof(error); optret = getsockopt( rsrv, SOL_SOCKET, SO_ERROR, &error, (socklen_t*)&len ); if ( optret < 0 || error != 0 ) { /* Solaris pending error */ errno = error; warning(" SOL_SOCKET SO_ERROR=%d", error); /*perror( "cfgst_connect" );*/ close( rsrv ); return INVALID_SOCKET; } } else { warning(" select error: sockfd not set"); close( rsrv ); return INVALID_SOCKET; } if ( !socket_block(rsrv) ) { close( rsrv ); return INVALID_SOCKET; } ok: notice("Connected to %s:%d", host, port); return rsrv; }
void chaos(region * r) { if (rng_int() % 100 < 8) { switch (rng_int() % 3) { case 0: /* Untote */ if (!fval(r->terrain, SEA_REGION)) { unit *u = random_unit(r); if (u && playerrace(u_race(u))) { ADDMSG(&u->faction->msgs, msg_message("chaos_disease", "unit", u)); u_setfaction(u, get_monsters()); u_setrace(u, get_race(RC_GHOUL)); } } break; case 1: /* Drachen */ if (random_unit(r)) { int mfac = 0; unit *u; switch (rng_int() % 3) { case 0: mfac = 100; u = createunit(r, get_monsters(), rng_int() % 8 + 1, get_race(RC_FIREDRAGON)); break; case 1: mfac = 500; u = createunit(r, get_monsters(), rng_int() % 4 + 1, get_race(RC_DRAGON)); break; default: mfac = 1000; u = createunit(r, get_monsters(), rng_int() % 2 + 1, get_race(RC_WYRM)); break; } if (mfac) set_money(u, u->number * (rng_int() % mfac)); fset(u, UFL_ISNEW | UFL_MOVED); } case 2: /* Terrainveränderung */ if (!fval(r->terrain, FORBIDDEN_REGION)) { if (!fval(r->terrain, SEA_REGION)) { direction_t dir; for (dir = 0; dir != MAXDIRECTIONS; ++dir) { region *rn = rconnect(r, dir); if (rn && fval(rn->terrain, SEA_REGION)) break; } if (dir != MAXDIRECTIONS) { ship *sh = r->ships; unit **up; while (sh) { ship *nsh = sh->next; float dmg = get_param_flt(global.parameters, "rules.ship.damage.atlantis", 0.50); damage_ship(sh, dmg); if (sh->damage >= sh->size * DAMAGE_SCALE) { remove_ship(&sh->region->ships, sh); } sh = nsh; } for (up = &r->units; *up;) { unit *u = *up; if (u_race(u) != get_race(RC_SPELL) && u->ship == 0 && !canfly(u)) { ADDMSG(&u->faction->msgs, msg_message("tidalwave_kill", "region unit", r, u)); remove_unit(up, u); } if (*up == u) up = &u->next; } ADDMSG(&r->msgs, msg_message("tidalwave", "region", r)); while (r->buildings) { remove_building(&r->buildings, r->buildings); } terraform_region(r, newterrain(T_OCEAN)); } } else { direction_t dir; for (dir = 0; dir != MAXDIRECTIONS; ++dir) { region *rn = rconnect(r, dir); if (rn && fval(rn->terrain, SEA_REGION)) break; } if (dir != MAXDIRECTIONS) { terraform_region(r, chaosterrain()); } } } } } }
/** create new island with up to nsize players * returns the number of players placed on the new island. */ int autoseed(newfaction ** players, int nsize, int max_agediff) { region *r = NULL; region_list *rlist = NULL; int rsize = 0, tsize = 0; int isize = REGIONS_PER_FACTION; /* target size for the island */ int psize = 0; /* players on this island */ const terrain_type *volcano_terrain = get_terrain("volcano"); static int nterrains = -1; static const terrain_type **terrainarr = 0; static int *distribution; assert(players); if (nterrains < 0) { int n = 0; const terrain_type *terrain = terrains(); for (nterrains = 0; terrain; terrain = terrain->next) { if (terrain->distribution) { ++nterrains; } } terrainarr = malloc(sizeof(terrain_type *) * nterrains); distribution = malloc(sizeof(int) * nterrains); for (terrain = terrains(); terrain; terrain = terrain->next) { if (terrain->distribution) { terrainarr[n] = terrain; distribution[n++] = terrain->distribution; } } } frame_regions(16, newterrain(T_FIREWALL)); if (listlen(*players) < MINFACTIONS) return 0; if (max_agediff > 0) { region *rmin = NULL; plane *hplane = get_homeplane(); /* find a spot that's adjacent to the previous island, but virgin. * like the last land virgin ocean region adjacent to land. */ for (r = regions; r; r = r->next) { struct plane *pl = rplane(r); if (r->age <= max_agediff && r->terrain == newterrain(T_OCEAN) && pl == hplane && virgin_region(r)) { direction_t d; for (d = 0; d != MAXDIRECTIONS; ++d) { region *rn = rconnect(r, d); if (rn && rn->land && rn->age <= max_agediff && virgin_region(rn)) { /* only expand islands that aren't single-islands and not too big already */ int size, inhabitants, maxage; get_island_info(rn, &size, &inhabitants, &maxage); if (maxage <= max_agediff && size >= 2 && size < MAXISLANDSIZE) { rmin = rn; break; } } } } } if (rmin != NULL) { faction *f; quicklist *ql, *rlist = get_island(rmin); int qi; for (ql = rlist, qi = 0; ql; ql_advance(&ql, &qi, 1)) { region *r = (region *)ql_get(ql, qi); unit *u; for (u = r->units; u; u = u->next) { f = u->faction; if (!fval(f, FFL_MARK)) { ++psize; fset(f, FFL_MARK); } } } ql_free(rlist); if (psize > 0) { for (f = factions; f; f = f->next) { freset(f, FFL_MARK); } } if (psize < PLAYERS_PER_ISLAND) { r = rmin; } } } if (r == NULL) { region *rmin = NULL; direction_t dmin = MAXDIRECTIONS; plane *hplane = get_homeplane(); /* find an empty spot. * rmin = the youngest ocean region that has a missing neighbour * dmin = direction in which it's empty */ for (r = regions; r; r = r->next) { struct plane *pl = rplane(r); if (r->terrain == newterrain(T_OCEAN) && pl == hplane && (rmin == NULL || r->age <= max_agediff)) { direction_t d; for (d = 0; d != MAXDIRECTIONS; ++d) { region *rn = rconnect(r, d); if (rn == NULL) break; } if (d != MAXDIRECTIONS) { rmin = r; dmin = d; } } } /* create a new region where we found the empty spot, and make it the first * in our island. island regions are kept in rlist, so only new regions can * get populated, and old regions are not overwritten */ if (rmin != NULL) { plane *pl = rplane(rmin); int x = rmin->x + delta_x[dmin]; int y = rmin->y + delta_y[dmin]; pnormalize(&x, &y, pl); assert(virgin_region(rconnect(rmin, dmin))); r = new_region(x, y, pl, 0); terraform_region(r, newterrain(T_OCEAN)); } } if (r != NULL) { add_regionlist(&rlist, r); fset(r, RF_MARK); rsize = 1; } while (rsize && (nsize || isize >= REGIONS_PER_FACTION)) { int i = rng_int() % rsize; region_list **rnext = &rlist; region_list *rfind; direction_t d; while (i--) rnext = &(*rnext)->next; rfind = *rnext; r = rfind->data; freset(r, RF_MARK); *rnext = rfind->next; free(rfind); --rsize; for (d = 0; d != MAXDIRECTIONS; ++d) { region *rn = rconnect(r, d); if (rn && fval(rn, RF_MARK)) continue; if (rn == NULL) { plane *pl = rplane(r); int x = r->x + delta_x[d]; int y = r->y + delta_y[d]; pnormalize(&x, &y, pl); rn = new_region(x, y, pl, 0); terraform_region(rn, newterrain(T_OCEAN)); } if (virgin_region(rn)) { add_regionlist(&rlist, rn); fset(rn, RF_MARK); ++rsize; } } if (volcano_terrain != NULL && (rng_int() % VOLCANO_CHANCE == 0)) { terraform_region(r, volcano_terrain); } else if (nsize && (rng_int() % isize == 0 || rsize == 0)) { newfaction **nfp, *nextf = *players; faction *f; unit *u; isize += REGIONS_PER_FACTION; terraform_region(r, preferred_terrain(nextf->race)); prepare_starting_region(r); ++tsize; assert(r->land && r->units == 0); u = addplayer(r, addfaction(nextf->email, nextf->password, nextf->race, nextf->lang, nextf->subscription)); f = u->faction; fset(f, FFL_ISNEW); f->alliance = nextf->allies; /* remove duplicate email addresses */ nfp = &nextf->next; while (*nfp) { newfaction *nf = *nfp; if (strcmp(nextf->email, nf->email) == 0) { *nfp = nf->next; free_newfaction(nf); } else nfp = &nf->next; } *players = nextf->next; free_newfaction(nextf); ++psize; --nsize; --isize; if (psize >= PLAYERS_PER_ISLAND) break; } else { terraform_region(r, random_terrain(terrainarr, distribution, nterrains)); --isize; } } if (nsize != 0) { log_error( ("Could not place all factions on the same island as requested\n")); } if (rlist) { #define MINOCEANDIST 3 #define MAXOCEANDIST 6 #define MAXFILLDIST 10 #define SPECIALCHANCE 80 region_list **rbegin = &rlist; int special = 1; int oceandist = MINOCEANDIST + (rng_int() % (MAXOCEANDIST - MINOCEANDIST)); while (oceandist--) { region_list **rend = rbegin; while (*rend) rend = &(*rend)->next; while (rbegin != rend) { direction_t d; region *r = (*rbegin)->data; rbegin = &(*rbegin)->next; for (d = 0; d != MAXDIRECTIONS; ++d) { region *rn = rconnect(r, d); if (rn == NULL) { const struct terrain_type *terrain = newterrain(T_OCEAN); plane *pl = rplane(r); int x = r->x + delta_x[d]; int y = r->y + delta_y[d]; pnormalize(&x, &y, pl); rn = new_region(x, y, pl, 0); if (rng_int() % SPECIALCHANCE < special) { terrain = random_terrain(terrainarr, distribution, nterrains); special = SPECIALCHANCE / 3; /* 33% chance auf noch eines */ } else { special = 1; } terraform_region(rn, terrain); /* the new region has an extra 20% chance to have mallorn */ if (rng_int() % 100 < 20) fset(r, RF_MALLORN); add_regionlist(rend, rn); } } } } while (*rbegin) { region *r = (*rbegin)->data; plane *pl = rplane(r); direction_t d; rbegin = &(*rbegin)->next; for (d = 0; d != MAXDIRECTIONS; ++d) if (rconnect(r, d) == NULL) { int i; for (i = 1; i != MAXFILLDIST; ++i) { int x = r->x + delta_x[d] * i; int y = r->y + delta_y[d] * i; pnormalize(&x, &y, pl); if (findregion(x, y)) { break; } } if (i != MAXFILLDIST) { while (--i) { region *rn; int x = r->x + delta_x[d] * i; int y = r->y + delta_y[d] * i; pnormalize(&x, &y, pl); rn = new_region(x, y, pl, 0); terraform_region(rn, newterrain(T_OCEAN)); } } } } while (rlist) { region_list *self = rlist; rlist = rlist->next; freset(self->data, RF_MARK); free(self); } } return tsize; }
void vm_process(VM *vm) { int a, b, opcode; opcode = vm->image[vm->ip]; switch(opcode) { case VM_NOP: break; case VM_LIT: vm->sp++; vm->ip++; TOS = vm->image[vm->ip]; break; case VM_DUP: vm->sp++; vm->data[vm->sp] = NOS; break; case VM_DROP: DROP break; case VM_SWAP: a = TOS; TOS = NOS; NOS = a; break; case VM_PUSH: vm->rsp++; TORS = TOS; DROP break; case VM_POP: vm->sp++; TOS = TORS; vm->rsp--; break; case VM_CALL: vm->ip++; vm->rsp++; TORS = vm->ip; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; case VM_JUMP: vm->ip++; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; case VM_RETURN: vm->ip = TORS; vm->rsp--; break; case VM_GT_JUMP: vm->ip++; if(NOS > TOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_LT_JUMP: vm->ip++; if(NOS < TOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_NE_JUMP: vm->ip++; if(TOS != NOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_EQ_JUMP: vm->ip++; if(TOS == NOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_FETCH: TOS = vm->image[TOS]; break; case VM_STORE: vm->image[TOS] = NOS; DROP DROP break; case VM_ADD: NOS += TOS; DROP break; case VM_SUB: NOS -= TOS; DROP break; case VM_MUL: NOS *= TOS; DROP break; case VM_DIVMOD: a = TOS; b = NOS; TOS = b / a; NOS = b % a; break; case VM_AND: a = TOS; b = NOS; DROP TOS = a & b; break; case VM_OR: a = TOS; b = NOS; DROP TOS = a | b; break; case VM_XOR: a = TOS; b = NOS; DROP TOS = a ^ b; break; case VM_SHL: a = TOS; b = NOS; DROP TOS = b << a; break; case VM_SHR: a = TOS; b = NOS; DROP TOS = b >>= a; break; case VM_ZERO_EXIT: if (TOS == 0) { DROP vm->ip = TORS; vm->rsp--; } break; case VM_INC: TOS += 1; break; case VM_DEC: TOS -= 1; break; case VM_IN: a = TOS; TOS = vm->ports[a]; vm->ports[a] = 0; break; case VM_OUT: vm->ports[0] = 0; vm->ports[TOS] = NOS; DROP DROP break; case VM_WAIT: if (vm->ports[0] == 1) break; /* Input */ if (vm->ports[0] == 0 && vm->ports[1] == 1) { vm->ports[1] = dev_getch(); vm->ports[0] = 1; } /* Output (character generator) */ if (vm->ports[2] == 1) { dev_putch(TOS); DROP vm->ports[2] = 0; vm->ports[0] = 1; } if (vm->ports[4] != 0) { vm->ports[0] = 1; switch (vm->ports[4]) { case 1: vm_save_image(vm, vm->filename); vm->ports[4] = 0; break; case 2: file_add(vm); vm->ports[4] = 0; break; case -1: vm->ports[4] = file_handle(vm); break; case -2: vm->ports[4] = file_readc(vm); break; case -3: vm->ports[4] = file_writec(vm); break; case -4: vm->ports[4] = file_closehandle(vm); break; case -5: vm->ports[4] = file_getpos(vm); break; case -6: vm->ports[4] = file_seek(vm); break; case -7: vm->ports[4] = file_size(vm); break; default: vm->ports[4] = 0; } } /* Capabilities */ if (vm->ports[5] != 0) { vm->ports[0] = 1; switch(vm->ports[5]) { case -1: vm->ports[5] = IMAGE_SIZE; break; case -2: vm->ports[5] = 0; break; case -3: vm->ports[5] = 0; break; case -4: vm->ports[5] = 0; break; case -5: vm->ports[5] = vm->sp; break; case -6: vm->ports[5] = vm->rsp; break; case -7: vm->ports[5] = 0; break; case -8: vm->ports[5] = time(NULL); break; case -9: vm->ports[5] = 0; vm->ip = IMAGE_SIZE; break; default: vm->ports[5] = 0; } } if (vm->ports[8] != 0) { vm->ports[0] = 1; switch (vm->ports[8]) { case -1: rsocket(vm); vm->ports[8] = 0; break; case -2: rbind(vm); vm->ports[8] = 0; break; case -3: rlisten(vm); vm->ports[8] = 0; break; case -4: raccept(vm); vm->ports[8] = 0; break; case -5: rclose(vm); vm->ports[8] = 0; break; case -6: rsend(vm); vm->ports[8] = 0; break; case -7: rrecv(vm); vm->ports[8] = 0; break; case -8: rconnect(vm); vm->ports[8] = 0; break; default: vm->ports[8] = 0; } vm->ports[8] = 0; } break; default: vm->rsp++; TORS = vm->ip; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; } vm->ports[3] = 1; }
void piracy_cmd(unit * u, order *ord) { region *r = u->region; ship *sh = u->ship, *sh2; direction_t target_dir; struct { const faction *target; int value; } aff[MAXDIRECTIONS]; int saff = 0; int *il; if (!validate_pirate(u, ord)) { return; } il = parse_ids(ord); /* Feststellen, ob schon ein anderer alliierter Pirat ein * Ziel gefunden hat. */ target_dir = find_piracy_target(u, il); /* Wenn nicht, sehen wir, ob wir ein Ziel finden. */ if (target_dir == NODIRECTION) { direction_t dir; /* Einheit ist also Kapitän. Jetzt gucken, in wievielen * Nachbarregionen potentielle Opfer sind. */ for (dir = 0; dir < MAXDIRECTIONS; dir++) { region *rc = rconnect(r, dir); aff[dir].value = 0; aff[dir].target = 0; if (rc && fval(rc->terrain, SAIL_INTO) && can_takeoff(sh, r, rc)) { for (sh2 = rc->ships; sh2; sh2 = sh2->next) { unit *cap = ship_owner(sh2); if (cap) { faction *f = visible_faction(cap->faction, cap); if (alliedunit(u, f, HELP_FIGHT)) continue; if (!il || intlist_find(il, cap->faction->no)) { // TODO: shouldn't this be f->no? ++aff[dir].value; if (rng_int() % aff[dir].value == 0) { aff[dir].target = f; } } } } /* Und aufaddieren. */ saff += aff[dir].value; } } if (saff != 0) { saff = rng_int() % saff; for (dir = 0; dir != MAXDIRECTIONS; ++dir) { if (saff < aff[dir].value) { target_dir = dir; a_add(&r->attribs, mk_piracy(u->faction, aff[dir].target, target_dir)); break; } saff -= aff[dir].value; } } } free(il); /* Wenn kein Ziel gefunden, entsprechende Meldung generieren */ if (target_dir == NODIRECTION) { ADDMSG(&u->faction->msgs, msg_message("piratenovictim", "ship region", sh, r)); return; } /* Meldung generieren */ ADDMSG(&u->faction->msgs, msg_message("piratesawvictim", "ship region dir", sh, r, target_dir)); /* Befehl konstruieren */ set_order(&u->thisorder, create_order(K_MOVE, u->faction->locale, "%s", LOC(u->faction->locale, directions[target_dir]))); /* Bewegung ausführen */ init_order(u->thisorder); move_cmd(u, true); }