diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index 480050b88..79dfda44f 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -2787,7 +2787,9 @@ guard_on_cmd(unit * u, struct order * ord) if (fval(u->region->terrain, SEA_REGION)) { cmistake(u, ord, 2, MSG_EVENT); } else { - if (fval(u, RCF_ILLUSIONARY) || u->race == new_race[RC_SPELL]) { + if (fval(u, UFL_MOVED)) { + cmistake(u, ord, 187, MSG_EVENT); + } else if (fval(u->race, RCF_ILLUSIONARY) || u->race == new_race[RC_SPELL]) { cmistake(u, ord, 95, MSG_EVENT); } else { /* Monster der Monsterpartei dürfen immer bewachen */ diff --git a/src/common/gamecode/randenc.c b/src/common/gamecode/randenc.c index 670838713..7d0dd3370 100644 --- a/src/common/gamecode/randenc.c +++ b/src/common/gamecode/randenc.c @@ -610,7 +610,7 @@ damage_unit(unit *u, const char *dam, boolean physical, boolean magic) int h; int i, dead = 0, hp_rem = 0, heiltrank; - if (fval(u, RCF_ILLUSIONARY) || u->race == new_race[RC_SPELL]) { + if (fval(u->race, RCF_ILLUSIONARY) || u->race == new_race[RC_SPELL]) { return 0; } diff --git a/src/common/gamecode/report.c b/src/common/gamecode/report.c index 30cbe6001..3b0aaebce 100644 --- a/src/common/gamecode/report.c +++ b/src/common/gamecode/report.c @@ -2618,7 +2618,7 @@ writeturn(void) sprintf(zText, "%s/turn", basepath()); f = cfopen(zText, "w"); if (!f) return; - fprintf(f,"%d",turn); + fprintf(f, "%d\n", turn); fclose(f); } diff --git a/src/common/kernel/build.c b/src/common/kernel/build.c index 2e66177c7..6a7d30ae2 100644 --- a/src/common/kernel/build.c +++ b/src/common/kernel/build.c @@ -1131,6 +1131,11 @@ leave_cmd(unit * u, struct order * ord) { region * r = u->region; + if (fval(u, UFL_ENTER)) { + /* if we just entered this round, then we don't leave again */ + return 0; + } + if (fval(r->terrain, SEA_REGION) && u->ship) { if(!fval(u->race, RCF_SWIM)) { cmistake(u, ord, 11, MSG_MOVE); @@ -1244,12 +1249,6 @@ do_misc(boolean lasttry) if(lasttry) cmistake(u, ord, 6, MSG_MOVE); break; } - /* Gebäude auf dem Ozean sollte man betreten dürfen - if(rterrain(r) == T_OCEAN) { - if (lasttry) cmistake(u, ord, 297, MSG_MOVE); - break; - } - */ if (!mayenter(r, u, b)) { if(lasttry) { sprintf(buf, "Der Eintritt in %s wurde verwehrt", @@ -1277,11 +1276,13 @@ do_misc(boolean lasttry) if (buildingowner(r, b) == 0) { fset(u, UFL_OWNER); } + fset(u, UFL_ENTER); break; case P_SHIP: sh = getship(r); entership(u, sh, ord, lasttry); + fset(u, UFL_ENTER); break; default: diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c index fd582c685..160a7595d 100644 --- a/src/common/kernel/eressea.c +++ b/src/common/kernel/eressea.c @@ -2433,8 +2433,8 @@ setguard(unit * u, unsigned int flags) } if (flags == GUARD_NONE) { freset(u, UFL_GUARD); - if (a) a_remove(&u->attribs, a); - return; + if (a) a_remove(&u->attribs, a); + return; } fset(u, UFL_GUARD); if (!a) a = a_add(&u->attribs, a_new(&at_guard)); diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c index 3c9555ef4..e343eff36 100644 --- a/src/common/kernel/save.c +++ b/src/common/kernel/save.c @@ -718,6 +718,7 @@ create_backup(char *file) char bfile[MAX_PATH]; int c = 1; + if (access(file, R_OK) == 0) return; do { sprintf(bfile, "%s.backup%d", file, c); c++; @@ -1956,7 +1957,7 @@ readgame(const char * filename, int backup) } int -writegame(const char *filename, char quiet) +writegame(const char *filename, int quiet) { char *base; int n; diff --git a/src/common/kernel/save.h b/src/common/kernel/save.h index 423931861..b638fd08c 100644 --- a/src/common/kernel/save.h +++ b/src/common/kernel/save.h @@ -37,7 +37,7 @@ FILE * cfopen(const char *filename, const char *mode); int readorders(const char *); int creategame(void); extern int readgame(const char * filename, int backup); -int writegame(const char *filename, char quiet); +int writegame(const char *filename, int quiet); extern void rsf(FILE * F, char *s, size_t len); @@ -83,6 +83,8 @@ extern int a_readstring(struct attrib * a, FILE * F); extern void a_writestring(const struct attrib * a, FILE * F); extern void a_finalizestring(struct attrib * a); +extern void create_backup(char *file); + #ifdef __cplusplus } #endif diff --git a/src/common/kernel/unit.c b/src/common/kernel/unit.c index ec6d0be33..571607630 100644 --- a/src/common/kernel/unit.c +++ b/src/common/kernel/unit.c @@ -934,7 +934,7 @@ u_setfaction(unit * u, faction * f) } } -/* vorsicht Sprüche können u->number == 0 (RS_FARVISION) haben! */ +/* vorsicht Sprüche können u->number == RS_FARVISION haben! */ void set_number(unit * u, int count) { diff --git a/src/common/kernel/unit.h b/src/common/kernel/unit.h index 879f3cf47..bd2d7d7e6 100644 --- a/src/common/kernel/unit.h +++ b/src/common/kernel/unit.h @@ -45,6 +45,7 @@ struct item; #define UFL_SIEGE (1<<12) /* speedup: belagert eine burg, siehe attribut */ #define UFL_TARGET (1<<13) /* speedup: hat ein target, siehe attribut */ #define UFL_WERE (1<<14) +#define UFL_ENTER (1<<15) /* unit has entered a ship/building and will not leave it */ /* warning: von 512/1024 gewechslet, wegen konflikt mit NEW_FOLLOW */ #define UFL_LOCKED (1<<16) /* Einheit kann keine Personen aufnehmen oder weggeben, nicht rekrutieren. */ @@ -210,7 +211,6 @@ extern struct building * inside_building(const struct unit * u); extern void free_units(void); extern struct faction * dfindhash(int no); extern void u_setfaction(struct unit * u, struct faction * f); -/* vorsicht Sprüche können u->number == 0 (RS_FARVISION) haben! */ extern void set_number(struct unit * u, int count); extern boolean learn_skill(struct unit * u, skill_t sk, double chance); diff --git a/src/common/util/log.c b/src/common/util/log.c index 666411727..b3ffd7df6 100644 --- a/src/common/util/log.c +++ b/src/common/util/log.c @@ -19,7 +19,7 @@ without prior permission by the authors of Eressea. #include /* TODO: set from external function */ -static int flags = LOG_FLUSH|LOG_CPERROR|LOG_CPWARNING; +int log_flags = LOG_FLUSH|LOG_CPERROR|LOG_CPWARNING; static FILE * logfile; void @@ -44,7 +44,7 @@ log_printf(const char * format, ...) va_start(marker, format); vfprintf(logfile, format, marker); va_end(marker); - if (flags & LOG_FLUSH) { + if (log_flags & LOG_FLUSH) { log_flush(); } } @@ -89,7 +89,7 @@ check_dupe(const char * format, const char * type) if (dupes) { fprintf(logfile, "%s: last error repeated %d times\n", last_type, dupes+1); if (logfile!=stderr) { - if (flags & LOG_CPERROR) { + if (log_flags & LOG_CPERROR) { fprintf(stderr, "%s: last error repeated %d times\n", last_type, dupes+1); } } @@ -113,13 +113,13 @@ _log_warn(const char * format, ...) vfprintf(logfile, format, marker); va_end(marker); if (logfile!=stderr) { - if (flags & LOG_CPWARNING) { + if (log_flags & LOG_CPWARNING) { fputs("WARNING: ", stderr); va_start(marker, format); vfprintf(stderr, format, marker); va_end(marker); } - if (flags & LOG_FLUSH) { + if (log_flags & LOG_FLUSH) { log_flush(); } } @@ -139,7 +139,7 @@ _log_error(const char * format, ...) vfprintf(logfile, format, marker); va_end(marker); if (logfile!=stderr) { - if (flags & LOG_CPERROR) { + if (log_flags & LOG_CPERROR) { fputs("ERROR: ", stderr); va_start(marker, format); vfprintf(stderr, format, marker); @@ -162,13 +162,13 @@ _log_info(unsigned int flag, const char * format, ...) vfprintf(logfile, format, marker); va_end(marker); if (logfile!=stderr) { - if (flags & flag) { + if (log_flags & flag) { fprintf(stderr, "INFO[%u]: ", flag); va_start(marker, format); vfprintf(stderr, format, marker); va_end(marker); } - if (flags & LOG_FLUSH) { + if (log_flags & LOG_FLUSH) { log_flush(); } } diff --git a/src/common/util/log.h b/src/common/util/log.h index 07008330b..22482d20b 100644 --- a/src/common/util/log.h +++ b/src/common/util/log.h @@ -34,6 +34,7 @@ extern "C" { #define LOG_CPWARNING (1<<1) #define LOG_CPERROR (1<<2) + extern int log_flags; #ifdef __cplusplus } #endif diff --git a/src/eressea.sln b/src/eressea.sln index 1b2548def..988081204 100644 --- a/src/eressea.sln +++ b/src/eressea.sln @@ -73,6 +73,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eressea-lua", "eressea\eres {4C837BEC-A428-4287-84B3-8F8F9DE7FA00} = {4C837BEC-A428-4287-84B3-8F8F9DE7FA00} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmtool", "eressea\gmtool.vcproj", "{57BA2AEE-5C65-4839-9294-C0FA2915A06C}" + ProjectSection(ProjectDependencies) = postProject + {C14E3D2B-8189-4570-A4E3-9010C873E4FD} = {C14E3D2B-8189-4570-A4E3-9010C873E4FD} + {EF495253-2EEC-4F83-B6C0-D651F88B2198} = {EF495253-2EEC-4F83-B6C0-D651F88B2198} + {1D80D05F-BCF5-4971-8F06-D9581FD3B1F4} = {1D80D05F-BCF5-4971-8F06-D9581FD3B1F4} + {601CF164-F483-4DE7-8014-64BDD30680B5} = {601CF164-F483-4DE7-8014-64BDD30680B5} + {EDB0DE67-8215-4AF7-ACA1-F23CB11FF211} = {EDB0DE67-8215-4AF7-ACA1-F23CB11FF211} + {0EE778AB-8445-40DB-8F65-6BE378A91B97} = {0EE778AB-8445-40DB-8F65-6BE378A91B97} + {330712B5-8B27-4B17-B3CF-7A02CC0F93C3} = {330712B5-8B27-4B17-B3CF-7A02CC0F93C3} + {4C837BEC-A428-4287-84B3-8F8F9DE7FA00} = {4C837BEC-A428-4287-84B3-8F8F9DE7FA00} + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -150,6 +162,12 @@ Global {749A2F7C-B9C3-4CEB-B1B2-1D4587E68719}.Profile.Build.0 = Profile|Win32 {749A2F7C-B9C3-4CEB-B1B2-1D4587E68719}.Release.ActiveCfg = Release|Win32 {749A2F7C-B9C3-4CEB-B1B2-1D4587E68719}.Release.Build.0 = Release|Win32 + {57BA2AEE-5C65-4839-9294-C0FA2915A06C}.Debug.ActiveCfg = Debug|Win32 + {57BA2AEE-5C65-4839-9294-C0FA2915A06C}.Debug.Build.0 = Debug|Win32 + {57BA2AEE-5C65-4839-9294-C0FA2915A06C}.Profile.ActiveCfg = Profile|Win32 + {57BA2AEE-5C65-4839-9294-C0FA2915A06C}.Profile.Build.0 = Profile|Win32 + {57BA2AEE-5C65-4839-9294-C0FA2915A06C}.Release.ActiveCfg = Release|Win32 + {57BA2AEE-5C65-4839-9294-C0FA2915A06C}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/src/eressea/Jamfile b/src/eressea/Jamfile index 7c78175f0..23cf321da 100644 --- a/src/eressea/Jamfile +++ b/src/eressea/Jamfile @@ -7,10 +7,15 @@ SubDirHdrs $(SUBDIR)/../common/util ; SubDirHdrs $(SUBDIR)/../common ; SubDirHdrs $(SUBDIR)/.. ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) curses ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) lua ] ; +SubDirC++Flags -DHAVE_LUA ; + SubDirHdrs $(XMLHDRS) ; LUASERVER = eressea-lua ; SERVER = eressea ; +GMTOOL = gmtool ; SERVER_SOURCES = main.c korrektur.c ; LUASERVER_SOURCES = @@ -32,25 +37,33 @@ LUASERVER_SOURCES = console.c ; +GMTOOL_SOURCES = + listbox.c + gmtool.c + editing.c + ; + +# the curses-based GM tool +Main $(GMTOOL) : $(GMTOOL_SOURCES) ; +LinkLibraries $(GMTOOL) : + kernel modules items attributes spells races triggers util ; +libxml2 $(GMTOOL) ; +LINKLIBS on $(GMTOOL) += -L$(LUABIND_ROOT)/lib -lm -lncurses ; + +# old eressea server. use only for testing. LinkLibraries $(SERVER) : gamecode kernel items modules attributes spells races triggers util ; -LinkLibraries $(LUASERVER) : - gamecode kernel items modules attributes spells races triggers util ; - libxml2 $(SERVER) ; LINKLIBS on $(SERVER) += -L$(LUABIND_ROOT)/lib -lm ; +Main $(SERVER) : $(SERVER_SOURCES) ; +# eressea-server with lua scripting +LinkLibraries $(LUASERVER) : + gamecode kernel items modules attributes spells races triggers util ; luabind $(LUASERVER) ; libxml2 $(LUASERVER) ; LINKLIBS on $(LUASERVER) += -lm -ldl -lstdc++ ; +UsingLua ; +UsingLuabind ; +Main $(LUASERVER) : $(LUASERVER_SOURCES) ; -if ! $(WITHOUT_LUA) { - SEARCH_SOURCE += [ FDirName $(SUBDIR) lua ] ; - SubDirC++Flags -DHAVE_LUA ; - UsingLua ; - UsingLuabind ; - - Main $(LUASERVER) : $(LUASERVER_SOURCES) ; -} - -Main $(SERVER) : $(SERVER_SOURCES) ; diff --git a/src/eressea/curses/listbox.c b/src/eressea/curses/listbox.c new file mode 100644 index 000000000..792efdb3d --- /dev/null +++ b/src/eressea/curses/listbox.c @@ -0,0 +1,164 @@ +/* vi: set ts=2: +* +-------------------+ Christian Schlittchen +* | | Enno Rehling +* | Eressea PBEM host | Katja Zedel +* | (c) 1998 - 2006 | +* | | 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 */ +#include +#include + +#include "listbox.h" + +#include +#include + +void +insert_selection(list_selection ** p_sel, list_selection * prev, const char * str, void * payload) +{ + list_selection * sel = calloc(sizeof(list_selection), 1); + sel->str = strdup(str); + sel->data = payload; + if (*p_sel) { + list_selection * s; + sel->next = *p_sel; + sel->prev = sel->next->prev; + sel->next->prev=sel; + if (sel->prev) { + sel->prev->next = sel; + sel->index=sel->prev->index+1; + } + for (s=sel->next;s;s=s->next) { + s->index = s->prev->index+1; + } + *p_sel = sel; + } else { + *p_sel = sel; + sel->prev = prev; + if (prev) sel->index=prev->index+1; + } +} + +list_selection ** +push_selection(list_selection ** p_sel, char * str, void * payload) +{ + list_selection * sel = calloc(sizeof(list_selection), 1); + list_selection * prev = NULL; + sel->str = str; + sel->data = payload; + while (*p_sel) { + prev = *p_sel; + p_sel=&prev->next; + } + *p_sel = sel; + if (prev) { + sel->prev = prev; + sel->index = prev->index+1; + } + return p_sel; +} + +#define SX (stdscr->_maxx) +#define SY (stdscr->_maxy) + +list_selection * +do_selection(list_selection * sel, const char * title, void (*perform)(list_selection *, void *), void * data) +{ + WINDOW * wn; + boolean update = true; + list_selection *s; + list_selection *top = sel; + list_selection *current = top; + int i; + int height = 0, width = (int)strlen(title)+8; + for (s=sel;s;s=s->next) { + if ((int)strlen(s->str)>width) width = (int)strlen(s->str); + ++height; + } + if (height==0 || width==0) return NULL; + if (width+3>SX) width=SX-4; + if (height+2>SY) height=SY-2; + + wn = newwin(height+2, width+4, (SY - height - 2) / 2, (SX - width - 4) / 2); + + for (;;) { + int input; + if (update) { + wclear(wn); + for (s=top;s!=NULL && top->index+height!=s->index;s=s->next) { + i = s->index-top->index; + wmove(wn, i + 1, 4); + waddnstr(wn, s->str, -1); + } + wborder(wn, 0, 0, 0, 0, 0, 0, 0, 0); + mvwprintw(wn, 0, 2, "[ %s ]", title); + update = false; + } + i = current->index-top->index; + wattron(wn, A_BOLD | COLOR_PAIR(COLOR_YELLOW)); + wmove(wn, i + 1, 2); + waddstr(wn, "->"); + wmove(wn, i + 1, 4); + waddnstr(wn, current->str, width); + wattroff(wn, A_BOLD | COLOR_PAIR(COLOR_YELLOW)); + + wrefresh(wn); + + input = getch(); + + wmove(wn, i + 1, 2); + waddstr(wn, " "); + wmove(wn, i + 1, 4); + waddnstr(wn, current->str, width); + + switch (input) { + case KEY_DOWN: + if (current->next) { + current = current->next; + if (current->index-height>=top->index) { + top=current; + update = true; + } + } + break; + case KEY_UP: + if (current->prev) { + if (current==top) { + top = sel; + while (top->index+heightindex) top=top->next; + update = true; + } + current = current->prev; + } + break; + case 27: + case 'q': + delwin(wn); + return NULL; + case 10: + case 13: + if (perform) perform(current, data); + else { + delwin(wn); + return current; + } + break; + default: + s = current->next; + if (s==NULL) s = top; + while (s!=current) { + if (tolower(s->str[0])==tolower(input)) { + current = s; + update = true; + } else { + s = s->next; + if (s==NULL) s = top; + } + } + } + } +} diff --git a/src/eressea/curses/listbox.h b/src/eressea/curses/listbox.h new file mode 100644 index 000000000..ab2c7f9bc --- /dev/null +++ b/src/eressea/curses/listbox.h @@ -0,0 +1,16 @@ +#ifndef CURSES_LISTBOX +#define CURSES_LISTBOX + +typedef struct list_selection { + struct list_selection * next; + struct list_selection * prev; + int index; + char * str; + void * data; +} list_selection; + +extern struct list_selection * do_selection(struct list_selection * sel, const char * title, void (*perform)(struct list_selection *, void *), void * data); +extern struct list_selection ** push_selection(struct list_selection ** p_sel, char * str, void * payload); +extern void insert_selection(struct list_selection ** p_sel, struct list_selection * prev, const char * str, void * payload); + +#endif /* CURSES_LISTBOX */ diff --git a/src/eressea/editing.c b/src/eressea/editing.c new file mode 100644 index 000000000..fcde1366e --- /dev/null +++ b/src/eressea/editing.c @@ -0,0 +1,41 @@ +/* vi: set ts=2: + * +-------------------+ Christian Schlittchen + * | | Enno Rehling + * | Eressea PBEM host | Katja Zedel + * | (c) 1998 - 2006 | + * | | This program may not be used, modified or distributed + * +-------------------+ without prior permission by the authors of Eressea. + * + */ + +#include +#include +#include "editing.h" + +#include + +void +make_block(short x, short y, short radius, const struct terrain_type * terrain) +{ + short cx, cy; + region *r; + + 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); + terraform_region(r, terrain); + } + } + } + } +} + +void +make_island(short x, short y, int size) +{ + /* region_list * island; */ +} diff --git a/src/eressea/editing.h b/src/eressea/editing.h new file mode 100644 index 000000000..7cd936947 --- /dev/null +++ b/src/eressea/editing.h @@ -0,0 +1,17 @@ +/* vi: set ts=2: + * +-------------------+ Christian Schlittchen + * | | Enno Rehling + * | Eressea PBEM host | Katja Zedel + * | (c) 1998 - 2006 | + * | | This program may not be used, modified or distributed + * +-------------------+ without prior permission by the authors of Eressea. + * + */ + +#ifndef GM_EDITING +#define GM_EDITING + +extern void make_block(short x, short y, short radius, const struct terrain_type * terrain); +extern void make_island(short x, short y, int size); + +#endif /* GM_EDITING */ diff --git a/src/eressea/gmtool.c b/src/eressea/gmtool.c new file mode 100644 index 000000000..d125bc3a0 --- /dev/null +++ b/src/eressea/gmtool.c @@ -0,0 +1,1166 @@ +/* vi: set ts=2: + * +-------------------+ Christian Schlittchen + * | | Enno Rehling + * | Eressea PBEM host | Katja Zedel + * | (c) 1998 - 2006 | + * | | 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 */ +#include +#include +#include + +#include "gmtool.h" +#include "editing.h" +#include "curses/listbox.h" + +#include +#include +#include +#ifdef MUSEUM_MODULE +#include +#endif +#ifdef ARENA_MODULE +#include +#endif +#ifdef WORMHOLE_MODULE +#include +#endif +#ifdef DUNGEON_MODULE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +extern char * g_reportdir; +extern char * g_datadir; +extern char * g_basedir; +extern char * g_resourcedir; + +static int g_quit; +static const char * g_logfile = "gmtool.log"; +static int force_color = 0; + +#define IFL_SHIPS (1<<0) +#define IFL_UNITS (1<<1) +#define IFL_FACTIONS (1<<2) +#define IFL_BUILDINGS (1<<3) + +static int +usage(const char * prog, const char * arg) +{ + if (arg) { + fprintf(stderr, "unknown argument: %s\n\n", arg); + } + fprintf(stderr, "Usage: %s [options]\n" + "-b basedir : gibt das basisverzeichnis an\n" + "-d datadir : gibt das datenverzeichnis an\n" + "-r resdir : gibt das resourceverzeichnis an\n" + "-t turn : read this datafile, not the most current one\n" + "-v : be verbose\n" + "-l logfile : write messages to \n" + "--xml xmlfile : read settings from .\n" + "--lomem : save RAM\n" + "--color : force color mode\n" + "--help : help\n", prog); + return -1; +} + +static int +read_args(int argc, char **argv) +{ + int i; + + quiet = 1; + turn = first_turn; + + for (i=1;i!=argc;++i) { + if (argv[i][0]!='-') { + return usage(argv[0], argv[i]); + } else if (argv[i][1]=='-') { /* long format */ + if (strncmp(argv[i]+2, "xml", 3)==0) { + if (argv[i][5]=='=') xmlfile = argv[i]+6; + else xmlfile = argv[++i]; + } else if (strncmp(argv[i]+2, "log", 3)==0) { + if (argv[i][5]=='=') g_logfile = argv[i]+6; + else g_logfile = argv[++i]; + } else if (strncmp(argv[i]+2, "res", 3)==0) { + if (argv[i][5]=='=') g_resourcedir = argv[i]+6; + else g_resourcedir = argv[++i]; + } else if (strncmp(argv[i]+2, "base", 4)==0) { + if (argv[i][6]=='=') g_basedir = argv[i]+7; + else g_basedir = argv[++i]; + } else if (strncmp(argv[i]+2, "turn", 4)==0) { + if (argv[i][6]=='=') turn = atoi(argv[i]+7); + else turn = atoi(argv[++i]); + } else if (strncmp(argv[i]+2, "data", 4)==0) { + if (argv[i][6]=='=') g_datadir = argv[i]+7; + else g_datadir = argv[++i]; + } else if (strcmp(argv[i]+2, "lomem")==0) { + lomem = true; + } else if (strcmp(argv[i]+2, "color")==0) { + force_color = 1; + } else if (strcmp(argv[i]+2, "help")==0) + return usage(argv[0], NULL); + else + return usage(argv[0], argv[i]); + } else { + int k; + boolean next = false; + + for (k=0;!next && argv[i][k];++k) { + int c = argv[i][k]; + switch (c) { + case 'd': + g_datadir = argv[++i]; + next = true; + break; + case 'r': + g_resourcedir = argv[++i]; + next = true; + break; + case 'b': + g_basedir = argv[++i]; + next = true; + break; + case 'i': + xmlfile = argv[++i]; + next = true; + break; + case 't': + turn = atoi(argv[++i]); + next = true; + break; + case 'v': + quiet = 0; + break; + default: + usage(argv[0], argv[i]); + } + } + } + } + return 0; +} + +static void +game_init(void) +{ + init_triggers(); + init_xmas(); + + register_races(); + register_resources(); + register_buildings(); + register_ships(); + register_spells(); +#ifdef DUNGEON_MODULE + register_dungeon(); +#endif +#ifdef MUSEUM_MODULE + register_museum(); +#endif +#ifdef ARENA_MODULE + register_arena(); +#endif +#ifdef WORMHOLE_MODULE + register_wormholes(); +#endif + + register_itemtypes(); + register_xmlreader(); + + init_data(xmlfile); + + init_locales(); + /* init_resources(); must be done inside the xml-read, because requirements use items */ + + init_attributes(); + init_races(); + init_itemtypes(); + init_rawmaterials(); + + init_gmcmd(); +#ifdef INFOCMD_MODULE + init_info(); +#endif +} + +static void +game_done(void) +{ +} + +static void +init_curses(void) +{ + initscr(); + + if (has_colors() || force_color) { + short bcol = COLOR_BLACK; + start_color(); + if (can_change_color()) { + init_color(COLOR_YELLOW, 1000, 1000, 0); + } + init_pair(COLOR_BLACK, COLOR_BLACK, bcol); + init_pair(COLOR_GREEN, COLOR_GREEN, bcol); + init_pair(COLOR_GREEN, COLOR_GREEN, bcol); + init_pair(COLOR_RED, COLOR_RED, bcol); + init_pair(COLOR_CYAN, COLOR_CYAN, bcol); + init_pair(COLOR_WHITE, COLOR_WHITE, bcol); + init_pair(COLOR_MAGENTA, COLOR_MAGENTA, bcol); + init_pair(COLOR_BLUE, COLOR_BLUE, bcol); + init_pair(COLOR_YELLOW, COLOR_YELLOW, bcol); + init_pair(COLOR_YELLOW, COLOR_YELLOW, bcol); + init_pair(COLOR_WHITE, COLOR_WHITE, bcol); + + attrset(COLOR_PAIR(COLOR_BLACK)); + bkgd(' ' | COLOR_PAIR(COLOR_BLACK)); + bkgdset(' ' | COLOR_PAIR(COLOR_BLACK)); + } + + keypad(stdscr, TRUE); /* enable keyboard mapping */ + nonl(); /* tell curses not to do NL->CR/NL on output */ + cbreak(); /* take input chars one at a time, no wait for \n */ + noecho(); /* don't echo input */ + scrollok(stdscr, FALSE); + wclear(stdscr); +} + +static map_region * +mr_get(const view * vi, int xofs, int yofs) +{ + return vi->regions + xofs + yofs * vi->extent.width; +} + +static coordinate * +point2coor(const point * p, coordinate * c) +{ + int x, y; + assert(p && c); + /* wegen division (-1/2==0): + * verschiebung um (0x200000,0x200000) ins positive */ + x = p->x + TWIDTH*0x200000+TWIDTH*0x100000; + y = p->y + THEIGHT*0x200000; + c->x = (x - y * TWIDTH / 2) / TWIDTH - 0x200000; + c->y = y / THEIGHT - 0x200000; + return c; +} + +static point * +coor2point(const coordinate * c, point * p) +{ + assert(c && p); + p->x = c->x * TWIDTH + c->y * TWIDTH / 2; + p->y = c->y * THEIGHT; + return p; +} + +static window * wnd_first, * wnd_last; + +static window * +win_create(WINDOW * hwin) +{ + window * wnd = calloc(1, sizeof(window)); + wnd->handle = hwin; + if (wnd_first!=NULL) { + wnd->next = wnd_first; + wnd_first->prev = wnd; + wnd_first = wnd; + } else { + wnd_first = wnd; + wnd_last = wnd; + } + return wnd; +} + +static void +untag_region(selection * s, const coordinate * c) +{ + unsigned int key = ((c->x << 12) ^ c->y); + 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; + tp=&t->nexthash; + } + if (!*tp) return; + *tp = t->nexthash; + free(t); + return; +} + +static void +tag_region(selection * s, const coordinate * c) +{ + unsigned int key = ((c->x << 12) ^ c->y); + 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; + tp=&t->nexthash; + } + *tp = calloc(1, sizeof(tag)); + (*tp)->coord = *c; + return; +} + +static int +tagged_region(selection * s, const coordinate * c) +{ + unsigned int key = ((c->x << 12) ^ c->y); + 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; + tp=&t->nexthash; + } + return 0; +} + +static int +mr_tile(const map_region * mr) +{ + if (mr!=NULL && mr->r!=NULL) { + const region * r = mr->r; + switch (r->terrain->_name[0]) { + case 'o' : + return '.' | COLOR_PAIR(COLOR_CYAN); + case 'd' : + return 'D' | COLOR_PAIR(COLOR_YELLOW) | A_BOLD; + case 't' : + return '%' | COLOR_PAIR(COLOR_YELLOW) | A_BOLD; + case 'f' : + if (r->terrain->_name[1]=='o') { /* fog */ + return '.' | COLOR_PAIR(COLOR_YELLOW) | A_NORMAL; + } else if (r->terrain->_name[1]=='i') { /* firewall */ + return '%' | COLOR_PAIR(COLOR_RED) | A_BOLD; + } + case 'h' : + return 'H' | COLOR_PAIR(COLOR_YELLOW) | A_NORMAL; + case 'm' : + return '^' | COLOR_PAIR(COLOR_WHITE) | A_NORMAL; + case 'p' : + if (r_isforest(r)) return '#' | COLOR_PAIR(COLOR_GREEN) | A_NORMAL; + return '+' | COLOR_PAIR(COLOR_GREEN) | A_BOLD; + case 'g' : + return '*' | COLOR_PAIR(COLOR_WHITE) | A_BOLD; + case 's' : + return 'S' | COLOR_PAIR(COLOR_MAGENTA) | A_NORMAL; + } + return r->terrain->_name[0] | COLOR_PAIR(COLOR_RED); + } + return ' ' | COLOR_PAIR(COLOR_WHITE); +} + +static void +paint_map(window * wnd, const state * st) +{ + WINDOW * win = wnd->handle; + int lines = getmaxy(win); + int cols = getmaxx(win); + int x, y; + + lines = lines/THEIGHT; + cols = cols/TWIDTH; + for (y = 0; y!=lines; ++y) { + int yp = (lines - y - 1) * THEIGHT; + for (x = 0; x!=cols; ++x) { + int attr = 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; + } + if (mr) { + mvwaddch(win, yp, xp, mr_tile(mr) | attr); + } + } + } +} + +static map_region * +cursor_region(const view * v, const coordinate * c) +{ + coordinate relpos; + int cx, cy; + + relpos.x = c->x - v->topleft.x; + relpos.y = c->y - v->topleft.y; + cy = relpos.y; + cx = relpos.x + cy/2; + return mr_get(v, cx, cy); +} + +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 attr = 0; + map_region * mr = cursor_region(v, c); + coordinate relpos; + int cx, cy; + + relpos.x = c->x - v->topleft.x; + relpos.y = c->y - v->topleft.y; + cy = relpos.y; + cx = relpos.x + cy/2; + + yp = (lines - cy - 1) * THEIGHT; + xp = cx * TWIDTH + (cy & 1) * TWIDTH/2; + if (s && tagged_region(s, &mr->coord)) attr = A_REVERSE; + if (mr->r) { + mvwaddch(win, yp, xp, mr_tile(mr) | attr); + } + else mvwaddch(win, yp, xp, ' ' | attr | COLOR_PAIR(COLOR_YELLOW)); + if (show) { + attr = A_BOLD; + mvwaddch(win, yp, xp-1, '<' | attr | COLOR_PAIR(COLOR_YELLOW)); + mvwaddch(win, yp, xp+1, '>' | attr | COLOR_PAIR(COLOR_YELLOW)); + } else { + attr = A_NORMAL; + mvwaddch(win, yp, xp-1, ' ' | attr | COLOR_PAIR(COLOR_WHITE)); + mvwaddch(win, yp, xp+1, ' ' | attr | COLOR_PAIR(COLOR_WHITE)); + } + wmove(win, yp, xp); +} + + + +static void +paint_status(window * wnd, const state * st) +{ + WINDOW * win = wnd->handle; + const char * name = ""; + const char * terrain = "----"; + map_region * mr = cursor_region(&st->display, &st->cursor); + if (mr && mr->r) { + if (mr->r->land) { + name = mr->r->land->name; + } else { + name = mr->r->terrain->_name; + } + terrain = mr->r->terrain->_name; + } + mvwprintw(win, 0, 0, "%4d %4d | %.4s | %.20s", st->cursor.x, st->cursor.y, terrain, name); + wclrtoeol(win); +} + +static boolean +handle_info_region(window * wnd, state * st, int c) +{ + return false; +} + +static void +paint_info_region(window * wnd, const state * st) +{ + WINDOW * win = wnd->handle; + int size = getmaxx(win)-2; + int line = 0, maxline = getmaxy(win)-2; + map_region * mr = cursor_region(&st->display, &st->cursor); + + unused(st); + werase(win); + wborder(win, 0, 0, 0, 0, 0, 0, 0, 0); + if (mr && mr->r) { + const region * r = mr->r; + if (r->land) { + mvwaddnstr(win, line++, 1, r->land->name, size); + } else { + mvwaddnstr(win, line++, 1, r->terrain->_name, size); + } + line++; + mvwprintw(win, line++, 1, "%s, age %d", r->terrain->_name, r->age); + if (r->land) { + mvwprintw(win, line++, 1, "$:%6d P:%5d", r->land->money, r->land->peasants); + mvwprintw(win, line++, 1, "H:%6d %s:%5d", r->land->horses, (r->flags&RF_MALLORN)?"M":"T", r->land->trees[1]+r->land->trees[2]); + } + line++; + if (r->ships && (st->info_flags & IFL_SHIPS)) { + ship * sh; + wattron(win, A_BOLD | COLOR_PAIR(COLOR_YELLOW)); + mvwaddnstr(win, line++, 1, "* ships:", size-5); + wattroff(win, A_BOLD | COLOR_PAIR(COLOR_YELLOW)); + for (sh=r->ships;sh && linenext) { + mvwprintw(win, line, 1, "%.4s ", itoa36(sh->no)); + mvwaddnstr(win, line++, 6, (char*)sh->type->name[0], size-5); + } + } + if (r->units && (st->info_flags & IFL_FACTIONS)) { + unit * u; + wattron(win, A_BOLD | COLOR_PAIR(COLOR_YELLOW)); + mvwaddnstr(win, line++, 1, "* factions:", size-5); + wattroff(win, A_BOLD | COLOR_PAIR(COLOR_YELLOW)); + for (u=r->units;u && linenext) { + if (!fval(u->faction, FL_MARK)) { + mvwprintw(win, line, 1, "%.4s ", itoa36(u->faction->no)); + mvwaddnstr(win, line++, 6, u->faction->name, size-5); + fset(u->faction, FL_MARK); + } + } + for (u=r->units;u && linenext) { + freset(u->faction, FL_MARK); + } + } + if (r->units && (st->info_flags & IFL_UNITS)) { + unit * u; + wattron(win, A_BOLD | COLOR_PAIR(COLOR_YELLOW)); + mvwaddnstr(win, line++, 1, "* units:", size-5); + wattroff(win, A_BOLD | COLOR_PAIR(COLOR_YELLOW)); + for (u=r->units;u && linenext) { + mvwprintw(win, line, 1, "%.4s ", itoa36(u->no)); + mvwaddnstr(win, line++, 6, u->name, size-5); + } + } + } +} + +static char * +askstring(WINDOW * win, const char * q, char * buffer, size_t size) +{ + werase(win); + mvwaddstr(win, 0, 0, (char*)q); + wmove(win, 0, (int)(strlen(q)+1)); + echo(); + wgetnstr(win, buffer, (int)size); + noecho(); + return buffer; +} + +static void +statusline(WINDOW * win, const char * str) +{ + mvwaddstr(win, 0, 0, (char*)str); + wclrtoeol(win); + wrefresh(win); +} + +static void +terraform_at(coordinate * c, const terrain_type *terrain) +{ + if (terrain!=NULL) { + short x = (short)c->x, y = (short)c->y; + region * r = findregion(x, y); + if (r==NULL) r = new_region(x, y); + terraform_region(r, terrain); + } +} + +static void +terraform_selection(selection * selected, const terrain_type *terrain) +{ + int i; + + if (terrain==NULL) return; + for (i=0;i!=MAXTHASH;++i) { + tag ** tp = &selected->tags[i]; + while (*tp) { + tag * t = *tp; + short x = (short)t->coord.x, y = (short)t->coord.y; + region * r = findregion(x, y); + if (r==NULL) r = new_region(x, y); + terraform_region(r, terrain); + tp = &t->nexthash; + } + } +} + +const terrain_type * +select_terrain(const terrain_type * default_terrain) +{ + list_selection *prev, *ilist = NULL, **iinsert; + list_selection *selected = NULL; + const terrain_type * terrain = terrains(); + + if (!terrain) return NULL; + iinsert = &ilist; + prev = ilist; + + while (terrain) { + insert_selection(iinsert, NULL, 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; +} + +static coordinate * +region2coord(const region * r, coordinate * c) +{ + c->x = r->x; + c->y = r->y; + c->p = r->planep?r->planep->id:0; + return c; +} + +#ifdef __PDCURSES__ +#define FAST_UP CTL_UP +#define FAST_DOWN CTL_DOWN +#define FAST_LEFT CTL_LEFT +#define FAST_RIGHT CTL_RIGHT +#else +#define FAST_UP KEY_PPAGE +#define FAST_DOWN KEY_NPAGE +#define FAST_LEFT KEY_SLEFT +#define FAST_RIGHT KEY_SRIGHT +#endif + +static void +handlekeys(state * st) +{ + window * wnd; + int c = getch(); + coordinate * cursor = &st->cursor; + static char locate[80]; + static int findmode = 0; + region *r; + boolean invert = false; + char sbuffer[80]; + + switch(c) { + case FAST_RIGHT: + cursor->x+=10; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + break; + case FAST_LEFT: + cursor->x-=10; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + break; + case FAST_UP: + cursor->y+=10; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + break; + case FAST_DOWN: + cursor->y-=10; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + break; + case KEY_UP: + cursor->y++; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + break; + case KEY_DOWN: + cursor->y--; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + break; + case KEY_RIGHT: + cursor->x++; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + break; + case KEY_LEFT: + cursor->x--; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + break; + case KEY_SAVE: + case KEY_F(2): + if (st->modified) { + char datafile[MAX_PATH]; + + askstring(st->wnd_status->handle, "save as:", datafile, sizeof(datafile)); + if (strlen(datafile)>0) { + create_backup(datafile); + remove_empty_units(); + writegame(datafile, quiet); + st->modified = 0; + } + } + break; + case 'B': + make_block((short)st->cursor.x, (short)st->cursor.y, 6, select_terrain(NULL)); + 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((short)st->cursor.x, (short)st->cursor.y, 6, newterrain(T_OCEAN)); + st->modified = 1; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + st->wnd_map->update |= 1; + break; + case 0x09: /* tab = next selected*/ + if (regions!=NULL) { + map_region * mr = cursor_region(&st->display, cursor); + region * first = mr->r; + region * r = (first&&first->next)?first->next:regions; + while (r!=first) { + coordinate coord; + region2coord(r, &coord); + if (tagged_region(st->selected, &coord)) { + st->cursor = coord; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + break; + } + r = r->next; + if (!r && first) r = regions; + } + } + break; + + case 'a': + if (regions!=NULL) { + map_region * mr = cursor_region(&st->display, cursor); + if (mr->r) { + region * r = mr->r; + if (r->planep==NULL) { + r = r_standard_to_astral(r); + } else if (r->planep==get_astralplane()) { + r = r_astral_to_standard(r); + } else { + r = NULL; + } + if (r!=NULL) { + region2coord(r, &st->cursor); + } else { + beep(); + } + } + } + break; + case 'g': + askstring(st->wnd_status->handle, "goto-x:", sbuffer, 12); + if (sbuffer[0]) { + askstring(st->wnd_status->handle, "goto-y:", sbuffer+16, 12); + if (sbuffer[16]) { + st->cursor.x = atoi(sbuffer); + st->cursor.y = atoi(sbuffer+16); + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + } + } + break; + case 't': + terraform_at(&st->cursor, select_terrain(NULL)); + st->modified = 1; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + st->wnd_map->update |= 1; + break; + case 'I': + statusline(st->wnd_status->handle, "info-"); + do { + c = getch(); + switch (c) { + case 's': + st->info_flags ^= IFL_SHIPS; + if (st->info_flags & IFL_SHIPS) statusline(st->wnd_status->handle, "info-ships true"); + else statusline(st->wnd_status->handle, "info-ships false"); + break; + case 'b': + st->info_flags ^= IFL_BUILDINGS; + if (st->info_flags & IFL_BUILDINGS) statusline(st->wnd_status->handle, "info-buildings true"); + else statusline(st->wnd_status->handle, "info-buildings false"); + case 'f': + st->info_flags ^= IFL_FACTIONS; + if (st->info_flags & IFL_FACTIONS) statusline(st->wnd_status->handle, "info-factions true"); + else statusline(st->wnd_status->handle, "info-factions false"); + break; + case 'u': + st->info_flags ^= IFL_UNITS; + if (st->info_flags & IFL_UNITS) statusline(st->wnd_status->handle, "info-units true"); + else statusline(st->wnd_status->handle, "info-units false"); + break; + case 27: /* esc */ + break; + default: + beep(); + c = 0; + } + } while (c==0); + break; + case 'U': + invert = true; + /* !! intentional fall-through !! */ + case 'T': + statusline(st->wnd_status->handle, "untag-"+(invert?0:2)); + findmode = getch(); + if (findmode=='n') { /* none */ + int i; + statusline(st->wnd_status->handle, "tag-none"); + for (i=0;i!=MAXTHASH;++i) { + tag ** tp = &st->selected->tags[i]; + while (*tp) { + tag * t = *tp; + *tp = t->nexthash; + free(t); + } + } + } + else if (findmode=='u') { + sprintf(sbuffer, "%stag-units", invert?"un":""); + statusline(st->wnd_status->handle, sbuffer); + for (r=regions;r;r=r->next) { + if (r->units) { + coordinate coord; + if (invert) untag_region(st->selected, region2coord(r, &coord)); + else tag_region(st->selected, region2coord(r, &coord)); + } + } + } + else if (findmode=='s') { + sprintf(sbuffer, "%stag-ships", invert?"un":""); + statusline(st->wnd_status->handle, sbuffer); + for (r=regions;r;r=r->next) { + if (r->ships) { + coordinate coord; + if (invert) untag_region(st->selected, region2coord(r, &coord)); + else tag_region(st->selected, region2coord(r, &coord)); + } + } + } + else if (findmode=='f') { + askstring(st->wnd_status->handle, "untag-faction:"+(invert?0:2), sbuffer, 12); + if (sbuffer[0]) { + faction * f = findfaction(atoi36(sbuffer)); + + if (f!=NULL) { + unit * u; + coordinate coord; + + sprintf(sbuffer, "%stag-terrain: %s", invert?"un":"", itoa36(f->no)); + statusline(st->wnd_status->handle, sbuffer); + for (u=f->units;u;u=u->nextF) { + if (invert) untag_region(st->selected, region2coord(u->region, &coord)); + else tag_region(st->selected, region2coord(u->region, &coord)); + } + } else { + statusline(st->wnd_status->handle, "faction not found."); + beep(); + break; + } + } + } + else if (findmode=='t') { + const struct terrain_type * terrain; + statusline(st->wnd_status->handle, "untag-terrain: "+(invert?0:2)); + terrain = select_terrain(NULL); + if (terrain!=NULL) { + sprintf(sbuffer, "%stag-terrain: %s", invert?"un":"", terrain->_name); + statusline(st->wnd_status->handle, sbuffer); + for (r=regions;r;r=r->next) { + if (r->terrain==terrain) { + coordinate coord; + if (invert) untag_region(st->selected, region2coord(r, &coord)); + else tag_region(st->selected, region2coord(r, &coord)); + } + } + } + } else { + statusline(st->wnd_status->handle, "unknown command."); + beep(); + break; + } + st->wnd_info->update |= 3; + st->wnd_status->update |= 3; + st->wnd_map->update |= 3; + break; + case ';': + statusline(st->wnd_status->handle, "tag-"); + switch (getch()) { + case 't': + terraform_selection(st->selected, select_terrain(NULL)); + st->modified = 1; + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + st->wnd_map->update |= 1; + break; + case 'm': + break; + default: + statusline(st->wnd_status->handle, "unknown command."); + beep(); + } + break; + case ' ': + if (tagged_region(st->selected, cursor)) untag_region(st->selected, cursor); + else tag_region(st->selected, cursor); + break; + case '/': + statusline(st->wnd_status->handle, "find-"); + findmode = getch(); + if (findmode=='r') { + askstring(st->wnd_status->handle, "find-region:", locate, sizeof(locate)); + } else if (findmode=='u') { + askstring(st->wnd_status->handle, "find-unit:", locate, sizeof(locate)); + } else if (findmode=='f') { + askstring(st->wnd_status->handle, "find-faction:", locate, sizeof(locate)); + } else { + statusline(st->wnd_status->handle, "unknown command."); + beep(); + break; + } + /* achtung: fall-through ist absicht: */ + if (!strlen(locate)) break; + case 'n': + if (findmode=='u') { + unit * u = findunit(atoi36(locate)); + r = u?u->region:NULL; + } else if (findmode && regions!=NULL) { + struct faction * f = NULL; + map_region * mr = cursor_region(&st->display, cursor); + region * first = (mr->r && mr->r->next)?mr->r->next:regions; + + if (findmode=='f') { + f = findfaction(atoi36(locate)); + if (f==NULL) { + statusline(st->wnd_status->handle, "faction not found."); + beep(); + break; + } + } + for (r=first;;) { + if (findmode=='r' && r->land && r->land->name && strstr(r->land->name, locate)) { + break; + } else if (findmode=='f') { + unit * u; + for (u=r->units;u;u=u->next) { + if (u->faction==f) { + break; + } + } + if (u) break; + } + r = r->next; + if (r==NULL) r = regions; + if (r==first) { + r = NULL; + statusline(st->wnd_status->handle, "not found."); + beep(); + break; + } + } + } else { + r = NULL; + } + if (r!=NULL) { + region2coord(r, &st->cursor); + st->wnd_info->update |= 1; + st->wnd_status->update |= 1; + } + break; + case 'Q': + g_quit = 1; + break; + default: + for (wnd=wnd_first;wnd!=NULL;wnd=wnd->next) { + if (wnd->handlekey) { + if (wnd->handlekey(wnd, st, c)) break; + } + } + if (wnd==NULL) { + sprintf(sbuffer, "getch: 0x%x", c); + statusline(st->wnd_status->handle, sbuffer); + } + break; + } +} + +static void +init_view(view * display, WINDOW * win) +{ + display->topleft.x = 1; + display->topleft.y = 1; + display->topleft.p = 0; + display->plane = 0; + display->extent.width = getmaxx(win)/TWIDTH; + display->extent.height = getmaxy(win)/THEIGHT; + display->regions = calloc(display->extent.height * display->extent.width, sizeof(map_region)); +} + +static void +update_view(view * vi) +{ + int i, j; + for (i=0;i!=vi->extent.width;++i) { + for (j=0;j!=vi->extent.height;++j) { + 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->r = findregion((short)mr->coord.x, (short)mr->coord.y); + } + } +} + +static void +run_mapper(void) +{ + WINDOW * hwinstatus; + WINDOW * hwininfo; + WINDOW * hwinmap; + int width, height, x, y; + int split = 20; + state st; + point tl; + init_curses(); + curs_set(1); + + getbegyx(stdscr, x, y); + width = getmaxx(stdscr); + height = getmaxy(stdscr); + + hwinmap = subwin(stdscr, getmaxy(stdscr)-1, getmaxx(stdscr)-split, y, x); + hwininfo = subwin(stdscr, getmaxy(stdscr)-1, split, y, x+getmaxx(stdscr)-split); + hwinstatus = subwin(stdscr, 1, width, height-1, x); + + st.wnd_map = win_create(hwinmap); + st.wnd_map->paint = &paint_map; + st.wnd_map->update = 1; + st.wnd_info = win_create(hwininfo); + st.wnd_info->paint = &paint_info_region; + st.wnd_info->handlekey = &handle_info_region; + st.wnd_info->update = 1; + st.wnd_status = win_create(hwinstatus); + st.wnd_status->paint = &paint_status; + st.wnd_status->update = 1; + st.display.plane = 0; + st.cursor.p = 0; + st.cursor.x = 0; + st.cursor.y = 0; + st.selected = calloc(1, sizeof(struct selection)); + st.modified = 0; + st.info_flags = 0xFFFFFFFF; + + init_view(&st.display, hwinmap); + coor2point(&st.display.topleft, &tl); + + while (!g_quit) { + point p; + window * wnd; + view * vi = &st.display; + + getbegyx(hwinmap, x, y); + width = getmaxx(hwinmap)-x; + height = getmaxy(hwinmap)-y; + coor2point(&st.cursor, &p); + + if (st.cursor.p != vi->plane) { + vi->plane = st.cursor.p; + st.wnd_map->update |= 1; + } + if (p.y < tl.y) { + vi->topleft.y = st.cursor.y-vi->extent.height/2; + st.wnd_map->update |= 1; + } + else if (p.y >= tl.y + vi->extent.height * THEIGHT) { + vi->topleft.y = st.cursor.y-vi->extent.height/2; + st.wnd_map->update |= 1; + } + if (p.x <= tl.x) { + vi->topleft.x = st.cursor.x+(st.cursor.y-vi->topleft.y)/2-vi->extent.width / 2; + st.wnd_map->update |= 1; + } + else if (p.x >= tl.x + vi->extent.width * TWIDTH-1) { + vi->topleft.x = st.cursor.x+(st.cursor.y-vi->topleft.y)/2-vi->extent.width / 2; + st.wnd_map->update |= 1; + } + + if (st.wnd_map->update) { + update_view(vi); + coor2point(&vi->topleft, &tl); + } + for (wnd=wnd_last;wnd!=NULL;wnd=wnd->prev) { + if (wnd->update && wnd->paint) { + if (wnd->update & 2) wclear(wnd->handle); + if (wnd->update & 1) { + wnd->paint(wnd, &st); + } + wnd->update = 0; + } + } + draw_cursor(st.wnd_map->handle, st.selected, vi, &st.cursor, 1); + for (wnd=wnd_first;wnd!=NULL;wnd=wnd->next) wrefresh(wnd->handle); + draw_cursor(st.wnd_map->handle, st.selected, vi, &st.cursor, 0); + + handlekeys(&st); + } + curs_set(1); + endwin(); +} + +int +main(int argc, char *argv[]) +{ + int i; + char * lc_ctype; + char * lc_numeric; + + lc_ctype = setlocale(LC_CTYPE, ""); + lc_numeric = setlocale(LC_NUMERIC, "C"); + if (lc_ctype) lc_ctype = strdup(lc_ctype); + if (lc_numeric) lc_numeric = strdup(lc_numeric); + + log_flags = LOG_FLUSH; + log_open(g_logfile); + + global.data_version = RELEASE_VERSION; + + kernel_init(); + i = read_args(argc, argv); + if (i!=0) return i; + game_init(); + + + if (turn>first_turn) { + char datafile[12]; + sprintf(datafile, "%u", turn); + readgame(datafile, 0); + } + + run_mapper(); + + game_done(); + kernel_done(); + + log_close(); + + setlocale(LC_CTYPE, lc_ctype); + setlocale(LC_NUMERIC, lc_numeric); + + free(lc_ctype); + free(lc_numeric); + + return 0; +} diff --git a/src/eressea/gmtool.h b/src/eressea/gmtool.h new file mode 100644 index 000000000..d5838841f --- /dev/null +++ b/src/eressea/gmtool.h @@ -0,0 +1,77 @@ +/* vi: set ts=2: + * +-------------------+ Christian Schlittchen + * | | Enno Rehling + * | Eressea PBEM host | Katja Zedel + * | (c) 1998 - 2006 | + * | | This program may not be used, modified or distributed + * +-------------------+ without prior permission by the authors of Eressea. + * + */ + +/* types imported from eressea: */ +struct region; + +typedef struct extent { + /* Ein Vektor */ + int width, height; +} extent; + +typedef struct point { + /* Eine Koordinate in einer Ascii-Karte */ + int x, y; +} point; + +typedef struct coordinate { + /* Eine Koordinate in der Welt */ + int x, y, p; +} coordinate; + +typedef struct map_region { + struct region * r; + coordinate coord; +} map_region; + +typedef struct view { + struct map_region * regions; + int plane; + coordinate topleft; /* upper left corner in map. */ + extent extent; /* dimensions. */ +} view; + +typedef struct tag { + coordinate coord; + struct tag * nexthash; +} tag; + +#define MAXTHASH 512 + +typedef struct selection { + tag * tags[MAXTHASH]; +} selection; + +typedef struct state { + coordinate cursor; + selection * selected; + struct state * undo; + struct faction * topf; + view display; + int modified; + unsigned int info_flags; + struct window * wnd_info; + struct window * wnd_map; + struct window * wnd_status; +} state; + +typedef struct window { + boolean (*handlekey)(struct window * win, struct state * st, int key); + void (*paint)(struct window * win, const struct state * st); + + WINDOW * handle; + struct window * next; + struct window * prev; + boolean initialized; + int update; +} window; + +#define TWIDTH 2 /* width of tile */ +#define THEIGHT 1 /* height of tile */ diff --git a/src/eressea/server.cpp b/src/eressea/server.cpp index e3810c628..abde15336 100644 --- a/src/eressea/server.cpp +++ b/src/eressea/server.cpp @@ -251,16 +251,6 @@ game_init(void) #ifdef INFOCMD_MODULE init_info(); #endif - -#ifdef REMOVE_THIS - render_init(); - { - FILE * F = fopen("messagetypes.txt", "w"); - debug_messagetypes(F); - fclose(F); - abort(); - } -#endif } #ifdef SHORTPWDS @@ -434,6 +424,7 @@ usage(const char * prog, const char * arg) "-x n : Lädt nur die ersten n regionen\n" "-f x y : Lädt nur die regionen ab (x,y)\n" "-v befehlsdatei : verarbeitet automatisch die angegebene Befehlsdatei\n" + "-q : be less verbose\n" "-d datadir : gibt das datenverzeichnis an\n" "-b basedir : gibt das basisverzeichnis an\n" "-r resdir : gibt das resourceverzeichnis an\n" diff --git a/src/lua.hpp b/src/lua.hpp index c7216703d..14d8eeeed 100644 --- a/src/lua.hpp +++ b/src/lua.hpp @@ -1,7 +1,12 @@ +#ifdef __cplusplus extern "C" { +#endif + #include #include #include + +#ifdef __cplusplus } #ifndef LUABIND_BETA @@ -14,3 +19,5 @@ extern "C" { # define LUABIND_DEVEL 2 # endif #endif + +#endif diff --git a/src/mapper/map_tools.c b/src/mapper/map_tools.c index 03526b1ea..761245a5f 100644 --- a/src/mapper/map_tools.c +++ b/src/mapper/map_tools.c @@ -374,7 +374,7 @@ do_selection(selection * sel, const char * title, void (*perform)(selection *, v break; default: s = current->next; - while (s!=current) { + while (s && s!=current) { if (tolower(s->str[0])==tolower(input)) { current = s; update = true; diff --git a/src/mapper/mapper.c b/src/mapper/mapper.c index 9aa9537d6..c210d36ed 100644 --- a/src/mapper/mapper.c +++ b/src/mapper/mapper.c @@ -70,9 +70,6 @@ #include #include -extern char *reportdir; -extern char *datadir; -extern char *basedir; extern int maxregions; extern boolean dirtyload; char datafile[256]; @@ -1667,12 +1664,14 @@ main(int argc, char *argv[]) #endif /* register_dungeon(); */ + register_itemtypes(); register_xmlreader(); init_data(xmlfile); init_locales(); init_attributes(); - + init_races(); + init_itemtypes(); init_rawmaterials(); init_gmcmd(); diff --git a/src/mapper/mapper.h b/src/mapper/mapper.h index c21ce2000..b3d6cfe3a 100644 --- a/src/mapper/mapper.h +++ b/src/mapper/mapper.h @@ -72,7 +72,6 @@ void NeuePartei(struct region * r); void RemovePartei(void); int ParteiListe(void); int koor_distance(int a, int b, int x, int y); -int create_backup(char *file); void SpecialFunction(struct region *r); extern WINDOW *mywin; diff --git a/src/res/eressea.xml b/src/res/eressea.xml index 76c36d810..769e8786c 100644 --- a/src/res/eressea.xml +++ b/src/res/eressea.xml @@ -55,8 +55,8 @@ - - + + @@ -70,12 +70,12 @@ - eressea-server@eressea.upb.de - eressea-server@eressea.upb.de + eressea-server@eressea.kn-bremen.de + eressea-server@eressea.kn-bremen.de - Bitte denke daran, deine Befehle mit dem Betreff ERESSEA BEFEHLE an eressea-server@eressea.upb.de zu senden. Am besten, du verwendest die Befehlsvorlage am Ende des Reports. - Remember to send your orders to eressea-server@eressea.upb.de with the subject ERESSEA ORDERS. + Bitte denke daran, deine Befehle mit dem Betreff ERESSEA BEFEHLE an eressea-server@eressea.kn-bremen.de zu senden. Am besten, du verwendest die Befehlsvorlage am Ende des Reports. + Remember to send your orders to eressea-server@eressea.kn-bremen.de with the subject ERESSEA ORDERS. ERESSEA BEFEHLE diff --git a/src/res/messages.xml b/src/res/messages.xml index ad4211c9e..86d22a7f2 100644 --- a/src/res/messages.xml +++ b/src/res/messages.xml @@ -4009,16 +4009,6 @@ "$unit($unit) in $region($region): '$order($command)' - You cannot cast this spell in a swamp." "$unit($unit) in $region($region): '$order($command)' - You cannot cast this spell in a swamp." - - - - - - - "$unit($unit) in $region($region): '$order($command)' - Hier gibt es bereits gute Straßen." - "$unit($unit) in $region($region): '$order($command)' - There are already sufficient roads here." - "$unit($unit) in $region($region): '$order($command)' - There are already sufficient roads here." - @@ -4038,6 +4028,16 @@ "$unit($unit) in $region($region): '$order($command)' - Der Zauber scheint ungewöhnlich schwach zu sein. Irgendetwas hat die magischen Energien abgeleitet." "$unit($unit) in $region($region): '$order($command)' - the spell seems exceptionally weak. Something has interfred with the magical energies." + + + + + + + "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann den Befehl in dieser nicht ausführen, da sie sich bewegt hat oder in einen Kampf verwickelt war." + "$unit($unit) in $region($region): '$order($command)' - The unit cannot execute this command because it has either moved or been in combat." + "$unit($unit) in $region($region): '$order($command)' - The unit cannot execute this command because it has either moved or been in combat." +