diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c index de78d6906..70ca66f09 100644 --- a/src/common/gamecode/creport.c +++ b/src/common/gamecode/creport.c @@ -81,7 +81,7 @@ extern int verbosity; boolean opt_cr_absolute_coords = false; /* globals */ -#define C_REPORT_VERSION 64 +#define C_REPORT_VERSION 65 #define TAG_LOCALE "de" #ifdef TAG_LOCALE @@ -309,8 +309,9 @@ cr_region(variant var, char * buffer, const void * userdata) const faction * report = (const faction*)userdata; region * r = (region *)var.v; if (r) { - plane * p = r->planep; - sprintf(buffer, "%d %d %d", region_x(r, report), region_y(r, report), p?p->id:0); + plane * pl = rplane(r); + int nx = region_x(r, report), ny = region_y(r, report); + sprintf(buffer, "%d %d %d", nx, ny, plane_id(pl)); return 0; } return -1; @@ -419,14 +420,17 @@ cr_regions(variant var, char * buffer, const void * userdata) if (rdata!=NULL && rdata->nregions>0) { region * r = rdata->regions[0]; - int i, z = r->planep?r->planep->id:0; + plane * pl = rplane(r); + int i, z = plane_id(pl); char * wp = buffer; + int nx = region_x(r, f), ny = region_y(r, f); - wp += sprintf(wp, "\"%d %d %d", region_x(r, f), region_y(r, f), z); + wp += sprintf(wp, "\"%d %d %d", nx, ny, z); for (i=1;i!=rdata->nregions;++i) { r = rdata->regions[i]; - z = r->planep?r->planep->id:0; - wp += sprintf(wp, ", %d %d %d", region_x(r, f), region_y(r, f), z); + pl = rplane(r); + z = plane_id(pl); + wp += sprintf(wp, ", %d %d %d", nx, ny, z); } strcat(wp, "\""); } else { @@ -1093,17 +1097,25 @@ cr_output_region(FILE * F, report_context * ctx, seen_region * sr) { faction * f = ctx->f; region * r = sr->r; + plane * pl = rplane(r); + int plid = plane_id(pl), nx, ny; const char * tname; - if (!r->planep) { - if (opt_cr_absolute_coords) { - fprintf(F, "REGION %d %d\n", r->x, r->x); - } else { - fprintf(F, "REGION %d %d\n", region_x(r, f), region_y(r, f)); - } + + if (opt_cr_absolute_coords) { + nx = r->x; + ny = r->y; } else { - fprintf(F, "REGION %d %d %d\n", region_x(r, f), region_y(r, f), r->planep->id); + nx = region_x(r, f); + ny = region_y(r, f); + } + + if (plid==0) { + fprintf(F, "REGION %d %d\n", nx, ny); + } else { + fprintf(F, "REGION %d %d %d\n", nx, ny, plid); } fprintf(F, "%d;id\n", r->uid); + if (r->land) { const char * str = rname(r, f->locale); if (str && str[0]) { @@ -1200,7 +1212,9 @@ cr_output_region(FILE * F, report_context * ctx, seen_region * sr) region_list *rl2 = rl; while(rl2) { region * r = rl2->data; - fprintf(F, "SCHEMEN %d %d\n", region_x(r, f), region_y(r, f)); + plane * pl = rplane(r); + int nx = region_x(r, f), ny = region_y(r, f); + fprintf(F, "SCHEMEN %d %d\n", nx, ny); fprintf(F, "\"%s\";Name\n", rname(r, f->locale)); rl2 = rl2->next; } @@ -1275,6 +1289,7 @@ cr_output_region(FILE * F, report_context * ctx, seen_region * sr) static int report_computer(const char * filename, report_context * ctx, const char * charset) { + static int era = -1; int i; faction * f = ctx->f; const char * prefix; @@ -1288,6 +1303,9 @@ report_computer(const char * filename, report_context * ctx, const char * charse int enc = xmlParseCharEncoding(charset); FILE * F = fopen(filename, "wt"); + if (era<0) { + era = get_param_int(global.parameters, "world.era", 2); + } if (F==NULL) { perror(filename); return -1; @@ -1310,7 +1328,7 @@ report_computer(const char * filename, report_context * ctx, const char * charse fprintf(F, "\"%s\";Koordinaten\n", "Hex"); fprintf(F, "%d;Basis\n", 36); fprintf(F, "%d;Runde\n", turn); - fputs("2;Zeitalter\n", F); + fprintf(F, "%d;Zeitalter\n", era); if (mailto!=NULL) { fprintf(F, "\"%s\";mailto\n", mailto); fprintf(F, "\"%s\";mailcmd\n", locale_string(f->locale, "mailcmd")); @@ -1389,9 +1407,12 @@ report_computer(const char * filename, report_context * ctx, const char * charse { struct bmsg * bm; for (bm=f->battles;bm;bm=bm->next) { - if (!bm->r->planep) fprintf(F, "BATTLE %d %d\n", region_x(bm->r, f), region_y(bm->r, f)); + plane * pl = rplane(bm->r); + int plid = plane_id(pl); + int nx = region_x(bm->r, f), ny = region_y(bm->r, f); + if (!plid) fprintf(F, "BATTLE %d %d\n", nx, ny); else { - fprintf(F, "BATTLE %d %d %d\n", region_x(bm->r, f), region_y(bm->r, f), bm->r->planep->id); + fprintf(F, "BATTLE %d %d %d\n", nx, ny, plid); } cr_output_messages(F, bm->msgs, f); } @@ -1452,9 +1473,18 @@ crwritemap(const char * filename) { FILE * F = fopen(filename, "w+"); region * r; + + fprintf(F, "VERSION %d\n", C_REPORT_VERSION); + fputs("\"UTF-8\";charset\n", F); + for (r=regions;r;r=r->next) { - plane * p = r->planep; - fprintf(F, "REGION %d %d %d\n", r->x, r->y, p?p->id:0); + plane * pl = rplane(r); + int plid = plane_id(pl); + if (plid) { + fprintf(F, "REGION %d %d %d\n", r->x, r->y, plid); + } else { + fprintf(F, "REGION %d %d\n", r->x, r->y); + } fprintf(F, "\"%s\";Name\n\"%s\";Terrain\n", rname(r, default_locale), LOC(default_locale, terrain_name(r))); } fclose(F); diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c index 6ee805560..13739720c 100644 --- a/src/common/gamecode/economy.c +++ b/src/common/gamecode/economy.c @@ -622,6 +622,7 @@ give_cmd(unit * u, order * ord) int i, n, rule = rule_give(); const item_type * itype; param_t p; + plane * pl; init_tokens(ord); skip_token(); @@ -652,7 +653,8 @@ give_cmd(unit * u, order * ord) /* UFL_TAKEALL ist ein grober Hack. Generalisierung tut not, ist aber nicht * wirklich einfach. */ - if (r->planep && fval(r->planep, PFL_NOGIVE) && (!u2 || !fval(u2, UFL_TAKEALL))) { + pl = rplane(r); + if (pl && fval(pl, PFL_NOGIVE) && (!u2 || !fval(u2, UFL_TAKEALL))) { cmistake(u, ord, 268, MSG_COMMERCE); return; } @@ -1811,15 +1813,12 @@ make_cmd(unit * u, struct order * ord) * aufruf von make geeicht */ if (p == P_ROAD) { - if(r->planep && fval(r->planep, PFL_NOBUILD)) { + plane * pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { cmistake(u, ord, 275, MSG_PRODUCE); } else { direction_t d = finddirection(getstrtoken(), u->faction->locale); if (d!=NODIRECTION) { - if(r->planep && fval(r->planep, PFL_NOBUILD)) { - cmistake(u, ord, 94, MSG_PRODUCE); - return 0; - } build_road(r, u, m, d); } else { /* Die Richtung wurde nicht erkannt */ @@ -1828,7 +1827,8 @@ make_cmd(unit * u, struct order * ord) } return 0; } else if (p == P_SHIP) { - if(r->planep && fval(r->planep, PFL_NOBUILD)) { + plane * pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { cmistake(u, ord, 276, MSG_PRODUCE); } else { continue_ship(r, u, m); @@ -1872,13 +1872,15 @@ make_cmd(unit * u, struct order * ord) } if (stype != NOSHIP) { - if(r->planep && fval(r->planep, PFL_NOBUILD)) { + plane * pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { cmistake(u, ord, 276, MSG_PRODUCE); } else { create_ship(r, u, stype, m, ord); } - } else if (btype != NOBUILDING) { - if(r->planep && fval(r->planep, PFL_NOBUILD)) { + } else if (btype != NOBUILDING) { + plane * pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { cmistake(u, ord, 94, MSG_PRODUCE); } else { build_building(u, btype, m, ord); @@ -2836,6 +2838,7 @@ steal_cmd(unit * u, struct order * ord, request ** stealorders) unit * u2 = NULL; region * r = u->region; faction * f = NULL; + plane * pl; assert(skill_enabled[SK_PERCEPTION] && skill_enabled[SK_STEALTH]); @@ -2849,7 +2852,8 @@ steal_cmd(unit * u, struct order * ord, request ** stealorders) return; } - if (r->planep && fval(r->planep, PFL_NOATTACK)) { + pl = rplane(r); + if (pl && fval(pl, PFL_NOATTACK)) { cmistake(u, ord, 270, MSG_INCOME); return; } diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index 874c696e4..00be2a839 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -189,6 +189,7 @@ help_money(const unit * u) static void get_food(region *r) { + plane * pl = rplane(r); unit *u; int peasantfood = rpeasants(r)*10; faction * owner = region_get_owner(r); @@ -307,7 +308,7 @@ get_food(region *r) } } } - if (r->planep == NULL || !fval(r->planep, PFL_NOFEED)) { + if (pl == NULL || !fval(pl, PFL_NOFEED)) { if (peasantfood>=hungry) { peasantfood -= hungry; hungry = 0; diff --git a/src/common/gamecode/monster.c b/src/common/gamecode/monster.c index dbfad47c8..27aeddc26 100644 --- a/src/common/gamecode/monster.c +++ b/src/common/gamecode/monster.c @@ -426,10 +426,13 @@ set_new_dragon_target(unit * u, region * r, int range) free_regionlist(rlist); #else - int x, y; - for (x = r->x - range; x < r->x + range; x++) { - for (y = r->y - range; y < r->y + range; y++) { - region * r2 = findregion(x, y); + int tx, ty; + for (tx = r->x - range; tx < r->x + range; tx++) { + for (ty = r->y - range; ty < r->y + range; ty++) { + region * r2; + int x = tx, y = ty; + pnormalize(&x, &y, r->planep); + r2 = findregion(x, y); if (r2!=NULL) { int affinity = dragon_affinity_value(r2, u); if (affinity > max_affinity) { diff --git a/src/common/gamecode/report.c b/src/common/gamecode/report.c index e3d086516..ff508f89a 100644 --- a/src/common/gamecode/report.c +++ b/src/common/gamecode/report.c @@ -1332,7 +1332,6 @@ report_template(const char * filename, report_context * ctx, const char * charse { faction * f = ctx->f; region *r; - plane *pl; FILE * F = fopen(filename, "wt"); seen_region * sr = NULL; char buf[8192], * bufp; @@ -1384,15 +1383,16 @@ report_template(const char * filename, report_context * ctx, const char * charse if (u->faction == f && !fval(u->race, RCF_INVISIBLE)) { order * ord; if (!dh) { + plane * pl = getplane(r); + int nx = region_x(r, f), ny = region_y(r, f); rps_nowrap(F, ""); rnl(F); - pl = getplane(r); if (pl && pl->id != 0) { - sprintf(buf, "%s %d,%d,%d ; %s", LOC(f->locale, parameters[P_REGION]), region_x(r,f), - region_y(r,f), pl->id, rname(r, f->locale)); + sprintf(buf, "%s %d,%d,%d ; %s", LOC(f->locale, parameters[P_REGION]), + nx, ny, pl->id, rname(r, f->locale)); } else { - sprintf(buf, "%s %d,%d ; %s", LOC(f->locale, parameters[P_REGION]), region_x(r,f), - region_y(r,f), rname(r, f->locale)); + sprintf(buf, "%s %d,%d ; %s", LOC(f->locale, parameters[P_REGION]), + nx, ny, rname(r, f->locale)); } rps_nowrap(F, buf); rnl(F); diff --git a/src/common/gamecode/study.c b/src/common/gamecode/study.c index 37fab76b2..0e890a0bf 100644 --- a/src/common/gamecode/study.c +++ b/src/common/gamecode/study.c @@ -265,7 +265,7 @@ int teach_cmd(unit * u, struct order * ord) { static const curse_type * gbdream_ct = NULL; - + plane * pl; region * r = u->region; int teaching, i, j, count, academy=0; unit *u2; @@ -285,7 +285,8 @@ teach_cmd(unit * u, struct order * ord) return 0; } - if (r->planep && fval(r->planep, PFL_NOTEACH)) { + pl = rplane(r); + if (pl && fval(pl, PFL_NOTEACH)) { cmistake(u, ord, 273, MSG_EVENT); return 0; } diff --git a/src/common/gamecode/xmlreport.c b/src/common/gamecode/xmlreport.c index 3a8b66b7a..7105b2fc2 100644 --- a/src/common/gamecode/xmlreport.c +++ b/src/common/gamecode/xmlreport.c @@ -592,15 +592,18 @@ xml_region(report_context * ctx, seen_region * sr) unit * u; ship * sh = r->ships; building * b = r->buildings; + plane * pl = rplane(r); + int nx = region_x(r, ctx->f), ny = region_y(r, ctx->f); + pnormalize(&nx, &ny, pl); /* TODO: entertain-quota, recruits, salary, prices, curses, borders, apparitions (Schemen), spells, travelthru, messages */ xmlNewNsProp(node, xct->ns_xml, XML_XML_ID, xml_ref_region(r)); child = xmlAddChild(node, xmlNewNode(xct->ns_atl, BAD_CAST "coordinate")); - xmlNewNsProp(child, xct->ns_atl, BAD_CAST "x", xml_i(region_x(r, ctx->f))); - xmlNewNsProp(child, xct->ns_atl, BAD_CAST "y", xml_i(region_y(r, ctx->f))); - if (r->planep) { - xmlNewNsProp(child, xct->ns_atl, BAD_CAST "plane", (xmlChar *)r->planep->name); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "x", xml_i(nx)); + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "y", xml_i(ny)); + if (pl && pl->name) { + xmlNewNsProp(child, xct->ns_atl, BAD_CAST "plane", (xmlChar *)pl->name); } child = xmlAddChild(node, xmlNewNode(xct->ns_atl, BAD_CAST "terrain")); diff --git a/src/common/kernel/alliance.c b/src/common/kernel/alliance.c index 8874bdfb1..296b55dd5 100644 --- a/src/common/kernel/alliance.c +++ b/src/common/kernel/alliance.c @@ -46,6 +46,18 @@ without prior permission by the authors of Eressea. alliance * alliances = NULL; +void +free_alliance(alliance * al) +{ + free(al->name); + while (al->members) { + faction_list * m = al->members; + al->members = m->next; + free(m); + } + free(al); +} + alliance * makealliance(int id, const char * name) { diff --git a/src/common/kernel/alliance.h b/src/common/kernel/alliance.h index 24a01387a..45928f6b2 100644 --- a/src/common/kernel/alliance.h +++ b/src/common/kernel/alliance.h @@ -48,6 +48,7 @@ extern alliance * findalliance(int id); extern alliance * makealliance(int id, const char * name); extern const char * alliancename(const struct alliance * al); extern void setalliance(struct faction * f, alliance * al); +void free_alliance(struct alliance * al); extern void alliance_cmd(void); diff --git a/src/common/kernel/battle.c b/src/common/kernel/battle.c index d045c3f4d..87fe4c550 100644 --- a/src/common/kernel/battle.c +++ b/src/common/kernel/battle.c @@ -3865,10 +3865,11 @@ join_allies(battle * b) } for (sa=s+1;sa!=b->sides+b->nsides;++sa) { + plane * pl = rplane(r); if (enemy(s, sa)) continue; if (friendly(s, sa)) continue; - if (!alliedgroup(r->planep, f, sa->faction, f->allies, HELP_FIGHT)) continue; - if (!alliedgroup(r->planep, sa->faction, f, sa->faction->allies, HELP_FIGHT)) continue; + if (!alliedgroup(pl, f, sa->faction, f->allies, HELP_FIGHT)) continue; + if (!alliedgroup(pl, sa->faction, f, sa->faction->allies, HELP_FIGHT)) continue; set_friendly(s, sa); } @@ -3961,8 +3962,9 @@ init_battle(region * r, battle **bp) unit *u2; fighter *c1, *c2; ship * lsh = NULL; + plane * pl = rplane(r); - if (r->planep && fval(r->planep, PFL_NOATTACK)) { + if (pl && fval(pl, PFL_NOATTACK)) { cmistake(u, ord, 271, MSG_BATTLE); continue; } diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c index e1971acd4..2dac71fee 100644 --- a/src/common/kernel/eressea.c +++ b/src/common/kernel/eressea.c @@ -91,9 +91,6 @@ #include #endif -int world_width = -1; -int world_height = -1; - /* exported variables */ region *regions; faction *factions; @@ -948,7 +945,7 @@ alliedunit(const unit * u, const faction * f2, int mode) assert(u->region); /* the unit should be in a region, but it's possible that u->number==0 (TEMP units) */ if (u->faction == f2) return mode; if (u->faction != NULL && f2!=NULL) { - plane * pl = u->region->planep; + plane * pl = rplane(u->region); automode = mode & autoalliance(pl, u->faction, f2); if (pl!=NULL && (pl->flags & PFL_NOALLIANCES)) @@ -1163,7 +1160,10 @@ update_lighthouse(building * lh) int y; for (y=-d;y<=d;++y) { attrib * a; - region * r2 = findregion(x+r->x, y+r->y); + region * r2; + int px = r->x+x, py = r->y+y; + pnormalize(&px, &py, rplane(r)); + r2 = findregion(px, py); if (r2==NULL) continue; if (!fval(r2->terrain, SEA_REGION)) continue; if (distance(r, r2) > d) continue; @@ -2475,6 +2475,7 @@ int lifestyle(const unit * u) { int need; + plane * pl; static int gamecookie = -1; if (gamecookie!=global.cookie) { gamecookie = global.cookie; @@ -2484,7 +2485,8 @@ lifestyle(const unit * u) need = maintenance_cost(u); - if(u->region->planep && fval(u->region->planep, PFL_NOFEED)) + pl = rplane(u->region); + if (pl && fval(pl, PFL_NOFEED)) return 0; #if KARMA_MODULE @@ -2935,8 +2937,6 @@ has_limited_skills (const struct unit * u) void attrib_init(void) { - world_width = get_param_int(global.parameters, "world.width", 0); - world_height = get_param_int(global.parameters, "world.height", 0); /* Alle speicherbaren Attribute müssen hier registriert werden */ at_register(&at_shiptrail); at_register(&at_familiar); @@ -3064,6 +3064,11 @@ free_gamedata(void) free_regions(); free_borders(); + while (alliances) { + alliance * al = alliances; + alliances = al->next; + free_alliance(al); + } while (factions) { faction * f = factions; factions = f->next; diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h index 5ba79d0d4..c489de11c 100644 --- a/src/common/kernel/eressea.h +++ b/src/common/kernel/eressea.h @@ -115,9 +115,6 @@ extern const char *parameters[MAXPARAMS]; #define want(option) (1<faction, tx, 0); int y = rel_to_abs(0, u->faction, ty, 1); - region *rt = findregion(x,y); + region *rt; + + pnormalize(&x, &y, rplane(u->region)); + rt = findregion(x,y); if (rt!=NULL) { spllprm * spobj = *spobjp = malloc(sizeof(spllprm)); @@ -2528,13 +2531,15 @@ cast_cmd(unit * u, order * ord) unit *familiar = NULL, *mage = u; const char * s; spell * sp; + plane * pl; spellparameter *args = NULL; if (LongHunger(u)) { cmistake(u, ord, 224, MSG_MAGIC); return 0; } - if (r->planep && fval(r->planep, PFL_NOMAGIC)) { + pl = rplane(r); + if (pl && fval(pl, PFL_NOMAGIC)) { cmistake(u, ord, 269, MSG_MAGIC); return 0; } @@ -2555,10 +2560,12 @@ cast_cmd(unit * u, order * ord) s = getstrtoken(); } if (findparam(s, u->faction->locale) == P_REGION) { - short t_x = (short)getint(); - short t_y = (short)getint(); - t_x = rel_to_abs(getplane(u->region),u->faction,t_x,0); - t_y = rel_to_abs(getplane(u->region),u->faction,t_y,1); + int t_x = getint(); + int t_y = getint(); + plane * pl = getplane(u->region); + t_x = rel_to_abs(pl, u->faction, t_x,0); + t_y = rel_to_abs(pl, u->faction, t_y,1); + pnormalize(&t_x, &t_y, pl); target_r = findregion(t_x, t_y); if (!target_r) { /* Fehler "Die Region konnte nicht verzaubert werden" */ diff --git a/src/common/kernel/move.c b/src/common/kernel/move.c index 747248678..83a764873 100644 --- a/src/common/kernel/move.c +++ b/src/common/kernel/move.c @@ -200,7 +200,7 @@ entrance_allowed(const struct unit * u, const struct region * r) #ifdef REGIONOWNERS faction * owner = region_get_owner(r); if (owner == NULL || u->faction == owner) return true; - if (alliedfaction(r->planep, owner, u->faction, HELP_TRAVEL)) return true; + if (alliedfaction(rplane(r), owner, u->faction, HELP_TRAVEL)) return true; return false; #else return true; diff --git a/src/common/kernel/plane.c b/src/common/kernel/plane.c index 856e70e05..ac5513344 100644 --- a/src/common/kernel/plane.c +++ b/src/common/kernel/plane.c @@ -1,7 +1,7 @@ /* vi: set ts=2: * - * - * Eressea PB(E)M host Copyright (C) 1998-2003 + * + * Eressea PB(E)M host Copyright (C) 1998-2003 * Christian Schlittchen (corwin@amber.kn-bremen.de) * Katja Zedel (katze@felidae.kn-bremen.de) * Henning Peters (faroul@beyond.kn-bremen.de) @@ -40,195 +40,239 @@ struct plane *planes; +int plane_width(const plane * pl) +{ + if (pl) { + return pl->maxx-pl->minx+1; + } + return 0; +} + +int plane_height(const plane * pl) +{ + if (pl) { + return pl->maxy-pl->miny+1; + } + return 0; +} + +static plane * home_plane = NULL; + +plane * +get_homeplane(void) +{ + return home_plane; +} + + plane * getplane(const region *r) { - if(r) - return r->planep; - - return NULL; + if (r) { + return r->_plane; + } + return get_homeplane(); } plane * getplanebyid(int id) { - plane *p; + plane *p; - for (p=planes; p; p=p->next) - if (p->id == id) - return p; - return NULL; + for (p=planes; p; p=p->next) { + if (p->id == id) { + return p; + } + } + return NULL; } plane * getplanebyname(const char * name) { - plane *p; + plane *p; - for (p=planes; p; p=p->next) - if (!strcmp(p->name, name)) - return p; - return NULL; + for (p=planes; p; p=p->next) + if (!strcmp(p->name, name)) + return p; + return NULL; } plane * findplane(int x, int y) { - plane *pl; + plane *pl; - for(pl=planes;pl;pl=pl->next) { - if(x >= pl->minx && x <= pl->maxx - && y >= pl->miny && y <= pl->maxy) { - return pl; - } - } - return NULL; + for(pl=planes;pl;pl=pl->next) { + if(x >= pl->minx && x <= pl->maxx + && y >= pl->miny && y <= pl->maxy) { + return pl; + } + } + return NULL; } int getplaneid(const region *r) { - if(r) { - plane * pl = getplane(r); - if (pl) return pl->id; + if(r) { + plane * pl = getplane(r); + if (pl) return pl->id; - for(pl=planes;pl;pl=pl->next) { - if(r->x >= pl->minx && r->x <= pl->maxx - && r->y >= pl->miny && r->y <= pl->maxy) { - return pl->id; - } - } - } - return 0; + for(pl=planes;pl;pl=pl->next) { + if(r->x >= pl->minx && r->x <= pl->maxx + && r->y >= pl->miny && r->y <= pl->maxy) { + return pl->id; + } + } + } + return 0; } static int ursprung_x(const faction *f, const plane *pl, const region * rdefault) { - ursprung *ur; - int id = 0; + ursprung *ur; + int id = 0; - if(!f) - return 0; + if(!f) + return 0; - if(pl) - id = pl->id; + if(pl) + id = pl->id; - for(ur = f->ursprung; ur; ur = ur->next) { - if(ur->id == id) - return ur->x; - } - if (!rdefault) return 0; - set_ursprung((faction*)f, id, rdefault->x - plane_center_x(pl), rdefault->y - plane_center_y(pl)); - return rdefault->x - plane_center_x(pl); + for(ur = f->ursprung; ur; ur = ur->next) { + if(ur->id == id) + return ur->x; + } + if (!rdefault) return 0; + set_ursprung((faction*)f, id, rdefault->x - plane_center_x(pl), rdefault->y - plane_center_y(pl)); + return rdefault->x - plane_center_x(pl); } static int ursprung_y(const faction *f, const plane *pl, const region * rdefault) { - ursprung *ur; - int id = 0; + ursprung *ur; + int id = 0; - if(!f) - return 0; + if(!f) + return 0; - if(pl) - id = pl->id; + if(pl) + id = pl->id; - for(ur = f->ursprung; ur; ur = ur->next) { - if(ur->id == id) - return ur->y; - } - if (!rdefault) return 0; - set_ursprung((faction*)f, id, rdefault->x - plane_center_x(pl), rdefault->y - plane_center_y(pl)); - return rdefault->y - plane_center_y(pl); + for(ur = f->ursprung; ur; ur = ur->next) { + if(ur->id == id) + return ur->y; + } + if (!rdefault) return 0; + set_ursprung((faction*)f, id, rdefault->x - plane_center_x(pl), rdefault->y - plane_center_y(pl)); + return rdefault->y - plane_center_y(pl); } int plane_center_x(const plane *pl) { - if(pl == NULL) - return 0; + if(pl == NULL) + return 0; - return(pl->minx + pl->maxx)/2; + return(pl->minx + pl->maxx)/2; } int plane_center_y(const plane *pl) { - if(pl == NULL) - return 0; + if(pl == NULL) + return 0; - return(pl->miny + pl->maxy)/2; + return(pl->miny + pl->maxy)/2; } int region_x(const region *r, const faction *f) { - plane *pl = r->planep; - return r->x - ursprung_x(f, pl, r) - plane_center_x(pl); + plane *pl = rplane(r); + int x = r->x - plane_center_x(pl); + if (f) { + int width = plane_width(pl); + int width_2 = width/2; + x -= ursprung_x(f, pl, r); + if (x>width_2) x -= width; + } + return x; } int region_y(const region *r, const faction *f) { - plane *pl = r->planep; - return r->y - plane_center_y(pl) - ursprung_y(f, pl, r); + plane *pl = rplane(r); + int y = r->y - plane_center_y(pl); + if (f) { + int height = plane_height(pl); + int height_2 = height/2; + y -= ursprung_y(f, pl, r); + if (y>height_2) y -= height; + } + return y; } void set_ursprung(faction *f, int id, int x, int y) { - ursprung *ur; - assert(f!=NULL); - for(ur=f->ursprung;ur;ur=ur->next) { - if (ur->id == id) { - ur->x = ur->x + x; - ur->y = ur->y + y; - return; - } - } + ursprung *ur; + assert(f!=NULL); + for(ur=f->ursprung;ur;ur=ur->next) { + if (ur->id == id) { + ur->x = ur->x + x; + ur->y = ur->y + y; + return; + } + } - ur = calloc(1, sizeof(ursprung)); - ur->id = id; - ur->x = x; - ur->y = y; + ur = calloc(1, sizeof(ursprung)); + ur->id = id; + ur->x = x; + ur->y = y; - addlist(&f->ursprung, ur); + addlist(&f->ursprung, ur); } plane * create_new_plane(int id, const char *name, int minx, int maxx, int miny, int maxy, int flags) { - plane *pl = getplanebyid(id); + plane *pl = getplanebyid(id); - if (pl) return pl; - pl = calloc(1, sizeof(plane)); + if (pl) return pl; + pl = calloc(1, sizeof(plane)); - pl->next = NULL; - pl->id = id; - pl->name = strdup(name); - pl->minx = minx; - pl->maxx = maxx; - pl->miny = miny; - pl->maxy = maxy; - pl->flags = flags; + pl->next = NULL; + pl->id = id; + if (name) pl->name = strdup(name); + pl->minx = minx; + pl->maxx = maxx; + pl->miny = miny; + pl->maxy = maxy; + pl->flags = flags; - addlist(&planes, pl); - return pl; + addlist(&planes, pl); + if (id==0) { + home_plane = pl; + } + return pl; } /* Umrechnung Relative-Absolute-Koordinaten */ int rel_to_abs(const struct plane *pl, const struct faction * f, int rel, unsigned char index) { - assert(index == 0 || index == 1); + assert(index == 0 || index == 1); - if(index == 0) - return (rel + ursprung_x(f, pl, NULL) + plane_center_x(pl)); + if(index == 0) + return (rel + ursprung_x(f, pl, NULL) + plane_center_x(pl)); - return (rel + ursprung_y(f, pl, NULL) + plane_center_y(pl)); + return (rel + ursprung_y(f, pl, NULL) + plane_center_y(pl)); } @@ -269,9 +313,9 @@ read_plane_reference(plane ** pp, struct storage * store) boolean is_watcher(const struct plane * p, const struct faction * f) { - struct watcher * w; - if (!p) return false; - w = p->watchers; - while (w && w->faction!=f) w=w->next; - return (w!=NULL); + struct watcher * w; + if (!p) return false; + w = p->watchers; + while (w && w->faction!=f) w=w->next; + return (w!=NULL); } diff --git a/src/common/kernel/plane.h b/src/common/kernel/plane.h index f931b3284..417b67b01 100644 --- a/src/common/kernel/plane.h +++ b/src/common/kernel/plane.h @@ -1,6 +1,6 @@ /* vi: set ts=2: * - * Eressea PB(E)M host Copyright (C) 1998-2003 + * Eressea PB(E)M host Copyright (C) 1998-2003 * Christian Schlittchen (corwin@amber.kn-bremen.de) * Katja Zedel (katze@felidae.kn-bremen.de) * Henning Peters (faroul@beyond.kn-bremen.de) @@ -42,21 +42,23 @@ extern "C" { #define PFL_SEESPECIAL 32768 /* far seeing */ typedef struct watcher { - struct watcher * next; - struct faction * faction; - unsigned char mode; + struct watcher * next; + struct faction * faction; + unsigned char mode; } watcher; typedef struct plane { - struct plane *next; - struct watcher * watchers; - int id; - char *name; - int minx, maxx, miny, maxy; - unsigned int flags; - struct attrib *attribs; + struct plane *next; + struct watcher * watchers; + int id; + char *name; + int minx, maxx, miny, maxy; + unsigned int flags; + struct attrib *attribs; } plane; +#define plane_id(pl) ( (pl) ? (pl)->id : 0 ) + extern struct plane *planes; struct plane *getplane(const struct region *r); @@ -69,14 +71,16 @@ int region_y(const struct region *r, const struct faction *f); int plane_center_x(const struct plane *pl); int plane_center_y(const struct plane *pl); void set_ursprung(struct faction *f, int id, int x, int y); -plane * create_new_plane(int id, const char *name, int minx, int maxx, int miny, int maxy, int flags); -plane * getplanebyname(const char *); +struct plane * create_new_plane(int id, const char *name, int minx, int maxx, int miny, int maxy, int flags); +struct plane * getplanebyname(const char *); +struct plane * get_homeplane(void); extern int rel_to_abs(const struct plane *pl, const struct faction * f, int rel, unsigned char index); extern boolean is_watcher(const struct plane * p, const struct faction * f); extern int resolve_plane(variant data, void * addr); extern void write_plane_reference(const plane * p, struct storage * store); extern int read_plane_reference(plane ** pp, struct storage * store); - +extern int plane_width(const plane * pl); +extern int plane_height(const plane * pl); #ifdef __cplusplus } #endif diff --git a/src/common/kernel/region.c b/src/common/kernel/region.c index 3935598e4..efaecfceb 100644 --- a/src/common/kernel/region.c +++ b/src/common/kernel/region.c @@ -116,8 +116,9 @@ write_regionname(const region * r, const faction * f, char * buffer, size_t size if (r==NULL) { strcpy(buf, "(null)"); } else { - snprintf(buf, size, "%s (%d,%d)", rname(r, lang), - region_x(r, f), region_y(r, f)); + plane * pl = rplane(r); + int nx = region_x(r, f), ny = region_y(r, f); + snprintf(buf, size, "%s (%d,%d)", rname(r, lang), nx, ny); } buf[size-1] = 0; return buffer; @@ -357,7 +358,7 @@ int a_readmoveblock(attrib *a, storage * store) { moveblock *m = (moveblock *)(a->data.v); - int i; + int i; i = store->r_int(store); m->dir = (direction_t)i; @@ -375,7 +376,6 @@ attrib_type at_moveblock = { "moveblock", a_initmoveblock, NULL, NULL, a_writemoveblock, a_readmoveblock }; - #define coor_hashkey(x, y) (unsigned int)((x<<16) + y) #define RMAXHASH MAXREGIONS static region * regionhash[RMAXHASH]; @@ -433,26 +433,31 @@ static int hash_requests; static int hash_misses; #endif -void cnormalize(int * x, int * y) +boolean pnormalize(int * x, int * y, const plane * pl) { - if (world_width && x) { - if (*x<0) { - *x = world_width - abs(*x) % world_width; + if (pl) { + if (x) { + int width = pl->maxx - pl->minx + 1; + int nx = *x - pl->minx; + nx = (nx>0)?nx:(width-(-nx)%width); + *x = nx % width+ pl->minx; } - *x = *x % world_width; - } - if (world_height && y) { - if (*y<0) { - *y = world_height - abs(*y) % world_height; + if (y) { + int height = pl->maxy - pl->miny + 1; + int ny = *y - pl->miny; + ny = (ny>0)?ny:(height-(-ny)%height); + *y = ny % height + pl->miny; } - *y = *y % world_height; } + return false; /* TBD */ } static region * rfindhash(int x, int y) { - unsigned int rid = coor_hashkey(x, y); + unsigned int rid; + + rid = coor_hashkey(x, y); #if HASH_STATISTICS ++hash_requests; #endif @@ -509,13 +514,17 @@ region * r_connect(const region * r, direction_t dir) { region * result; + int x, y; #ifdef FAST_CONNECT region * rmodify = (region*)r; assert (dir>=0 && dirconnect[dir]) return r->connect[dir]; #endif assert(dirx + delta_x[dir], r->y + delta_y[dir]); + 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; @@ -531,20 +540,19 @@ findregion(int x, int y) return rfindhash(x, y); } -int -koor_distance(int x1, int y1, int x2, int y2) +/* Contributed by Hubert Mackenberg. Thanks. + * x und y Abstand zwischen x1 und x2 berechnen + */ +static int +koor_distance_orig(int x1, int y1, int x2, int y2) { - /* Contributed by Hubert Mackenberg. Thanks. - * x und y Abstand zwischen x1 und x2 berechnen - */ int dx = x1 - x2; int dy = y1 - y2; /* Bei negativem dy am Ursprung spiegeln, das veraendert * den Abstand nicht */ - if ( dy < 0 ) - { + if ( dy < 0 ) { dy = -dy; dx = -dx; } @@ -552,9 +560,71 @@ koor_distance(int x1, int y1, int x2, int y2) /* * dy ist jetzt >=0, fuer dx sind 3 Faelle zu untescheiden */ - if ( dx >= 0 ) return dx + dy; - else if (-dx >= dy) return -dx; - else return dy; + if ( dx >= 0 ) { + int result = dx + dy; + return result; + } + else if (-dx >= dy) { + int result = -dx; + return result; + } + else { + return dy; + } +} + +static int +koor_distance_wrap_xy(int x1, int y1, int x2, int y2, int width, int height) +{ + int dx = x1 - x2; + int dy = y1 - y2; + int result, dist; + int mindist = MIN(width, height) >> 1; + + /* Bei negativem dy am Ursprung spiegeln, das veraendert + * den Abstand nicht + */ + if ( dy < 0 ) { + dy = -dy; + dx = -dx; + } + if (dx<0) { + dx = width + dx; + } + /* dx,dy is now pointing northeast */ + result = dx + dy; + if (result<=mindist) return result; + + dist = (width-dx) + (height-dy); /* southwest */ + if (dist>=0 && dist=0 && dist=0 && distx, from->y, to->x, to->y); + plane * pl = rplane(from); + if (pl == rplane(to)) { + direction_t dir = koor_reldirection(from->x, from->y, to->x, to->y, pl); - if (dir==NODIRECTION) { - spec_direction *sd = special_direction(from, to); - if (sd!=NULL && sd->active) return D_SPECIAL; + if (dir==NODIRECTION) { + spec_direction *sd = special_direction(from, to); + if (sd!=NULL && sd->active) return D_SPECIAL; + } + return dir; } - return dir; + return NODIRECTION; } void @@ -856,9 +933,12 @@ static region *last; static unsigned int max_index = 0; region * -new_region(int x, int y, unsigned int uid) +new_region(int x, int y, struct plane * pl, unsigned int uid) { - region *r = rfindhash(x, y); + 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)); @@ -871,7 +951,7 @@ new_region(int x, int y, unsigned int uid) r->y = y; r->uid = uid; r->age = 1; - r->planep = findplane(x, y); + r->_plane = pl; rhash(r); hash_uid(r); if (last) diff --git a/src/common/kernel/region.h b/src/common/kernel/region.h index 8d7f8eed8..08d4502a3 100644 --- a/src/common/kernel/region.h +++ b/src/common/kernel/region.h @@ -113,7 +113,7 @@ typedef struct region { and lastregion */ unsigned int uid; /* a unique id */ int x, y; - struct plane *planep; + struct plane * _plane; /* to access, use rplane(r) */ char *display; unsigned int flags; unsigned short age; @@ -229,9 +229,10 @@ int r_demand(const struct region * r, const struct luxury_type * ltype); const char * write_regionname(const struct region * r, const struct faction * f, char * buffer, size_t size); -struct region * new_region(int x, int y, unsigned int uid); +struct region * new_region(int x, int y, struct plane * pl, unsigned int uid); void remove_region(region ** rlist, region * r); void terraform_region(struct region * r, const struct terrain_type * terrain); +boolean pnormalize(int * x, int * y, const struct plane * pl); extern const int delta_x[MAXDIRECTIONS]; extern const int delta_y[MAXDIRECTIONS]; diff --git a/src/common/kernel/reports.c b/src/common/kernel/reports.c index e71ac7022..7ed45a221 100644 --- a/src/common/kernel/reports.c +++ b/src/common/kernel/reports.c @@ -747,7 +747,7 @@ bufunit(const faction * f, const unit * u, int indent, int mode, char * buf, siz dh=0; if (!getarnt && f) { - if (alliedfaction(u->region->planep, f, fv, HELP_ALL)) { + if (alliedfaction(rplane(u->region), f, fv, HELP_ALL)) { dh = 1; } } @@ -1275,7 +1275,7 @@ prepare_reports(void) for (r = regions; r ; r = r->next) { attrib *ru; unit * u; - plane * p = r->planep; + plane * p = rplane(r); reorder_units(r); @@ -1351,7 +1351,7 @@ prepare_report(faction * f) for (;sr!=NULL;sr=sr->next) { if (sr->mode>see_neighbour) { region * r = sr->r; - plane * p = r->planep; + plane * p = rplane(r); void (*view)(struct seen_region **, region *, faction *) = view_default; if (p && fval(p, PFL_SEESPECIAL)) { @@ -1624,14 +1624,15 @@ trailinto(const region * r, const struct locale * lang) size_t f_regionid(const region * r, const faction * f, char * buffer, size_t size) { - if (!r) { strncpy(buffer, "(Chaos)", size); } else { - plane * pl = r->planep; + plane * pl = rplane(r); + const char * name = pl?pl->name:0; + int nx = region_x(r, f), ny = region_y(r, f); strncpy(buffer, rname(r, f->locale), size); buffer[size-1]=0; - sprintf(buffer+strlen(buffer), " (%d,%d%s%s)", region_x(r,f), region_y(r,f), pl?",":"", pl?pl->name:""); + sprintf(buffer+strlen(buffer), " (%d,%d%s%s)", nx, ny, name?",":"", (name)?name:""); } return strlen(buffer); } diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c index 8a72d542a..9e38dbf61 100644 --- a/src/common/kernel/save.c +++ b/src/common/kernel/save.c @@ -895,7 +895,8 @@ readregion(struct storage * store, int x, int y) } if (r==NULL) { - r = new_region(x, y, uid); + plane * pl = findplane(x, y); + r = new_region(x, y, pl, uid); } else { assert(uid==0 || r->uid==uid); current_region = r; diff --git a/src/common/kernel/teleport.c b/src/common/kernel/teleport.c index a8262c813..9f10ac87a 100644 --- a/src/common/kernel/teleport.c +++ b/src/common/kernel/teleport.c @@ -80,9 +80,11 @@ astralregions(const region * r, boolean (*valid)(const region *)) for (y=-TP_RADIUS;y<=+TP_RADIUS;++y) { region * rn; int dist = koor_distance(0, 0, x, y); + int nx = r->x+x, ny = r->y+y; if (dist > TP_RADIUS) continue; - rn = findregion(r->x+x, r->y+y); + pnormalize(&nx, &ny, rplane(r)); + rn = findregion(nx, ny); if (rn!=NULL && (valid==NULL || valid(rn))) add_regionlist(&rlist, rn); } } @@ -105,8 +107,8 @@ r_astral_to_standard(const region *r) assert(is_astral(r)); x = (r->x-TE_CENTER_X)*TP_DISTANCE; y = (r->y-TE_CENTER_Y)*TP_DISTANCE; - - r2 = findregion(x,y); + pnormalize(&x, &y, rplane(r)); + r2 = findregion(x, y); if (r2==NULL || rplane(r2)!=get_normalplane()) return NULL; return r2; @@ -117,13 +119,17 @@ all_in_range(const region *r, int n, boolean (*valid)(const region *)) { int x, y; region_list *rlist = NULL; + plane * pl = rplane(r); if (r == NULL) return NULL; for (x = r->x-n; x <= r->x+n; x++) { for (y = r->y-n; y <= r->y+n; y++) { if (koor_distance(r->x, r->y, x, y) <= n) { - region * r2 = findregion(x, y); + region * r2; + int nx = x, ny = y; + pnormalize(&nx, &ny, pl); + r2 = findregion(nx, ny); if (r2!=NULL && (valid==NULL || valid(r2))) add_regionlist(&rlist, r2); } } @@ -196,24 +202,23 @@ void create_teleport_plane(void) { region *r; + plane * hplane = get_homeplane(); plane * aplane = get_astralplane(); const terrain_type * fog = get_terrain("fog"); for (r=regions;r;r=r->next) { - if (r->planep == NULL) { + plane * pl = rplane(r); + if (pl == hplane) { region *ra = tpregion(r); if (ra==NULL) { int x = TE_CENTER_X+real2tp(r->x); int y = TE_CENTER_Y+real2tp(r->y); - plane * pl = findplane(x, y); + pnormalize(&x, &y, aplane); - if (aplane && pl==aplane) { - ra = new_region(x, y, 0); - terraform_region(ra, fog); - ra->planep = aplane; - } + ra = new_region(x, y, aplane, 0); + terraform_region(ra, fog); } } } diff --git a/src/common/kernel/unit.c b/src/common/kernel/unit.c index 44ae378b4..6f199b7d7 100644 --- a/src/common/kernel/unit.c +++ b/src/common/kernel/unit.c @@ -1243,9 +1243,12 @@ get_modifier(const unit *u, skill_t sk, int level, const region *r, boolean noit int bskill = level; int skill = bskill; - if (r->planep && sk == SK_STEALTH && fval(r->planep, PFL_NOSTEALTH)) return 0; - assert(r); + if (sk == SK_STEALTH) { + plane * pl = rplane(r); + if (pl &&fval(pl, PFL_NOSTEALTH)) return 0; + } + skill += rc_skillmod(u->race, r, sk); skill += att_modification(u, sk); diff --git a/src/common/modules/autoseed.c b/src/common/modules/autoseed.c index 29b7ca151..091aaa903 100644 --- a/src/common/modules/autoseed.c +++ b/src/common/modules/autoseed.c @@ -423,17 +423,22 @@ free_newfaction(newfaction * nf) 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->ageplanep) 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) { - rn = new_region(r->x+delta_x[d], r->y+delta_y[d], 0); + 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; } @@ -513,12 +518,13 @@ autoseed(newfaction ** players, int nsize, int max_agediff) 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 * p = r->planep; - if (r->age<=max_agediff && r->terrain == newterrain(T_OCEAN) && p==NULL && virgin_region(r)) { + 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); @@ -559,13 +565,14 @@ autoseed(newfaction ** players, int nsize, int max_agediff) 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 * p = r->planep; - if (r->terrain == newterrain(T_OCEAN) && p==0 && (rmin==NULL || r->age<=max_agediff)) { + 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); @@ -582,10 +589,12 @@ autoseed(newfaction ** players, int nsize, int max_agediff) * 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))); - x = rmin->x + delta_x[dmin]; - y = rmin->y + delta_y[dmin]; - r = new_region(x, y, 0); + r = new_region(x, y, pl, 0); terraform_region(r, newterrain(T_OCEAN)); } } @@ -611,7 +620,11 @@ autoseed(newfaction ** players, int nsize, int max_agediff) region * rn = rconnect(r, d); if (rn && fval(rn, RF_MARK)) continue; if (rn==NULL) { - rn = new_region(r->x + delta_x[d], r->y + delta_y[d], 0); + 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)) { @@ -691,7 +704,11 @@ autoseed(newfaction ** players, int nsize, int max_agediff) region * rn = rconnect(r, d); if (rn==NULL) { const struct terrain_type * terrain = newterrain(T_OCEAN); - rn = new_region(r->x + delta_x[d], r->y + delta_y[d], 0); + 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 */ @@ -709,18 +726,26 @@ autoseed(newfaction ** players, int nsize, int max_agediff) } 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) { - if (findregion(r->x + i*delta_x[d], r->y + i*delta_y[d])) + 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 = new_region(r->x + i*delta_x[d], r->y + i*delta_y[d], 0); + 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)); } } @@ -808,7 +833,11 @@ random_neighbours(region * r, region_list ** rlist, const terrain_type *(*terraf region * rn = rconnect(r, dir); if (rn==NULL) { const terrain_type * terrain = terraformer(dir); - rn = new_region(r->x+delta_x[dir], r->y+delta_y[dir], 0); + 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) { @@ -847,7 +876,11 @@ oceans_around(region * r, region * rn[]) for (n=0;n!=MAXDIRECTIONS;++n) { region * rx = rn[n]; if (rx==NULL) { - rx = new_region(r->x+delta_x[n], r->y+delta_y[n], 0); + 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; } @@ -874,6 +907,7 @@ smooth_island(region_list * island) if (nland==1) { get_neighbours(r, rn); + oceans_around(r, rn); for (n=0;n!=MAXDIRECTIONS;++n) { int n1 = (n+1)%MAXDIRECTIONS; int n2 = (n+1+MAXDIRECTIONS)%MAXDIRECTIONS; @@ -920,7 +954,8 @@ build_island_e3(int x, int y, int numfactions, int minsize) int nfactions = 0; region_list * rlist = NULL; region_list * island = NULL; - region * r = new_region(x, y, 0); + plane * pl = findplane(x, y); + region * r = new_region(x, y, pl, 0); int nsize = 1; int q, maxq = INT_MIN, minq = INT_MAX; @@ -943,33 +978,35 @@ build_island_e3(int x, int y, int numfactions, int minsize) smooth_island(island); - for (rlist=island;rlist;rlist=rlist->next) { - r = rlist->data; - if (r->land && fval(r, RF_MARK)) { - region *rn[MAXDIRECTIONS]; + if (nsize>minsize/2) { + for (rlist=island;rlist;rlist=rlist->next) { + r = rlist->data; + if (r->land && fval(r, RF_MARK)) { + region *rn[MAXDIRECTIONS]; - get_neighbours(r, rn); - q = region_quality(r,rn); - if (q>=MIN_QUALITY && nfactions=MIN_QUALITY && nfactionsnext) { - r = rlist->data; - if (!r->land && fval(r, RF_MARK)) { - region *rn[MAXDIRECTIONS]; - get_neighbours(r, rn); - q = region_quality(r, rn); - if (q>=MIN_QUALITY*4/3 && nfactionsnext) { + r = rlist->data; + if (!r->land && fval(r, RF_MARK)) { + region *rn[MAXDIRECTIONS]; + get_neighbours(r, rn); + q = region_quality(r, rn); + if (q>=MIN_QUALITY*4/3 && nfactionsregion); + const struct plane * pl = rplane(u->region); int id = getid(); - int x = rel_to_abs(p, u->faction, getint(), 0); - int y = rel_to_abs(p, u->faction, getint(), 1); - region * r = findregion(x, y); + int x = rel_to_abs(pl, u->faction, getint(), 0); + int y = rel_to_abs(pl, u->faction, getint(), 1); building * b = findbuilding(id); - if (b==NULL || r==NULL || p!=rplane(b->region) || p!=rplane(r)) { + 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 { @@ -211,9 +214,11 @@ gm_terraform(const tnode * tnext, void * data, struct order * ord) int x = rel_to_abs(p, u->faction, getint(), 0); int y = rel_to_abs(p, u->faction, getint(), 1); const char * c = getstrtoken(); - region * r = findregion(x, y); variant token; tnode * 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."); @@ -613,7 +618,7 @@ gmcommands(void) faction * gm_addquest(const char * email, const char * name, int radius, unsigned int flags) { - plane * p; + plane * pl; watcher * w = calloc(sizeof(watcher), 1); region * center; boolean invalid = false; @@ -635,15 +640,16 @@ gm_addquest(const char * email, const char * name, int radius, unsigned int flag } while (invalid); maxx = minx+2*radius; cx = minx+radius; maxy = miny+2*radius; cy = miny+radius; - p = create_new_plane(rng_int(), name, minx, maxx, miny, maxy, flags); - center = new_region(cx, cy, 0); + pl = create_new_plane(rng_int(), name, minx, maxx, miny, maxy, flags); + center = new_region(cx, cy, pl, 0); for (x=0;x<=2*radius;++x) { int y; for (y=0;y<=2*radius;++y) { region * r = findregion(minx+x, miny+y); - if (!r) r = new_region(minx+x, miny+y, 0); + if (!r) { + r = new_region(minx+x, miny+y, pl, 0); + } freset(r, RF_ENCOUNTER); - r->planep = p; if (distance(r, center)==radius) { terraform_region(r, newterrain(T_FIREWALL)); } else if (r==center) { @@ -655,11 +661,11 @@ gm_addquest(const char * email, const char * name, int radius, unsigned int flag } /* watcher: */ - f = gm_addfaction(email, p, center); + f = gm_addfaction(email, pl, center); w->faction = f; w->mode = see_unit; - w->next = p->watchers; - p->watchers = w; + w->next = pl->watchers; + pl->watchers = w; return f; } @@ -726,7 +732,7 @@ plane * gm_addplane(int radius, unsigned int flags, const char * name) { region * center; - plane * p; + plane * pl; boolean invalid = false; int minx, miny, maxx, maxy, cx, cy; int x; @@ -745,15 +751,14 @@ gm_addplane(int radius, unsigned int flags, const char * name) } while (invalid); maxx = minx+2*radius; cx = minx+radius; maxy = miny+2*radius; cy = miny+radius; - p = create_new_plane(rng_int(), name, minx, maxx, miny, maxy, flags); - center = new_region(cx, cy, 0); + pl = create_new_plane(rng_int(), name, minx, maxx, miny, maxy, flags); + center = new_region(cx, cy, pl, 0); for (x=0;x<=2*radius;++x) { int y; for (y=0;y<=2*radius;++y) { region * r = findregion(minx+x, miny+y); - if (!r) r = new_region(minx+x, miny+y, 0); + if (!r) r = new_region(minx+x, miny+y, pl, 0); freset(r, RF_ENCOUNTER); - r->planep = p; if (distance(r, center)==radius) { terraform_region(r, newterrain(T_FIREWALL)); } else if (r==center) { @@ -763,5 +768,5 @@ gm_addplane(int radius, unsigned int flags, const char * name) } } } - return p; + return pl; } diff --git a/src/common/modules/museum.c b/src/common/modules/museum.c index c5d1d4d53..f494fc5b0 100644 --- a/src/common/modules/museum.c +++ b/src/common/modules/museum.c @@ -345,11 +345,12 @@ use_museumticket(unit *u, const struct item_type *itype, int amount, order * ord { attrib *a; region *r = u->region; + plane * pl = rplane(r); unused(amount); /* Prüfen ob in normaler Plane und nur eine Person */ - if(r->planep != NULL) { + if (pl != get_homeplane()) { cmistake(u, ord, 265, MSG_MAGIC); return 0; } diff --git a/src/eressea/editing.c b/src/eressea/editing.c index a287605e0..49365fdf8 100644 --- a/src/eressea/editing.c +++ b/src/eressea/editing.c @@ -39,14 +39,17 @@ make_block(int x, int y, int radius, const struct terrain_type * terrain) { int cx, cy; region *r; + plane * pl = findplane(x, y); if (terrain==NULL) return; for (cx = x - radius; cx != x+radius; ++cx) { for (cy = y - radius; cy != y+radius; ++cy) { - if (koor_distance(cx, cy, x, y) < radius) { - if (!findregion(cx, cy)) { - r = new_region(cx, cy, 0); + int nx = cx, ny = cy; + pnormalize(&nx, &ny, pl); + if (koor_distance(nx, ny, x, y) < radius) { + if (!findregion(nx, ny)) { + r = new_region(nx, ny, pl, 0); terraform_region(r, terrain); } } diff --git a/src/eressea/gmtool.c b/src/eressea/gmtool.c index a6aacb8c4..73d6ebb46 100644 --- a/src/eressea/gmtool.c +++ b/src/eressea/gmtool.c @@ -134,6 +134,13 @@ init_curses(void) refresh(); } +void cnormalize(const coordinate * c, int * x, int * y) +{ + *x = c->x; + *y = c->y; + pnormalize(x, y, c->pl); +} + map_region * mr_get(const view * vi, int xofs, int yofs) { @@ -168,14 +175,14 @@ win_create(WINDOW * hwin) } static void -untag_region(selection * s, const coordinate * c) +untag_region(selection * s, int nx, int ny) { - unsigned int key = ((c->x << 12) ^ c->y); + unsigned int key = ((nx << 12) ^ ny); tag ** tp = &s->tags[key & (MAXTHASH-1)]; tag * t = NULL; while (*tp) { t = *tp; - if (t->coord.p==c->p && t->coord.x==c->x && t->coord.y==c->y) break; + if (t->coord.x==nx && t->coord.y==ny) break; tp=&t->nexthash; } if (!*tp) return; @@ -185,28 +192,30 @@ untag_region(selection * s, const coordinate * c) } static void -tag_region(selection * s, const coordinate * c) +tag_region(selection * s, int nx, int ny) { - unsigned int key = ((c->x << 12) ^ c->y); + unsigned int key = ((nx << 12) ^ ny); tag ** tp = &s->tags[key & (MAXTHASH-1)]; while (*tp) { tag * t = *tp; - if (t->coord.p==c->p && t->coord.x==c->x && t->coord.y==c->y) return; + if (t->coord.x==nx && t->coord.y==ny) return; tp=&t->nexthash; } *tp = calloc(1, sizeof(tag)); - (*tp)->coord = *c; + (*tp)->coord.x = nx; + (*tp)->coord.y = ny; + (*tp)->coord.pl = findplane(nx, ny); return; } static int -tagged_region(selection * s, const coordinate * c) +tagged_region(selection * s, int nx, int ny) { - unsigned int key = ((c->x << 12) ^ c->y); + unsigned int key = ((nx << 12) ^ ny); tag ** tp = &s->tags[key & (MAXTHASH-1)]; while (*tp) { tag * t = *tp; - if (t->coord.x==c->x && t->coord.p==c->p && t->coord.y==c->y) return 1; + if (t->coord.x==nx && t->coord.y==ny) return 1; tp=&t->nexthash; } return 0; @@ -254,22 +263,25 @@ paint_map(window * wnd, const state * st) WINDOW * win = wnd->handle; int lines = getmaxy(win); int cols = getmaxx(win); - int x, y; + int vx, vy; lines = lines/THEIGHT; cols = cols/TWIDTH; - for (y = 0; y!=lines; ++y) { - int yp = (lines - y - 1) * THEIGHT; - for (x = 0; x!=cols; ++x) { + for (vy = 0; vy!=lines; ++vy) { + int yp = (lines - vy - 1) * THEIGHT; + for (vx = 0; vx!=cols; ++vx) { + map_region * mr = mr_get(&st->display, vx, vy); int attr = 0; int hl = 0; - int xp = x * TWIDTH + (y & 1) * TWIDTH/2; - map_region * mr = mr_get(&st->display, x, y); - - if (mr && st && tagged_region(st->selected, &mr->coord)) { - attr |= A_REVERSE; - } + int xp = vx * TWIDTH + (vy & 1) * TWIDTH/2; + int nx, ny; if (mr) { + if (st) { + cnormalize(&mr->coord, &nx, &ny); + if (tagged_region(st->selected, nx, ny)) { + attr |= A_REVERSE; + } + } if (mr->r && mr->r->flags & RF_MAPPER_HIGHLIGHT) hl = 1; mvwaddch(win, yp, xp, mr_tile(mr, hl) | attr); } @@ -297,7 +309,7 @@ static void draw_cursor(WINDOW * win, selection * s, const view * v, const coordinate * c, int show) { int lines = getmaxy(win)/THEIGHT; - int xp, yp; + int xp, yp, nx, ny; int attr = 0; map_region * mr = cursor_region(v, c); coordinate relpos; @@ -312,7 +324,8 @@ draw_cursor(WINDOW * win, selection * s, const view * v, const coordinate * c, i yp = (lines - cy - 1) * THEIGHT; xp = cx * TWIDTH + (cy & 1) * TWIDTH/2; - if (s && tagged_region(s, &mr->coord)) attr = A_REVERSE; + cnormalize(&mr->coord, &nx, &ny); + if (s && tagged_region(s, nx, ny)) attr = A_REVERSE; if (mr->r) { int hl = 0; if (mr->r->flags & RF_MAPPER_HIGHLIGHT) hl = 1; @@ -339,7 +352,7 @@ paint_status(window * wnd, const state * st) { WINDOW * win = wnd->handle; const char * name = ""; - int uid = 0; + int nx, ny, uid = 0; const char * terrain = "----"; map_region * mr = cursor_region(&st->display, &st->cursor); if (mr && mr->r) { @@ -351,7 +364,8 @@ paint_status(window * wnd, const state * st) } terrain = mr->r->terrain->_name; } - mvwprintw(win, 0, 0, "%4d %4d | %.4s | %.20s (%d)", st->cursor.x, st->cursor.y, terrain, name, uid); + cnormalize(&st->cursor, &nx, &ny); + mvwprintw(win, 0, 0, "%4d %4d | %.4s | %.20s (%d)", nx, ny, terrain, name, uid); wclrtoeol(win); } @@ -449,9 +463,13 @@ static void terraform_at(coordinate * c, const terrain_type *terrain) { if (terrain!=NULL) { - int x = c->x, y = c->y; - region * r = findregion(x, y); - if (r==NULL) r = new_region(x, y, 0); + region * r; + int nx = c->x, ny = c->y; + pnormalize(&nx, &ny, c->pl); + r = findregion(nx, ny); + if (r==NULL) { + r = new_region(nx, ny, c->pl, 0); + } terraform_region(r, terrain); } } @@ -465,10 +483,16 @@ terraform_selection(selection * selected, const terrain_type *terrain) for (i=0;i!=MAXTHASH;++i) { tag ** tp = &selected->tags[i]; while (*tp) { + region * r; tag * t = *tp; - int x = t->coord.x, y = t->coord.y; - region * r = findregion(x, y); - if (r==NULL) r = new_region(x, y, 0); + int nx = t->coord.x, ny = t->coord.y; + plane * pl = t->coord.pl; + + pnormalize(&nx, &ny, pl); + r = findregion(nx, ny); + if (r==NULL) { + r = new_region(nx, ny, pl, 0); + } terraform_region(r, terrain); tp = &t->nexthash; } @@ -530,7 +554,7 @@ region2coord(const region * r, coordinate * c) { c->x = r->x; c->y = r->y; - c->p = r->planep?r->planep->id:0; + c->pl = rplane(r); return c; } @@ -556,13 +580,10 @@ highlight_region(region *r, int toggle) } void -select_coordinate(struct selection * selected, int x, int y, int toggle) +select_coordinate(struct selection * selected, int nx, int ny, int toggle) { - coordinate coord = { 0 }; - coord.x = x; - coord.y = y; - if (toggle) tag_region(selected, &coord); - else untag_region(selected, &coord); + if (toggle) tag_region(selected, nx, ny); + else untag_region(selected, nx, ny); } enum { MODE_MARK, MODE_SELECT, MODE_UNMARK, MODE_UNSELECT }; @@ -729,7 +750,7 @@ handlekey(state * st, int c) region *r; char sbuffer[80]; static char kbuffer[80]; - int n; + int n, nx, ny; switch(c) { case FAST_RIGHT: @@ -791,15 +812,17 @@ handlekey(state * st, int c) /* make_block(st->cursor.x, st->cursor.y, 6, select_terrain(st, NULL)); */ + cnormalize(&st->cursor, &nx, &ny); n = rng_int() % 8 + 8; - build_island_e3(st->cursor.x, st->cursor.y, n, n*3); + build_island_e3(nx, ny, n, n*3); st->modified = 1; st->wnd_info->update |= 1; st->wnd_status->update |= 1; st->wnd_map->update |= 1; break; case 0x02: /* CTRL+b */ - make_block(st->cursor.x, st->cursor.y, 6, newterrain(T_OCEAN)); + cnormalize(&st->cursor, &nx, &ny); + make_block(nx, ny, 6, newterrain(T_OCEAN)); st->modified = 1; st->wnd_info->update |= 1; st->wnd_status->update |= 1; @@ -811,10 +834,12 @@ handlekey(state * st, int c) if (mr) { region * first = mr->r; region * cur = (first&&first->next)?first->next:regions; + while (cur!=first) { coordinate coord; region2coord(cur, &coord); - if (tagged_region(st->selected, &coord)) { + cnormalize(&coord, &nx, &ny); + if (tagged_region(st->selected, nx, ny)) { st->cursor = coord; st->wnd_info->update |= 1; st->wnd_status->update |= 1; @@ -827,12 +852,31 @@ handlekey(state * st, int c) } break; + case 'p': + if (planes) { + plane * pl = planes; + if (cursor->pl) { + while (pl && pl!=cursor->pl) { + pl = pl->next; + } + if (pl->next) { + cursor->pl = pl->next; + } else { + cursor->pl = get_homeplane(); + } + } else { + cursor->pl = planes; + } + } + break; + case 'a': if (regions!=NULL) { map_region * mr = cursor_region(&st->display, cursor); if (mr && mr->r) { region * cur = mr->r; - if (cur->planep==NULL) { + plane * pl = rplane(cur); + if (pl==NULL) { cur = r_standard_to_astral(cur); } else if (is_astral(cur)) { cur = r_astral_to_standard(cur); @@ -948,8 +992,9 @@ handlekey(state * st, int c) } break; case ' ': - if (tagged_region(st->selected, cursor)) untag_region(st->selected, cursor); - else tag_region(st->selected, cursor); + cnormalize(cursor, &nx, &ny); + if (tagged_region(st->selected, nx, ny)) untag_region(st->selected, nx, ny); + else tag_region(st->selected, nx, ny); break; case 'A': sprintf(sbuffer, "%s/newfactions", basepath()); @@ -1055,8 +1100,8 @@ init_view(view * display, WINDOW * win) { display->topleft.x = 1; display->topleft.y = 1; - display->topleft.p = 0; - display->plane = 0; + display->topleft.pl = get_homeplane(); + display->pl = get_homeplane(); display->size.width = getmaxx(win)/TWIDTH; display->size.height = getmaxy(win)/THEIGHT; display->regions = calloc(display->size.height * display->size.width, sizeof(map_region)); @@ -1071,7 +1116,8 @@ update_view(view * vi) map_region * mr = mr_get(vi, i, j); mr->coord.x = vi->topleft.x + i - j/2; mr->coord.y = vi->topleft.y + j; - mr->coord.p = vi->plane; + mr->coord.pl = vi->pl; + pnormalize(&mr->coord.x, &mr->coord.y, mr->coord.pl); mr->r = findregion(mr->coord.x, mr->coord.y); } } @@ -1081,8 +1127,8 @@ state * state_open(void) { state * st = calloc(sizeof(state), 1); - st->display.plane = 0; - st->cursor.p = 0; + st->display.pl = get_homeplane(); + st->cursor.pl = get_homeplane(); st->cursor.x = 0; st->cursor.y = 0; st->selected = calloc(1, sizeof(struct selection)); @@ -1154,8 +1200,8 @@ run_mapper(void) height = getmaxy(hwinmap)-y; coor2point(&st->cursor, &p); - if (st->cursor.p != vi->plane) { - vi->plane = st->cursor.p; + if (st->cursor.pl != vi->pl) { + vi->pl = st->cursor.pl; st->wnd_map->update |= 1; } if (p.y < tl.y) { diff --git a/src/eressea/gmtool_structs.h b/src/eressea/gmtool_structs.h index f475bb46d..7ba9d7e5c 100644 --- a/src/eressea/gmtool_structs.h +++ b/src/eressea/gmtool_structs.h @@ -29,8 +29,9 @@ typedef struct point { } point; typedef struct coordinate { - /* Eine Koordinate in der Welt */ - int x, y, p; + /* Eine Koordinate im Editor, nicht normalisiert */ + int x, y; + struct plane * pl; } coordinate; typedef struct map_region { @@ -40,7 +41,7 @@ typedef struct map_region { typedef struct view { struct map_region * regions; - int plane; + struct plane * pl; coordinate topleft; /* upper left corner in map. */ extent size; /* dimensions. */ } view; @@ -69,6 +70,7 @@ typedef struct state { } state; extern map_region * cursor_region(const view * v, const coordinate * c); +extern void cnormalize(const coordinate * c, int * x, int * y); extern state * current_state; #define TWIDTH 2 /* width of tile */ diff --git a/src/eressea/lua/gm.cpp b/src/eressea/lua/gm.cpp index 61311c093..3f54943d1 100644 --- a/src/eressea/lua/gm.cpp +++ b/src/eressea/lua/gm.cpp @@ -56,8 +56,11 @@ public: node = node->nexthash; } coordinate * c = &self->coord; - unsigned int key = ((c->x << 12) ^ c->y); - unsigned int hash = key & (MAXTHASH-1); + unsigned int hash; + int nx, ny; + + cnormalize(c, &nx, &ny); + hash = ((nx << 12) ^ ny) & (MAXTHASH-1); return next_tag(hash+1, current_state); } @@ -77,13 +80,16 @@ selected_regions(void) static void gmtool_select_coordinate(int x, int y, bool select) { - select_coordinate(current_state->selected, x, y, select?1:0); + int nx = x, ny = y; + plane * pl = findplane(x, y); + pnormalize(&nx, &ny, pl); + select_coordinate(current_state->selected, nx, ny, select?1:0); } static void gmtool_select_region(region& r, bool select) { - select_coordinate(current_state->selected, r.x, r.y, select?1:0); + select_coordinate(current_state->selected, r.x, r.y, select?1:0); } static void gmtool_open(void) diff --git a/src/eressea/lua/region.cpp b/src/eressea/lua/region.cpp index 4b376a0a3..04e3bce91 100644 --- a/src/eressea/lua/region.cpp +++ b/src/eressea/lua/region.cpp @@ -89,8 +89,8 @@ region_getherbtype(const region * r) { static int region_plane(const region * r) { - if (r->planep==NULL) return 0; - return r->planep->id; + plane * pl = rplane(r); + return plane_id(pl); } static void @@ -197,7 +197,10 @@ region_terraform(int x, int y, const char * tname) } return NULL; } - if (r==NULL) r = new_region(x, y, 0); + if (r==NULL) { + struct plane * pl = findplane(x, y); + r = new_region(x, y, pl, 0); + } terraform_region(r, terrain); return r; } @@ -224,12 +227,13 @@ region_remove(region * r) } static void -plane_remove(int plane_id) +plane_remove(int plid) { region ** rp = ®ions; while (*rp) { region * r = *rp; - if (r->planep && r->planep->id==plane_id) { + plane * pl = rplane(r); + if (pl && pl->id==plid) { remove_region(rp, r); } else { rp = &r->next; @@ -240,19 +244,23 @@ plane_remove(int plane_id) void region_move(region * r, int x, int y) { - if (findregion(x,y)) { + if (findregion(x, y)) { log_error(("Bei %d, %d gibt es schon eine Region.\n", x, y)); return; } #ifdef FAST_CONNECT direction_t dir; + plane * pl = rplane(r); for (dir=0;dir!=MAXDIRECTIONS;++dir) { region * rn = r->connect[dir]; + int nx = x + delta_x[dir]; + int ny = y + delta_y[dir]; + pnormalize(&nx, &ny, pl); if (rn!=NULL) { direction_t reldir = reldirection(rn, r); rn->connect[reldir] = NULL; } - rn = findregion(x+delta_x[dir], y+delta_y[dir]); + rn = findregion(nx, ny); if (rn!=NULL) { direction_t reldir = (direction_t)((dir + 3) % MAXDIRECTIONS); rn->connect[reldir] = r; diff --git a/src/eressea/tolua/bind_gmtool.c b/src/eressea/tolua/bind_gmtool.c index 031f0dc03..c2e9302ca 100644 --- a/src/eressea/tolua/bind_gmtool.c +++ b/src/eressea/tolua/bind_gmtool.c @@ -40,11 +40,13 @@ tolua_current_region(lua_State* L) static int tolua_select_coordinate(lua_State* L) { - int x = (int)tolua_tonumber(L, 1, 0); - int y = (int)tolua_tonumber(L, 2, 0); + int nx = (int)tolua_tonumber(L, 1, 0); + int ny = (int)tolua_tonumber(L, 2, 0); int select = tolua_toboolean(L, 3, 0); + plane * pl = findplane(nx, ny); + pnormalize(&nx, &ny, pl); if (current_state) { - select_coordinate(current_state->selected, x, y, select); + select_coordinate(current_state->selected, nx, ny, select); } return 0; } @@ -155,10 +157,13 @@ tolua_state_close(lua_State* L) static int tolua_make_island(lua_State * L) { - int x = (int)tolua_tonumber(L, 1, 0); - int y = (int)tolua_tonumber(L, 2, 0); - int n = (int)tolua_tonumber(L, 3, 0); - n = build_island_e3(x, y, n, n*3); + plane * pl = (plane *)tolua_tousertype(L, 1, 0); + int x = (int)tolua_tonumber(L, 2, 0); + int y = (int)tolua_tonumber(L, 3, 0); + int s = (int)tolua_tonumber(L, 4, 0); + int n = (int)tolua_tonumber(L, 5, s / 3); + if (pl) pnormalize(&x, &y, pl); + n = build_island_e3(x, y, n, s); tolua_pushnumber(L, n); return 1; } @@ -166,11 +171,13 @@ tolua_make_island(lua_State * L) static int tolua_make_block(lua_State * L) { - int x = (int)tolua_tonumber(L, 1, 0); - int y = (int)tolua_tonumber(L, 2, 0); - int r = (int)tolua_tonumber(L, 3, 6); - const char * str = tolua_tostring(L, 4, "ocean"); + plane * pl = (plane *)tolua_tousertype(L, 1, 0); + int x = (int)tolua_tonumber(L, 2, 0); + int y = (int)tolua_tonumber(L, 3, 0); + int r = (int)tolua_tonumber(L, 4, 6); + const char * str = tolua_tostring(L, 5, "ocean"); const struct terrain_type * ter = get_terrain(str); + if (pl) pnormalize(&x, &y, pl); make_block(x, y, r, ter); return 0; } diff --git a/src/eressea/tolua/bind_region.c b/src/eressea/tolua/bind_region.c index b6e00f4ba..56b50fe00 100644 --- a/src/eressea/tolua/bind_region.c +++ b/src/eressea/tolua/bind_region.c @@ -24,8 +24,9 @@ without prior permission by the authors of Eressea. #include #include #include +#include #include - +#include #include #include @@ -220,10 +221,13 @@ 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); - + plane * pl = (plane *)tolua_tousertype(L, 4, 0); const terrain_type * terrain = get_terrain(tname); - region * r = findregion(x, y); - region * result = r; + region * r, * result; + + if (!pl) pl = findplane(x, y); + pnormalize(&x, &y, pl); + r = result = findregion(x, y); if (terrain==NULL) { if (r!=NULL) { @@ -234,7 +238,7 @@ tolua_region_create(lua_State* L) } } if (r==NULL) { - result = new_region(x, y, 0); + result = new_region(x, y, pl, 0); } if (result) { terraform_region(result, terrain); @@ -336,15 +340,96 @@ tolua_region_tostring(lua_State *L) return 1; } +static int +tolua_plane_get(lua_State* L) +{ + int id = (int)tolua_tonumber(L, 1, 0); + plane * pl = getplanebyid(id); + + tolua_pushusertype(L, pl, "plane"); + return 1; +} + +static int +tolua_plane_create(lua_State* L) +{ + int id = (int)tolua_tonumber(L, 1, 0); + int x = (int)tolua_tonumber(L, 2, 0); + int y = (int)tolua_tonumber(L, 3, 0); + int width = (int)tolua_tonumber(L, 4, 0); + int height = (int)tolua_tonumber(L, 5, 0); + const char * name = tolua_tostring(L, 6, 0); + plane * pl; + + pl = create_new_plane(id, name, x, x+width-1, y, y+height-1, 0); + + tolua_pushusertype(L, pl, "plane"); + return 1; +} + +static int tolua_plane_get_name(lua_State* L) +{ + plane* self = (plane*) tolua_tousertype(L, 1, 0); + tolua_pushstring(L, self->name); + return 1; +} + +static int tolua_plane_set_name(lua_State* L) +{ + plane* self = (plane*)tolua_tousertype(L, 1, 0); + const char * str = tolua_tostring(L, 2, 0); + free(self->name); + if (str) self->name = strdup(str); + else self->name = 0; + return 0; +} + +static int +tolua_plane_get_id(lua_State* L) +{ + plane * self = (plane *)tolua_tousertype(L, 1, 0); + tolua_pushnumber(L, (lua_Number)self->id); + return 1; +} + +static int +tolua_plane_tostring(lua_State *L) +{ + plane * self = (plane *)tolua_tousertype(L, 1, 0); + lua_pushstring(L, self->name); + return 1; +} + +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_pushnumber(L, result); + return 1; +} + void tolua_region_open(lua_State* L) { /* register user types */ tolua_usertype(L, "region"); + tolua_usertype(L, "plane"); tolua_module(L, NULL, 0); tolua_beginmodule(L, NULL); { + tolua_function(L, "distance", tolua_distance); + tolua_cclass(L, "region", "region", "", NULL); tolua_beginmodule(L, "region"); { @@ -386,6 +471,18 @@ tolua_region_open(lua_State* L) tolua_variable(L, "objects", tolua_region_get_objects, 0); } tolua_endmodule(L); + + tolua_cclass(L, "plane", "plane", "", NULL); + tolua_beginmodule(L, "plane"); + { + tolua_function(L, "create", tolua_plane_create); + tolua_function(L, "get", tolua_plane_get); + tolua_function(L, "__tostring", tolua_plane_tostring); + + tolua_variable(L, "id", tolua_plane_get_id, NULL); + tolua_variable(L, "name", tolua_plane_get_name, tolua_plane_set_name); + } + tolua_endmodule(L); } tolua_endmodule(L); } diff --git a/src/eressea/tolua/bind_unit.c b/src/eressea/tolua/bind_unit.c index 5b3ee81c9..757020299 100644 --- a/src/eressea/tolua/bind_unit.c +++ b/src/eressea/tolua/bind_unit.c @@ -834,7 +834,7 @@ tolua_unit_create(lua_State* L) { faction * f = (faction *)tolua_tousertype(L, 1, 0); region * r = (region *)tolua_tousertype(L, 2, 0); - int num = (int)tolua_tonumber(L, 3, 0); + int num = (int)tolua_tonumber(L, 3, 1); if (f && r) { const race * rc = f->race; const char * rcname = tolua_tostring(L, 4, NULL); diff --git a/src/eressea/tolua/bindings.c b/src/eressea/tolua/bindings.c index 5d68e280a..67f244a96 100644 --- a/src/eressea/tolua/bindings.c +++ b/src/eressea/tolua/bindings.c @@ -29,6 +29,7 @@ without prior permission by the authors of Eressea. #include #include #include +#include #include #include #include @@ -554,7 +555,9 @@ static int tolua_write_map(lua_State* L) { const char * filename = tolua_tostring(L, 1, 0); - crwritemap(filename); + if (filename) { + crwritemap(filename); + } return 0; } @@ -602,7 +605,11 @@ tolua_get_region(lua_State* L) { int x = (int)tolua_tonumber(L, 1, 0); int y = (int)tolua_tonumber(L, 2, 0); - region * r = findregion(x, y); + struct plane * pl = (struct plane *)tolua_tousertype(L, 3, 0); + region * r; + if (!pl) pl = findplane(x, y); + pnormalize(&x, &y, pl); + r = findregion(x, y); tolua_pushusertype(L, r, "region"); return 1; diff --git a/src/res/e2k9.xml b/src/res/e2k9.xml index eb6bc1ab1..69df32c15 100644 --- a/src/res/e2k9.xml +++ b/src/res/e2k9.xml @@ -130,6 +130,7 @@ + @@ -145,6 +146,7 @@ + diff --git a/src/scripts/tests.lua b/src/scripts/tests.lua index 4f1d17bf5..74d5eef74 100644 --- a/src/scripts/tests.lua +++ b/src/scripts/tests.lua @@ -249,9 +249,8 @@ local function test_spells() free_game() local r = region.create(0, 0, "plain") local f = faction.create("enno@eressea.de", "human", "de") - local u = unit.create(f, r) + local u = unit.create(f, r, 1) u.race = "elf" - u.number = 1 u:clear_orders() u:add_item("money", 10000) u:set_skill("magic", 5) @@ -261,14 +260,19 @@ local function test_spells() local nums = 0 if f.spells~=nil then for sp in f.spells do - nums = nums + 1 + nums = nums + 1 end + assert(nums>0) + for sp in u.spells do + nums = nums - 1 + end + assert(nums==0) + else + for sp in u.spells do + nums = nums + 1 + end + assert(nums>0) end - assert(nums>0) - for sp in u.spells do - nums = nums - 1 - end - assert(nums==0) end local function test_produce() @@ -438,7 +442,10 @@ function test_id() assert(get_building(fortytwo)==b) assert(get_building(atoi36(fortytwo))==b) - local s = ship.create(r, "boat") + local s = ship.create(r, "canoe") + if (s==nil) then + s = ship.create(r, "boat") + end -- s.id = atoi36("42") local fortytwo = itoa36(s.id) assert(get_ship(fortytwo)==s) @@ -513,7 +520,7 @@ mytests = { ["taxes"] = test_taxes } fail = 0 -for k, v in pairs(mytests) do +for k, v in pairs(tests) do local status, err = pcall(v) if not status then fail = fail + 1