/* vi: set ts=2: * * 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) * Enno Rehling (enno@eressea-pbem.de) * Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de) * * This program may not be used, modified or distributed without * prior permission by the authors of Eressea. */ /* wenn config.h nicht vor curses included wird, kompiliert es unter windows nicht */ /* wenn curses.h nicht vor mapper included wird, kennt es die structs nicht. TODO: curses-teil separieren (map_tools.h) */ #include #include #include #include "mapper.h" /* kernel includes */ #include #include #include #include #include #include #include #include #include #include #include #include /* util includes */ #include #include /* libc includes */ #include typedef struct menulist { struct menulist *next, *prev; int *val; char *text; } menulist; enum { C_COOL, C_TEMPERATE, C_DRY, C_TROPIC, MAXCLIMATES }; static int climate(int y) { if (y < -BLOCKSIZE) return C_COOL; if (y > 2 * BLOCKSIZE) return C_TROPIC; if (y > BLOCKSIZE) return C_DRY; return C_TEMPERATE; } #define MAXSEEDSIZE 17 static char maxseeds[MAXCLIMATES][8] = { {0, 1, 3, 3, 0, 3, 3, 4,}, /* Summe muß MAXSEEDSIZE sein */ {0, 5, 4, 2, 0, 2, 3, 1,}, {0, 6, 1, 0, 6, 2, 2, 0,}, {0, 4, 5, 4, 0, 2, 2, 0,}, }; static terrain_t terrain_create(int climate) { int i = rng_int() % MAXSEEDSIZE; terrain_t terrain = T_OCEAN; while (i > maxseeds[climate][terrain]) i -= maxseeds[climate][terrain++]; return terrain; } static terrain_t newblock[BLOCKSIZE][BLOCKSIZE]; void block_create(short x1, short y1, int size, char chaotisch, int special, const terrain_type * terrain) { int local_climate, k; short x, y; vset fringe; vset_init(&fringe); /* x1 = blockcoord(x1); y1 = blockcoord(y1); */ local_climate = climate(y1); memset(newblock, T_OCEAN, sizeof newblock); x = BLOCKSIZE / 2; y = BLOCKSIZE / 2; vset_add(&fringe, (void *) (((short) (x) << 16) + ((short) (y) & 0xFFFF))); for (x=0;x!=BLOCKSIZE;++x) { for (y=0;y!=BLOCKSIZE;++y) { /* add the borders of the block taht have a * non-ocean region in them to the fringe * */ int i; direction_t d; int nb[4][3]; memset(nb, 0, sizeof(nb)); for (d=0;d!=MAXDIRECTIONS;++d) { region * r = findregion(x1 + delta_x[d] + x, y1 + delta_y[d]); if (r && rterrain(r)!=T_OCEAN) { nb[0][0] = x; nb[0][1] = 0; nb[0][2] = 1; } r = findregion(x1 + delta_x[d] + x, y1 + BLOCKSIZE - 1 + delta_y[d]); if (r && rterrain(r)!=T_OCEAN) { nb[1][0] = x; nb[1][1] = BLOCKSIZE - 1; nb[1][2] = 1; } r = findregion(x1 + delta_x[d] + BLOCKSIZE - 1, y1 + y + delta_y[d]); if (r && rterrain(r)!=T_OCEAN) { nb[2][0] = BLOCKSIZE - 1; nb[2][1] = y; nb[2][2] = 1; } r = findregion(x1 + delta_x[d], y1 + y + delta_y[d]); if (r && rterrain(r)!=T_OCEAN) { nb[3][0] = 0; nb[3][1] = y; nb[3][2] = 1; } } for (i=0;i!=3;++i) if (nb[i][2]) { vset_add(&fringe, (void *) (((short) nb[i][0] << 16) + ((short) nb[i][1] & 0xFFFF))); } } } for (k = 0; k != size; ++k) { int c = (int) fringe.data[rng_int() % fringe.size]; direction_t d; x = (short)(c >> 16); y = (short)(c & 0xFFFF); assert(newblock[x][y] == T_OCEAN); newblock[x][y] = terrain_create(local_climate); vset_erase(&fringe, (void *) c); for (d = 0; d != MAXDIRECTIONS; ++d) { short dx = x+delta_x[d]; short dy = y+delta_y[d]; if (dx >= 0 && dx < BLOCKSIZE && dy >= 0 && dy < BLOCKSIZE && newblock[dx][dy] == T_OCEAN) vset_add(&fringe, (void *) (((short) (dx) << 16) + ((short) (dy) & 0xFFFF))); } } { /* newblock wird innerhalb der Rahmen in die Karte kopiert, die * Landstriche werden benannt und bevoelkert, und die produkte * p1 und p2 des Kontinentes werden gesetzt. */ region *r; int i, i1 = -1, i2 = -1; const luxury_type *ltype, *p1 = NULL, *p2=NULL; int maxlux = get_maxluxuries(); if (maxlux>0) { i1 = (item_t)(rng_int() % maxlux); do { i2 = (item_t)(rng_int() % maxlux); } while (i2 == i1); } ltype = luxurytypes; for (i=0;!p1 || !p2;++i) { if (i==i1) p1=ltype; else if (i==i2) p2=ltype; ltype=ltype->next; } for (x = 0; x != BLOCKSIZE; x++) { for (y = 0; y != BLOCKSIZE; y++) { const luxury_type * sale = (rng_int()%2)?p1:p2; r = findregion(x1 + x - BLOCKSIZE/2, y1 + y - BLOCKSIZE/2); if (r && !fval(r->terrain, SEA_REGION)) continue; if (r==NULL) r = new_region(x1 + x - BLOCKSIZE/2, y1 + y - BLOCKSIZE/2); if (chaotisch) fset(r, RF_CHAOTIC); if (special == 1) { terraform_region(r, terrain); } else if (special == 2) { if (newblock[x][y] != T_OCEAN) terraform_region(r, terrain); else terraform(r, T_OCEAN); } else { terraform(r, newblock[x][y]); } if (r->land && sale) setluxuries(r, sale); } } } vset_destroy(&fringe); } static void addmenulist(menulist ** SP, const char *s, int *val) { menulist *S, *X; S = calloc(1, sizeof(menulist)); S->text = strdup(s); S->val = val; S->next = 0; if (*SP) { for (X = *SP; X->next; X = X->next); X->next = S; S->prev = X; } else { S->prev = 0; *SP = S; } } /* Wilder Hack: Zur Übergabe an addmenulist() brauchen wir Adressen, * die die r*-Funktionen natürlich nicht mehr liefern. Also diese * Variablen als Zwischenpuffer. */ static int peasants, money, trees, horses, iron, laen, chaotisch; static int saplings, seeds; static int ironlevel, laenlevel, stone, stonelevel; static void get_region(region *r) { struct rawmaterial *res; peasants = rpeasants(r); money = rmoney(r); trees = rtrees(r,2); saplings = rtrees(r,1); seeds = rtrees(r,0); horses = rhorses(r); iron = -1; ironlevel = -1; laen = -1; laenlevel = -1; stone = -1; stonelevel = -1; for (res=r->resources;res;res=res->next) { const item_type * itype = resource2item(res->type->rtype); if(itype == olditemtype[I_IRON]) { iron = res->amount; ironlevel = res->level + itype->construction->minskill - 1; } else if(itype == olditemtype[I_LAEN]) { laen = res->amount; laenlevel = res->level + itype->construction->minskill - 1; } else if(itype == olditemtype[I_STONE]) { stone = res->amount; stonelevel = res->level + itype->construction->minskill - 1; } } chaotisch = fval(r, RF_CHAOTIC); } static void put_region(region *r) { struct rawmaterial *res; rsetpeasants(r, peasants); rsetmoney(r,money); rsettrees(r,2,trees); rsettrees(r,1,saplings); rsettrees(r,0,seeds); rsethorses(r, horses); for (res=r->resources;res;res=res->next) { const item_type * itype = resource2item(res->type->rtype); if(itype == olditemtype[I_IRON]) { res->amount = iron; res->level = ironlevel - itype->construction->minskill + 1; } else if(itype == olditemtype[I_LAEN]) { res->amount = laen; res->level = laenlevel - itype->construction->minskill + 1; } else if(itype == olditemtype[I_STONE]) { res->amount = stone; res->level = stonelevel - itype->construction->minskill + 1; } } if (chaotisch) fset(r, RF_CHAOTIC); else freset(r, RF_CHAOTIC); } static void create_region_menu(menulist ** menu, region * r) { char str[80]; unit *u; building *b; ship *sh; faction *f; get_region(r); addmenulist(menu, "Peasants", &peasants); addmenulist(menu, "Silver", &money); if (fval(r, RF_MALLORN)) { addmenulist(menu, "Mallorntrees", &trees); addmenulist(menu, "Mallornsaplings", &saplings); addmenulist(menu, "Mallornseeds", &seeds); } else { addmenulist(menu, "Trees", &trees); addmenulist(menu, "Saplings", &saplings); addmenulist(menu, "Seeds", &seeds); } addmenulist(menu, "Horses", &horses); /* if(iron != -1) { */ addmenulist(menu, "Iron", &iron); addmenulist(menu, "Ironlevel", &ironlevel); /* } */ /* if(laen != -1) { */ addmenulist(menu, "Laen", &laen); addmenulist(menu, "Laenlevel", &laenlevel); /* } */ /* if(stone != -1) { */ addmenulist(menu, "Stone", &stone); addmenulist(menu, "Stonelevel", &stonelevel); /* } */ addmenulist(menu, "Chaos-Factor", &chaotisch); if (r->planep) { strcpy(buf,"Plane: "); strncpy(str, r->planep->name, 30); str[30] = 0; sncat(buf, str, BUFSIZE); sncat(buf, " (", BUFSIZE); sncat(buf, r->planep->name, BUFSIZE); sncat(buf, ")", BUFSIZE); addmenulist(menu, buf, 0); } strcpy(buf, "Buildings:"); if (!r->buildings) { sncat(buf, " keine", BUFSIZE); addmenulist(menu, buf, 0); } else { addmenulist(menu, buf, 0); for (b = r->buildings; b; b = b->next) { sprintf(buf, " %s: ", Buildingid(b)); for (u = r->units; u; u = u->next) if (u->building == b && fval(u, UFL_OWNER)) { strncpy(str, u->name, 28); str[28] = 0; sncat(buf, str, BUFSIZE); sprintf(str, " (%s), Partei %s", unitid(u), factionid(u->faction)); sncat(buf, str, BUFSIZE); break; } if (!u) sncat(buf, "steht leer", BUFSIZE); addmenulist(menu, buf, 0); } } strcpy(buf, "Ships:"); if (!r->ships) { sncat(buf, " keine", BUFSIZE); addmenulist(menu, buf, 0); } else { addmenulist(menu, buf, 0); for (sh = r->ships; sh; sh = sh->next) { sprintf(buf, " %s: ", shipname(sh)); if (sh->size!=sh->type->construction->maxsize) sncat(buf, "(im Bau) ", BUFSIZE); for (u = r->units; u; u = u->next) if (u->ship == sh && fval(u, UFL_OWNER)) { strncpy(str, u->name, 28); str[28] = 0; sncat(buf, str, BUFSIZE); sprintf(str, " (%s), Partei %s", unitid(u), factionid(u->faction)); sncat(buf, str, BUFSIZE); break; } if (!u) sncat(buf, "ohne Besitzer", BUFSIZE); addmenulist(menu, buf, 0); } } strcpy(buf, "Parteien:"); if (!r->units) { sncat(buf, " keine", BUFSIZE); addmenulist(menu, buf, 0); } else { for (f = factions; f; f = f->next) f->num_people = f->no_units = 0; for (u = r->units; u; u = u->next) { u->faction->no_units++; u->faction->num_people += u->number; } addmenulist(menu, buf, 0); for (f = factions; f; f = f->next) { if (f->no_units) { sprintf(buf, " %s: ", factionname(f)); sprintf(str, "Einheiten: %d; Leute: %d", f->no_units, f->num_people); sncat(buf, str, BUFSIZE); addmenulist(menu, buf, 0); } } } } char modified = 0; WINDOW *mywin; int pline; #define Printw(x,l) \ { \ wmove(mywin,l,4); \ Addstr(x->text); \ if (x->val) wprintw(mywin, (NCURSES_CONST char*)": %d",(char*)*(x->val)); \ } \ static void modify_value(menulist * v) { int vl; vl = map_input(mywin, 40, pline, "Neuer Wert", -1, 999999, *(v->val)); Movexy(4, pline); wclrtoeol(mywin); Printw(v, pline); if (vl != *(v->val)) { modified = 1; *(v->val) = vl; } } void NeuesSchiff(region * r) { ship_type *stype[40]; /* Maximal 40 Schiffe */ ship_typelist *st; ship *s; WINDOW *win; int i, q, y, maxtype; for(st = shiptypes, maxtype=0; st; st=st->next, maxtype++) { stype[maxtype] = (ship_type *)st->type; } win = openwin(SX - 10, 6, "< Neues Schiff erschaffen >"); q = 0; y = 2; wmove(win, y, 4); for (i = 0; i < maxtype; i++) { sprintf(buf, "%d=%s; ", i, stype[i]->name[0]); q += strlen(buf); if (q > SX - 20) { q = strlen(buf); y++; wmove(win, y, 4); } waddnstr(win, buf, -1); } wrefresh(win); q = map_input(win, 2, 1, "Schiffstyp", -1, maxtype, 0); if (q < 0) { delwin(win); return; } for (; y > 0; y--) { wmove(win, y, 2); wclrtoeol(win); wrefresh(win); wmove(win, y, win->_maxx); waddch(win, '|'); wrefresh(win); } wmove(win, 1, 2); wAddstr(stype[q]->name[0]); wrefresh(win); s = new_ship(stype[q], default_locale, r); s->region = r; strcpy(buf, my_input(win, 2, 2, "Name: ", NULL)); if (strlen(buf) > 0) set_string(&s->name, buf); if (clipunit) { wmove(win, 3, 2); wAddstr("Einheit im Clip: "); wAddstr(Unitid(clipunit)); wmove(win, 4, 2); if (yes_no(win, "Clipunit als Besitzer?", 'n')) { leave(clipregion, clipunit); if (r != clipregion) translist(&clipregion->units, &r->units, clipunit); clipunit->ship = s; fset(clipunit, UFL_OWNER); } } delwin(win); modified = 1; } static const char * oldbuildings[] = { "castle", "lighthouse", "mine", "quarry", "harbour", "academy", "magictower", "smithy", "sawmill", "stables", "monument", "dam", "caravan", "tunnel", "inn", "stonecircle", "blessedstonecircle", "illusion", NULL }; void NeueBurg(region * r) { building *b; WINDOW *win; int i, q, y; win = openwin(SX - 10, 10, "< Neues Gebäude erschaffen >"); q = 0; y = 2; wmove(win, y, 4); for (i = 0; oldbuildings[i]; i++) { sprintf(buf, "%d=%s; ", i, oldbuildings[i]); q += strlen(buf); if (q > SX - 20) { q = strlen(buf); y++; wmove(win, y, 4); } waddnstr(win, buf, -1); } wrefresh(win); q = map_input(win, 2, 1, "Gebäudetyp", -1, i, 0); if (q < 0) { delwin(win); return; } for (; y > 0; y--) { wmove(win, y, 4); wclrtoeol(win); wrefresh(win); wmove(win, y, win->_maxx); waddch(win, '|'); } wmove(win, 1, 2); wAddstr((char*)oldbuildings[q]); wrefresh(win); b = new_building(bt_find(oldbuildings[q]), r, NULL); b->size = map_input(win, 2, 2, "Grösse", 1, 99999, 1); strcpy(buf, my_input(win, 2, 3, "Name: ", NULL)); if (strlen(buf) > 0) set_string(&b->name, buf); if (clipunit) { wmove(win, 4, 2); wAddstr("Einheit im Clip: "); wAddstr(Unitid(clipunit)); wmove(win, 5, 2); if (yes_no(win, "Clipunit als Besitzer?", 'n')) { leave(clipregion, clipunit); if (r != clipregion) translist(&clipregion->units, &r->units, clipunit); clipunit->building = b; fset(clipunit, UFL_OWNER); } } delwin(win); modified = 1; } int modify_region(region * r) { menulist *eh = NULL, *unten, *oben, *hlp = NULL, *such = NULL, *mpoint; int line, ch, bottom, bot; size_t lt; char *s = NULL, *txt, *suchtext = NULL; create_region_menu(&eh, r); clear(); strncpy(buf, rname(r, NULL), 65); buf[65] = 0; movexy(0, 0); printw((char*)"%s (%d,%d):", buf, r->x, r->y); for (line = 0; line <= SX; line++) buf[line] = '-'; movexy(0, SY - 1); addstr(buf); movexy(0, 1); addstr(buf); movexy(0, SY); addstr(": Neuer Wert; T: neuer Text; u: Units; B: neue Burg; S: neues Schiff"); refresh(); mywin = newwin(SY - 3, SX, 2, 0); wclear(mywin); bot = mywin->_maxy + 1; for (line = 0, unten = eh; line < bot && unten->next; line++, unten = unten->next) { Printw(unten, line); wrefresh(mywin); } Printw(unten, line); wrefresh(mywin); bottom = line - 1; mpoint = oben = eh; /* unten=unten->prev; */ scrollok(mywin, TRUE); pline = 0; for (;;) { Movexy(1, pline); if (mpoint->val) { wattron(mywin, A_BOLD); Addstr("=>"); wattroff(mywin, A_BOLD); move(SY, 0); clrtoeol(); addstr(": Neuer Wert; T: neuer Text; u: Units; B: neue Burg; S: neues Schiff"); refresh(); } else { Addstr("->"); move(SY, 0); clrtoeol(); addstr("u: Units; T: neuer Text; B: neue Burg; S: neues Schiff"); refresh(); } wrefresh(mywin); ch = getch(); Movexy(1, pline); Addstr(" "); switch (ch) { case KEY_DOWN: if (mpoint->next) { mpoint = mpoint->next; if (pline > bottom) { pline--; if (unten->next) { wscrl(mywin, 1); Printw(unten, bottom); unten = unten->next; oben = oben->next; } } pline++; } else beep(); break; case KEY_UP: if (mpoint->prev) { mpoint = mpoint->prev; pline--; if (pline < 0) { pline++; if (oben->prev) { unten = unten->prev; oben = oben->prev; wscrl(mywin, -1); Printw(oben, 0); } } } else beep(); break; case KEY_RIGHT: case KEY_NPAGE: for (line = 0; line < 20 && unten->next; line++) { oben = oben->next; unten = unten->next; if (mpoint->next) mpoint = mpoint->next; else pline--; } wclear(mywin); for (line = 0, hlp = oben; line < bot && hlp->next; line++, hlp = hlp->next) { Printw(hlp, line); wrefresh(mywin); } Printw(hlp, line); wrefresh(mywin); bottom = line - 1; if (pline < 0) pline = 0; break; case KEY_PPAGE: case KEY_LEFT: for (line = 0; line < 20 && oben->prev; line++) { oben = oben->prev; unten = unten->prev; if (mpoint->prev) mpoint = mpoint->prev; else pline++; } wclear(mywin); for (line = 0, hlp = oben; line < bot && hlp->next; line++, hlp = hlp->next) { Printw(hlp, line); wrefresh(mywin); } Printw(hlp, line); wrefresh(mywin); bottom = line - 1; if (pline > bottom) pline = bottom; break; case 12: /* ^L -> redraw */ wclear(mywin); for (line = 0, hlp = oben; line < bot && hlp->next; line++, hlp = hlp->next) { Printw(hlp, line); wrefresh(mywin); } Printw(hlp, line); wrefresh(mywin); bottom = line - 1; break; case '/': suchtext = my_input(0, 0, 0, (char*)"Suchtext: ", NULL); such = eh; case 'n': line = 0; lt = strlen(suchtext); while (such->next && !line) { s = such->text; while (strlen(s) >= lt && !line) { if (strncasecmp(s, suchtext, lt) == 0) line = 1; s++; } such = such->next; } if (line) { wclear(mywin); Movexy(4, 0); txt = such->prev->text; s--; ch = *s; *s = 0; Addstr(txt); wattron(mywin, A_REVERSE); *s = (char)ch; txt = s; ch = txt[lt]; txt[lt] = 0; Addstr(txt); wattroff(mywin, A_REVERSE); txt[lt] = (char)ch; txt += lt; Addstr(txt); if (such->prev->val) { sprintf(buf, ": %d", *(such->prev->val)); Addstr(buf); } for (line = 0, hlp = oben; line < bot && hlp->next; line++, hlp = hlp->next) { Printw(hlp, line); wrefresh(mywin); } Printw(hlp, line); wrefresh(mywin); bottom = line - 1; oben = such->prev ? such->prev : such; unten = hlp->prev; mpoint = oben; pline = 0; } else { movexy(0, SY); beep(); clrtoeol(); printw((char*)"'%s' nicht gefunden.", suchtext); refresh(); } break; case KEY_HELP: case '?': case 'h': movexy(0, SY); clrtoeol(); addstr(": Neuer Wert; u: Einheitenliste; B: neue Burg; S: neues Schiff"); refresh(); break; case '>': wclear(mywin); do { unten = unten->next; oben = oben->next; } while (unten->next); for (line = 0, hlp = oben; line < bot && hlp; line++, hlp = hlp->next) { Printw(hlp, line); wrefresh(mywin); } Printw(hlp, line); wrefresh(mywin); bottom = line - 1; mpoint = unten; pline = bottom; break; case '<': wclear(mywin); for (line = 0, unten = eh; line < bot && unten->next; line++, unten = unten->next) { Printw(unten, line); wrefresh(mywin); } Printw(hlp, line); wrefresh(mywin); bottom = line - 1; mpoint = such = oben = eh; unten = unten->prev; pline = 0; break; case 10: case 13: if (mpoint->val) { modify_value(mpoint); for (line = 0, unten = eh; line < bot && unten->next; line++, unten = unten->next) { Printw(unten, line); wrefresh(mywin); } Printw(unten, line); wrefresh(mywin); } else beep(); break; case 'T': case 'B': if (fval(r->terrain, LAND_REGION)) { NeueBurg(r); return 1; } else beep(); case 'S': NeuesSchiff(r); return 1; case 'u': while (showunits(r)); wclear(mywin); for (line = 0, hlp = oben; line < bot && hlp->next; line++, hlp = hlp->next) { Printw(hlp, line); wrefresh(mywin); } Printw(hlp, line); wrefresh(mywin); bottom = line - 1; break; case 27: /* Esc */ case 'q': put_region(r); delwin(mywin); freelist(eh); return 0; } } } void make_new_region(short x, short y) { WINDOW *win; region *r; const terrain_type * terrain = NULL; win = openwin(SX - 10, 10, "< Region erzeugen >"); x = (short)map_input(win, 2, 1, "X-Koordinate", -999, 999, x); y = (short)map_input(win, 2, 2, "Y-Koordinate", -999, 999, y); wmove(win, 3, 2); if ((r=findregion(x, y))!=NULL) { if (!yes_no(win, "Dort ist schon etwas! Überschreiben?", 'n')) return; else { wmove(win, 3, 2); wclrtoeol(win); wmove(win, 3, win->_maxx); waddch(win, '|'); } } else r=new_region(x,y); terrain = select_terrain(NULL); terraform_region(r, terrain); wrefresh(win); wmove(win, 4, 3); if(yes_no(win, "Chaotische Region?", 'n')) { fset(r, RF_CHAOTIC); } else { freset(r, RF_CHAOTIC); } modified=1; } #define BLOCK_RADIUS 6 void make_ocean_block(short x, short y) { short cx, cy; region *r; for(cx = x - BLOCK_RADIUS; cx < x+BLOCK_RADIUS; cx++) { for(cy = y - BLOCK_RADIUS; cy < y+BLOCK_RADIUS; cy++) { if(koor_distance(cx, cy, x, y) < BLOCK_RADIUS) { if (!findregion(cx, cy)) { r = new_region(cx, cy); terraform(r, T_OCEAN); } } } } } const terrain_type * select_terrain(const terrain_type * default_terrain) { selection *prev, *ilist = NULL, **iinsert; selection *selected = NULL; const terrain_type * terrain = terrains(); if (!terrain) return NULL; iinsert = &ilist; prev = ilist; while (terrain) { push_selection(iinsert, terrain->_name, (void*)terrain); terrain = terrain->next; } selected = do_selection(ilist, "Terrain", NULL, NULL); if (selected==NULL) return NULL; return (const terrain_type*)selected->data; } void make_new_block(int x, int y) { WINDOW *win; int z, special = 0; char chaos; const terrain_type * terrain = NULL; win = openwin(SX - 10, 10, "< Block erzeugen >"); x = map_input(win, 2, 1, "X-Koordinate innerhalb des Blocks", -999, 999, x); y = map_input(win, 2, 2, "Y-Koordinate innerhalb des Blocks", -999, 999, y); wmove(win, 3, 2); if (findregion(x, y)) { if (!yes_no(win, "Dort ist schon etwas! Überschreiben?", 'n')) return; else { wmove(win, 3, 2); wclrtoeol(win); wmove(win, 3, win->_maxx); waddch(win, '|'); } } z = 2; wmove(win, ++z, 2); if (yes_no(win, "Mini-Insel?", 'n')) special = 4; else { wmove(win, ++z, 2); if (yes_no(win, "Nur Wasser?", 'n')) { special = 1; terrain = newterrain(T_OCEAN); } else { wmove(win, ++z, 2); if (yes_no(win, "1-Terrain-Insel?", 'n')) { terrain = select_terrain(NULL); } } } wmove(win, ++z, 2); if (special != 1) chaos = (char)(yes_no(win, "Chaotischer Block?", 'n') ? 1 : 0); else chaos = 0; block_create(x, y, ISLANDSIZE, chaos, special, terrain); if (y < MINY) MINY -= 9; else if (y > MAXY) MAXY += 9; if (x < MINX) MINX -= 9; else if (x > MAXX) MAXX += 9; modified = 1; } static terrain_t choose_terrain(terrain_t t) { int q; if (rng_int()%100 < 50) return t; if (rng_int()%100 < 10) return T_OCEAN; q = rng_int()%100; switch (t) { case T_OCEAN: if(rng_int()%100 < 60) return T_OCEAN; switch(rng_int()%6) { case 0: return T_SWAMP; case 1: return T_PLAIN; case 2: return T_GLACIER; case 3: return T_DESERT; case 4: return T_HIGHLAND; case 5: return T_MOUNTAIN; } break; case T_PLAIN: if (q<20) return T_SWAMP; if (q<40) return T_MOUNTAIN; if (q<50) return T_HIGHLAND; if (q<80) return T_DESERT; if (q<90) return T_GLACIER; break; case T_SWAMP: if (q<40) return T_PLAIN; if (q<65) return T_HIGHLAND; if (q<80) return T_MOUNTAIN; if (q<90) return T_GLACIER; if (q<95) return T_DESERT; break; case T_HIGHLAND: if (q<35) return T_PLAIN; if (q<50) return T_MOUNTAIN; if (q<70) return T_GLACIER; if (q<80) return T_SWAMP; if (q<90) return T_DESERT; break; case T_DESERT: if (q<35) return T_PLAIN; if (q<45) return T_MOUNTAIN; if (q<50) return T_GLACIER; if (q<55) return T_SWAMP; if (q<70) return T_HIGHLAND; break; case T_MOUNTAIN: if (q<35) return T_PLAIN; if (q<65) return T_HIGHLAND; if (q<80) return T_GLACIER; if (q<90) return T_SWAMP; if (q<95) return T_DESERT; break; case T_GLACIER: if (q<35) return T_PLAIN; if (q<50) return T_MOUNTAIN; if (q<70) return T_HIGHLAND; if (q<90) return T_SWAMP; if (q<95) return T_DESERT; break; } return t; } region *t_queue[10000]; int t_queue_len = 0; void push(region *r) { t_queue[t_queue_len] = r; t_queue_len++; } static region * shift(void) { int p; region *r; if(t_queue_len == 0) return NULL; p = rng_int()%t_queue_len; r = t_queue[p]; memmove(&t_queue[p], &t_queue[p+1], (10000-p)*sizeof(region *)); t_queue_len--; return r; } static const luxury_type * tradegood = NULL; void settg(region *r) { const luxury_type * ltype; int g = get_maxluxuries(); if (tradegood==NULL) tradegood = luxurytypes; for (ltype=luxurytypes; ltype; ltype=ltype->next) { if (ltype!=tradegood) r_setdemand(r, ltype, 1 + rng_int() % 5); } r_setdemand(r, tradegood, 0); if (g>0 && (rng_int()%10)<2) { int t = rng_int() % g; for (tradegood = luxurytypes;t;--t) { tradegood = tradegood->next; } } } boolean Create_Island(region *r, int * n, const terrain_type * terrain, int x, int y) { terrain_t t = oldterrain(terrain); if (!r) return false; if (*n == 0) return true; if((t == T_MOUNTAIN || t == T_GLACIER) && rng_int()%100 < 5) { terraform(r,T_VOLCANO); } else { terraform_region(r, terrain); } if (r->land) settg(r); (*n)--; return false; } void create_island(region *r, int n, const struct terrain_type * terrain) { short sx=r->x, sy=r->y, i, x = 0, y = 0; direction_t d; boolean abbruch=false; region *r2; for(r2=regions; r2; r2=r2->next) { r2->msgs = (void *)0; } tradegood = NULL; terraform_region(r, terrain); if(r->land) settg(r); r->msgs = (void *)(rng_int()%6); push(r); for(d=0; dmsgs = (void *)(int)d; } } while (n>0 && (r=shift())!=NULL) { for(i = -1; i <= 1; i++) { int d = ((int)r->msgs + i + 6)%6; switch(d) { case 0: x=r->x-1; y=r->y; /* Westen */ break; case 1: x=r->x-1; y=r->y+1; /* Nordwesten */ break; case 2: x=r->x; y=r->y+1; /* Nordosten */ break; case 3: x=r->x+1; y=r->y; /* Osten */ break; case 4: x=r->x+1; y=r->y-1; /* Südosten */ break; case 5: x=r->x; y=r->y-1; /* Südwesten */ break; } r2 = findregion(x,y); if (r2 && fval(r2->terrain, SEA_REGION)) { const terrain_type * terrain = NULL; do { terrain_t t = choose_terrain(oldterrain(r2->terrain)); terrain = newterrain(t); } while (terrain==NULL); r2->msgs = (void *)d; push(r2); abbruch = Create_Island(r2, &n, terrain, sx, sy); } if (abbruch) break; } } t_queue_len = 0; }