From: Markus Armbruster Date: Sat, 2 Feb 2008 20:03:12 +0000 (+0100) Subject: Clean up library dependencies X-Git-Tag: v4.3.12~194 X-Git-Url: http://git.pond.sub.org/?p=empserver;a=commitdiff_plain;h=77e95bd7882e96502e2dc76424228cf83b48b722 Clean up library dependencies Move stuff to untangle the ugly cyclic dependencies between the archives built for selected subdirectories of src/lib/: * Move common/io.c to empthread/ because it requires empthread stuff * Move parts of subs/nstr.c to common/nstreval.c to satisfy common/ef_verify.o * Move getstarg.c getstring.c onearg.c from gen/ to subs/ because they require stuff from there * Move bridgefall.c check.c damage.c empobj.c journal.c maps.c sectdamage.c from common/ to subs/ because they require stuff from there * Move cnumb.c from subs/ to common/ to satisfy common/type.o * Move log.c fsize.c from common/ to gen/ because they really belong there * Move emp_config.c mapdist.c from gen/ to common/ because they really belong there, and require stuff from libglobal.a Also package as/ as libas.a to satisfy common/path.o. Remaining dependencies: lib needs -------------------------------------------- libas.a libglobal.a libcommon.a libas.a libglobal.a libgen.a libgen.a libglobal.a liblwp.a libgen.a libw32.a[*] libgen.a [*] Except for service.o, which can only be linked into the server Link order now: liblwp.a libcommon.a libas.a libgen.a libglobal.a libw32.a. The position of libw32.a is not quite right, but works anyway. --- diff --git a/Make.mk b/Make.mk index 9449545f4..2508e1b72 100644 --- a/Make.mk +++ b/Make.mk @@ -102,7 +102,7 @@ obj := $(csrc:.c=.o) $(filter %.o, $(ac:.c=.o)) # Dependencies: deps := $(obj:.o=.d) # Library archives: -libs := $(addprefix lib/, libcommon.a libgen.a libglobal.a) +libs := $(addprefix lib/, libcommon.a libas.a libgen.a libglobal.a) # Programs: util := $(addprefix src/util/, $(addsuffix $(EXEEXT), empsched fairland files pconfig)) client := src/client/empire$(EXEEXT) @@ -115,17 +115,17 @@ info.nr := $(addprefix info.nr/, $(info)) info.html := $(addprefix info.html/, $(addsuffix .html, $(info))) # Conditionally generated files: +empth_obj := src/lib/empthread/io.o +empth_lib := ifeq ($(empthread),LWP) -empth_obj := src/lib/empthread/lwp.o src/lib/empthread/posix.o -empth_lib := lib/liblwp.a +empth_obj += src/lib/empthread/lwp.o src/lib/empthread/posix.o +empth_lib += lib/liblwp.a endif ifeq ($(empthread),POSIX) -empth_obj := src/lib/empthread/pthread.o src/lib/empthread/posix.o -empth_lib := +empth_obj += src/lib/empthread/pthread.o src/lib/empthread/posix.o endif ifeq ($(empthread),Windows) -empth_obj := src/lib/empthread/ntthread.o -empth_lib := +empth_obj += src/lib/empthread/ntthread.o endif ifeq ($(empthread),Windows) # really: W32, regardless of thread package @@ -262,7 +262,7 @@ info.html/%.html: info/%.t # Compilation -$(server): $(filter src/server/% src/lib/as/% src/lib/commands/% src/lib/player/% src/lib/subs/% src/lib/update/%, $(obj)) $(empth_obj) $(libs) $(empth_lib) +$(server): $(filter src/server/% src/lib/commands/% src/lib/player/% src/lib/subs/% src/lib/update/%, $(obj)) $(empth_obj) $(empth_lib) $(libs) $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(client): $(filter src/client/%, $(obj)) src/lib/global/version.o @@ -273,6 +273,7 @@ endif $(util): $(libs) +lib/libas.a: $(filter src/lib/as/%, $(obj)) lib/libcommon.a: $(filter src/lib/common/%, $(obj)) lib/libgen.a: $(filter src/lib/gen/%, $(obj)) lib/libglobal.a: $(filter src/lib/global/%, $(obj)) diff --git a/include/prototypes.h b/include/prototypes.h index 3ed8becfc..24d14f3ef 100644 --- a/include/prototypes.h +++ b/include/prototypes.h @@ -259,38 +259,16 @@ int zdon(void); */ /* bestpath.c */ extern char *bestownedpath(char *, char *, int, int, int, int, int); -/* bridgefall.c */ -extern void bridgefall(struct sctstr *, struct emp_qelem *); -extern void knockdown(struct sctstr *, struct emp_qelem *); -/* damage.c */ -extern void landdamage(struct lndstr *, int); -extern void ship_damage(struct shpstr *, int); -extern int damage(int, int); -extern void shipdamage(struct shpstr *, int); -extern void land_damage(struct lndstr *, int); -extern void planedamage(struct plnstr *, int); -extern int nukedamage(struct nchrstr *, int, int); -extern int effdamage(int, int); -extern void item_damage(int, short *); -extern int commdamage(int, int, i_type); -/* check.c */ -extern int check_sect_ok(struct sctstr *); -extern int check_ship_ok(struct shpstr *); -extern int check_land_ok(struct lndstr *); -extern int check_nuke_ok(struct nukstr *); -extern int check_plane_ok(struct plnstr *); -extern int check_comm_ok(struct comstr *); -extern int check_loan_ok(struct lonstr *); -extern int check_trade_ok(struct trdstr *); /* conftab.c */ extern int read_builtin_tables(void); extern int read_custom_tables(void); +/* cnumb.c */ +extern int cnumb(char *); /* ef_verify.c */ /* in file.h */ -/* fsize.c */ -extern int fsize(int); -extern int blksize(int); -extern time_t fdate(int); +/* emp_config.c */ +extern int emp_config(char *file); +extern void print_config(FILE * fp); /* hap_fact.c */ extern double hap_fact(struct natstr *, struct natstr *); extern double hap_req(struct natstr *np); @@ -303,17 +281,15 @@ extern int loginit(char *); extern int logreopen(void); extern void logerror(char *, ...) ATTRIBUTE((format (printf, 1, 2))); /* more in misc.h */ -/* maps.c */ -extern int do_map(int bmap, int unit_type, char *arg1, char *arg2); -extern int draw_map(int, char, int, struct nstr_sect *); -extern int unit_map(int, int, struct nstr_sect *, char *); -extern int display_region_map(int bmap, int unit_type, coord curx, - coord cury, char *arg); -extern int bmaps_intersect(natid, natid); -extern int share_bmap(natid, natid, struct nstr_sect *, char, char *); +/* mapdist.c */ +extern int diffx(int, int); +extern int diffy(int, int); +extern int deltax(int, int); +extern int deltay(int, int); +extern int mapdist(int, int, int, int); /* move.c */ /* in path.h */ -/* nstr_subs.c */ +/* nstreval.c */ /* in nsc.h */ /* path.c */ extern void bp_enable_cachepath(void); @@ -331,9 +307,6 @@ extern int read_schedule(char *, time_t[], int, time_t, time_t); /* res_pop.c */ extern int max_population(float, int, int); extern int max_pop(float, struct sctstr *); -/* sectdamage.c */ -extern int sect_damage(struct sctstr *, int, struct emp_qelem *); -extern int sectdamage(struct sctstr *, int, struct emp_qelem *); /* stmtch.c */ /* in match.h */ /* type.c */ @@ -348,21 +321,16 @@ extern int xundump(FILE *, char *, int *, int); /* * src/lib/gen/ *.c */ -/* emp_config.c */ -extern int emp_config(char *file); -extern void print_config(FILE * fp); +/* fsize.c */ +extern int fsize(int); +extern int blksize(int); +extern time_t fdate(int); extern int roll(int); extern int roundavg(double); extern int chance(double); extern int disassoc(void); -extern int diffx(int, int); -extern int diffy(int, int); -extern int deltax(int, int); -extern int deltay(int, int); -extern int mapdist(int, int, int, int); extern char *effadv(int); -extern int onearg(char *, char *); extern int parse(char *, char *, char **, char **, char **, char **); extern int ldround(double, int); extern int roundintby(int, int); @@ -430,19 +398,40 @@ extern void stop_service(void); /* askyn.c */ extern int confirm(char *); extern int askyn(char *); +/* bridgefall.c */ +extern void bridgefall(struct sctstr *, struct emp_qelem *); +extern void knockdown(struct sctstr *, struct emp_qelem *); /* bsanct.c */ extern void bsanct(void); /* caploss.c */ extern void caploss(struct sctstr *, natid, char *); +/* check.c */ +extern int check_sect_ok(struct sctstr *); +extern int check_ship_ok(struct shpstr *); +extern int check_land_ok(struct lndstr *); +extern int check_nuke_ok(struct nukstr *); +extern int check_plane_ok(struct plnstr *); +extern int check_comm_ok(struct comstr *); +extern int check_loan_ok(struct lonstr *); +extern int check_trade_ok(struct trdstr *); /* chkmoney.c */ extern int chkmoney(long, long, char *); extern int check_cost(int, int, long, int *, char *); -/* cnumb.c */ -extern int cnumb(char *); /* coastal.c */ extern void set_coastal(struct sctstr *, int, int); /* control.c */ extern int military_control(struct sctstr *); +/* damage.c */ +extern void landdamage(struct lndstr *, int); +extern void ship_damage(struct shpstr *, int); +extern int damage(int, int); +extern void shipdamage(struct shpstr *, int); +extern void land_damage(struct lndstr *, int); +extern void planedamage(struct plnstr *, int); +extern int nukedamage(struct nchrstr *, int, int); +extern int effdamage(int, int); +extern void item_damage(int, short *); +extern int commdamage(int, int, i_type); /* detonate.c */ extern int detonate(struct nukstr *, coord, coord, int); /* disloan.c */ @@ -486,7 +475,15 @@ extern int num_shipsatxy(coord, coord, int, int); extern int has_units(coord, coord, natid, struct lndstr *); extern int adj_units(coord, coord, natid); extern int islist(char *); -/* src/lib/subs/mission.c */ +/* maps.c */ +extern int do_map(int bmap, int unit_type, char *arg1, char *arg2); +extern int draw_map(int, char, int, struct nstr_sect *); +extern int unit_map(int, int, struct nstr_sect *, char *); +extern int display_region_map(int bmap, int unit_type, coord curx, + coord cury, char *arg); +extern int bmaps_intersect(natid, natid); +extern int share_bmap(natid, natid, struct nstr_sect *, char, char *); +/* mission.c */ extern char *mission_name(short); extern int collateral_damage(coord, coord, int, struct emp_qelem *); extern int mission_pln_equip(struct plist *, struct ichrstr *, int, char); @@ -536,6 +533,8 @@ extern int nuk_on_plane(struct nukstr *, int); extern int nxtitem(struct nstr_item *, void *); /* nxtsct.c */ extern int nxtsct(struct nstr_sect *, struct sctstr *); +/* onearg.c */ +extern int onearg(char *, char *); /* plane.c */ extern char *prplane(struct plnstr *); extern int pln_postread(int, void *); @@ -631,6 +630,9 @@ extern int sct_postread(int, void *); extern int sct_prewrite(int, void *); extern void item_prewrite(short *); extern int issector(char *); +/* sectdamage.c */ +extern int sect_damage(struct sctstr *, int, struct emp_qelem *); +extern int sectdamage(struct sctstr *, int, struct emp_qelem *); /* ship.c */ extern char *prship(struct shpstr *); extern int shp_postread(int, void *); diff --git a/src/lib/common/bridgefall.c b/src/lib/common/bridgefall.c deleted file mode 100644 index c11529d1e..000000000 --- a/src/lib/common/bridgefall.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * bridgefall.c: Knock a bridge down - * - * Known contributors to this file: - * Steve McClure, 1998 - */ - -#include - -#include "file.h" -#include "land.h" -#include "lost.h" -#include "misc.h" -#include "nat.h" -#include "nsc.h" -#include "nuke.h" -#include "optlist.h" -#include "path.h" -#include "plague.h" -#include "plane.h" -#include "prototypes.h" -#include "sect.h" -#include "xy.h" - -void -bridgefall(struct sctstr *sp, struct emp_qelem *list) -{ - int i; - int j; - struct sctstr sect; - struct sctstr bh_sect; - int nx; - int ny; - int nnx; - int nny; - - for (i = 1; i <= 6; i++) { - nx = sp->sct_x + diroff[i][0]; - ny = sp->sct_y + diroff[i][1]; - getsect(nx, ny, §); - if (sect.sct_type != SCT_BSPAN) - continue; - for (j = 1; j <= 6; j++) { - nnx = nx + diroff[j][0]; - nny = ny + diroff[j][1]; - if (nnx == sp->sct_x && nny == sp->sct_y) - continue; - getsect(nnx, nny, &bh_sect); - if (bh_sect.sct_type == SCT_BHEAD && - bh_sect.sct_newtype == SCT_BHEAD) - break; - if (bh_sect.sct_type == SCT_BTOWER) - break; - /* With EASY_BRIDGES, it just has to be next to any - land */ - if (opt_EASY_BRIDGES) { - if (bh_sect.sct_type != SCT_WATER && - bh_sect.sct_type != SCT_BSPAN) - break; - } - } - if (j > 6) { - knockdown(§, list); - putsect(§); - } - } -} - -/* Knock down a bridge span. Note that this does NOT write the - * sector out to the database, it's up to the caller to do that. */ -void -knockdown(struct sctstr *sp, struct emp_qelem *list) -{ - struct lndstr land; - struct plnstr plane; - struct nukstr nuke; - struct nstr_item ni; - struct natstr *np; - - mpr(sp->sct_own, - "Crumble... SCREEEECH! Splash! Bridge%s falls at %s!\n", - sp->sct_type == SCT_BTOWER ? " tower" : "", - xyas(sp->sct_x, sp->sct_y, sp->sct_own)); - sp->sct_type = SCT_WATER; - sp->sct_newtype = SCT_WATER; - makelost(EF_SECTOR, sp->sct_own, 0, sp->sct_x, sp->sct_y); - sp->sct_own = 0; - sp->sct_oldown = 0; - sp->sct_mobil = 0; - sp->sct_effic = 0; - - /* Sink all the units */ - snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); - while (nxtitem(&ni, &land)) { - if (land.lnd_own == 0) - continue; - if (land.lnd_ship >= 0) - continue; - np = getnatp(land.lnd_own); - if (np->nat_flags & NF_BEEP) - mpr(land.lnd_own, "\07"); - mpr(land.lnd_own, " AARGH! %s tumbles to its doom!\n", - prland(&land)); - land.lnd_effic = 0; - putland(land.lnd_uid, &land); - } - /* Sink all the planes */ - snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y); - while (nxtitem(&ni, &plane)) { - if (plane.pln_own == 0) - continue; - if (plane.pln_flags & PLN_LAUNCHED) - continue; - if (plane.pln_ship >= 0) - continue; - /* Is this plane flying in this list? */ - if (ac_isflying(&plane, list)) - continue; - np = getnatp(plane.pln_own); - if (np->nat_flags & NF_BEEP) - mpr(plane.pln_own, "\07"); - mpr(plane.pln_own, " AARGH! %s tumbles to its doom!\n", - prplane(&plane)); - plane.pln_effic = 0; - putplane(plane.pln_uid, &plane); - } - /* Sink all the nukes */ - snxtitem_xy(&ni, EF_NUKE, sp->sct_x, sp->sct_y); - while (nxtitem(&ni, &nuke)) { - if (nuke.nuk_own == 0) - continue; - if (nuke.nuk_plane >= 0) - continue; - np = getnatp(nuke.nuk_own); - if (np->nat_flags & NF_BEEP) - mpr(nuke.nuk_own, "\07"); - mpr(nuke.nuk_own, " %s sinks to the bottom of the sea!\n", - prnuke(&nuke)); - nuke.nuk_effic = 0; - putnuke(nuke.nuk_uid, &nuke); - } - memset(sp->sct_item, 0, sizeof(sp->sct_item)); - memset(sp->sct_del, 0, sizeof(sp->sct_del)); - memset(sp->sct_dist, 0, sizeof(sp->sct_dist)); - sp->sct_pstage = PLG_HEALTHY; - sp->sct_ptime = 0; - sp->sct_che = 0; - sp->sct_che_target = 0; -} diff --git a/src/lib/common/check.c b/src/lib/common/check.c deleted file mode 100644 index d8b315076..000000000 --- a/src/lib/common/check.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * check.c: Check a sector, plane, land unit, ship or nuke - * - * Known contributors to this file: - * Steve McClure, 1998 - */ - -#include - -#include "commodity.h" -#include "file.h" -#include "land.h" -#include "loan.h" -#include "misc.h" -#include "nat.h" -#include "nsc.h" -#include "nuke.h" -#include "plane.h" -#include "player.h" -#include "prototypes.h" -#include "sect.h" -#include "ship.h" -#include "trade.h" -#include "xy.h" - -/* Note that timestamps make things tricky. And, we don't - * really care about the timestamp, we just care about the rest - * of the structure. So, we make a copy, and zero the timestamps - * in both copies, and then compare. */ - -int -check_sect_ok(struct sctstr *sectp) -{ - struct sctstr chksect; - struct sctstr tsect; - - getsect(sectp->sct_x, sectp->sct_y, &chksect); - memcpy(&tsect, sectp, sizeof(struct sctstr)); - tsect.sct_timestamp = chksect.sct_timestamp = 0; - if (memcmp(&tsect, &chksect, sizeof(struct sctstr))) { - pr("Sector %s has changed!\n", - xyas(sectp->sct_x, sectp->sct_y, player->cnum)); - return 0; - } - return 1; -} - -int -check_ship_ok(struct shpstr *shipp) -{ - struct shpstr chkship; - struct shpstr tship; - - getship(shipp->shp_uid, &chkship); - memcpy(&tship, shipp, sizeof(struct shpstr)); - tship.shp_timestamp = chkship.shp_timestamp = 0; - if (memcmp(&tship, &chkship, sizeof(struct shpstr))) { - pr("Ship #%d has changed!\n", shipp->shp_uid); - return 0; - } - return 1; -} - -int -check_plane_ok(struct plnstr *planep) -{ - struct plnstr chkplane; - struct plnstr tplane; - - getplane(planep->pln_uid, &chkplane); - memcpy(&tplane, planep, sizeof(struct plnstr)); - tplane.pln_timestamp = chkplane.pln_timestamp = 0; - if (memcmp(&tplane, &chkplane, sizeof(struct plnstr))) { - pr("Plane #%d has changed!\n", planep->pln_uid); - return 0; - } - return 1; -} - -int -check_land_ok(struct lndstr *landp) -{ - struct lndstr chkland; - struct lndstr tland; - - getland(landp->lnd_uid, &chkland); - memcpy(&tland, landp, sizeof(struct lndstr)); - tland.lnd_timestamp = chkland.lnd_timestamp = 0; - if (memcmp(&tland, &chkland, sizeof(struct lndstr))) { - pr("Land unit #%d has changed!\n", landp->lnd_uid); - return 0; - } - return 1; -} - -int -check_nuke_ok(struct nukstr *nukep) -{ - struct nukstr chknuke; - struct nukstr tnuke; - - getnuke(nukep->nuk_uid, &chknuke); - memcpy(&tnuke, nukep, sizeof(struct nukstr)); - tnuke.nuk_timestamp = chknuke.nuk_timestamp = 0; - if (memcmp(&tnuke, &chknuke, sizeof(struct nukstr))) { - pr("Nuke %d has changed!\n", nukep->nuk_uid); - return 0; - } - return 1; -} - -int -check_loan_ok(struct lonstr *loanp) -{ - struct lonstr chkloan; - - getloan(loanp->l_uid, &chkloan); - if (memcmp(loanp, &chkloan, sizeof(struct lonstr))) { - pr("Loan %d has changed!\n", loanp->l_uid); - return 0; - } - return 1; -} - -int -check_comm_ok(struct comstr *commp) -{ - struct comstr chkcomm; - - getcomm(commp->com_uid, &chkcomm); - if (memcmp(commp, &chkcomm, sizeof(struct comstr))) { - pr("Commodity %d has changed!\n", commp->com_uid); - return 0; - } - return 1; -} - -int -check_trade_ok(struct trdstr *tp) -{ - struct trdstr chktrade; - - gettrade(tp->trd_uid, &chktrade); - if (memcmp(tp, &chktrade, sizeof(struct trdstr))) { - pr("Trade lot #%d has changed!\n", tp->trd_uid); - return 0; - } - return 1; -} diff --git a/src/lib/common/cnumb.c b/src/lib/common/cnumb.c new file mode 100644 index 000000000..26a48b112 --- /dev/null +++ b/src/lib/common/cnumb.c @@ -0,0 +1,74 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * cnumb.c: Return country number give country name + * + * Known contributors to this file: + * + */ + +#include + +#include "file.h" +#include "match.h" +#include "nat.h" +#include "prototypes.h" + +/* + * Search for a country matching CNTRY, return its number. + * Return M_NOTFOUND if no such country exists, M_NOTUNIQUE if there + * are several. + */ +int +cnumb(char *cntry) +{ + char *ncp; + char *cp; + struct natstr *natp; + int res; + natid cn; + + res = M_NOTFOUND; + for (cn = 0; cn < MAXNOC; cn++) { + if ((natp = getnatp(cn)) == 0) + break; + if (natp->nat_stat == STAT_UNUSED) + continue; + ncp = natp->nat_cnam; + for (cp = cntry; *cp == *ncp; cp++, ncp++) { + if (*cp == 0) + return cn; /* exact match */ + } + if (*cp == 0) { + /* is a prefix */ + if (res >= 0) + return M_NOTUNIQUE; + res = cn; + } + } + return res; +} diff --git a/src/lib/common/damage.c b/src/lib/common/damage.c deleted file mode 100644 index 11684fb6f..000000000 --- a/src/lib/common/damage.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * damage.c: Damage stuff. - * - * Known contributors to this file: - * Dave Pare, 1989 - * Steve McClure, 1997 - */ - -#include - -#include "damage.h" -#include "land.h" -#include "misc.h" -#include "nsc.h" -#include "nuke.h" -#include "optlist.h" -#include "plane.h" -#include "prototypes.h" -#include "sect.h" -#include "ship.h" - -void -item_damage(int pct, short *item) -{ - int lose; - i_type i; - - for (i = I_NONE + 1; i <= I_MAX; ++i) { - if (opt_SUPER_BARS && i == I_BAR) - continue; - lose = roundavg((double)item[i] * pct * 0.01); - if (i == I_CIVIL || i == I_MILIT || i == I_UW) - lose = ldround(people_damage * lose, 1); - item[i] = item[i] >= lose ? item[i] - lose : 0; - } -} - -void -ship_damage(struct shpstr *sp, int dam) -{ - if (dam <= 0) - return; - if (dam > 100) - dam = 100; - - mpr(sp->shp_own, "\t%s takes %d\n", prship(sp), dam); - - sp->shp_effic = damage((int)sp->shp_effic, dam); - if (sp->shp_mobil > 0) - sp->shp_mobil = damage((int)sp->shp_mobil, dam); - if (opt_FUEL && sp->shp_fuel) - sp->shp_fuel = damage((int)sp->shp_fuel, dam); - item_damage(dam, sp->shp_item); -} - -void -shipdamage(struct shpstr *sp, int dam) -{ - ship_damage(sp, (int)(dam / (1.0 + sp->shp_armor / 100.0))); -} - -void -land_damage(struct lndstr *lp, int dam) -{ - if (dam <= 0) - return; - if (dam > 100) - dam = 100; - - mpr(lp->lnd_own, "\t%s takes %d\n", prland(lp), dam); - if (lchr[(int)lp->lnd_type].l_flags & L_SPY) { - /* Spies die! */ - lp->lnd_effic = 0; - } else { - lp->lnd_effic = damage((int)lp->lnd_effic, dam); - if (lp->lnd_mobil > 0) - lp->lnd_mobil = damage((int)lp->lnd_mobil, dam); - if (opt_FUEL && lp->lnd_fuel) - lp->lnd_fuel = damage((int)lp->lnd_fuel, dam); - item_damage(dam, lp->lnd_item); - } -} - -void -landdamage(struct lndstr *lp, int dam) -{ - double damage_factor, m; - - m = land_mob_max; - - /* fortification reduces damage */ - damage_factor = m / (m + lp->lnd_harden); - - /* vulnerable units take more damage */ - damage_factor *= lp->lnd_vul / 100.0; - - land_damage(lp, ldround(damage_factor * dam, 1)); -} - -void -planedamage(struct plnstr *pp, int dam) -{ - if (dam <= 0) - return; - if (dam > 100) - dam = 100; - - mpr(pp->pln_own, "\t%s takes %d\n", prplane(pp), dam); - pp->pln_effic = damage((int)pp->pln_effic, dam); - if (pp->pln_mobil > 0) - pp->pln_mobil = damage((int)pp->pln_mobil, dam); -} - -/* - * nukedamage() actually just calculates damage - * rather than inflicting it. - */ -int -nukedamage(struct nchrstr *ncp, int range, int airburst) -{ - int dam; - int rad; - - rad = ncp->n_blast; - if (airburst) - rad = (int)(rad * 1.5); - if (rad < range) - return 0; - if (airburst) { - /* larger area, less center damage */ - dam = (int)((ncp->n_dam * 0.75) - (range * 20)); - } else { - /* smaller area, more center damage */ - dam = (int)(ncp->n_dam / (range + 1.0)); - } - if (dam < 5) - dam = 0; - return dam; -} - -int -damage(int amt, int pct) -{ - int tmp; - int lost; - - if (amt <= 0) - return 0; - tmp = amt * pct; - lost = tmp / 100; - if (random() % 100 < tmp % 100) - lost++; - return amt - lost; -} - -/* asymptotic damage to commodities, efficiency, and sectors */ -int -effdamage(int amt, int dam) -{ - return damage(amt, PERCENT_DAMAGE(dam)); -} - -int -commdamage(int amt, int dam, i_type vtype) -{ - int lost; - - if (vtype == I_BAR && opt_SUPER_BARS) - return amt; - - lost = amt - effdamage(amt, dam); - - if (vtype == I_MILIT || vtype == I_CIVIL || vtype == I_UW) - lost = ldround(people_damage * lost, 1); - return amt - lost; -} diff --git a/src/lib/common/emp_config.c b/src/lib/common/emp_config.c new file mode 100644 index 000000000..7997b9a54 --- /dev/null +++ b/src/lib/common/emp_config.c @@ -0,0 +1,246 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * emp_config.c: Allows config file to control server config. from a file + * + * Known contributors to this file: + * Julian Onions, 1995 + * Steve McClure, 1998-2000 + */ + +/* + * STILL TO DO + * + * Change other constants - such as MAXNOC etc. + * Just requires variables to be assigned, then dynamic allocation in + * a few places. Some checks needed in the server to check the world + * hasn't changed size etc. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "file.h" +#include "misc.h" +#include "optlist.h" +#include "prototypes.h" + +/* Dummy one */ +static int emp_config_dummy; + +/* things that can be changed */ +struct keymatch configkeys[] = { +#define EMP_CONFIG_C_OUTPUT +#include "econfig-spec.h" +#undef EMP_CONFIG_C_OUTPUT +}; + +static struct keymatch *keylookup(char *key, struct keymatch tbl[]); +static void set_paths(char *); + +/* + * read in empire configuration + */ +int +emp_config(char *file) +{ + FILE *fp; + char scanspace[1024]; + char *av[128]; + char buf[1024]; + struct keymatch *kp; + int lno = 0; + int errors = 0; + int i; + + if (!file) + file = dflt_econfig; + errno = 0; + if ((fp = fopen(file, "r")) == NULL) { + if (file == dflt_econfig && errno == ENOENT) + goto done; + fprintf(stderr, "Can't open %s for reading (%s)\n", + file, strerror(errno)); + return -1; + } + + while (fgets(buf, sizeof(buf), fp) != NULL) { + ++lno; + for (i = 0; buf[i] && isspace(buf[i]); ++i) ; + if (!buf[i] || buf[i] == '#') + continue; + if (parse(buf, scanspace, av, NULL, NULL, NULL) < 0) { + fprintf(stderr, "%s:%d: Can't parse line %s", file, lno, buf); + errors = 1; + continue; + } + if ((kp = keylookup(av[0], configkeys)) == NULL) { + fprintf(stderr, "%s:%d: Unknown config key %s\n", + file, lno, av[0]); + errors = 1; + continue; + } + if (av[1] == NULL) { + fprintf(stderr, "%s:%d: Config key %s needs a value\n", + file, lno, av[0]); + errors = 1; + continue; + } + i = 2; + switch (kp->km_type) { + case NSC_INT: + *(int *)kp->km_data = atoi(av[1]); + break; + case NSC_FLOAT: + *(float *)kp->km_data = atof(av[1]); + break; + case NSC_DOUBLE: + *(double *)kp->km_data = atof(av[1]); + break; + case NSC_LONG: + *(long *)kp->km_data = atol(av[1]); + break; + case NSC_STRING: + if (kp->km_flags & KM_ALLOC) + free(*(char **)kp->km_data); + *(char **)kp->km_data = strdup(av[1]); + kp->km_flags |= KM_ALLOC; + break; + default: + assert(0); + } + if (av[i] != NULL) { + fprintf(stderr, "%s:%d: Junk after value of config key %s\n", + file, lno, av[0]); + errors = 1; + } + } + + fclose(fp); + +done: + WORLD_X &= ~1; /* force even */ + set_paths(file); + + return -errors; +} + +/* find the key in the table */ +static struct keymatch * +keylookup(char *command, struct keymatch *tbl) +{ + struct keymatch *kp; + + if (command == 0 || *command == 0) + return 0; + for (kp = tbl; kp->km_key != 0; kp++) { + if (strcmp(kp->km_key, command) == 0) + return kp; + } + return NULL; +} + +static void +set_paths(char *econfig) +{ + char *slash; + char *cwd = getcwd(NULL, 0); + +#ifdef _WIN32 + /* normalize path separator to '\\', for easier searching: */ + econfig = _fullpath(NULL, econfig, 0); + slash = strrchr(econfig, '\\'); + configdir = malloc(slash - econfig + 1); + memcpy(configdir, econfig, slash - econfig); + configdir[slash - econfig] = 0; +#else + if ((slash = strrchr(econfig, '/'))) { + configdir = malloc(slash - econfig + 1); + memcpy(configdir, econfig, slash - econfig); + configdir[slash - econfig] = 0; + } else + configdir = strdup(cwd); + + if (configdir[0] != '/') { + char *tmp = configdir; + size_t len = strlen(cwd); + + configdir = malloc(len + 1 + strlen(tmp) + 1); + sprintf(configdir, "%s/%s", cwd, tmp); + free(tmp); + } +#endif /* !_WIN32 */ + + schedulefil = malloc(strlen(configdir) + 10); + sprintf(schedulefil, "%s/schedule", configdir); + + free(cwd); +} + +void +print_config(FILE *fp) +{ + struct keymatch *kp; + + fprintf(fp, "# Empire Configuration File:\n"); + for (kp = configkeys; kp->km_key; kp++) { + if (kp->km_comment) { + if (kp->km_comment[0] != '\n' && kp->km_comment[0] != '#') + fprintf(fp, "\n# "); + fprintf(fp, "%s\n", kp->km_comment); + } + if (!kp->km_key[0]) + continue; + switch (kp->km_type) { + case NSC_STRING: + fprintf(fp, "%s \"%s\"\n", kp->km_key, *(char **)kp->km_data); + break; + case NSC_INT: + fprintf(fp, "%s %d\n", kp->km_key, *(int *)kp->km_data); + break; + case NSC_FLOAT: + fprintf(fp, "%s %g\n", kp->km_key, *(float *)kp->km_data); + break; + case NSC_DOUBLE: + fprintf(fp, "%s %g\n", kp->km_key, *(double *)kp->km_data); + break; + case NSC_LONG: + fprintf(fp, "%s %ld\n", kp->km_key, *(long *)kp->km_data); + break; + default: + assert(0); + } + } + + fprintf(fp, "\n"); +} diff --git a/src/lib/common/empobj.c b/src/lib/common/empobj.c deleted file mode 100644 index 35a18d07f..000000000 --- a/src/lib/common/empobj.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * empobj.c: Common functions on struct empobj and - * union empobj_storage - * - * Known contributors to this file: - * Ron Koenderink, 2006 - * Markus Armbruster, 2006 - */ - -#include - -#include "empobj.h" -#include "file.h" -#include "optlist.h" -#include "prototypes.h" - -char * -obj_nameof(struct empobj *gp) -{ - switch (gp->ef_type) { - case EF_SHIP: - return prship((struct shpstr *)gp); - case EF_PLANE: - return prplane((struct plnstr *)gp); - case EF_LAND: - return prland((struct lndstr *)gp); - case EF_NUKE: - return prnuke((struct nukstr *)gp); - } - CANT_REACH(); - return "The Beast #666"; -} - -struct empobj * -get_empobjp(int type, int id) -{ - if (CANT_HAPPEN(type == EF_SECTOR || type == EF_BAD)) - return NULL; - return ef_ptr(type, id); -} - -int -put_empobj(struct empobj *gp) -{ - switch (gp->ef_type) - { - case EF_SECTOR: - return ef_write(gp->ef_type, sctoff(gp->x, gp->y), gp); - case EF_NATION: - case EF_BMAP: - case EF_MAP: - return ef_write(gp->ef_type, gp->own, gp); - default: - return ef_write(gp->ef_type, gp->uid, gp); - } -} - -struct empobj_chr * -get_empobj_chr(struct empobj *gp) -{ - switch (gp->ef_type) { - case EF_LAND: - return (struct empobj_chr *)&lchr[(int)gp->type]; - case EF_SHIP: - return (struct empobj_chr *)&mchr[(int)gp->type]; - case EF_PLANE: - return (struct empobj_chr *)&plchr[(int)gp->type]; - case EF_NUKE: - return (struct empobj_chr *)&nchr[(int)gp->type]; - case EF_SECTOR: - return (struct empobj_chr *)&dchr[(int)gp->type]; - } - CANT_REACH(); - return NULL; -} - -char * -emp_obj_chr_name(struct empobj *gp) -{ - switch (gp->ef_type) { - case EF_LAND: - return lchr[(int)gp->type].l_name; - case EF_SHIP: - return mchr[(int)gp->type].m_name; - case EF_PLANE: - return plchr[(int)gp->type].pl_name; - case EF_NUKE: - return nchr[(int)gp->type].n_name; - case EF_SECTOR: - return dchr[(int)gp->type].d_name; - } - CANT_REACH(); - return NULL; -} - -int -get_empobj_mob_max(int type) -{ - switch (type) { - case EF_SHIP: - return ship_mob_max; - case EF_LAND: - return land_mob_max; - case EF_PLANE: - return plane_mob_max; - case EF_SECTOR: - return sect_mob_max; - } - CANT_REACH(); - return -1; -} diff --git a/src/lib/common/fsize.c b/src/lib/common/fsize.c deleted file mode 100644 index 36af6d263..000000000 --- a/src/lib/common/fsize.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * fsize.c: BSD dependant file and block sizing routines - * - * Known contributors to this file: - * Dave Pare, 1986 - * Doug Hay, 1998 - * Steve McClure, 1998 - */ - -#include - -#include -#include -#include "prototypes.h" - -/* - * return the size of the file in bytes. - */ -int -fsize(int fd) -{ - struct stat statb; - - if (fstat(fd, &statb) < 0) - return -1; - return statb.st_size; -} - -/* - * Return the preferred block size for I/O on FD. - */ -int -blksize(int fd) -{ -#if defined(_WIN32) - return 2048; -#else /* !_WIN32 */ - struct stat statb; - - if (fstat(fd, &statb) < 0) - return 1024; - return statb.st_blksize; -#endif /* !_WIN32 */ -} - -time_t -fdate(int fd) -{ - struct stat statb; - - if (fstat(fd, &statb) < 0) - return 0; - return statb.st_mtime; -} diff --git a/src/lib/common/journal.c b/src/lib/common/journal.c deleted file mode 100644 index ed111a25c..000000000 --- a/src/lib/common/journal.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the - * related information and legal notices. It is expected that any future - * projects/authors will amend these files as needed. - * - * --- - * - * journal.c: Log a journal of events to a file - * - * Known contributors to this file: - * Markus Armbruster, 2004-2007 - */ - -/* - * Journal file format: each line logs an event, and looks like this: - * - * TIME THREAD EVENT DATA - * - * Events and their data are: - * - * startup - * shutdown - * login CNUM HOSTADDR USER - * logout CNUM - * input INPUT - * update ETU - */ - -#include - -#include -#include -#include -#include -#include -#include "misc.h" -#include "empthread.h" -#include "journal.h" -#include "optlist.h" -#include "player.h" -#include "prototypes.h" - -static char journal_fname[] = "journal.log"; -static FILE *journal; - -static FILE * -journal_open(void) -{ - return fopen(journal_fname, "a+"); -} - -static void -journal_entry(char *fmt, ...) -{ - static char buf[1024]; - va_list ap; - time_t now; - unsigned char *p; - - if (journal) { - time(&now); - fprintf(journal, "%.24s %p ", ctime(&now), empth_self()); - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf) - 1, fmt, ap); - va_end(ap); - - for (p = (unsigned char *)buf; *p; p++) { - if (isprint(*p)) - putc(*p, journal); - else - fprintf(journal, "\\%03o", *p); - } - fputs("\n", journal); - if (debug) - fflush(journal); - if (ferror(journal)) { - logerror("Error writing journal (%s)", strerror(errno)); - clearerr(journal); - } - } -} - -int -journal_startup(void) -{ - if (!keep_journal) - return 0; - journal = journal_open(); - if (!journal) { - logerror("Can't open %s (%s)", journal_fname, strerror(errno)); - return -1; - } - journal_entry("startup"); - return 0; -} - -void -journal_shutdown(void) -{ - journal_entry("shutdown"); - if (journal) { - fclose(journal); - journal = NULL; - } -} - -int -journal_reopen(void) -{ - FILE *j; - - if (!keep_journal) - return 0; - j = journal_open(); - if (!j) { - logerror("Can't open %s (%s)", journal_fname, strerror(errno)); - return -1; - } - if (journal) - fclose(journal); - journal = j; - return 0; -} - -void -journal_login(void) -{ - journal_entry("login %d %s %s", - player->cnum, player->hostaddr, player->userid); -} - -void -journal_logout(void) -{ - journal_entry("logout %d", player->cnum); -} - -void -journal_input(char *input) -{ - journal_entry("input %s", input); -} - -void -journal_update(int etu) -{ - journal_entry("update %d", etu); -} diff --git a/src/lib/common/log.c b/src/lib/common/log.c deleted file mode 100644 index 1a49c0d3d..000000000 --- a/src/lib/common/log.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * log.c: Log an Empire error to a file - * - * Known contributors to this file: - * Dave Pare, 1989 - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include "misc.h" -#include "optlist.h" -#include "player.h" -#include "prototypes.h" - -/* Debugging? If yes call abort() on internal error. */ -int debug = 0; - -static char logfile[32]; -static int logfd = -1; - -static int logopen(void); - -/* - * Points log file at PROGRAM.log - */ -int -loginit(char *program) -{ - sprintf(logfile, "%.*s.log", (int)sizeof(logfile) - 5, program); - logfd = logopen(); - return logfd; -} - -static int -logopen(void) -{ - int fd; - - fd = open(logfile, O_WRONLY | O_CREAT | O_APPEND, S_IRWUG); - if (fd < 0) - logerror("Can't open %s (%s)", logfile, strerror(errno)); - return fd; -} - -int -logreopen(void) -{ - int newfd, res; - - if ((newfd = logopen()) < 0) - return -1; - res = close(logfd); - logfd = newfd; - if (res < 0) - logerror("Can't close %s (%s)", logfile, strerror(errno)); - return res; -} - -/* - * Write a line to the log file and to stderr. - * Messages are silently truncated after 512 characters or a newline. - */ -void -logerror(char *format, ...) -{ - enum { - ctime_len = 24, /* output of ctime() less the newline */ - msg_space = 512 /* space for formatted message */ - }; - va_list list; - time_t now; - char buf[ctime_len + 1 + msg_space + 2]; - char *msg, *p; - - va_start(list, format); - msg = buf + ctime_len + 1; - vsnprintf(msg, msg_space, format, list); - buf[sizeof(buf)-2] = 0; - p = msg + strlen(msg); - p[0] = '\n'; - p[1] = 0; - p = strchr(msg, '\n'); - p[1] = 0; - fputs(msg, stderr); - if (logfd >= 0) { - time(&now); - memcpy(buf, ctime(&now), ctime_len); - buf[ctime_len] = ' '; - write(logfd, buf, strlen(buf)); - } - va_end(list); -} - -/* - * Log internal error MSG occured in FILE:LINE. - * If debugging, call abort(), else return 1. - */ -int -oops(char *msg, char *file, int line) -{ - logerror("Oops: %s in %s:%d", msg ? msg : "bug", file, line); - if (debug) abort(); - return 1; -} - -/* - * Report out-of-memory condition and terminate the program. - * Use this with restraint! Clean error recovery is preferable, but - * not always feasible (e.g. halfway through the update) or worthwhile - * (during server startup). - */ -void -exit_nomem(void) -{ - logerror("Memory exhausted"); - exit(1); -} diff --git a/src/lib/common/mapdist.c b/src/lib/common/mapdist.c new file mode 100644 index 000000000..cac702f45 --- /dev/null +++ b/src/lib/common/mapdist.c @@ -0,0 +1,110 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * mapdist.c: Return the distance between two sectors + * + * Known contributors to this file: + * + */ + +/* + * mapdist returns (integer) distance between two sectors. + */ + +#include + +#include "misc.h" +#include "optlist.h" +#include "prototypes.h" + +int +diffx(int x1, int x2) +{ + int dx; + + dx = x1 - x2; + dx = dx % WORLD_X; + if (dx > WORLD_X / 2) + dx = dx - WORLD_X; + if (dx < -WORLD_X / 2) + dx = dx + WORLD_X; + return dx; +} + +int +diffy(int y1, int y2) +{ + int dy; + + dy = y1 - y2; + dy = dy % WORLD_Y; + if (dy > WORLD_Y / 2) + dy = dy - WORLD_Y; + if (dy < -WORLD_Y / 2) + dy = dy + WORLD_Y; + return dy; +} + +int +deltax(int x1, int x2) +{ + int dx; + + dx = abs(x1 - x2); + dx = dx % WORLD_X; + if (dx > WORLD_X / 2) + dx = WORLD_X - dx; + return dx; +} + +int +deltay(int y1, int y2) +{ + int dy; + + dy = abs(y1 - y2); + dy = dy % WORLD_Y; + if (dy > WORLD_Y / 2) + dy = WORLD_Y - dy; + return dy; +} + +int +mapdist(int x1, int y1, int x2, int y2) +{ + int dx, dy; + + x1 = x1 % WORLD_X; + y1 = y1 % WORLD_Y; + x2 = x2 % WORLD_X; + y2 = y2 % WORLD_Y; + dx = deltax(x1, x2); + dy = deltay(y1, y2); + if (dx > dy) + return (dx - dy) / 2 + dy; + return dy; +} diff --git a/src/lib/common/maps.c b/src/lib/common/maps.c deleted file mode 100644 index b60d5d670..000000000 --- a/src/lib/common/maps.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * maps.c: Map routines - * - * Known contributors to this file: - * Ken Stevens, 1995 - * Steve McClure, 1998 - * Ron Koenderink, 2006 - */ - -#include - -#include -#include "com.h" -#include "empobj.h" -#include "file.h" -#include "land.h" -#include "map.h" -#include "misc.h" -#include "nat.h" -#include "nsc.h" -#include "nuke.h" -#include "optlist.h" -#include "plane.h" -#include "player.h" -#include "prototypes.h" -#include "sect.h" -#include "ship.h" -#include "xy.h" - -static int bmnxtsct(struct nstr_sect *); -static char map_char(unsigned char type, natid own, int owner_or_god); - -int -do_map(int bmap, int unit_type, char *arg, char *map_flags_arg) -{ - struct nstr_sect ns; - char origin = '\0'; - char *b; - int map_flags = 0; - - if (!snxtsct(&ns, arg)) { - if (unit_map(unit_type, atoi(arg), &ns, &origin)) - return RET_FAIL; - } - for (b = map_flags_arg; b && *b; b++) { - switch (*b) { - case 's': - case 'S': - map_flags |= MAP_SHIP; - break; - case 'l': - case 'L': - map_flags |= MAP_LAND; - break; - case 'p': - case 'P': - map_flags |= MAP_PLANE; - break; - case 'n': - case 'N': - map_flags |= MAP_NUKE; - break; - case 'h': - case 'H': - map_flags |= MAP_HIGH; - break; - case '*': - map_flags |= MAP_ALL; - break; - case 't': - if (bmap != 'b') - goto bad_flag; - bmap = 't'; - *(b + 1) = 0; - break; - case 'r': - if (bmap != 'b') - goto bad_flag; - bmap = 'r'; - *(b + 1) = 0; - break; - default: - bad_flag: - pr("Bad flag %c!\n", *b); - break; - } - } - return draw_map(bmap, origin, map_flags, &ns); -} - -int -draw_map(int bmap, char origin, int map_flags, struct nstr_sect *nsp) -{ - struct natstr *np; - struct range range; - struct nstr_item ni; - union empobj_storage unit; - coord x, y; - int i; - /* Note this is not re-entrant anyway, so we keep the buffers - around */ - static unsigned char *bitmap = NULL; - static char *wmapbuf = NULL; - static char **wmap = NULL; - static int ef_mappable[] = { EF_PLANE, EF_SHIP, EF_LAND, EF_NUKE, EF_BAD }; - static int ef_unit_map[] = { MAP_PLANE, MAP_SHIP, MAP_LAND, MAP_NUKE }; - char *name; - - if (!wmapbuf) - wmapbuf = malloc(WORLD_Y * MAPWIDTH(1)); - if (!wmap) { - wmap = malloc(WORLD_Y * sizeof(char *)); - if (wmap && wmapbuf) { - for (i = 0; i < WORLD_Y; i++) - wmap[i] = &wmapbuf[MAPWIDTH(1) * i]; - } else if (wmap) { - free(wmap); - wmap = NULL; - } - } - if (!bitmap) - bitmap = malloc((WORLD_X * WORLD_Y) / 8); - if (!wmapbuf || !wmap || !bitmap) { - pr("Memory error, tell the deity.\n"); - logerror("malloc failed in draw_map\n"); - return RET_FAIL; - } - - if (bmap == 'r') { - if (!confirm("Are you sure you want to revert your bmap? ")) - return RET_OK; - } - if (!(player->command->c_flags & C_MOD)) { - logerror("%s command needs C_MOD flag set", - player->command->c_form); - player->command->c_flags |= C_MOD; - } - np = getnatp(player->cnum); - /* zap any conditionals */ - nsp->ncond = 0; - xyrelrange(np, &nsp->range, &range); - border(&range, " ", ""); - blankfill(wmapbuf, &nsp->range, 1); - if (bmap) { - int c; - switch (bmap) { - default: - CANT_REACH(); - bmap = 'b'; - /* fall through */ - case 'b': - while (bmnxtsct(nsp) && !player->aborted) { - if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)])) - wmap[nsp->dy][nsp->dx] = c; - } - break; - case 't': - while (bmnxtsct(nsp) && !player->aborted) { - if (0 != (c = player->map[sctoff(nsp->x, nsp->y)])) - wmap[nsp->dy][nsp->dx] = c; - } - break; - case 'r': - while (bmnxtsct(nsp) && !player->aborted) { - player->bmap[sctoff(nsp->x, nsp->y)] = - player->map[sctoff(nsp->x, nsp->y)]; - if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)])) - wmap[nsp->dy][nsp->dx] = c; - } - ef_write(EF_BMAP, player->cnum, player->bmap); - break; - case 'n': - { - struct sctstr sect; - - if (!player->god) { - memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8); - bitinit2(nsp, bitmap, player->cnum); - } - while (nxtsct(nsp, §) && !player->aborted) { - if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap)) - continue; - wmap[nsp->dy][nsp->dx] - = map_char(sect.sct_newtype, sect.sct_own, - player->owner); - } - break; - } - } - } else { - struct sctstr sect; - char mapch; - int changed = 0; - - if (!player->god) { - memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8); - bitinit2(nsp, bitmap, player->cnum); - } - while (nxtsct(nsp, §) && !player->aborted) { - if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap)) - continue; - mapch = map_char(sect.sct_type, sect.sct_own, player->owner); - wmap[nsp->dy][nsp->dx] = mapch; - changed |= map_set(player->cnum, nsp->x, nsp->y, mapch, 0); - } - if (changed) - writemap(player->cnum); - } - if (player->aborted) - return RET_OK; - - i = 0; - while (ef_mappable[i] != EF_BAD) { - if (map_flags & ef_unit_map[i]) { - snxtitem_all(&ni, ef_mappable[i]); - while (nxtitem(&ni, &unit)) { - if (unit.gen.own == 0) - continue; - if (unit.gen.own != player->cnum && !player->god) - continue; - if (!xyinrange(unit.gen.x, unit.gen.y, &nsp->range)) - continue; - - x = xnorm(unit.gen.x - nsp->range.lx); - y = ynorm(unit.gen.y - nsp->range.ly); - - if (ef_mappable[i] == EF_NUKE) - wmap[y][x] = 'N'; - else { - if ((name = emp_obj_chr_name(&unit.gen)) == NULL) - return RET_FAIL; - wmap[y][x] = *name & ~0x20; - } - } - } - i++; - } - if (map_flags & MAP_HIGH) { - struct sctstr sect; - - snxtsct_rewind(nsp); - if (!player->god) { - memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8); - bitinit2(nsp, bitmap, player->cnum); - } - while (nxtsct(nsp, §) && !player->aborted) { - if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap)) - continue; - if (sect.sct_own == player->cnum) - wmap[nsp->dy][nsp->dx] |= 0x80; - } - } - if (origin) - wmap[5][10] = origin & ~0x20; - for (y = nsp->range.ly, i = 0; i < nsp->range.height; y++, i++) { - int yval; - - yval = yrel(np, y); - wmap[i][nsp->range.width] = '\0'; - pr("%4d %s %-4d\n", yval, wmap[i], yval); - if (y >= WORLD_Y) - y -= WORLD_Y; - } - border(&range, " ", ""); - return RET_OK; -} - -/* - * get the next sector in the range - */ -static int -bmnxtsct(struct nstr_sect *np) -{ - while (1) { - np->dx++; - np->x++; - if (np->x >= WORLD_X) - np->x = 0; - if (np->dx >= np->range.width) { - np->dx = 0; - np->x = np->range.lx; - np->dy++; - if (np->dy >= np->range.height) - return 0; - np->y++; - if (np->y >= WORLD_Y) - np->y = 0; - } - if ((np->y + np->x) & 01) - continue; - if (np->type == NS_DIST) { - np->curdist = mapdist(np->x, np->y, np->cx, np->cy); - if (np->curdist > np->dist) - continue; - } - np->id = sctoff(np->x, np->y); - return 1; - } - /*NOTREACHED*/ -} - -/* - * Return character to use in maps for sector type TYPE owned by OWN. - * If OWNER_OR_GOD, the map is for the sector's owner or a deity. - */ -static char -map_char(unsigned char type, natid own, int owner_or_god) -{ - if (CANT_HAPPEN(type > SCT_TYPE_MAX || !dchr[type].d_mnem)) - return '?'; - if (owner_or_god - || type == SCT_WATER || type == SCT_MOUNT || type == SCT_WASTE - || (!own && (type == SCT_RURAL || type == SCT_PLAINS))) - return dchr[type].d_mnem; - return '?'; -} - -int -unit_map(int unit_type, int uid, struct nstr_sect *nsp, char *originp) -{ - struct empobj *gp; - struct range range; - char *name; - - gp = get_empobjp(unit_type, uid); - if (!gp || (gp->own != player->cnum && !player->god) || gp->own == 0) - return RET_FAIL; - - if (unit_type == EF_NUKE) - *originp = 'n'; - else { - if ((name = emp_obj_chr_name(gp)) == NULL) - return RET_FAIL; - *originp = *name; - } - - range.lx = xnorm(gp->x - 10); - range.hx = xnorm(gp->x + 11); - range.ly = ynorm(gp->y - 5); - range.hy = ynorm(gp->y + 6); - xysize_range(&range); - snxtsct_area(nsp, &range); - return RET_OK; -} - -int -display_region_map(int bmap, int unit_type, coord curx, coord cury, - char *arg) -{ - char coordinates[80]; - char *map_flag_arg; - - if (!arg || !*arg) { - struct natstr *np; - - np = getnatp(player->cnum); - sprintf(coordinates, "%d:%d,%d:%d", - xrel(np, curx - 10), xrel(np, curx + 11), - yrel(np, cury - 5), yrel(np, cury + 6)); - arg = coordinates; - map_flag_arg = NULL; - } else { - map_flag_arg = strchr(arg, ' '); - if (map_flag_arg != NULL) { - *map_flag_arg++ = '\0'; - while (isspace(*map_flag_arg)) map_flag_arg++; - } - } - player->condarg = NULL; - return do_map(bmap, unit_type, arg, map_flag_arg); -} - -int -bmaps_intersect(natid a, natid b) -{ - char *mapa = ef_ptr(EF_MAP, a); - char *mapb = ef_ptr(EF_MAP, b); - int i; - - for (i = 0; i < WORLD_SZ(); i++) - if (mapa[i] && mapa[i] != ' ' && mapb[i] && mapb[i] != ' ') - return 1; - return 0; -} - -/* Note that this requires that the BMAP is mapped into memory */ - -int -share_bmap(natid from, natid to, struct nstr_sect *ns, char des, - char *from_name) -{ - char *from_bmap = ef_ptr(EF_BMAP, from); - char *to_bmap = ef_ptr(EF_BMAP, to); - int n = 0; - struct sctstr sect; - char fromdes; - char todes; - char from_des = *from_name; - - if (isalpha(from_des)) - from_des &= ~0x20; - - while (nxtsct(ns, §)) { - if (!(fromdes = from_bmap[sctoff(ns->x, ns->y)])) - continue; - todes = to_bmap[sctoff(ns->x, ns->y)]; - if (todes && - todes != '?' && - todes != '.' && todes != ' ' && todes != from_des) - continue; - if (sect.sct_own == from) { - if (fromdes != '=' && fromdes != 'h' && fromdes != des) - fromdes = from_des; - } - if (todes == fromdes) - continue; - n += map_set(to, ns->x, ns->y, fromdes, 1); - } - - if (n) - writebmap(to); - return n; -} diff --git a/src/lib/common/nstreval.c b/src/lib/common/nstreval.c new file mode 100644 index 000000000..9bb35dc85 --- /dev/null +++ b/src/lib/common/nstreval.c @@ -0,0 +1,173 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * nstreval.c: evaluate compiled values + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1997 + * Markus Armbruster, 2004-2006 + */ + +#include + +#include +#include "file.h" +#include "nat.h" +#include "nsc.h" +#include "optlist.h" + + +/* + * Evaluate VAL. + * If VAL is symbolic, evaluate it into a promoted value type. + * Use coordinate system of country CNUM. + * PTR points to a context object of the type that was used to compile + * the value. + * Unless WANT is NSC_NOTYPE, coerce the value to promoted value type + * WANT. VAL must be coercible. That's the case if a previous + * nstr_coerce_val(VAL, WANT, STR) succeeded. + */ +void +nstr_exec_val(struct valstr *val, natid cnum, void *ptr, nsc_type want) +{ + char *memb_ptr; + nsc_type valtype; + int idx; + struct natstr *natp; + + switch (val->val_cat) { + default: + CANT_REACH(); + /* fall through */ + case NSC_VAL: + valtype = val->val_type; + break; + case NSC_OFF: + valtype = NSC_LONG; + memb_ptr = ptr; + memb_ptr += val->val_as.sym.off; + idx = val->val_as.sym.idx; + switch (val->val_type) { + case NSC_CHAR: + val->val_as.lng = ((signed char *)memb_ptr)[idx]; + break; + case NSC_UCHAR: + val->val_as.lng = ((unsigned char *)memb_ptr)[idx]; + break; + case NSC_SHORT: + val->val_as.lng = ((short *)memb_ptr)[idx]; + break; + case NSC_USHORT: + val->val_as.lng = ((unsigned short *)memb_ptr)[idx]; + break; + case NSC_INT: + val->val_as.lng = ((int *)memb_ptr)[idx]; + break; + case NSC_LONG: + val->val_as.lng = ((long *)memb_ptr)[idx]; + break; + case NSC_XCOORD: + val->val_as.lng = xrel(getnatp(cnum), ((short *)memb_ptr)[idx]); + break; + case NSC_YCOORD: + val->val_as.lng = yrel(getnatp(cnum), ((short *)memb_ptr)[idx]); + break; + case NSC_HIDDEN: + val->val_as.lng = -1; + if (CANT_HAPPEN(((struct natstr *)ptr)->ef_type != EF_NATION)) + break; + natp = getnatp(cnum); + if (!opt_HIDDEN + || natp->nat_stat == STAT_GOD + || (getcontact(natp, idx) && getcontact(ptr, idx))) + val->val_as.lng = ((unsigned char *)memb_ptr)[idx]; + break; + case NSC_FLOAT: + val->val_as.dbl = ((float *)memb_ptr)[idx]; + valtype = NSC_DOUBLE; + break; + case NSC_DOUBLE: + val->val_as.dbl = ((double *)memb_ptr)[idx]; + valtype = NSC_DOUBLE; + break; + case NSC_STRINGY: + CANT_HAPPEN(idx); + val->val_as.str.maxsz = val->val_as.sym.len; + val->val_as.str.base = (char *)memb_ptr; + valtype = NSC_STRING; + break; + case NSC_STRING: + val->val_as.str.base = ((char **)memb_ptr)[idx]; + val->val_as.str.maxsz = INT_MAX; + valtype = NSC_STRING; + break; + case NSC_TIME: + val->val_as.lng = ((time_t *)memb_ptr)[idx]; + break; + default: + CANT_REACH(); + val->val_as.lng = 0; + } + val->val_cat = NSC_VAL; + } + + if (valtype == want) + ; + else if (want == NSC_DOUBLE) { + if (valtype == NSC_LONG) { + valtype = want; + val->val_as.dbl = val->val_as.lng; + } + } else if (want == NSC_STRING) + CANT_REACH(); /* FIXME implement */ + + if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) { + valtype = want; + switch (want) { + case NSC_LONG: val->val_as.lng = 0; break; + case NSC_DOUBLE: val->val_as.dbl = 0.0; break; + case NSC_STRING: val->val_as.str.base = NULL; break; + default: + CANT_REACH(); + } + } + + val->val_type = valtype; +} + +char * +symbol_by_value(int key, struct symbol *table) +{ + int i; + + for (i = 0; table[i].name; i++) + if (key == table[i].value) + return table[i].name; + + return NULL; +} diff --git a/src/lib/common/sectdamage.c b/src/lib/common/sectdamage.c deleted file mode 100644 index 6dcacbb70..000000000 --- a/src/lib/common/sectdamage.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * sectdamage.c: Damage a sector - * - * Known contributors to this file: - * Dave Pare, 1989 - * Steve McClure, 1996 - */ - -#include - -#include "combat.h" -#include "damage.h" -#include "file.h" -#include "land.h" -#include "misc.h" -#include "nat.h" -#include "nsc.h" -#include "optlist.h" -#include "plane.h" -#include "prototypes.h" -#include "sect.h" -#include "ship.h" -#include "xy.h" - -int -sect_damage(struct sctstr *sp, int dam, struct emp_qelem *list) -{ - int eff; - - if (dam <= 0) - return 0; - if (dam > 100) - dam = 100; - - sp->sct_effic = damage(sp->sct_effic, dam); - sp->sct_avail = damage(sp->sct_avail, dam); - sp->sct_road = damage(sp->sct_road, dam); - sp->sct_rail = damage(sp->sct_rail, dam); - sp->sct_defense = damage(sp->sct_defense, dam); - - eff = dam; - - if (sp->sct_mobil > 0) - sp->sct_mobil = damage(sp->sct_mobil, dam); - item_damage(dam, sp->sct_item); - if (opt_EASY_BRIDGES == 0) { - if (sp->sct_effic < SCT_MINEFF && sp->sct_type == SCT_BHEAD) - bridgefall(sp, list); - } else { - if (sp->sct_effic < SCT_MINEFF && sp->sct_type == SCT_BSPAN) - knockdown(sp, list); - } - putsect(sp); - return eff; -} - -int -sectdamage(struct sctstr *sp, int dam, struct emp_qelem *list) -{ - struct nstr_item ni; - struct lndstr land; - struct plnstr plane; - int eff; - - /* Some sectors are harder/easier to kill.. */ - /* Average sector has a dstr of 1, so adjust */ - /* the damage accordingly. Makes forts a pain */ - dam = ldround(dam / sector_strength(sp), 1); - - eff = sect_damage(sp, PERCENT_DAMAGE(dam), list); - - /* Damage all the land units in the sector */ - /* Units don't take full damage */ - dam = ldround(DPERCENT_DAMAGE(dam * unit_damage), 1); - if (dam <= 0) - return eff; - - snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); - while (nxtitem(&ni, &land)) { - if (!land.lnd_own) - continue; - landdamage(&land, dam); - putland(land.lnd_uid, &land); - } - - dam = dam / 7; - if (dam <= 0) - return eff; - snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y); - while (nxtitem(&ni, &plane)) { - if (!plane.pln_own) - continue; - if (plane.pln_flags & PLN_LAUNCHED) - continue; - if (plane.pln_ship >= 0) - continue; - /* Is this plane flying in this list? */ - if (ac_isflying(&plane, list)) - continue; - planedamage(&plane, dam); - putplane(plane.pln_uid, &plane); - } - return eff; -} diff --git a/src/lib/empthread/io.c b/src/lib/empthread/io.c new file mode 100644 index 000000000..4c42a55ef --- /dev/null +++ b/src/lib/empthread/io.c @@ -0,0 +1,350 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * io.c: Arrange for input and output on a file descriptor to be queued. + * + * Known contributors to this file: + * Doug Hay, 1998 + * Steve McClure, 1998 + */ + +/* + * Arrange for input and output on a file descriptor + * to be queued. Provide main loop -- a mechanism for + * blocking across all registered file descriptors, and + * reading or writing when appropriate. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "empio.h" +#include "empthread.h" +#include "ioqueue.h" +#include "misc.h" +#include "queue.h" +#include "server.h" + +struct iop { + int fd; + struct ioqueue *input; + struct ioqueue *output; + int flags; + int bufsize; +}; + +void +io_init(void) +{ +} + +struct iop * +io_open(int fd, int flags, int bufsize) +{ + struct iop *iop; + + flags = flags & (IO_READ | IO_WRITE | IO_NBLOCK | IO_NEWSOCK); + if ((flags & (IO_READ | IO_WRITE)) == 0) + return NULL; + iop = malloc(sizeof(struct iop)); + if (!iop) + return NULL; + iop->fd = fd; + iop->input = 0; + iop->output = 0; + iop->flags = 0; + iop->bufsize = bufsize; + if ((flags & IO_READ) && (flags & IO_NEWSOCK) == 0) + iop->input = ioq_create(bufsize); + if ((flags & IO_WRITE) && (flags & IO_NEWSOCK) == 0) + iop->output = ioq_create(bufsize); + if (flags & IO_NBLOCK) + io_noblocking(iop, 1); /* FIXME check success */ + iop->flags = flags; + return iop; +} + +void +io_close(struct iop *iop) +{ + + if (iop->input != 0) + ioq_destroy(iop->input); + if (iop->output != 0) + ioq_destroy(iop->output); + (void)close(iop->fd); + free(iop); +} + +int +io_input(struct iop *iop, int waitforinput) +{ + char buf[IO_BUFSIZE]; + int cc; + + /* Not a read IOP */ + if ((iop->flags & IO_READ) == 0) + return -1; + /* IOP is markes as in error. */ + if (iop->flags & IO_ERROR) + return -1; + /* Wait for the file to have input. */ + if (waitforinput) { + empth_select(iop->fd, EMPTH_FD_READ); + } + /* Do the actual read. */ + cc = read(iop->fd, buf, sizeof(buf)); + if (cc < 0) { + /* would block, so nothing to read. */ + if (errno == EAGAIN || errno == EWOULDBLOCK) + return 0; + + /* Some form of file error occurred... */ + iop->flags |= IO_ERROR; + return -1; + } + + /* We eof'd */ + if (cc == 0) { + iop->flags |= IO_EOF; + return 0; + } + + /* Append the input to the IOQ. */ + ioq_append(iop->input, buf, cc); + return cc; +} + +int +io_inputwaiting(struct iop *iop) +{ + return ioq_qsize(iop->input); +} + +int +io_outputwaiting(struct iop *iop) +{ + return ioq_qsize(iop->output); +} + +int +io_output(struct iop *iop, int waitforoutput) +{ + struct iovec iov[16]; + int cc; + int n; + int remain; + + /* If there is no output waiting. */ + if (!io_outputwaiting(iop)) + return 0; + + /* If the iop is not write enabled. */ + if ((iop->flags & IO_WRITE) == 0) + return -1; + + /* If the io is marked as in error... */ + if (iop->flags & IO_ERROR) + return -1; + + /* make the iov point to the data in the queue. */ + /* I.E., each of the elements in the queue. */ + /* returns the number of elements in the iov. */ + n = ioq_makeiov(iop->output, iov, IO_BUFSIZE); + + if (n <= 0) { + return 0; + } + + /* wait for the file to be output ready. */ + if (waitforoutput != IO_NOWAIT) { + /* This waits for the file to be ready for writing, */ + /* and lets other threads run. */ + empth_select(iop->fd, EMPTH_FD_WRITE); + } + + /* Do the actual write. */ + cc = writev(iop->fd, iov, n); + + /* if it failed.... */ + if (cc < 0) { + /* Hmm, it would block. file is opened noblock, soooooo.. */ + if (errno == EAGAIN || errno == EWOULDBLOCK) { + /* If there are remaining bytes, set the IO as remaining.. */ + remain = ioq_qsize(iop->output); + return remain; + } + iop->flags |= IO_ERROR; + return -1; + } + + /* If no bytes were written, something happened.. Like an EOF. */ + if (cc == 0) { + iop->flags |= IO_EOF; + return 0; + } + + /* Remove the number of written bytes from the queue. */ + ioq_dequeue(iop->output, cc); + + return cc; +} + +int +io_peek(struct iop *iop, char *buf, int nbytes) +{ + if ((iop->flags & IO_READ) == 0) + return -1; + return ioq_peek(iop->input, buf, nbytes); +} + +int +io_read(struct iop *iop, char *buf, int nbytes) +{ + int cc; + + if ((iop->flags & IO_READ) == 0) + return -1; + cc = ioq_peek(iop->input, buf, nbytes); + if (cc > 0) + ioq_dequeue(iop->input, cc); + return cc; +} + +int +io_write(struct iop *iop, char *buf, int nbytes, int doWait) +{ + int len; + + if ((iop->flags & IO_WRITE) == 0) + return -1; + ioq_append(iop->output, buf, nbytes); + len = ioq_qsize(iop->output); + if (len > iop->bufsize) { + if (doWait) { + io_output_all(iop); + } else { + /* only try a write every BUFSIZE characters */ + if (((len - nbytes) % iop->bufsize) < (len % iop->bufsize)) + io_output(iop, IO_NOWAIT); + } + } + return nbytes; +} + +int +io_output_all(struct iop *iop) +{ + int n; + + /* + * Mustn't block a player thread while update is pending, or else + * a malicous player could delay the update indefinitely + */ + while ((n = io_output(iop, IO_NOWAIT)) > 0 && !play_wrlock_wanted) + empth_select(iop->fd, EMPTH_FD_WRITE); + + return n; +} + +int +io_gets(struct iop *iop, char *buf, int nbytes) +{ + if ((iop->flags & IO_READ) == 0) + return -1; + return ioq_gets(iop->input, buf, nbytes); +} + +int +io_puts(struct iop *iop, char *buf) +{ + if ((iop->flags & IO_WRITE) == 0) + return -1; + return ioq_puts(iop->output, buf); +} + +int +io_shutdown(struct iop *iop, int flags) +{ + flags &= (IO_READ | IO_WRITE); + if ((iop->flags & flags) != flags) + return -1; + if (flags & IO_READ) { + shutdown(iop->fd, 0); + ioq_drain(iop->input); + } + if (flags & IO_WRITE) { + shutdown(iop->fd, 1); + ioq_drain(iop->output); + } + return 0; +} + +int +io_noblocking(struct iop *iop, int value) +{ + int flags; + + flags = fcntl(iop->fd, F_GETFL, 0); + if (flags < 0) + return -1; + if (value == 0) + flags &= ~O_NONBLOCK; + else + flags |= O_NONBLOCK; + if (fcntl(iop->fd, F_SETFL, flags) < 0) + return -1; + if (value == 0) + iop->flags &= ~IO_NBLOCK; + else + iop->flags |= IO_NBLOCK; + return 0; +} + +int +io_error(struct iop *iop) +{ + return iop->flags & IO_ERROR; +} + +int +io_eof(struct iop *iop) +{ + return iop->flags & IO_EOF; +} + +int +io_fileno(struct iop *iop) +{ + return iop->fd; +} diff --git a/src/lib/gen/emp_config.c b/src/lib/gen/emp_config.c deleted file mode 100644 index 7997b9a54..000000000 --- a/src/lib/gen/emp_config.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * emp_config.c: Allows config file to control server config. from a file - * - * Known contributors to this file: - * Julian Onions, 1995 - * Steve McClure, 1998-2000 - */ - -/* - * STILL TO DO - * - * Change other constants - such as MAXNOC etc. - * Just requires variables to be assigned, then dynamic allocation in - * a few places. Some checks needed in the server to check the world - * hasn't changed size etc. - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include "file.h" -#include "misc.h" -#include "optlist.h" -#include "prototypes.h" - -/* Dummy one */ -static int emp_config_dummy; - -/* things that can be changed */ -struct keymatch configkeys[] = { -#define EMP_CONFIG_C_OUTPUT -#include "econfig-spec.h" -#undef EMP_CONFIG_C_OUTPUT -}; - -static struct keymatch *keylookup(char *key, struct keymatch tbl[]); -static void set_paths(char *); - -/* - * read in empire configuration - */ -int -emp_config(char *file) -{ - FILE *fp; - char scanspace[1024]; - char *av[128]; - char buf[1024]; - struct keymatch *kp; - int lno = 0; - int errors = 0; - int i; - - if (!file) - file = dflt_econfig; - errno = 0; - if ((fp = fopen(file, "r")) == NULL) { - if (file == dflt_econfig && errno == ENOENT) - goto done; - fprintf(stderr, "Can't open %s for reading (%s)\n", - file, strerror(errno)); - return -1; - } - - while (fgets(buf, sizeof(buf), fp) != NULL) { - ++lno; - for (i = 0; buf[i] && isspace(buf[i]); ++i) ; - if (!buf[i] || buf[i] == '#') - continue; - if (parse(buf, scanspace, av, NULL, NULL, NULL) < 0) { - fprintf(stderr, "%s:%d: Can't parse line %s", file, lno, buf); - errors = 1; - continue; - } - if ((kp = keylookup(av[0], configkeys)) == NULL) { - fprintf(stderr, "%s:%d: Unknown config key %s\n", - file, lno, av[0]); - errors = 1; - continue; - } - if (av[1] == NULL) { - fprintf(stderr, "%s:%d: Config key %s needs a value\n", - file, lno, av[0]); - errors = 1; - continue; - } - i = 2; - switch (kp->km_type) { - case NSC_INT: - *(int *)kp->km_data = atoi(av[1]); - break; - case NSC_FLOAT: - *(float *)kp->km_data = atof(av[1]); - break; - case NSC_DOUBLE: - *(double *)kp->km_data = atof(av[1]); - break; - case NSC_LONG: - *(long *)kp->km_data = atol(av[1]); - break; - case NSC_STRING: - if (kp->km_flags & KM_ALLOC) - free(*(char **)kp->km_data); - *(char **)kp->km_data = strdup(av[1]); - kp->km_flags |= KM_ALLOC; - break; - default: - assert(0); - } - if (av[i] != NULL) { - fprintf(stderr, "%s:%d: Junk after value of config key %s\n", - file, lno, av[0]); - errors = 1; - } - } - - fclose(fp); - -done: - WORLD_X &= ~1; /* force even */ - set_paths(file); - - return -errors; -} - -/* find the key in the table */ -static struct keymatch * -keylookup(char *command, struct keymatch *tbl) -{ - struct keymatch *kp; - - if (command == 0 || *command == 0) - return 0; - for (kp = tbl; kp->km_key != 0; kp++) { - if (strcmp(kp->km_key, command) == 0) - return kp; - } - return NULL; -} - -static void -set_paths(char *econfig) -{ - char *slash; - char *cwd = getcwd(NULL, 0); - -#ifdef _WIN32 - /* normalize path separator to '\\', for easier searching: */ - econfig = _fullpath(NULL, econfig, 0); - slash = strrchr(econfig, '\\'); - configdir = malloc(slash - econfig + 1); - memcpy(configdir, econfig, slash - econfig); - configdir[slash - econfig] = 0; -#else - if ((slash = strrchr(econfig, '/'))) { - configdir = malloc(slash - econfig + 1); - memcpy(configdir, econfig, slash - econfig); - configdir[slash - econfig] = 0; - } else - configdir = strdup(cwd); - - if (configdir[0] != '/') { - char *tmp = configdir; - size_t len = strlen(cwd); - - configdir = malloc(len + 1 + strlen(tmp) + 1); - sprintf(configdir, "%s/%s", cwd, tmp); - free(tmp); - } -#endif /* !_WIN32 */ - - schedulefil = malloc(strlen(configdir) + 10); - sprintf(schedulefil, "%s/schedule", configdir); - - free(cwd); -} - -void -print_config(FILE *fp) -{ - struct keymatch *kp; - - fprintf(fp, "# Empire Configuration File:\n"); - for (kp = configkeys; kp->km_key; kp++) { - if (kp->km_comment) { - if (kp->km_comment[0] != '\n' && kp->km_comment[0] != '#') - fprintf(fp, "\n# "); - fprintf(fp, "%s\n", kp->km_comment); - } - if (!kp->km_key[0]) - continue; - switch (kp->km_type) { - case NSC_STRING: - fprintf(fp, "%s \"%s\"\n", kp->km_key, *(char **)kp->km_data); - break; - case NSC_INT: - fprintf(fp, "%s %d\n", kp->km_key, *(int *)kp->km_data); - break; - case NSC_FLOAT: - fprintf(fp, "%s %g\n", kp->km_key, *(float *)kp->km_data); - break; - case NSC_DOUBLE: - fprintf(fp, "%s %g\n", kp->km_key, *(double *)kp->km_data); - break; - case NSC_LONG: - fprintf(fp, "%s %ld\n", kp->km_key, *(long *)kp->km_data); - break; - default: - assert(0); - } - } - - fprintf(fp, "\n"); -} diff --git a/src/lib/gen/fsize.c b/src/lib/gen/fsize.c new file mode 100644 index 000000000..36af6d263 --- /dev/null +++ b/src/lib/gen/fsize.c @@ -0,0 +1,80 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * fsize.c: BSD dependant file and block sizing routines + * + * Known contributors to this file: + * Dave Pare, 1986 + * Doug Hay, 1998 + * Steve McClure, 1998 + */ + +#include + +#include +#include +#include "prototypes.h" + +/* + * return the size of the file in bytes. + */ +int +fsize(int fd) +{ + struct stat statb; + + if (fstat(fd, &statb) < 0) + return -1; + return statb.st_size; +} + +/* + * Return the preferred block size for I/O on FD. + */ +int +blksize(int fd) +{ +#if defined(_WIN32) + return 2048; +#else /* !_WIN32 */ + struct stat statb; + + if (fstat(fd, &statb) < 0) + return 1024; + return statb.st_blksize; +#endif /* !_WIN32 */ +} + +time_t +fdate(int fd) +{ + struct stat statb; + + if (fstat(fd, &statb) < 0) + return 0; + return statb.st_mtime; +} diff --git a/src/lib/gen/getstarg.c b/src/lib/gen/getstarg.c deleted file mode 100644 index 62605d706..000000000 --- a/src/lib/gen/getstarg.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * getstarg.c: Get a string argument (ask if not there) - * - * Known contributors to this file: - * - */ - -#include - -#include -#include "misc.h" - -/* - * Get string argument. - * If INPUT is not empty, use it, else prompt for more input using PROMPT. - * Copy input to BUF[1024]. - * Return BUF on success, else NULL. - */ -char * -getstarg(char *input, char *prompt, char *buf) -{ - *buf = '\0'; - if (input == 0 || *input == 0) { - if (getstring(prompt, buf) == 0) - return 0; - } else { - strcpy(buf, input); - } - return buf; -} diff --git a/src/lib/gen/getstring.c b/src/lib/gen/getstring.c deleted file mode 100644 index 8f07230bf..000000000 --- a/src/lib/gen/getstring.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * getstring.c: get string, printing a prompt if there is one - * - * Known contributors to this file: - * - */ - -#include - -#include "prototypes.h" - -/* - * Print sub-prompt PROMPT, receive a line of input into BUF[1024]. - * Return BUF on success, else NULL. - */ -char * -getstring(char *prompt, char *buf) -{ - *buf = '\0'; - if (prmptrd(prompt, buf, 1024) < 0) - return NULL; - return buf; -} - -/* - * Print sub-prompt PROMPT, receive a line of UTF-8 input into BUF[1024]. - * Return BUF on success, else NULL. - */ -char * -ugetstring(char *prompt, char *buf) -{ - *buf = '\0'; - if (uprmptrd(prompt, buf, 1024) < 0) - return NULL; - return buf; -} diff --git a/src/lib/gen/io.c b/src/lib/gen/io.c deleted file mode 100644 index 4c42a55ef..000000000 --- a/src/lib/gen/io.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * io.c: Arrange for input and output on a file descriptor to be queued. - * - * Known contributors to this file: - * Doug Hay, 1998 - * Steve McClure, 1998 - */ - -/* - * Arrange for input and output on a file descriptor - * to be queued. Provide main loop -- a mechanism for - * blocking across all registered file descriptors, and - * reading or writing when appropriate. - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include "empio.h" -#include "empthread.h" -#include "ioqueue.h" -#include "misc.h" -#include "queue.h" -#include "server.h" - -struct iop { - int fd; - struct ioqueue *input; - struct ioqueue *output; - int flags; - int bufsize; -}; - -void -io_init(void) -{ -} - -struct iop * -io_open(int fd, int flags, int bufsize) -{ - struct iop *iop; - - flags = flags & (IO_READ | IO_WRITE | IO_NBLOCK | IO_NEWSOCK); - if ((flags & (IO_READ | IO_WRITE)) == 0) - return NULL; - iop = malloc(sizeof(struct iop)); - if (!iop) - return NULL; - iop->fd = fd; - iop->input = 0; - iop->output = 0; - iop->flags = 0; - iop->bufsize = bufsize; - if ((flags & IO_READ) && (flags & IO_NEWSOCK) == 0) - iop->input = ioq_create(bufsize); - if ((flags & IO_WRITE) && (flags & IO_NEWSOCK) == 0) - iop->output = ioq_create(bufsize); - if (flags & IO_NBLOCK) - io_noblocking(iop, 1); /* FIXME check success */ - iop->flags = flags; - return iop; -} - -void -io_close(struct iop *iop) -{ - - if (iop->input != 0) - ioq_destroy(iop->input); - if (iop->output != 0) - ioq_destroy(iop->output); - (void)close(iop->fd); - free(iop); -} - -int -io_input(struct iop *iop, int waitforinput) -{ - char buf[IO_BUFSIZE]; - int cc; - - /* Not a read IOP */ - if ((iop->flags & IO_READ) == 0) - return -1; - /* IOP is markes as in error. */ - if (iop->flags & IO_ERROR) - return -1; - /* Wait for the file to have input. */ - if (waitforinput) { - empth_select(iop->fd, EMPTH_FD_READ); - } - /* Do the actual read. */ - cc = read(iop->fd, buf, sizeof(buf)); - if (cc < 0) { - /* would block, so nothing to read. */ - if (errno == EAGAIN || errno == EWOULDBLOCK) - return 0; - - /* Some form of file error occurred... */ - iop->flags |= IO_ERROR; - return -1; - } - - /* We eof'd */ - if (cc == 0) { - iop->flags |= IO_EOF; - return 0; - } - - /* Append the input to the IOQ. */ - ioq_append(iop->input, buf, cc); - return cc; -} - -int -io_inputwaiting(struct iop *iop) -{ - return ioq_qsize(iop->input); -} - -int -io_outputwaiting(struct iop *iop) -{ - return ioq_qsize(iop->output); -} - -int -io_output(struct iop *iop, int waitforoutput) -{ - struct iovec iov[16]; - int cc; - int n; - int remain; - - /* If there is no output waiting. */ - if (!io_outputwaiting(iop)) - return 0; - - /* If the iop is not write enabled. */ - if ((iop->flags & IO_WRITE) == 0) - return -1; - - /* If the io is marked as in error... */ - if (iop->flags & IO_ERROR) - return -1; - - /* make the iov point to the data in the queue. */ - /* I.E., each of the elements in the queue. */ - /* returns the number of elements in the iov. */ - n = ioq_makeiov(iop->output, iov, IO_BUFSIZE); - - if (n <= 0) { - return 0; - } - - /* wait for the file to be output ready. */ - if (waitforoutput != IO_NOWAIT) { - /* This waits for the file to be ready for writing, */ - /* and lets other threads run. */ - empth_select(iop->fd, EMPTH_FD_WRITE); - } - - /* Do the actual write. */ - cc = writev(iop->fd, iov, n); - - /* if it failed.... */ - if (cc < 0) { - /* Hmm, it would block. file is opened noblock, soooooo.. */ - if (errno == EAGAIN || errno == EWOULDBLOCK) { - /* If there are remaining bytes, set the IO as remaining.. */ - remain = ioq_qsize(iop->output); - return remain; - } - iop->flags |= IO_ERROR; - return -1; - } - - /* If no bytes were written, something happened.. Like an EOF. */ - if (cc == 0) { - iop->flags |= IO_EOF; - return 0; - } - - /* Remove the number of written bytes from the queue. */ - ioq_dequeue(iop->output, cc); - - return cc; -} - -int -io_peek(struct iop *iop, char *buf, int nbytes) -{ - if ((iop->flags & IO_READ) == 0) - return -1; - return ioq_peek(iop->input, buf, nbytes); -} - -int -io_read(struct iop *iop, char *buf, int nbytes) -{ - int cc; - - if ((iop->flags & IO_READ) == 0) - return -1; - cc = ioq_peek(iop->input, buf, nbytes); - if (cc > 0) - ioq_dequeue(iop->input, cc); - return cc; -} - -int -io_write(struct iop *iop, char *buf, int nbytes, int doWait) -{ - int len; - - if ((iop->flags & IO_WRITE) == 0) - return -1; - ioq_append(iop->output, buf, nbytes); - len = ioq_qsize(iop->output); - if (len > iop->bufsize) { - if (doWait) { - io_output_all(iop); - } else { - /* only try a write every BUFSIZE characters */ - if (((len - nbytes) % iop->bufsize) < (len % iop->bufsize)) - io_output(iop, IO_NOWAIT); - } - } - return nbytes; -} - -int -io_output_all(struct iop *iop) -{ - int n; - - /* - * Mustn't block a player thread while update is pending, or else - * a malicous player could delay the update indefinitely - */ - while ((n = io_output(iop, IO_NOWAIT)) > 0 && !play_wrlock_wanted) - empth_select(iop->fd, EMPTH_FD_WRITE); - - return n; -} - -int -io_gets(struct iop *iop, char *buf, int nbytes) -{ - if ((iop->flags & IO_READ) == 0) - return -1; - return ioq_gets(iop->input, buf, nbytes); -} - -int -io_puts(struct iop *iop, char *buf) -{ - if ((iop->flags & IO_WRITE) == 0) - return -1; - return ioq_puts(iop->output, buf); -} - -int -io_shutdown(struct iop *iop, int flags) -{ - flags &= (IO_READ | IO_WRITE); - if ((iop->flags & flags) != flags) - return -1; - if (flags & IO_READ) { - shutdown(iop->fd, 0); - ioq_drain(iop->input); - } - if (flags & IO_WRITE) { - shutdown(iop->fd, 1); - ioq_drain(iop->output); - } - return 0; -} - -int -io_noblocking(struct iop *iop, int value) -{ - int flags; - - flags = fcntl(iop->fd, F_GETFL, 0); - if (flags < 0) - return -1; - if (value == 0) - flags &= ~O_NONBLOCK; - else - flags |= O_NONBLOCK; - if (fcntl(iop->fd, F_SETFL, flags) < 0) - return -1; - if (value == 0) - iop->flags &= ~IO_NBLOCK; - else - iop->flags |= IO_NBLOCK; - return 0; -} - -int -io_error(struct iop *iop) -{ - return iop->flags & IO_ERROR; -} - -int -io_eof(struct iop *iop) -{ - return iop->flags & IO_EOF; -} - -int -io_fileno(struct iop *iop) -{ - return iop->fd; -} diff --git a/src/lib/gen/log.c b/src/lib/gen/log.c new file mode 100644 index 000000000..1a49c0d3d --- /dev/null +++ b/src/lib/gen/log.c @@ -0,0 +1,150 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * log.c: Log an Empire error to a file + * + * Known contributors to this file: + * Dave Pare, 1989 + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "misc.h" +#include "optlist.h" +#include "player.h" +#include "prototypes.h" + +/* Debugging? If yes call abort() on internal error. */ +int debug = 0; + +static char logfile[32]; +static int logfd = -1; + +static int logopen(void); + +/* + * Points log file at PROGRAM.log + */ +int +loginit(char *program) +{ + sprintf(logfile, "%.*s.log", (int)sizeof(logfile) - 5, program); + logfd = logopen(); + return logfd; +} + +static int +logopen(void) +{ + int fd; + + fd = open(logfile, O_WRONLY | O_CREAT | O_APPEND, S_IRWUG); + if (fd < 0) + logerror("Can't open %s (%s)", logfile, strerror(errno)); + return fd; +} + +int +logreopen(void) +{ + int newfd, res; + + if ((newfd = logopen()) < 0) + return -1; + res = close(logfd); + logfd = newfd; + if (res < 0) + logerror("Can't close %s (%s)", logfile, strerror(errno)); + return res; +} + +/* + * Write a line to the log file and to stderr. + * Messages are silently truncated after 512 characters or a newline. + */ +void +logerror(char *format, ...) +{ + enum { + ctime_len = 24, /* output of ctime() less the newline */ + msg_space = 512 /* space for formatted message */ + }; + va_list list; + time_t now; + char buf[ctime_len + 1 + msg_space + 2]; + char *msg, *p; + + va_start(list, format); + msg = buf + ctime_len + 1; + vsnprintf(msg, msg_space, format, list); + buf[sizeof(buf)-2] = 0; + p = msg + strlen(msg); + p[0] = '\n'; + p[1] = 0; + p = strchr(msg, '\n'); + p[1] = 0; + fputs(msg, stderr); + if (logfd >= 0) { + time(&now); + memcpy(buf, ctime(&now), ctime_len); + buf[ctime_len] = ' '; + write(logfd, buf, strlen(buf)); + } + va_end(list); +} + +/* + * Log internal error MSG occured in FILE:LINE. + * If debugging, call abort(), else return 1. + */ +int +oops(char *msg, char *file, int line) +{ + logerror("Oops: %s in %s:%d", msg ? msg : "bug", file, line); + if (debug) abort(); + return 1; +} + +/* + * Report out-of-memory condition and terminate the program. + * Use this with restraint! Clean error recovery is preferable, but + * not always feasible (e.g. halfway through the update) or worthwhile + * (during server startup). + */ +void +exit_nomem(void) +{ + logerror("Memory exhausted"); + exit(1); +} diff --git a/src/lib/gen/mapdist.c b/src/lib/gen/mapdist.c deleted file mode 100644 index cac702f45..000000000 --- a/src/lib/gen/mapdist.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * mapdist.c: Return the distance between two sectors - * - * Known contributors to this file: - * - */ - -/* - * mapdist returns (integer) distance between two sectors. - */ - -#include - -#include "misc.h" -#include "optlist.h" -#include "prototypes.h" - -int -diffx(int x1, int x2) -{ - int dx; - - dx = x1 - x2; - dx = dx % WORLD_X; - if (dx > WORLD_X / 2) - dx = dx - WORLD_X; - if (dx < -WORLD_X / 2) - dx = dx + WORLD_X; - return dx; -} - -int -diffy(int y1, int y2) -{ - int dy; - - dy = y1 - y2; - dy = dy % WORLD_Y; - if (dy > WORLD_Y / 2) - dy = dy - WORLD_Y; - if (dy < -WORLD_Y / 2) - dy = dy + WORLD_Y; - return dy; -} - -int -deltax(int x1, int x2) -{ - int dx; - - dx = abs(x1 - x2); - dx = dx % WORLD_X; - if (dx > WORLD_X / 2) - dx = WORLD_X - dx; - return dx; -} - -int -deltay(int y1, int y2) -{ - int dy; - - dy = abs(y1 - y2); - dy = dy % WORLD_Y; - if (dy > WORLD_Y / 2) - dy = WORLD_Y - dy; - return dy; -} - -int -mapdist(int x1, int y1, int x2, int y2) -{ - int dx, dy; - - x1 = x1 % WORLD_X; - y1 = y1 % WORLD_Y; - x2 = x2 % WORLD_X; - y2 = y2 % WORLD_Y; - dx = deltax(x1, x2); - dy = deltay(y1, y2); - if (dx > dy) - return (dx - dy) / 2 + dy; - return dy; -} diff --git a/src/lib/gen/onearg.c b/src/lib/gen/onearg.c deleted file mode 100644 index 79c8e46eb..000000000 --- a/src/lib/gen/onearg.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * onearg.c: Get one argument, or ask if not there - * - * Known contributors to this file: - * - */ - -#include - -#include "prototypes.h" - -int -onearg(char *arg, char *prompt) -{ - int n; - char buf[1024]; - - if (arg == 0 || *arg == 0) { - if ((arg = getstring(prompt, buf)) == 0) - return -1; - } - n = atoi(arg); - if (n < 0) - return -1; - return n; -} diff --git a/src/lib/subs/bridgefall.c b/src/lib/subs/bridgefall.c new file mode 100644 index 000000000..c11529d1e --- /dev/null +++ b/src/lib/subs/bridgefall.c @@ -0,0 +1,175 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * bridgefall.c: Knock a bridge down + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#include + +#include "file.h" +#include "land.h" +#include "lost.h" +#include "misc.h" +#include "nat.h" +#include "nsc.h" +#include "nuke.h" +#include "optlist.h" +#include "path.h" +#include "plague.h" +#include "plane.h" +#include "prototypes.h" +#include "sect.h" +#include "xy.h" + +void +bridgefall(struct sctstr *sp, struct emp_qelem *list) +{ + int i; + int j; + struct sctstr sect; + struct sctstr bh_sect; + int nx; + int ny; + int nnx; + int nny; + + for (i = 1; i <= 6; i++) { + nx = sp->sct_x + diroff[i][0]; + ny = sp->sct_y + diroff[i][1]; + getsect(nx, ny, §); + if (sect.sct_type != SCT_BSPAN) + continue; + for (j = 1; j <= 6; j++) { + nnx = nx + diroff[j][0]; + nny = ny + diroff[j][1]; + if (nnx == sp->sct_x && nny == sp->sct_y) + continue; + getsect(nnx, nny, &bh_sect); + if (bh_sect.sct_type == SCT_BHEAD && + bh_sect.sct_newtype == SCT_BHEAD) + break; + if (bh_sect.sct_type == SCT_BTOWER) + break; + /* With EASY_BRIDGES, it just has to be next to any + land */ + if (opt_EASY_BRIDGES) { + if (bh_sect.sct_type != SCT_WATER && + bh_sect.sct_type != SCT_BSPAN) + break; + } + } + if (j > 6) { + knockdown(§, list); + putsect(§); + } + } +} + +/* Knock down a bridge span. Note that this does NOT write the + * sector out to the database, it's up to the caller to do that. */ +void +knockdown(struct sctstr *sp, struct emp_qelem *list) +{ + struct lndstr land; + struct plnstr plane; + struct nukstr nuke; + struct nstr_item ni; + struct natstr *np; + + mpr(sp->sct_own, + "Crumble... SCREEEECH! Splash! Bridge%s falls at %s!\n", + sp->sct_type == SCT_BTOWER ? " tower" : "", + xyas(sp->sct_x, sp->sct_y, sp->sct_own)); + sp->sct_type = SCT_WATER; + sp->sct_newtype = SCT_WATER; + makelost(EF_SECTOR, sp->sct_own, 0, sp->sct_x, sp->sct_y); + sp->sct_own = 0; + sp->sct_oldown = 0; + sp->sct_mobil = 0; + sp->sct_effic = 0; + + /* Sink all the units */ + snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); + while (nxtitem(&ni, &land)) { + if (land.lnd_own == 0) + continue; + if (land.lnd_ship >= 0) + continue; + np = getnatp(land.lnd_own); + if (np->nat_flags & NF_BEEP) + mpr(land.lnd_own, "\07"); + mpr(land.lnd_own, " AARGH! %s tumbles to its doom!\n", + prland(&land)); + land.lnd_effic = 0; + putland(land.lnd_uid, &land); + } + /* Sink all the planes */ + snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y); + while (nxtitem(&ni, &plane)) { + if (plane.pln_own == 0) + continue; + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if (plane.pln_ship >= 0) + continue; + /* Is this plane flying in this list? */ + if (ac_isflying(&plane, list)) + continue; + np = getnatp(plane.pln_own); + if (np->nat_flags & NF_BEEP) + mpr(plane.pln_own, "\07"); + mpr(plane.pln_own, " AARGH! %s tumbles to its doom!\n", + prplane(&plane)); + plane.pln_effic = 0; + putplane(plane.pln_uid, &plane); + } + /* Sink all the nukes */ + snxtitem_xy(&ni, EF_NUKE, sp->sct_x, sp->sct_y); + while (nxtitem(&ni, &nuke)) { + if (nuke.nuk_own == 0) + continue; + if (nuke.nuk_plane >= 0) + continue; + np = getnatp(nuke.nuk_own); + if (np->nat_flags & NF_BEEP) + mpr(nuke.nuk_own, "\07"); + mpr(nuke.nuk_own, " %s sinks to the bottom of the sea!\n", + prnuke(&nuke)); + nuke.nuk_effic = 0; + putnuke(nuke.nuk_uid, &nuke); + } + memset(sp->sct_item, 0, sizeof(sp->sct_item)); + memset(sp->sct_del, 0, sizeof(sp->sct_del)); + memset(sp->sct_dist, 0, sizeof(sp->sct_dist)); + sp->sct_pstage = PLG_HEALTHY; + sp->sct_ptime = 0; + sp->sct_che = 0; + sp->sct_che_target = 0; +} diff --git a/src/lib/subs/check.c b/src/lib/subs/check.c new file mode 100644 index 000000000..d8b315076 --- /dev/null +++ b/src/lib/subs/check.c @@ -0,0 +1,175 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * check.c: Check a sector, plane, land unit, ship or nuke + * + * Known contributors to this file: + * Steve McClure, 1998 + */ + +#include + +#include "commodity.h" +#include "file.h" +#include "land.h" +#include "loan.h" +#include "misc.h" +#include "nat.h" +#include "nsc.h" +#include "nuke.h" +#include "plane.h" +#include "player.h" +#include "prototypes.h" +#include "sect.h" +#include "ship.h" +#include "trade.h" +#include "xy.h" + +/* Note that timestamps make things tricky. And, we don't + * really care about the timestamp, we just care about the rest + * of the structure. So, we make a copy, and zero the timestamps + * in both copies, and then compare. */ + +int +check_sect_ok(struct sctstr *sectp) +{ + struct sctstr chksect; + struct sctstr tsect; + + getsect(sectp->sct_x, sectp->sct_y, &chksect); + memcpy(&tsect, sectp, sizeof(struct sctstr)); + tsect.sct_timestamp = chksect.sct_timestamp = 0; + if (memcmp(&tsect, &chksect, sizeof(struct sctstr))) { + pr("Sector %s has changed!\n", + xyas(sectp->sct_x, sectp->sct_y, player->cnum)); + return 0; + } + return 1; +} + +int +check_ship_ok(struct shpstr *shipp) +{ + struct shpstr chkship; + struct shpstr tship; + + getship(shipp->shp_uid, &chkship); + memcpy(&tship, shipp, sizeof(struct shpstr)); + tship.shp_timestamp = chkship.shp_timestamp = 0; + if (memcmp(&tship, &chkship, sizeof(struct shpstr))) { + pr("Ship #%d has changed!\n", shipp->shp_uid); + return 0; + } + return 1; +} + +int +check_plane_ok(struct plnstr *planep) +{ + struct plnstr chkplane; + struct plnstr tplane; + + getplane(planep->pln_uid, &chkplane); + memcpy(&tplane, planep, sizeof(struct plnstr)); + tplane.pln_timestamp = chkplane.pln_timestamp = 0; + if (memcmp(&tplane, &chkplane, sizeof(struct plnstr))) { + pr("Plane #%d has changed!\n", planep->pln_uid); + return 0; + } + return 1; +} + +int +check_land_ok(struct lndstr *landp) +{ + struct lndstr chkland; + struct lndstr tland; + + getland(landp->lnd_uid, &chkland); + memcpy(&tland, landp, sizeof(struct lndstr)); + tland.lnd_timestamp = chkland.lnd_timestamp = 0; + if (memcmp(&tland, &chkland, sizeof(struct lndstr))) { + pr("Land unit #%d has changed!\n", landp->lnd_uid); + return 0; + } + return 1; +} + +int +check_nuke_ok(struct nukstr *nukep) +{ + struct nukstr chknuke; + struct nukstr tnuke; + + getnuke(nukep->nuk_uid, &chknuke); + memcpy(&tnuke, nukep, sizeof(struct nukstr)); + tnuke.nuk_timestamp = chknuke.nuk_timestamp = 0; + if (memcmp(&tnuke, &chknuke, sizeof(struct nukstr))) { + pr("Nuke %d has changed!\n", nukep->nuk_uid); + return 0; + } + return 1; +} + +int +check_loan_ok(struct lonstr *loanp) +{ + struct lonstr chkloan; + + getloan(loanp->l_uid, &chkloan); + if (memcmp(loanp, &chkloan, sizeof(struct lonstr))) { + pr("Loan %d has changed!\n", loanp->l_uid); + return 0; + } + return 1; +} + +int +check_comm_ok(struct comstr *commp) +{ + struct comstr chkcomm; + + getcomm(commp->com_uid, &chkcomm); + if (memcmp(commp, &chkcomm, sizeof(struct comstr))) { + pr("Commodity %d has changed!\n", commp->com_uid); + return 0; + } + return 1; +} + +int +check_trade_ok(struct trdstr *tp) +{ + struct trdstr chktrade; + + gettrade(tp->trd_uid, &chktrade); + if (memcmp(tp, &chktrade, sizeof(struct trdstr))) { + pr("Trade lot #%d has changed!\n", tp->trd_uid); + return 0; + } + return 1; +} diff --git a/src/lib/subs/cnumb.c b/src/lib/subs/cnumb.c deleted file mode 100644 index 26a48b112..000000000 --- a/src/lib/subs/cnumb.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * --- - * - * See files README, COPYING and CREDITS in the root of the source - * tree for related information and legal notices. It is expected - * that future projects/authors will amend these files as needed. - * - * --- - * - * cnumb.c: Return country number give country name - * - * Known contributors to this file: - * - */ - -#include - -#include "file.h" -#include "match.h" -#include "nat.h" -#include "prototypes.h" - -/* - * Search for a country matching CNTRY, return its number. - * Return M_NOTFOUND if no such country exists, M_NOTUNIQUE if there - * are several. - */ -int -cnumb(char *cntry) -{ - char *ncp; - char *cp; - struct natstr *natp; - int res; - natid cn; - - res = M_NOTFOUND; - for (cn = 0; cn < MAXNOC; cn++) { - if ((natp = getnatp(cn)) == 0) - break; - if (natp->nat_stat == STAT_UNUSED) - continue; - ncp = natp->nat_cnam; - for (cp = cntry; *cp == *ncp; cp++, ncp++) { - if (*cp == 0) - return cn; /* exact match */ - } - if (*cp == 0) { - /* is a prefix */ - if (res >= 0) - return M_NOTUNIQUE; - res = cn; - } - } - return res; -} diff --git a/src/lib/subs/damage.c b/src/lib/subs/damage.c new file mode 100644 index 000000000..11684fb6f --- /dev/null +++ b/src/lib/subs/damage.c @@ -0,0 +1,202 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * damage.c: Damage stuff. + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1997 + */ + +#include + +#include "damage.h" +#include "land.h" +#include "misc.h" +#include "nsc.h" +#include "nuke.h" +#include "optlist.h" +#include "plane.h" +#include "prototypes.h" +#include "sect.h" +#include "ship.h" + +void +item_damage(int pct, short *item) +{ + int lose; + i_type i; + + for (i = I_NONE + 1; i <= I_MAX; ++i) { + if (opt_SUPER_BARS && i == I_BAR) + continue; + lose = roundavg((double)item[i] * pct * 0.01); + if (i == I_CIVIL || i == I_MILIT || i == I_UW) + lose = ldround(people_damage * lose, 1); + item[i] = item[i] >= lose ? item[i] - lose : 0; + } +} + +void +ship_damage(struct shpstr *sp, int dam) +{ + if (dam <= 0) + return; + if (dam > 100) + dam = 100; + + mpr(sp->shp_own, "\t%s takes %d\n", prship(sp), dam); + + sp->shp_effic = damage((int)sp->shp_effic, dam); + if (sp->shp_mobil > 0) + sp->shp_mobil = damage((int)sp->shp_mobil, dam); + if (opt_FUEL && sp->shp_fuel) + sp->shp_fuel = damage((int)sp->shp_fuel, dam); + item_damage(dam, sp->shp_item); +} + +void +shipdamage(struct shpstr *sp, int dam) +{ + ship_damage(sp, (int)(dam / (1.0 + sp->shp_armor / 100.0))); +} + +void +land_damage(struct lndstr *lp, int dam) +{ + if (dam <= 0) + return; + if (dam > 100) + dam = 100; + + mpr(lp->lnd_own, "\t%s takes %d\n", prland(lp), dam); + if (lchr[(int)lp->lnd_type].l_flags & L_SPY) { + /* Spies die! */ + lp->lnd_effic = 0; + } else { + lp->lnd_effic = damage((int)lp->lnd_effic, dam); + if (lp->lnd_mobil > 0) + lp->lnd_mobil = damage((int)lp->lnd_mobil, dam); + if (opt_FUEL && lp->lnd_fuel) + lp->lnd_fuel = damage((int)lp->lnd_fuel, dam); + item_damage(dam, lp->lnd_item); + } +} + +void +landdamage(struct lndstr *lp, int dam) +{ + double damage_factor, m; + + m = land_mob_max; + + /* fortification reduces damage */ + damage_factor = m / (m + lp->lnd_harden); + + /* vulnerable units take more damage */ + damage_factor *= lp->lnd_vul / 100.0; + + land_damage(lp, ldround(damage_factor * dam, 1)); +} + +void +planedamage(struct plnstr *pp, int dam) +{ + if (dam <= 0) + return; + if (dam > 100) + dam = 100; + + mpr(pp->pln_own, "\t%s takes %d\n", prplane(pp), dam); + pp->pln_effic = damage((int)pp->pln_effic, dam); + if (pp->pln_mobil > 0) + pp->pln_mobil = damage((int)pp->pln_mobil, dam); +} + +/* + * nukedamage() actually just calculates damage + * rather than inflicting it. + */ +int +nukedamage(struct nchrstr *ncp, int range, int airburst) +{ + int dam; + int rad; + + rad = ncp->n_blast; + if (airburst) + rad = (int)(rad * 1.5); + if (rad < range) + return 0; + if (airburst) { + /* larger area, less center damage */ + dam = (int)((ncp->n_dam * 0.75) - (range * 20)); + } else { + /* smaller area, more center damage */ + dam = (int)(ncp->n_dam / (range + 1.0)); + } + if (dam < 5) + dam = 0; + return dam; +} + +int +damage(int amt, int pct) +{ + int tmp; + int lost; + + if (amt <= 0) + return 0; + tmp = amt * pct; + lost = tmp / 100; + if (random() % 100 < tmp % 100) + lost++; + return amt - lost; +} + +/* asymptotic damage to commodities, efficiency, and sectors */ +int +effdamage(int amt, int dam) +{ + return damage(amt, PERCENT_DAMAGE(dam)); +} + +int +commdamage(int amt, int dam, i_type vtype) +{ + int lost; + + if (vtype == I_BAR && opt_SUPER_BARS) + return amt; + + lost = amt - effdamage(amt, dam); + + if (vtype == I_MILIT || vtype == I_CIVIL || vtype == I_UW) + lost = ldround(people_damage * lost, 1); + return amt - lost; +} diff --git a/src/lib/subs/empobj.c b/src/lib/subs/empobj.c new file mode 100644 index 000000000..35a18d07f --- /dev/null +++ b/src/lib/subs/empobj.c @@ -0,0 +1,137 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * empobj.c: Common functions on struct empobj and + * union empobj_storage + * + * Known contributors to this file: + * Ron Koenderink, 2006 + * Markus Armbruster, 2006 + */ + +#include + +#include "empobj.h" +#include "file.h" +#include "optlist.h" +#include "prototypes.h" + +char * +obj_nameof(struct empobj *gp) +{ + switch (gp->ef_type) { + case EF_SHIP: + return prship((struct shpstr *)gp); + case EF_PLANE: + return prplane((struct plnstr *)gp); + case EF_LAND: + return prland((struct lndstr *)gp); + case EF_NUKE: + return prnuke((struct nukstr *)gp); + } + CANT_REACH(); + return "The Beast #666"; +} + +struct empobj * +get_empobjp(int type, int id) +{ + if (CANT_HAPPEN(type == EF_SECTOR || type == EF_BAD)) + return NULL; + return ef_ptr(type, id); +} + +int +put_empobj(struct empobj *gp) +{ + switch (gp->ef_type) + { + case EF_SECTOR: + return ef_write(gp->ef_type, sctoff(gp->x, gp->y), gp); + case EF_NATION: + case EF_BMAP: + case EF_MAP: + return ef_write(gp->ef_type, gp->own, gp); + default: + return ef_write(gp->ef_type, gp->uid, gp); + } +} + +struct empobj_chr * +get_empobj_chr(struct empobj *gp) +{ + switch (gp->ef_type) { + case EF_LAND: + return (struct empobj_chr *)&lchr[(int)gp->type]; + case EF_SHIP: + return (struct empobj_chr *)&mchr[(int)gp->type]; + case EF_PLANE: + return (struct empobj_chr *)&plchr[(int)gp->type]; + case EF_NUKE: + return (struct empobj_chr *)&nchr[(int)gp->type]; + case EF_SECTOR: + return (struct empobj_chr *)&dchr[(int)gp->type]; + } + CANT_REACH(); + return NULL; +} + +char * +emp_obj_chr_name(struct empobj *gp) +{ + switch (gp->ef_type) { + case EF_LAND: + return lchr[(int)gp->type].l_name; + case EF_SHIP: + return mchr[(int)gp->type].m_name; + case EF_PLANE: + return plchr[(int)gp->type].pl_name; + case EF_NUKE: + return nchr[(int)gp->type].n_name; + case EF_SECTOR: + return dchr[(int)gp->type].d_name; + } + CANT_REACH(); + return NULL; +} + +int +get_empobj_mob_max(int type) +{ + switch (type) { + case EF_SHIP: + return ship_mob_max; + case EF_LAND: + return land_mob_max; + case EF_PLANE: + return plane_mob_max; + case EF_SECTOR: + return sect_mob_max; + } + CANT_REACH(); + return -1; +} diff --git a/src/lib/subs/getstarg.c b/src/lib/subs/getstarg.c new file mode 100644 index 000000000..62605d706 --- /dev/null +++ b/src/lib/subs/getstarg.c @@ -0,0 +1,56 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * getstarg.c: Get a string argument (ask if not there) + * + * Known contributors to this file: + * + */ + +#include + +#include +#include "misc.h" + +/* + * Get string argument. + * If INPUT is not empty, use it, else prompt for more input using PROMPT. + * Copy input to BUF[1024]. + * Return BUF on success, else NULL. + */ +char * +getstarg(char *input, char *prompt, char *buf) +{ + *buf = '\0'; + if (input == 0 || *input == 0) { + if (getstring(prompt, buf) == 0) + return 0; + } else { + strcpy(buf, input); + } + return buf; +} diff --git a/src/lib/subs/getstring.c b/src/lib/subs/getstring.c new file mode 100644 index 000000000..8f07230bf --- /dev/null +++ b/src/lib/subs/getstring.c @@ -0,0 +1,62 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * getstring.c: get string, printing a prompt if there is one + * + * Known contributors to this file: + * + */ + +#include + +#include "prototypes.h" + +/* + * Print sub-prompt PROMPT, receive a line of input into BUF[1024]. + * Return BUF on success, else NULL. + */ +char * +getstring(char *prompt, char *buf) +{ + *buf = '\0'; + if (prmptrd(prompt, buf, 1024) < 0) + return NULL; + return buf; +} + +/* + * Print sub-prompt PROMPT, receive a line of UTF-8 input into BUF[1024]. + * Return BUF on success, else NULL. + */ +char * +ugetstring(char *prompt, char *buf) +{ + *buf = '\0'; + if (uprmptrd(prompt, buf, 1024) < 0) + return NULL; + return buf; +} diff --git a/src/lib/subs/journal.c b/src/lib/subs/journal.c new file mode 100644 index 000000000..ed111a25c --- /dev/null +++ b/src/lib/subs/journal.c @@ -0,0 +1,169 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the + * related information and legal notices. It is expected that any future + * projects/authors will amend these files as needed. + * + * --- + * + * journal.c: Log a journal of events to a file + * + * Known contributors to this file: + * Markus Armbruster, 2004-2007 + */ + +/* + * Journal file format: each line logs an event, and looks like this: + * + * TIME THREAD EVENT DATA + * + * Events and their data are: + * + * startup + * shutdown + * login CNUM HOSTADDR USER + * logout CNUM + * input INPUT + * update ETU + */ + +#include + +#include +#include +#include +#include +#include +#include "misc.h" +#include "empthread.h" +#include "journal.h" +#include "optlist.h" +#include "player.h" +#include "prototypes.h" + +static char journal_fname[] = "journal.log"; +static FILE *journal; + +static FILE * +journal_open(void) +{ + return fopen(journal_fname, "a+"); +} + +static void +journal_entry(char *fmt, ...) +{ + static char buf[1024]; + va_list ap; + time_t now; + unsigned char *p; + + if (journal) { + time(&now); + fprintf(journal, "%.24s %p ", ctime(&now), empth_self()); + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf) - 1, fmt, ap); + va_end(ap); + + for (p = (unsigned char *)buf; *p; p++) { + if (isprint(*p)) + putc(*p, journal); + else + fprintf(journal, "\\%03o", *p); + } + fputs("\n", journal); + if (debug) + fflush(journal); + if (ferror(journal)) { + logerror("Error writing journal (%s)", strerror(errno)); + clearerr(journal); + } + } +} + +int +journal_startup(void) +{ + if (!keep_journal) + return 0; + journal = journal_open(); + if (!journal) { + logerror("Can't open %s (%s)", journal_fname, strerror(errno)); + return -1; + } + journal_entry("startup"); + return 0; +} + +void +journal_shutdown(void) +{ + journal_entry("shutdown"); + if (journal) { + fclose(journal); + journal = NULL; + } +} + +int +journal_reopen(void) +{ + FILE *j; + + if (!keep_journal) + return 0; + j = journal_open(); + if (!j) { + logerror("Can't open %s (%s)", journal_fname, strerror(errno)); + return -1; + } + if (journal) + fclose(journal); + journal = j; + return 0; +} + +void +journal_login(void) +{ + journal_entry("login %d %s %s", + player->cnum, player->hostaddr, player->userid); +} + +void +journal_logout(void) +{ + journal_entry("logout %d", player->cnum); +} + +void +journal_input(char *input) +{ + journal_entry("input %s", input); +} + +void +journal_update(int etu) +{ + journal_entry("update %d", etu); +} diff --git a/src/lib/subs/maps.c b/src/lib/subs/maps.c new file mode 100644 index 000000000..b60d5d670 --- /dev/null +++ b/src/lib/subs/maps.c @@ -0,0 +1,449 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * maps.c: Map routines + * + * Known contributors to this file: + * Ken Stevens, 1995 + * Steve McClure, 1998 + * Ron Koenderink, 2006 + */ + +#include + +#include +#include "com.h" +#include "empobj.h" +#include "file.h" +#include "land.h" +#include "map.h" +#include "misc.h" +#include "nat.h" +#include "nsc.h" +#include "nuke.h" +#include "optlist.h" +#include "plane.h" +#include "player.h" +#include "prototypes.h" +#include "sect.h" +#include "ship.h" +#include "xy.h" + +static int bmnxtsct(struct nstr_sect *); +static char map_char(unsigned char type, natid own, int owner_or_god); + +int +do_map(int bmap, int unit_type, char *arg, char *map_flags_arg) +{ + struct nstr_sect ns; + char origin = '\0'; + char *b; + int map_flags = 0; + + if (!snxtsct(&ns, arg)) { + if (unit_map(unit_type, atoi(arg), &ns, &origin)) + return RET_FAIL; + } + for (b = map_flags_arg; b && *b; b++) { + switch (*b) { + case 's': + case 'S': + map_flags |= MAP_SHIP; + break; + case 'l': + case 'L': + map_flags |= MAP_LAND; + break; + case 'p': + case 'P': + map_flags |= MAP_PLANE; + break; + case 'n': + case 'N': + map_flags |= MAP_NUKE; + break; + case 'h': + case 'H': + map_flags |= MAP_HIGH; + break; + case '*': + map_flags |= MAP_ALL; + break; + case 't': + if (bmap != 'b') + goto bad_flag; + bmap = 't'; + *(b + 1) = 0; + break; + case 'r': + if (bmap != 'b') + goto bad_flag; + bmap = 'r'; + *(b + 1) = 0; + break; + default: + bad_flag: + pr("Bad flag %c!\n", *b); + break; + } + } + return draw_map(bmap, origin, map_flags, &ns); +} + +int +draw_map(int bmap, char origin, int map_flags, struct nstr_sect *nsp) +{ + struct natstr *np; + struct range range; + struct nstr_item ni; + union empobj_storage unit; + coord x, y; + int i; + /* Note this is not re-entrant anyway, so we keep the buffers + around */ + static unsigned char *bitmap = NULL; + static char *wmapbuf = NULL; + static char **wmap = NULL; + static int ef_mappable[] = { EF_PLANE, EF_SHIP, EF_LAND, EF_NUKE, EF_BAD }; + static int ef_unit_map[] = { MAP_PLANE, MAP_SHIP, MAP_LAND, MAP_NUKE }; + char *name; + + if (!wmapbuf) + wmapbuf = malloc(WORLD_Y * MAPWIDTH(1)); + if (!wmap) { + wmap = malloc(WORLD_Y * sizeof(char *)); + if (wmap && wmapbuf) { + for (i = 0; i < WORLD_Y; i++) + wmap[i] = &wmapbuf[MAPWIDTH(1) * i]; + } else if (wmap) { + free(wmap); + wmap = NULL; + } + } + if (!bitmap) + bitmap = malloc((WORLD_X * WORLD_Y) / 8); + if (!wmapbuf || !wmap || !bitmap) { + pr("Memory error, tell the deity.\n"); + logerror("malloc failed in draw_map\n"); + return RET_FAIL; + } + + if (bmap == 'r') { + if (!confirm("Are you sure you want to revert your bmap? ")) + return RET_OK; + } + if (!(player->command->c_flags & C_MOD)) { + logerror("%s command needs C_MOD flag set", + player->command->c_form); + player->command->c_flags |= C_MOD; + } + np = getnatp(player->cnum); + /* zap any conditionals */ + nsp->ncond = 0; + xyrelrange(np, &nsp->range, &range); + border(&range, " ", ""); + blankfill(wmapbuf, &nsp->range, 1); + if (bmap) { + int c; + switch (bmap) { + default: + CANT_REACH(); + bmap = 'b'; + /* fall through */ + case 'b': + while (bmnxtsct(nsp) && !player->aborted) { + if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)])) + wmap[nsp->dy][nsp->dx] = c; + } + break; + case 't': + while (bmnxtsct(nsp) && !player->aborted) { + if (0 != (c = player->map[sctoff(nsp->x, nsp->y)])) + wmap[nsp->dy][nsp->dx] = c; + } + break; + case 'r': + while (bmnxtsct(nsp) && !player->aborted) { + player->bmap[sctoff(nsp->x, nsp->y)] = + player->map[sctoff(nsp->x, nsp->y)]; + if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)])) + wmap[nsp->dy][nsp->dx] = c; + } + ef_write(EF_BMAP, player->cnum, player->bmap); + break; + case 'n': + { + struct sctstr sect; + + if (!player->god) { + memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8); + bitinit2(nsp, bitmap, player->cnum); + } + while (nxtsct(nsp, §) && !player->aborted) { + if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap)) + continue; + wmap[nsp->dy][nsp->dx] + = map_char(sect.sct_newtype, sect.sct_own, + player->owner); + } + break; + } + } + } else { + struct sctstr sect; + char mapch; + int changed = 0; + + if (!player->god) { + memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8); + bitinit2(nsp, bitmap, player->cnum); + } + while (nxtsct(nsp, §) && !player->aborted) { + if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap)) + continue; + mapch = map_char(sect.sct_type, sect.sct_own, player->owner); + wmap[nsp->dy][nsp->dx] = mapch; + changed |= map_set(player->cnum, nsp->x, nsp->y, mapch, 0); + } + if (changed) + writemap(player->cnum); + } + if (player->aborted) + return RET_OK; + + i = 0; + while (ef_mappable[i] != EF_BAD) { + if (map_flags & ef_unit_map[i]) { + snxtitem_all(&ni, ef_mappable[i]); + while (nxtitem(&ni, &unit)) { + if (unit.gen.own == 0) + continue; + if (unit.gen.own != player->cnum && !player->god) + continue; + if (!xyinrange(unit.gen.x, unit.gen.y, &nsp->range)) + continue; + + x = xnorm(unit.gen.x - nsp->range.lx); + y = ynorm(unit.gen.y - nsp->range.ly); + + if (ef_mappable[i] == EF_NUKE) + wmap[y][x] = 'N'; + else { + if ((name = emp_obj_chr_name(&unit.gen)) == NULL) + return RET_FAIL; + wmap[y][x] = *name & ~0x20; + } + } + } + i++; + } + if (map_flags & MAP_HIGH) { + struct sctstr sect; + + snxtsct_rewind(nsp); + if (!player->god) { + memset(bitmap, 0, (WORLD_X * WORLD_Y) / 8); + bitinit2(nsp, bitmap, player->cnum); + } + while (nxtsct(nsp, §) && !player->aborted) { + if (!player->god && !emp_getbit(nsp->x, nsp->y, bitmap)) + continue; + if (sect.sct_own == player->cnum) + wmap[nsp->dy][nsp->dx] |= 0x80; + } + } + if (origin) + wmap[5][10] = origin & ~0x20; + for (y = nsp->range.ly, i = 0; i < nsp->range.height; y++, i++) { + int yval; + + yval = yrel(np, y); + wmap[i][nsp->range.width] = '\0'; + pr("%4d %s %-4d\n", yval, wmap[i], yval); + if (y >= WORLD_Y) + y -= WORLD_Y; + } + border(&range, " ", ""); + return RET_OK; +} + +/* + * get the next sector in the range + */ +static int +bmnxtsct(struct nstr_sect *np) +{ + while (1) { + np->dx++; + np->x++; + if (np->x >= WORLD_X) + np->x = 0; + if (np->dx >= np->range.width) { + np->dx = 0; + np->x = np->range.lx; + np->dy++; + if (np->dy >= np->range.height) + return 0; + np->y++; + if (np->y >= WORLD_Y) + np->y = 0; + } + if ((np->y + np->x) & 01) + continue; + if (np->type == NS_DIST) { + np->curdist = mapdist(np->x, np->y, np->cx, np->cy); + if (np->curdist > np->dist) + continue; + } + np->id = sctoff(np->x, np->y); + return 1; + } + /*NOTREACHED*/ +} + +/* + * Return character to use in maps for sector type TYPE owned by OWN. + * If OWNER_OR_GOD, the map is for the sector's owner or a deity. + */ +static char +map_char(unsigned char type, natid own, int owner_or_god) +{ + if (CANT_HAPPEN(type > SCT_TYPE_MAX || !dchr[type].d_mnem)) + return '?'; + if (owner_or_god + || type == SCT_WATER || type == SCT_MOUNT || type == SCT_WASTE + || (!own && (type == SCT_RURAL || type == SCT_PLAINS))) + return dchr[type].d_mnem; + return '?'; +} + +int +unit_map(int unit_type, int uid, struct nstr_sect *nsp, char *originp) +{ + struct empobj *gp; + struct range range; + char *name; + + gp = get_empobjp(unit_type, uid); + if (!gp || (gp->own != player->cnum && !player->god) || gp->own == 0) + return RET_FAIL; + + if (unit_type == EF_NUKE) + *originp = 'n'; + else { + if ((name = emp_obj_chr_name(gp)) == NULL) + return RET_FAIL; + *originp = *name; + } + + range.lx = xnorm(gp->x - 10); + range.hx = xnorm(gp->x + 11); + range.ly = ynorm(gp->y - 5); + range.hy = ynorm(gp->y + 6); + xysize_range(&range); + snxtsct_area(nsp, &range); + return RET_OK; +} + +int +display_region_map(int bmap, int unit_type, coord curx, coord cury, + char *arg) +{ + char coordinates[80]; + char *map_flag_arg; + + if (!arg || !*arg) { + struct natstr *np; + + np = getnatp(player->cnum); + sprintf(coordinates, "%d:%d,%d:%d", + xrel(np, curx - 10), xrel(np, curx + 11), + yrel(np, cury - 5), yrel(np, cury + 6)); + arg = coordinates; + map_flag_arg = NULL; + } else { + map_flag_arg = strchr(arg, ' '); + if (map_flag_arg != NULL) { + *map_flag_arg++ = '\0'; + while (isspace(*map_flag_arg)) map_flag_arg++; + } + } + player->condarg = NULL; + return do_map(bmap, unit_type, arg, map_flag_arg); +} + +int +bmaps_intersect(natid a, natid b) +{ + char *mapa = ef_ptr(EF_MAP, a); + char *mapb = ef_ptr(EF_MAP, b); + int i; + + for (i = 0; i < WORLD_SZ(); i++) + if (mapa[i] && mapa[i] != ' ' && mapb[i] && mapb[i] != ' ') + return 1; + return 0; +} + +/* Note that this requires that the BMAP is mapped into memory */ + +int +share_bmap(natid from, natid to, struct nstr_sect *ns, char des, + char *from_name) +{ + char *from_bmap = ef_ptr(EF_BMAP, from); + char *to_bmap = ef_ptr(EF_BMAP, to); + int n = 0; + struct sctstr sect; + char fromdes; + char todes; + char from_des = *from_name; + + if (isalpha(from_des)) + from_des &= ~0x20; + + while (nxtsct(ns, §)) { + if (!(fromdes = from_bmap[sctoff(ns->x, ns->y)])) + continue; + todes = to_bmap[sctoff(ns->x, ns->y)]; + if (todes && + todes != '?' && + todes != '.' && todes != ' ' && todes != from_des) + continue; + if (sect.sct_own == from) { + if (fromdes != '=' && fromdes != 'h' && fromdes != des) + fromdes = from_des; + } + if (todes == fromdes) + continue; + n += map_set(to, ns->x, ns->y, fromdes, 1); + } + + if (n) + writebmap(to); + return n; +} diff --git a/src/lib/subs/nstr.c b/src/lib/subs/nstr.c index 2184646a1..2ce084032 100644 --- a/src/lib/subs/nstr.c +++ b/src/lib/subs/nstr.c @@ -39,8 +39,6 @@ #include #include "file.h" #include "match.h" -#include "nat.h" -#include "optlist.h" #include "player.h" #include "prototypes.h" @@ -568,133 +566,3 @@ nstr_coerce_val(struct valstr *val, nsc_type to, char *str) return 0; } - -/* - * Evaluate VAL. - * If VAL is symbolic, evaluate it into a promoted value type. - * Use coordinate system of country CNUM. - * PTR points to a context object of the type that was used to compile - * the value. - * Unless WANT is NSC_NOTYPE, coerce the value to promoted value type - * WANT. VAL must be coercible. That's the case if a previous - * nstr_coerce_val(VAL, WANT, STR) succeeded. - */ -void -nstr_exec_val(struct valstr *val, natid cnum, void *ptr, nsc_type want) -{ - char *memb_ptr; - nsc_type valtype; - int idx; - struct natstr *natp; - - switch (val->val_cat) { - default: - CANT_REACH(); - /* fall through */ - case NSC_VAL: - valtype = val->val_type; - break; - case NSC_OFF: - valtype = NSC_LONG; - memb_ptr = ptr; - memb_ptr += val->val_as.sym.off; - idx = val->val_as.sym.idx; - switch (val->val_type) { - case NSC_CHAR: - val->val_as.lng = ((signed char *)memb_ptr)[idx]; - break; - case NSC_UCHAR: - val->val_as.lng = ((unsigned char *)memb_ptr)[idx]; - break; - case NSC_SHORT: - val->val_as.lng = ((short *)memb_ptr)[idx]; - break; - case NSC_USHORT: - val->val_as.lng = ((unsigned short *)memb_ptr)[idx]; - break; - case NSC_INT: - val->val_as.lng = ((int *)memb_ptr)[idx]; - break; - case NSC_LONG: - val->val_as.lng = ((long *)memb_ptr)[idx]; - break; - case NSC_XCOORD: - val->val_as.lng = xrel(getnatp(cnum), ((short *)memb_ptr)[idx]); - break; - case NSC_YCOORD: - val->val_as.lng = yrel(getnatp(cnum), ((short *)memb_ptr)[idx]); - break; - case NSC_HIDDEN: - val->val_as.lng = -1; - if (CANT_HAPPEN(((struct natstr *)ptr)->ef_type != EF_NATION)) - break; - natp = getnatp(cnum); - if (!opt_HIDDEN - || natp->nat_stat == STAT_GOD - || (getcontact(natp, idx) && getcontact(ptr, idx))) - val->val_as.lng = ((unsigned char *)memb_ptr)[idx]; - break; - case NSC_FLOAT: - val->val_as.dbl = ((float *)memb_ptr)[idx]; - valtype = NSC_DOUBLE; - break; - case NSC_DOUBLE: - val->val_as.dbl = ((double *)memb_ptr)[idx]; - valtype = NSC_DOUBLE; - break; - case NSC_STRINGY: - CANT_HAPPEN(idx); - val->val_as.str.maxsz = val->val_as.sym.len; - val->val_as.str.base = (char *)memb_ptr; - valtype = NSC_STRING; - break; - case NSC_STRING: - val->val_as.str.base = ((char **)memb_ptr)[idx]; - val->val_as.str.maxsz = INT_MAX; - valtype = NSC_STRING; - break; - case NSC_TIME: - val->val_as.lng = ((time_t *)memb_ptr)[idx]; - break; - default: - CANT_REACH(); - val->val_as.lng = 0; - } - val->val_cat = NSC_VAL; - } - - if (valtype == want) - ; - else if (want == NSC_DOUBLE) { - if (valtype == NSC_LONG) { - valtype = want; - val->val_as.dbl = val->val_as.lng; - } - } else if (want == NSC_STRING) - CANT_REACH(); /* FIXME implement */ - - if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) { - valtype = want; - switch (want) { - case NSC_LONG: val->val_as.lng = 0; break; - case NSC_DOUBLE: val->val_as.dbl = 0.0; break; - case NSC_STRING: val->val_as.str.base = NULL; break; - default: - CANT_REACH(); - } - } - - val->val_type = valtype; -} - -char * -symbol_by_value(int key, struct symbol *table) -{ - int i; - - for (i = 0; table[i].name; i++) - if (key == table[i].value) - return table[i].name; - - return NULL; -} diff --git a/src/lib/subs/onearg.c b/src/lib/subs/onearg.c new file mode 100644 index 000000000..79c8e46eb --- /dev/null +++ b/src/lib/subs/onearg.c @@ -0,0 +1,52 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * onearg.c: Get one argument, or ask if not there + * + * Known contributors to this file: + * + */ + +#include + +#include "prototypes.h" + +int +onearg(char *arg, char *prompt) +{ + int n; + char buf[1024]; + + if (arg == 0 || *arg == 0) { + if ((arg = getstring(prompt, buf)) == 0) + return -1; + } + n = atoi(arg); + if (n < 0) + return -1; + return n; +} diff --git a/src/lib/subs/sectdamage.c b/src/lib/subs/sectdamage.c new file mode 100644 index 000000000..6dcacbb70 --- /dev/null +++ b/src/lib/subs/sectdamage.c @@ -0,0 +1,130 @@ +/* + * Empire - A multi-player, client/server Internet based war game. + * Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * --- + * + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. + * + * --- + * + * sectdamage.c: Damage a sector + * + * Known contributors to this file: + * Dave Pare, 1989 + * Steve McClure, 1996 + */ + +#include + +#include "combat.h" +#include "damage.h" +#include "file.h" +#include "land.h" +#include "misc.h" +#include "nat.h" +#include "nsc.h" +#include "optlist.h" +#include "plane.h" +#include "prototypes.h" +#include "sect.h" +#include "ship.h" +#include "xy.h" + +int +sect_damage(struct sctstr *sp, int dam, struct emp_qelem *list) +{ + int eff; + + if (dam <= 0) + return 0; + if (dam > 100) + dam = 100; + + sp->sct_effic = damage(sp->sct_effic, dam); + sp->sct_avail = damage(sp->sct_avail, dam); + sp->sct_road = damage(sp->sct_road, dam); + sp->sct_rail = damage(sp->sct_rail, dam); + sp->sct_defense = damage(sp->sct_defense, dam); + + eff = dam; + + if (sp->sct_mobil > 0) + sp->sct_mobil = damage(sp->sct_mobil, dam); + item_damage(dam, sp->sct_item); + if (opt_EASY_BRIDGES == 0) { + if (sp->sct_effic < SCT_MINEFF && sp->sct_type == SCT_BHEAD) + bridgefall(sp, list); + } else { + if (sp->sct_effic < SCT_MINEFF && sp->sct_type == SCT_BSPAN) + knockdown(sp, list); + } + putsect(sp); + return eff; +} + +int +sectdamage(struct sctstr *sp, int dam, struct emp_qelem *list) +{ + struct nstr_item ni; + struct lndstr land; + struct plnstr plane; + int eff; + + /* Some sectors are harder/easier to kill.. */ + /* Average sector has a dstr of 1, so adjust */ + /* the damage accordingly. Makes forts a pain */ + dam = ldround(dam / sector_strength(sp), 1); + + eff = sect_damage(sp, PERCENT_DAMAGE(dam), list); + + /* Damage all the land units in the sector */ + /* Units don't take full damage */ + dam = ldround(DPERCENT_DAMAGE(dam * unit_damage), 1); + if (dam <= 0) + return eff; + + snxtitem_xy(&ni, EF_LAND, sp->sct_x, sp->sct_y); + while (nxtitem(&ni, &land)) { + if (!land.lnd_own) + continue; + landdamage(&land, dam); + putland(land.lnd_uid, &land); + } + + dam = dam / 7; + if (dam <= 0) + return eff; + snxtitem_xy(&ni, EF_PLANE, sp->sct_x, sp->sct_y); + while (nxtitem(&ni, &plane)) { + if (!plane.pln_own) + continue; + if (plane.pln_flags & PLN_LAUNCHED) + continue; + if (plane.pln_ship >= 0) + continue; + /* Is this plane flying in this list? */ + if (ac_isflying(&plane, list)) + continue; + planedamage(&plane, dam); + putplane(plane.pln_uid, &plane); + } + return eff; +}