static int tolua_region_create(lua_State * L) { int x = (int)tolua_tonumber(L, 1, 0); int y = (int)tolua_tonumber(L, 2, 0); const char *tname = tolua_tostring(L, 3, 0); if (tname) { plane *pl = findplane(x, y); const terrain_type *terrain = get_terrain(tname); region *r, *result; if (!terrain) { return 0; } assert(!pnormalize(&x, &y, pl)); r = result = findregion(x, y); if (r != NULL && r->units != NULL) { /* TODO: error message */ result = NULL; } else if (r == NULL) { result = new_region(x, y, pl, 0); } if (result) { terraform_region(result, terrain); if (result->land) { fix_demand(result); } } tolua_pushusertype(L, result, TOLUA_CAST "region"); return 1; } return 0; }
region *new_region(int x, int y, struct plane *pl, int uid) { region *r; pnormalize(&x, &y, pl); r = rfindhash(x, y); if (r) { log_error("duplicate region discovered: %s(%d,%d)\n", regionname(r, NULL), x, y); if (r->units) log_error("duplicate region contains units\n"); return r; } r = calloc(1, sizeof(region)); r->x = x; r->y = y; r->uid = uid; r->age = 1; r->_plane = pl; rhash(r); hash_uid(r); if (last) addlist(&last, r); else addlist(®ions, r); last = r; assert(r->next == NULL); r->index = ++max_index; return r; }
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; } } } }
/** ** GM: TERRAFORM <x> <y> <terrain> ** requires: permission-key "gmterf" **/ static void gm_terraform(const void *tnext, struct unit *u, struct order *ord) { const struct plane *p = rplane(u->region); int x = rel_to_abs(p, u->faction, getint(), 0); int y = rel_to_abs(p, u->faction, getint(), 1); const char *c = getstrtoken(); variant token; void **tokens = get_translations(u->faction->locale, UT_TERRAINS); region *r; pnormalize(&x, &y, p); r = findregion(x, y); if (r == NULL || p != rplane(r)) { mistake(u, ord, "region is in another plane."); return; } else { /* checking permissions */ attrib *permissions = a_find(u->faction->attribs, &at_permissions); if (!permissions || !has_permission(permissions, atoi36("gmterf"))) return; } if (findtoken(*tokens, c, &token) != E_TOK_NOMATCH) { const terrain_type *terrain = (const terrain_type *)token.v; terraform_region(r, terrain); } }
/** ** GM: GATE <id> <x> <y> ** requires: permission-key "gmgate" **/ static void gm_gate(const void *tnext, struct unit * u, struct order *ord) { const struct plane *pl = rplane(u->region); int id = getid(); int x = rel_to_abs(pl, u->faction, getint(), 0); int y = rel_to_abs(pl, u->faction, getint(), 1); building *b = findbuilding(id); region *r; pnormalize(&x, &y, pl); r = findregion(x, y); if (b == NULL || r == NULL || pl != rplane(b->region) || pl != rplane(r)) { mistake(u, ord, "the unit cannot transform this building."); return; } else { /* checking permissions */ attrib *permissions = a_find(u->faction->attribs, &at_permissions); if (permissions && has_permission(permissions, atoi36("gmgate"))) { remove_triggers(&b->attribs, "timer", &tt_gate); remove_triggers(&b->attribs, "create", &tt_unguard); if (r != b->region) { add_trigger(&b->attribs, "timer", trigger_gate(b, r)); add_trigger(&b->attribs, "create", trigger_unguard(b)); fset(b, BLD_UNGUARDED); } } } }
static int tolua_distance(lua_State * L) { int x1 = (int)tolua_tonumber(L, 1, 0); int y1 = (int)tolua_tonumber(L, 2, 0); int x2 = (int)tolua_tonumber(L, 3, 0); int y2 = (int)tolua_tonumber(L, 4, 0); plane *pl = (plane *)tolua_tousertype(L, 5, 0); int result; if (!pl) pl = get_homeplane(); pnormalize(&x1, &y1, pl); pnormalize(&x2, &y2, pl); result = koor_distance(x1, y1, x2, y2); lua_pushinteger(L, result); return 1; }
static int tolua_plane_normalize(lua_State * L) { plane *self = (plane *)tolua_tousertype(L, 1, 0); int x = (int)tolua_tonumber(L, 2, 0); int y = (int)tolua_tonumber(L, 3, 0); pnormalize(&x, &y, self); lua_pushinteger(L, x); lua_pushinteger(L, y); return 2; }
static int tolua_faction_normalize(lua_State * L) { faction *f = (faction *)tolua_tousertype(L, 1, 0); region *r = (region *)tolua_tousertype(L, 2, 0); if (r) { plane *pl = rplane(r); int nx = r->x, ny = r->y; pnormalize(&nx, &ny, pl); adjust_coordinates(f, &nx, &ny, pl, r); tolua_pushnumber(L, (lua_Number)nx); tolua_pushnumber(L, (lua_Number)ny); return 2; } return 0; }
static void oceans_around(region * r, region * rn[]) { int n; for (n = 0; n != MAXDIRECTIONS; ++n) { region *rx = rn[n]; if (rx == NULL) { plane *pl = rplane(r); int x = r->x + delta_x[n]; int y = r->y + delta_y[n]; pnormalize(&x, &y, pl); rx = new_region(x, y, pl, 0); terraform_region(rx, newterrain(T_OCEAN)); rn[n] = rx; } } }
const char *write_regionname(const region * r, const faction * f, char *buffer, size_t size) { char *buf = (char *)buffer; const struct locale *lang = f ? f->locale : 0; if (r == NULL) { strlcpy(buf, "(null)", size); } else { plane *pl = rplane(r); int nx = r->x, ny = r->y; pnormalize(&nx, &ny, pl); adjust_coordinates(f, &nx, &ny, pl, r); slprintf(buf, size, "%s (%d,%d)", rname(r, lang), nx, ny); } return buffer; }
/* update_lighthouse: call this function whenever the size of a lighthouse changes * it adds temporary markers to the surrounding regions. * The existence of markers says nothing about the quality of the observer in * the lighthouse, for this may change more frequently. */ void update_lighthouse(building * lh) { if (is_building_type(lh->type, "lighthouse")) { region *r = lh->region; r->flags |= RF_LIGHTHOUSE; if (lh->size > 0) { int d = (int)log10(lh->size) + 1; int x; for (x = -d; x <= d; ++x) { int y; for (y = -d; y <= d; ++y) { attrib *a; region *r2; int px = r->x + x, py = r->y + y; pnormalize(&px, &py, rplane(r)); r2 = findregion(px, py); if (!r2 || !fval(r2->terrain, SEA_REGION)) continue; if (distance(r, r2) > d) continue; a = a_find(r2->attribs, &at_lighthouse); while (a && a->type == &at_lighthouse) { building *b = (building *)a->data.v; if (b == lh) break; a = a->next; } if (!a) { a = a_add(&r2->attribs, a_new(&at_lighthouse)); a->data.v = (void *)lh; } } } } } }
region *r_connect(const region * r, direction_t dir) { region *result; int x, y; #ifdef FAST_CONNECT region *rmodify = (region *)r; assert(dir >= 0 && dir < MAXDIRECTIONS); if (r->connect[dir]) return r->connect[dir]; #endif assert(dir < MAXDIRECTIONS); x = r->x + delta_x[dir]; y = r->y + delta_y[dir]; pnormalize(&x, &y, rplane(r)); result = rfindhash(x, y); #ifdef FAST_CONNECT if (result) { rmodify->connect[dir] = result; result->connect[back[dir]] = rmodify; } #endif return result; }
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 lua_paint_info(struct window *wnd, const struct state *st) { struct lua_State *L = paint_state; int nx = st->cursor.x, ny = st->cursor.y; pnormalize(&nx, &ny, st->cursor.pl); lua_rawgeti(L, LUA_REGISTRYINDEX, paint_handle); lua_pushinteger(L, nx); lua_pushinteger(L, ny); if (lua_pcall(L, 2, 1, 0) != 0) { const char *error = lua_tostring(L, -1); log_error("paint function failed: %s\n", error); lua_pop(L, 1); tolua_error(L, TOLUA_CAST "event handler call failed", NULL); } else { const char *result = lua_tostring(L, -1); WINDOW *win = wnd->handle; int size = getmaxx(win) - 2; int line = 0, maxline = getmaxy(win) - 2; const char *str = result; wxborder(win); while (*str && line < maxline) { const char *end = strchr(str, '\n'); if (!end) break; else { int bytes = (int)(end - str); if (bytes < size) bytes = size; mvwaddnstr(win, line++, 1, str, bytes); wclrtoeol(win); str = end + 1; } } } }
kernel void sample_z(global int *cur_y, global int *cur_z, global int *cur_r, global int *z_by_ry, global int *z_col_sum, global int *obs, global float *rand, uint N, uint D, uint K, uint f_img_width, float lambda, float epislon, float theta) { const uint V_SCALE = 0, H_SCALE = 1, V_TRANS = 2, H_TRANS = 3, NUM_TRANS = 4; uint h, w, new_index; // variables used in the for loop uint nth = get_global_id(0); // n is the index of data uint kth = get_global_id(1); // k is the index of features uint f_img_height = D / f_img_width; // calculate the prior probability of each cell is 1 float on_prob_temp = (z_col_sum[kth] - cur_z[nth * K + kth]) / (float)N; float off_prob_temp = 1 - (z_col_sum[kth] - cur_z[nth * K + kth]) / (float)N; // retrieve the transformation applied to this feature by this object int v_scale = cur_r[nth * (K * NUM_TRANS) + kth * NUM_TRANS + V_SCALE]; int h_scale = cur_r[nth * (K * NUM_TRANS) + kth * NUM_TRANS + H_SCALE]; int v_dist = cur_r[nth * (K * NUM_TRANS) + kth * NUM_TRANS + V_TRANS]; int h_dist = cur_r[nth * (K * NUM_TRANS) + kth * NUM_TRANS + H_TRANS]; int new_height = f_img_height + v_scale, new_width = f_img_width + h_scale; uint d, hh, ww; // extremely hackish way to calculate the likelihood for (d = 0; d < D; d++) { // if the kth feature can turn on a pixel at d if (cur_y[kth * D + d] == 1) { // unpack d into h and w and get new index h = d / f_img_width; w = d % f_img_width; for (hh = 0; hh < f_img_height; hh++) { for (ww = 0; ww < f_img_width; ww++) { if ((int)round((float)hh / new_height * f_img_height) == h & (int)round((float)ww / new_width * f_img_width) == w) { new_index = ((v_dist + hh) % f_img_height) * f_img_width + (h_dist + ww) % f_img_width; // then the corresponding observed pixel is at new_index // so, if the observed pixel at new_index is on if (obs[nth * D + new_index] == 1) { // if the nth object previously has the kth feature if (cur_z[nth * K + kth] == 1) { on_prob_temp *= 1 - pow(1 - lambda, z_by_ry[nth * D + new_index]) * (1 - epislon); off_prob_temp *= 1 - pow(1 - lambda, z_by_ry[nth * D + new_index] - 1) * (1 - epislon); } else { on_prob_temp *= 1 - pow(1 - lambda, z_by_ry[nth * D + new_index] + 1) * (1 - epislon); off_prob_temp *= 1 - pow(1 - lambda, z_by_ry[nth * D + new_index]) * (1 - epislon); } } else { on_prob_temp *= 1 - lambda; off_prob_temp *= 1.0f; } } } } } } //printf("index: %d post_on: %f post_off: %f\n", nth * K + kth, on_prob_temp, off_prob_temp); float post[2] = {on_prob_temp, off_prob_temp}; uint labels[2] = {1, 0}; pnormalize(post, 0, 2); //printf("before index: %d %f %f %d \n", nth * K + kth, post[0], post[1], cur_z[nth * K + kth]); cur_z[nth * K + kth] = sample(2, labels, post, 0, rand[nth * K + kth]); //printf("after index: %d %f %f %d \n", nth * K + kth, post[0], post[1], cur_z[nth * K + kth]); }
/** 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; }