Import of Empire 4.2.12

This commit is contained in:
Markus Armbruster 2003-08-23 12:23:04 +00:00
commit d8b7fdfae1
817 changed files with 126589 additions and 0 deletions

67
src/lib/common/Makefile Normal file
View file

@ -0,0 +1,67 @@
#
# Empire - A multi-player, client/server Internet based war game.
# Copyright (C) 1986-2000, 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.
#
# Makefile - Wolfpack, 1996
# Note that these could have been listed 1 per line, but I chose to just
# stick them all together this way to shorten the file.
include ../../../build.conf
include ../../make.src
include ../../make.defs
LIB = $(SRCDIR)/lib/libcommon.a
NTLIB = $(SRCDIR)\lib\libcommon.lib
OBJS = bestpath.o bridgefall.o check.o damage.o file.o fsize.o getvar.o \
hap_fact.o hours.o keyword.o land.o log.o mailbox.o maps.o move.o \
nat.o nstr_subs.o path.o res_pop.o sectdamage.o snxtit_subs.o \
snxtsct_subs.o stmtch.o tfact.o type.o vlist.o wantupd.o xy.o
NTOBJS = bestpath.obj bridgefall.obj check.obj damage.obj file.obj fsize.obj \
getvar.obj hap_fact.obj hours.obj keyword.obj land.obj log.obj \
mailbox.obj maps.obj move.obj nat.obj nstr_subs.obj path.obj res_pop.obj \
sectdamage.obj snxtit_subs.obj snxtsct_subs.obj stmtch.obj tfact.obj \
type.obj vlist.obj wantupd.obj xy.obj
all: $(LIB)
nt: $(NTLIB)
$(NTLIB): $(NTOBJS)
-del /q $@
lib /OUT:$@ /DEBUGTYPE:CV $(NTOBJS)
$(LIB): $(OBJS)
rm -f $(LIB)
ar cq $(LIB) $(OBJS)
$(RANLIB) $(LIB)
clean:
-(rm -f $(OBJS))
-(del /q $(NTOBJS))
include ../../make.rules
include Makedepend

322
src/lib/common/bestpath.c Normal file
View file

@ -0,0 +1,322 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* bestpath.c: Find the best path between sectors
*
* Known contributors to this file:
* Steve McClure, 1998-2000
*/
/*
* IMPORTANT: These routines are very selectively used in the server.
*
* "bestpath" is now obsolete (and removed)
* "bestownedpath" is only used to determine paths for ships and planes.
*
* Callers should not be calling these directly anymore. They should use
* the "BestShipPath", "BestAirPath", "BestLandPath" and "BestDistPath"
* functions. Note that those last two use the A* algorithms to find
* information.
*/
#include "gamesdef.h"
#include "misc.h"
#include "xy.h"
#include "var.h"
#include "sect.h"
#include "file.h"
#include "nat.h"
#include "common.h"
#include "optlist.h"
static int owned_and_navigable(s_char * , int , int , s_char * , int );
#define MAXROUTE 100 /* return '?' if path longer than this */
#define valid(x,y) (((x^y)&1)==0)
/* ________________________________________________________________
**
** bestpath(x1,y1,x2,y2,(s_char *)terrain);
**
** Calculate routing string to get from sector [x1,y1] to sector [x2,y2]
** via a specified type of terrain.
**
** Specify:
**
** x1,y1 starting coordinates
**
** x2,y2 destination coordinates
**
** terrain ptr to string showing the types of sectors that
** we're allowed to pass through:
**
** A null string enables routing through any kind of
** sector (useful for airplanes).
**
** A string that begins with an 'R' ensures that
** the source and destination sectors also match
** the specified type of terrain.
**
** A string that begins with a '~' (after the 'R',
** if necessary) specifies that we can pass through
** any kind of sector EXCEPT those in the remainder
** of the string.
**
** Examples:
**
** "R~.^" all sectors along route must be
** non-ocean, non-mountain
**
** "+" all sectors between start and end
** must be highway
**
** "h. " all sectors along route must be
** harbor, water, or unmapped
**
** 'bestpath' returns a pointer to a route string containing either:
**
** yugjbn - string of normal routing characters if route possible
** ? - if route is longer than MAXROUTE characters
** \0 - (null string) if no route possible
** h - if start and end points are the same sector
** ________________________________________________________________
*/
s_char *dirchar = "juygbn";
int dx[6] = { 2, 1,-1,-2,-1, 1 };
int dy[6] = { 0,-1,-1, 0, 1, 1 };
int tmp;
/*
* Ok, note that here we malloc some buffers. BUT, we never
* free them. Why, you may ask? Because we want to allocate
* them based on world size which is now (or soon to be) dynamic,
* but we don't want to allocate each and every time, since that
* would be slow. And, since world size only changes at init
* time, we can do this safely.
* We also share these buffers between "bestpath" and "bestownedpath"
* since you can never be in both functions at the same time. If that
* did happen, we'd already be so broken that it won't matter.
*/
static unsigned int *mapbuf = (unsigned int *)0;
static unsigned int **mapindex = (unsigned int **)0;
s_char *bestownedpath(s_char *bpath,
s_char *bigmap,
int x,
int y,
int ex,
int ey,
s_char *terrain,
int own)
{
int i, j, tx, ty, markedsectors, restr2;
int minx, maxx, miny, maxy, scanx, scany;
unsigned int routelen;
if (!mapbuf)
mapbuf = (unsigned int *)malloc((WORLD_X * WORLD_Y) *
sizeof(unsigned int));
if (!mapbuf)
return ((s_char *)0);
if (!mapindex) {
mapindex = (unsigned int **)malloc(WORLD_X * sizeof(unsigned int *));
if (mapindex) {
/* Setup the map pointers */
for (i = 0; i < WORLD_X; i++)
mapindex[i] = &mapbuf[WORLD_Y * i];
}
}
if (!mapindex)
return ((s_char *)0);
bpath[0] = 0;
if (0 != (restr2 = (*terrain == 'R')))
terrain++;
x = XNORM(x);
y = YNORM(y);
ex = XNORM(ex);
ey = YNORM(ey);
if (x == ex && y == ey) {
bpath[0] = 'h';
bpath[1] = 0;
return ((s_char *)bpath);
}
if (!valid(x,y) || !valid(ex,ey))
return((s_char *)0);
if (restr2 && (!owned_and_navigable(bigmap, x, y, terrain, own) ||
!owned_and_navigable(bigmap, x, y, terrain, own)))
return ((s_char *)0);
for (i = 0; i < WORLD_X; i++)
for (j = 0; j < WORLD_Y; j++)
mapindex[i][j] = 0xFFFF; /* clear the workspace */
routelen = 0; /* path length is now 0 */
mapindex[x][y] = 0; /* mark starting spot */
markedsectors = 1; /* source sector marked */
minx = x - 2; /* set X scan bounds */
maxx = x + 2;
miny = y - 1; /* set Y scan bounds */
maxy = y + 1;
do {
if (++routelen == MAXROUTE) {
bpath[0] = '?';
bpath[1] = 0;
return ((s_char *)bpath);
}
markedsectors = 0;
for (scanx = minx; scanx <= maxx; scanx++) {
x = XNORM(scanx);
for (scany = miny; scany <= maxy; scany++) {
y = YNORM(scany);
if (valid(x,y)) {
if ((((mapindex[x][y]) & 0x1FFF) == (routelen - 1))) {
for (i = 0; i < 6; i++) {
tx = x + dx[i];
ty = y + dy[i];
tx = XNORM(tx);
ty = YNORM(ty);
if (mapindex[tx][ty] == 0xFFFF) {
if (owned_and_navigable(bigmap, tx, ty, terrain, own) ||
(tx == ex && ty == ey && !restr2) ) {
mapindex[tx][ty] = ((i + 1) << 13) + routelen;
markedsectors++;
}
}
if (tx == ex && ty == ey) {
bpath[routelen] = 0;
while (routelen--) {
i = ((mapindex[tx][ty]) >> 13) - 1;
bpath[routelen] = dirchar[i];
tx = tx - dx[i];
ty = ty - dy[i];
tx = XNORM(tx);
ty = YNORM(ty);
}
return((s_char *)bpath);
}
}
}
}
}
}
miny--;
maxy++;
minx -= 2;
maxx += 2;
} while (markedsectors);
bpath[0] = 0;
return((s_char *)0); /* no route possible */
}
/* return TRUE if sector is passable */
static int
owned_and_navigable(s_char *map, int x, int y, s_char *terrain, int own)
{
s_char c;
s_char *t;
s_char mapspot; /* What this spot on the bmap is */
int negate;
struct sctstr *sect;
int rel;
/* No terrain to check? Everything is navigable! (this
probably means we are flying) */
if (!(*terrain))
return (1);
/* Are we checking this map? */
if (map) {
/* Do we know what this sector is? If not, we assume it's ok,
since otherwise we'll never venture anywhere */
mapspot = map[sctoff(x, y)];
if (mapspot == ' ' || mapspot == 0)
return (1);
/* Now, is it marked with a 'x' or 'X'? If so, avoid it! */
if (mapspot == 'x' || mapspot == 'X')
return (0);
} else {
/* We don't know what it is since we have no map, so return ok! */
return (1);
}
/* Now, check this bmap entry to see if it is one of the
terrain types. */
t = terrain;
if (*t == '~') {
negate = 1;
t++;
} else
negate = 0;
while (*t) {
if (*t == mapspot)
break;
t++;
}
if (negate && *t) {
/* We found it, so we say it's bad since we are negating */
return (0);
} else if (!negate && !*t) {
/* We didn't find it, so we say it's bad since we aren't negating */
return (0);
}
/* According to our bmap, this sector is ok so far. */
/* Ok, we made it this far. Now get the sector */
sect = getsectp(x, y);
c = dchr[sect->sct_type].d_mnem;
/* Ok, now, check the owner if needed */
if (own >= 0) {
if (sect->sct_own != own) {
rel = getrel(getnatp(sect->sct_own), own);
/* We can't sail through deity sectors, but we can sail
through any ocean */
if (rel < FRIENDLY && sect->sct_type != SCT_WATER)
return (0);
}
}
/* Ok, now, check these two sector types */
/* check for bad harbors. */
if (c == 'h' && sect->sct_effic < 2)
return (0);
/* check for bad bridges */
if (c == '=' && sect->sct_effic < 60)
return (0);
/* Woo-hoo, it's ok! */
return (1);
}

167
src/lib/common/bridgefall.c Normal file
View file

@ -0,0 +1,167 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* bridgefall.c: Knock a bridge down
*
* Known contributors to this file:
* Steve McClure, 1998
*/
#include "misc.h"
#include "var.h"
#include "sect.h"
#include "path.h"
#include "file.h"
#include "xy.h"
#include "plane.h"
#include "land.h"
#include "nsc.h"
#include "common.h"
#include "subs.h"
#include "lost.h"
#include "optlist.h"
void
bridgefall(struct sctstr *sp, struct emp_qelem *list)
{
register int i;
register 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, &sect);
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(&sect, list);
putsect(&sect);
}
}
}
/* 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 nstr_item ni;
int mines;
struct natstr *np;
if (sp->sct_type == SCT_BTOWER)
mpr(sp->sct_own, "Crumble... SCREEEECH! Splash! Bridge tower falls at %s!\n",
xyas(sp->sct_x, sp->sct_y, sp->sct_own));
else
mpr(sp->sct_own, "Crumble... SCREEEECH! Splash! Bridge falls at %s!\n",
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, (s_char *)&land)){
if (land.lnd_own == 0)
continue;
if(land.lnd_x != sp->sct_x || land.lnd_y != sp->sct_y)
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));
makelost(EF_LAND, land.lnd_own, land.lnd_uid, land.lnd_x, land.lnd_y);
land.lnd_own = 0;
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, (s_char *)&plane)){
if (plane.pln_own == 0)
continue;
if(plane.pln_x != sp->sct_x || plane.pln_y != sp->sct_y)
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));
makelost(EF_PLANE, plane.pln_own, plane.pln_uid, plane.pln_x, plane.pln_y);
plane.pln_own = 0;
plane.pln_effic = 0;
putplane(plane.pln_uid, &plane);
}
/*
* save only the mines; zero the rest of the
* commodities.
*/
mines = getvar(V_MINE, (caddr_t)sp, EF_SECTOR);
sp->sct_nv = 0;
if (mines > 0)
(void) putvar(V_MINE, mines, (caddr_t)sp, EF_SECTOR);
}

165
src/lib/common/check.c Normal file
View file

@ -0,0 +1,165 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* check.c: Check a sector, plane, land unit, ship or nuke
*
* Known contributors to this file:
* Steve McClure, 1998
*/
#include "misc.h"
#include "player.h"
#include "xy.h"
#include "file.h"
#include "var.h"
#include "sect.h"
#include "ship.h"
#include "plane.h"
#include "nuke.h"
#include "land.h"
#include "item.h"
#include "nsc.h"
#include "nat.h"
#include "commodity.h"
#include "loan.h"
#include "optlist.h"
#include "commands.h"
#include "trade.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("Nuclear stockpile %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;
}

199
src/lib/common/damage.c Normal file
View file

@ -0,0 +1,199 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* damage.c: Damage stuff.
*
* Known contributors to this file:
* Dave Pare, 1989
* Steve McClure, 1997
*/
#include "misc.h"
#include "var.h"
#include "sect.h"
#include "ship.h"
#include "land.h"
#include "plane.h"
#include "nuke.h"
#include "xy.h"
#include "nsc.h"
#include <fcntl.h>
#include "file.h"
#include "optlist.h"
#include "damage.h"
#include "common.h"
#include "gen.h"
#include "subs.h"
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);
sp->shp_nv = vl_damage(dam, sp->shp_vtype, sp->shp_vamt,
(int) sp->shp_nv);
}
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);
lp->lnd_nv = vl_damage(dam, lp->lnd_vtype, lp->lnd_vamt,
(int) lp->lnd_nv);
}
}
void
landdamage(struct lndstr *lp, int dam)
{
double damage_factor, m;
extern int land_mob_max;
m = (double)land_mob_max;
/* fortification reduces damage */
damage_factor = m / (m+((double)lp->lnd_harden));
if (damage_factor == 0.0)
damage_factor = 1.0;
/* 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(register int amt, int pct)
{
register int tmp;
register 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(register int amt, int dam)
{
return damage(amt, PERCENT_DAMAGE(dam));
}
int
commdamage(register int amt, int dam, int vtype)
{
extern double people_damage;
int lost;
if (vtype == V_BAR && opt_SUPER_BARS)
return amt;
lost = amt - effdamage(amt, dam);
if (vtype == V_MILIT ||
vtype == V_CIVIL ||
vtype == V_UW)
lost = ldround(people_damage * lost, 1);
return amt - lost;
}

494
src/lib/common/file.c Normal file
View file

@ -0,0 +1,494 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* file.c: Misc. operations on files
*
* Known contributors to this file:
* Dave Pare, 1989
* Steve McClure, 2000
*/
#ifdef Rel4
#include <string.h>
#endif /* Rel4 */
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#if !defined(_WIN32)
#include <unistd.h>
#endif
#include "misc.h"
#include "xy.h"
#include "nsc.h"
#include "file.h"
#include "match.h"
#include "struct.h"
#include "common.h"
#include "gen.h"
#ifdef Rel4
#include <unistd.h>
#endif
static void fillcache(struct empfile *ep, int start);
int
ef_open(int type, int mode, int how)
{
register struct empfile *ep;
static int block;
int size;
#if defined(_WIN32)
mode |= _O_BINARY;
#endif
if (ef_check(type) < 0)
return 0;
ep = &empfile[type];
if ((ep->fd = open(ep->file, mode, 0660)) < 0) {
logerror("%s: open failed", ep->file);
return 0;
}
if (block == 0)
block = blksize(ep->fd);
ep->baseid = 0;
ep->cids = 0;
ep->mode = mode;
ep->flags |= how;
ep->fids = fsize(ep->fd) / ep->size;
if (ep->flags & EFF_MEM)
ep->csize = ep->fids;
else
ep->csize = block / ep->size;
size = ep->csize * ep->size;
ep->cache = (s_char *)malloc(size);
if ((ep->cache == 0) && (size !=0)) {
logerror("ef_open: %s malloc(%d) failed\n", ep->file, size);
return 0;
}
if (ep->flags & EFF_MEM) {
if (read(ep->fd, ep->cache, size) != size) {
logerror("ef_open: read(%s) failed\n", ep->file);
return 0;
}
ep->cids = size / ep->size;
}
return 1;
}
int
ef_close(int type)
{
register struct empfile *ep;
int r;
if (ef_check(type) < 0)
return 0;
ep = &empfile[type];
if (ep->cache == 0) {
/* no cache implies never opened */
return 0;
}
ef_flush(type);
ep->flags &= ~EFF_MEM;
free(ep->cache);
ep->cache = 0;
if ((r = close(ep->fd)) < 0) {
logerror("ef_close: %s close(%d) -> %d",
ep->name, ep->fd, r);
}
return 1;
}
int
ef_flush(int type)
{
register struct empfile *ep;
int size;
int r;
if (ef_check(type) < 0)
return 0;
ep = &empfile[type];
if (ep->cache == 0) {
/* no cache implies never opened */
return 0;
}
size = ep->csize * ep->size;
if (ep->mode > 0 && (ep->flags & EFF_MEM)) {
if ((r = lseek(ep->fd, 0L, 0)) < 0) {
logerror("ef_flush: %s cache lseek(%d, 0L, 0) -> %d",
ep->name, ep->fd, r);
return 0;
}
if (write(ep->fd, ep->cache, size) != size) {
logerror("ef_flush: %s cache write(%d, %x, %d) -> %d",
ep->name, ep->fd, ep->cache, ep->size, r);
return 0;
}
}
/*ef_zapcache(type);*/
return 1;
}
s_char *
ef_ptr(int type, int id)
{
register struct empfile *ep;
if (ef_check(type) < 0)
return 0;
ep = &empfile[type];
if (id < 0 || id >= ep->fids)
return 0;
if ((ep->flags & EFF_MEM) == 0) {
logerror("ef_ptr: (%s) only valid for EFF_MEM entries",
ep->file);
return 0;
}
return (s_char *) (ep->cache + ep->size * id);
}
/*
* buffered read. Tries to read a large number of items.
* This system won't work if item size is > sizeof buffer area.
*/
int
ef_read(int type, int id, caddr_t ptr)
{
register struct empfile *ep;
caddr_t from;
if (ef_check(type) < 0)
return 0;
ep = &empfile[type];
if (id < 0)
return 0;
if (ep->flags & EFF_MEM) {
if (id >= ep->fids)
return 0;
from = ep->cache + (id * ep->size);
} else {
if (id >= ep->fids) {
ep->fids = fsize(ep->fd) / ep->size;
if (id >= ep->fids)
return 0;
}
if (ep->baseid + ep->cids <= id || ep->baseid > id)
fillcache(ep, id);
from = ep->cache + (id - ep->baseid) * ep->size;
}
bcopy(from, ptr, ep->size);
if (ep->postread)
ep->postread(id, ptr);
return 1;
}
static void
fillcache(struct empfile *ep, int start)
{
int n;
ep->baseid = start;
lseek(ep->fd, start * ep->size, 0);
n = read(ep->fd, ep->cache, ep->csize * ep->size);
ep->cids = n / ep->size;
}
#ifdef notdef
/*
* no-buffered read
* zaps read cache
*/
int
ef_nbread(int type, int id, caddr_t ptr)
{
register struct empfile *ep;
int r;
if (ef_check(type) < 0)
return 0;
ep = &empfile[type];
if (id < 0)
return 0;
if (id >= ep->fids) {
ep->fids = fsize(ep->fd) / ep->size;
if (id >= ep->fids)
return 0;
}
if ((r = lseek(ep->fd, id * ep->size, 0)) < 0) {
logerror("ef_nbread: %s #%d lseek(%d, %d, 0) -> %d",
ep->name, id, ep->fd, id * ep->size, r);
return 0;
}
if ((r = read(ep->fd, ptr, ep->size)) != ep->size) {
logerror("ef_nbread: %s #%d read(%d, %x, %d) -> %d",
ep->name, id, ep->fd, ptr, ep->size, r);
return 0;
}
ef_zapcache(type);
if (ep->postread)
ep->postread(id, ptr);
return 1;
}
#endif
/*
* buffered write. Modifies read cache (if applicable)
* and writes through to disk.
*/
int
ef_write(int type, int id, caddr_t ptr)
{
register int r;
register struct empfile *ep;
s_char *to;
if (ef_check(type) < 0)
return 0;
ep = &empfile[type];
if (id > 65536) {
/* largest unit id; this may bite us in large games */
logerror("ef_write: type %d id %d is too large!\n", type, id);
return 0;
}
if ((r = lseek(ep->fd, id * ep->size, 0)) < 0) {
logerror("ef_write: %s #%d lseek(%d, %d, 0) -> %d",
ep->name, id, ep->fd, id * ep->size, r);
return 0;
}
if (ep->prewrite)
ep->prewrite(id, ptr);
if ((r = write(ep->fd, ptr, ep->size)) != ep->size) {
logerror("ef_write: %s #%d write(%d, %x, %d) -> %d",
ep->name, id, ep->fd, ptr, ep->size, r);
return 0;
}
if (id >= ep->baseid && id < ep->baseid + ep->cids) {
/* update the cache if necessary */
to = ep->cache + (id - ep->baseid) * ep->size;
bcopy(ptr, to, ep->size);
}
if (id > ep->fids) {
logerror("WARNING ef_write: expanded %s by more than one id",
ep->name);
log_last_commands();
}
if (id >= ep->fids) {
if (ep->flags & EFF_MEM) {
logerror("file %s went beyond %d items; won't be able toread item w/o restart", ep->name, ep->fids);
} else {
/* write expanded file; ep->fids = last id + 1 */
ep->fids = id + 1;
}
}
return 1;
}
#ifdef notdef
/*
* no-buffered write
* zaps read cache
*/
int
ef_nbwrite(int type, int id, caddr_t ptr)
{
register struct empfile *ep;
register int r;
if (ef_check(type) < 0)
return 0;
ep = &empfile[type];
if (id > 65536) {
/* largest unit id; this may bite us in large games */
logerror("ef_nbwrite: %s id %d is too large!\n", ep->name, id);
return 0;
}
if ((r = lseek(ep->fd, id * ep->size, 0)) < 0) {
logerror("ef_nbwrite: %s #%d lseek(%d, %d, 0) -> %d",
ep->name, id, ep->fd, id * ep->size, r);
return 0;
}
if (ep->prewrite)
ep->prewrite(id, ptr);
if ((r = write(ep->fd, ptr, ep->size)) != ep->size) {
logerror("ef_nbwrite: %s #%d write(%d, %x, %d) -> %d",
ep->name, id, ep->fd, ptr, ep->size, r);
return 0;
}
ef_zapcache(type);
if (id >= ep->fids) {
/* write expanded file; ep->fids = last id + 1 */
ep->fids = id + 1;
}
return 1;
}
#endif
int
ef_extend(int type, int count)
{
register struct empfile *ep;
char *ptr;
int cur, max;
int mode, how;
int r;
if (ef_check(type) < 0)
return 0;
ep = &empfile[type];
max = ep->fids + count;
cur = ep->fids;
ptr = (s_char *)calloc(1, ep->size);
if ((r = lseek(ep->fd, ep->fids * ep->size, 0)) < 0) {
logerror("ef_extend: %s +#%d lseek(%d, %d, 0) -> %d",
ep->name, count, ep->fd, ep->fids * ep->size, r);
return 0;
}
for (cur = ep->fids; cur < max; cur++) {
if (ep->init)
ep->init(cur, ptr);
if ((r = write(ep->fd, ptr, ep->size)) != ep->size) {
logerror("ef_extend: %s +#%d write(%d, %x, %d) -> %d",
ep->name, count, ep->fd, ptr, ep->size, r);
return 0;
}
}
free(ptr);
if (ep->flags & EFF_MEM) {
/* XXX this will cause problems if there are ef_ptrs (to the
* old allocated structure) active when we do the re-open */
mode = ep->mode;
how = ep->flags;
ef_close(type);
ef_open(type, mode, how);
} else {
ep->fids += count;
}
return 1;
}
void
ef_zapcache(int type)
{
register struct empfile *ep = &empfile[type];
if ((ep->flags & EFF_MEM) == 0) {
ep->cids = 0;
ep->baseid = -1;
}
}
struct castr *
ef_cadef(int type)
{
return empfile[type].cadef;
}
int
ef_nelem(int type)
{
return empfile[type].fids;
}
int
ef_flags(int type)
{
return empfile[type].flags;
}
int
ef_lock(int type)
{
return file_lock(empfile[type].fd);
}
int
ef_unlock(int type)
{
return file_unlock(empfile[type].fd);
}
time_t
ef_mtime(int type)
{
extern time_t fdate(int fd);
if (empfile[type].fd <= 0)
return 0;
return fdate(empfile[type].fd);
}
int
ef_vars(int type, register s_char *sp, u_char **nvp, u_char **vp, u_short **ap)
{
register struct empfile *ef;
if (ef_check(type) < 0)
return 0;
ef = &empfile[type];
if ((ef->flags & EFF_COM) == 0)
return -1;
*nvp = (u_char *) (sp + ef->varoffs[0]);
*vp = (u_char *) (sp + ef->varoffs[1]);
*ap = (u_short *) (sp + ef->varoffs[2]);
return ef->maxvars;
}
int
ef_byname(s_char *name)
{
register struct empfile *ef;
register int i;
int len;
len = strlen(name);
for (i=0; i<EF_MAX; i++) {
ef = &empfile[i];
if (strncmp(ef->name, name, min(len, strlen(ef->name))) == 0)
return i;
}
return -1;
}
s_char *
ef_nameof(int type)
{
if (type < 0 || type >= EF_MAX)
return "bad item type";
return empfile[type].name;
}
int
ef_check(int type)
{
if (type < 0 || type >= EF_MAX) {
logerror("ef_ptr: bad EF_type %d\n", type);
return -1;
}
return 0;
}

92
src/lib/common/fsize.c Normal file
View file

@ -0,0 +1,92 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* fsize.c: BSD dependant file and block sizing routines
*
* Known contributors to this file:
* Dave Pare, 1986
* Doug Hay, 1998
* Steve McClure, 1998
*/
#include "misc.h"
#include "common.h"
#include <fcntl.h>
#include <sys/stat.h>
#if !defined(_WIN32)
#include <unistd.h>
#endif
/*
* 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 block size of the filesystem
* If it's not a filesystem, return 1024.
*/
int
blksize(int fd)
{
#if defined(_WIN32)
return 2048;
#elif (!defined (aix) && !defined (sgi))
struct stat statb;
if (fstat(fd, &statb) < 0)
return 1024;
return statb.st_blksize;
#else
return 1024;
#endif
}
time_t
fdate(int fd)
{
struct stat statb;
if (fstat(fd, &statb) < 0)
return 0;
return statb.st_mtime;
}
void
filetruncate(s_char *name)
{
close(open(name, O_RDWR|O_TRUNC, 0660));
}

118
src/lib/common/getvar.c Normal file
View file

@ -0,0 +1,118 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* getvar.c: Routines for manipulating variable lists.
*
* Known contributors to this file:
* Dave Pare, 1989
*/
#include "misc.h"
#include "var.h"
#include "file.h"
#include "common.h"
int
getvar(int vtype, s_char *sp, int ptype)
{
u_char *vtypep;
u_short *vamtp;
u_char *nvp;
int amt;
if (ef_vars(ptype, sp, &nvp, &vtypep, &vamtp) < 0) {
logerror("getvar: ptype %d has no vars", ptype);
return 0;
}
amt = vl_find(vtype, vtypep, vamtp, (int) *nvp);
if (amt < 0) {
logerror("getvar: vl_find returns %d, vtype %d",
amt, vtype);
return 0;
}
return amt;
}
int
getvec(int class, int *vec, s_char *sp, int ptype)
{
u_char *vtypep;
u_short *vamtp;
u_char *nvp;
int nv;
if (ef_vars(ptype, sp, &nvp, &vtypep, &vamtp) < 0) {
logerror("getvec: ptype %d has no vars", ptype);
return 0;
}
nv = vl_getvec(vtypep, vamtp, (int)*nvp, class, vec);
if (nv < 0) {
logerror("vl_getvec: returns %d, ptype %d\n",
nv, ptype);
return 0;
}
return nv;
}
int
putvar(int vtype, int amt, s_char *sp, int ptype)
{
u_char *vtypep;
u_short *vamtp;
u_char *nvp;
int maxv;
if (vtype < 0 || vtype > V_MAX) {
logerror("putvar: bad vtype %d\n", vtype);
return 0;
}
if ((maxv = ef_vars(ptype, sp, &nvp, &vtypep, &vamtp)) < 0) {
logerror("putvar: ptype %d has no vars", ptype);
return 0;
}
if (amt < 0)
amt = 0;
return vl_set(vtype, (u_int)amt, vtypep, vamtp, nvp, maxv);
}
int
putvec(int class, int *vec, s_char *sp, int ptype)
{
u_char *vtypep;
u_short *vamtp;
u_char *nvp;
int maxv,x;
if ((maxv = ef_vars(ptype, sp, &nvp, &vtypep, &vamtp)) < 0) {
logerror("putvec: ptype %d has no vars", ptype);
return 0;
}
for(x=0;x<I_MAX;x++)
if (vec[x] < 0)
vec[x] = 0;
return vl_setvec(vtypep, vamtp, nvp, maxv, class, vec);
}

66
src/lib/common/hap_fact.c Normal file
View file

@ -0,0 +1,66 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* hap_fact.c: Happiness effect on che
*
* Known contributors to this file:
* Steve McClure, 1996
*/
#include <stdio.h>
#include <ctype.h>
#include "misc.h"
#include "player.h"
#include "var.h"
#include "xy.h"
#include "sect.h"
#include "nat.h"
#include "news.h"
#include "nsc.h"
#include "item.h"
#include "file.h"
#include "common.h"
double hap_fact(struct natstr *tnat, struct natstr *vnat)
{
double hap_fact;
hap_fact = vnat->nat_level[NAT_HLEV];
if (hap_fact && tnat->nat_level[NAT_HLEV])
hap_fact = tnat->nat_level[NAT_HLEV] / hap_fact;
else if (!hap_fact && !tnat->nat_level[NAT_HLEV])
hap_fact = 1.0;
else if (tnat->nat_level[NAT_HLEV]) /* Target has happy, better fighting */
hap_fact = 2.0;
else /* Target has no happy, worse fighting */
hap_fact = 0.8;
if (hap_fact > 2.0)
hap_fact = 2.0;
if (hap_fact < 0.8)
hap_fact = 0.8;
return hap_fact;
}

100
src/lib/common/hours.c Normal file
View file

@ -0,0 +1,100 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* hours.c: Game hours determination; is it legal to play now?
*
* Known contributors to this file:
* Dave Pare, 1989
* Doug Hay, 1998
* Steve McClure, 1998
*/
#include <stdio.h>
#include "misc.h"
#include "nat.h"
#include "tel.h"
#include "proto.h"
#include "com.h"
#include "deity.h"
#include "keyword.h"
#include "file.h"
#include "common.h"
#if defined(Rel4) || defined(_WIN32)
#include <time.h>
#else
#include <sys/time.h>
#endif /* Rel4 */
/*
* returns true if game can be played now.
* Sets the number of minutes until the hours
* function must be re-called.
*/
int
gamehours(time_t now, int *hour)
{
extern s_char *game_days,*game_hours;
extern int errno;
extern struct tm *localtime(const time_t *);
register s_char *bp;
register struct tm *tm;
int day;
int curtime;
int okday[7];
int tomorrow;
tm = localtime(&now);
curtime = tm->tm_min + tm->tm_hour * 60;
bp = game_days;
if (*bp != 0) {
for (day=0; day<7; day++)
okday[day] = 0;
while (NULL != (bp = kw_parse(CF_WEEKDAY, bp, &day)))
okday[day] = 1;
} else {
for (day=0; day<7; day++)
okday[day] = 1;
}
if (!okday[tm->tm_wday])
return 0;
bp = game_hours;
if (*bp != 0) {
while (NULL != (bp = kw_parse(CF_TIMERANGE, bp, hour)))
if (curtime >= hour[0] && curtime < hour[1])
break;
if (bp == 0)
return 0;
} else {
hour[0] = 0;
hour[1] = 24*60;
}
tomorrow = tm->tm_wday + 1;
if (tomorrow >= 7)
tomorrow = 0;
return 1;
}

199
src/lib/common/keyword.c Normal file
View file

@ -0,0 +1,199 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* keyword.c: Find keywords in a file
*
* Known contributors to this file:
*
*/
#include "misc.h"
#include "keyword.h"
#include "gen.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "common.h"
struct kwtab {
struct kwtab *next;
s_char *name;
s_char *text;
};
struct kwtab *kw_list;
int
kw_read(FILE *fp)
{
register struct kwtab *kw;
register struct kwtab *next;
s_char buf[255];
s_char *p;
int n;
for (kw = kw_list; kw != 0; kw = next) {
next = kw->next;
free(kw->name);
free(kw->text);
free(kw);
}
kw_list = 0;
for (n=0; fgets(buf, sizeof(buf), fp) != 0; n++) {
/* Allow for comments.. any line starting with # */
if (buf[0] == '#')
continue;
p = rindex(buf, '\n');
if (p != 0)
*p = 0;
if ((p = index(buf, ':')) == 0) {
logerror("kw_read: Bad keyword line #%d\n", n);
return 0;
}
*p++ = 0;
while (*p && isspace(*p))
p++;
kw = (struct kwtab *) malloc(sizeof(*kw));
kw->name = strcpy(malloc(strlen(buf)+1), buf);
kw->text = strcpy(malloc(strlen(p)+1), p);
kw->next = kw_list;
kw_list = kw;
}
return n;
}
s_char *
kw_find(s_char *name)
{
register struct kwtab *kw;
for (kw = kw_list; kw != 0; kw = kw->next) {
if (strcmp(kw->name, name) == 0)
return kw->text;
}
return 0;
}
#define CF_VALUE 1
#define CF_TIME 2
#define CF_TIMERANGE 3
#define CF_WEEKDAY 4
/*
* destructive parse
*/
s_char *
kw_parse(int type, s_char *text, int *data)
{
s_char *get_time(s_char *ptr, int *data);
s_char *weekday(s_char *ptr, int *data);
s_char *next;
while (isspace(*text))
text++;
switch (type) {
case CF_VALUE:
*data = atoip(&text);
break;
case CF_TIME:
text = get_time(text, &data[0]);
break;
case CF_TIMERANGE:
if ((next = index(text, '-')) == 0)
return 0;
next++;
if ((text = get_time(text, &data[0])) == 0)
return 0;
text = get_time(next, &data[1]);
break;
case CF_WEEKDAY:
text = weekday(text, &data[0]);
break;
default:
text = 0;
break;
}
return text;
}
struct day {
s_char *string;
int day[7];
} day[] = {
{ "smtwtfs", { -1, 0, -1, 2, -1, 4, -1 } },
{ "uouehra", { 0, 1, 2, 3, 4, 5, 6 } }
};
s_char *
weekday(s_char *ptr, int *data)
{
register s_char *string;
register int c;
register int n;
c = *ptr++;
if (isupper(c))
c = tolower(c);
string = day[0].string;
for (n=0; n<7; n++) {
if (string[n] != c)
continue;
if (day[0].day[n] >= 0)
break;
if (day[1].string[n] == *ptr)
break;
}
if (n == 7)
return 0;
*data = day[1].day[n];
while (*ptr && !isspace(*ptr))
ptr++;
return ptr;
}
s_char *
get_time(s_char *ptr, int *data)
{
int hour;
int minute;
if (!isdigit(*ptr))
return 0;
hour = atoip(&ptr);
minute = 0;
if (*ptr) {
if (*ptr != ':')
return 0;
ptr++;
if (!isdigit(*ptr))
return 0;
minute = atoip(&ptr);
}
*data = (hour * 60) + minute;
return ptr;
}

98
src/lib/common/land.c Normal file
View file

@ -0,0 +1,98 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* land.c: Misc. land unit routines
*
* Known contributors to this file:
*
*/
#include "misc.h"
#include "var.h"
#include "sect.h"
#include "nat.h"
#include "var.h"
#include "file.h"
#include "path.h"
#include "xy.h"
#include "land.h"
#include "nsc.h"
#include "common.h"
#include "subs.h"
int
adj_units(coord x, coord y, natid own)
{
register int i;
struct sctstr sect;
for (i = DIR_FIRST; i <= DIR_LAST; i++) {
getsect(x + diroff[i][0], y + diroff[i][1], &sect);
if (has_units(sect.sct_x, sect.sct_y, own, 0))
return 1;
}
return 0;
}
int
has_units(coord x, coord y, natid cn, struct lndstr *lp)
{
register int n;
struct lndstr land;
for (n=0; ef_read(EF_LAND, n, (s_char *)&land); n++) {
if(land.lnd_x != x || land.lnd_y != y)
continue;
if (lp) {
/* Check this unit. If it is this one, we don't want
it included in the count. */
if (lp->lnd_uid == land.lnd_uid)
continue;
}
if (land.lnd_own == cn)
return 1;
}
return 0;
}
int
has_units_with_mob(coord x, coord y, natid cn)
{
struct nstr_item ni;
struct lndstr land;
snxtitem_xy(&ni,EF_LAND,x,y);
while(nxtitem(&ni,(s_char *)&land)) {
if (land.lnd_own != cn)
continue;
if (land.lnd_mobil > 0)
return 1;
}
return 0;
}

164
src/lib/common/log.c Normal file
View file

@ -0,0 +1,164 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* log.c: Log an Empire error to a file
*
* Known contributors to this file:
* Dave Pare, 1989
*/
#include "misc.h"
#include <errno.h>
#include <stdlib.h>
#if !defined(_WIN32)
#include <unistd.h>
#endif
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#ifdef Rel4
#include <string.h>
#endif /* Rel4 */
#include <time.h>
#include "deity.h"
#include "player.h"
#include "common.h"
static s_char *logfile = 0;
s_char *
getlogfile()
{
return (s_char *)logfile;
}
/*
* Points logfile at datadir/"program".log
*/
void
loginit(void)
{
extern s_char program[];
extern s_char *datadir;
s_char buf[1024];
#if !defined(_WIN32)
sprintf(buf, "%s/%s.log", datadir, program);
#else
sprintf(buf, "%s\\%s.log", datadir, program);
#endif
logfile = malloc(strlen(buf) + 1);
strcpy(logfile, buf);
}
/*VARARGS*/
void logerror(s_char *format, ...)
{
#if !defined(Rel4) && !defined(__linux__) && !defined(__ppc__)
extern s_char *sys_errlist[];
#endif
#ifndef sgi
extern int errno;
#endif /* sgi */
va_list list;
time_t now;
s_char buf[512];
s_char cbuf[512];
s_char buf1[512];
int logf;
/* s_char *error; */
s_char *p;
if (logfile == 0)
loginit();
va_start(list, format);
vsprintf(buf, format, list);
if ((p = index(buf, '\n')) != 0)
*p = 0;
(void) time(&now);
/* error = "log";
if (errno != 0)
error = sys_errlist[errno];
(void) sprintf(buf1, "%s; (%s) %s", buf, error, ctime(&now));
*/
strcpy(cbuf, ctime(&now));
if ((p = index(cbuf, '\n')) != 0)
*p = 0;
(void) sprintf(buf1, "%s %s\n", cbuf, buf);
if ((logf = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
return;
(void) write(logf, buf1, strlen(buf1));
(void) close(logf);
errno = 0;
#ifdef notdef
if (player) {
pr("A system error has occured; please notify the deity.\n");
pr(buf1);
}
#endif
va_end(list);
}
/*VARARGS*/
void filelogerror(s_char *format, ...)
{
#if !defined(Rel4) && !defined(__linux__) && !defined(__ppc__)
extern s_char *sys_errlist[];
#endif /* Rel4 */
#ifndef sgi
extern int errno;
#endif /* sgi */
va_list list;
time_t now;
s_char buf[512];
s_char buf1[512];
int logf;
s_char *error;
s_char *p;
if (logfile == 0)
loginit();
va_start(list, format);
vsprintf(buf, format, list);
if ((p = index(buf, '\n')) != 0)
*p = 0;
(void) time(&now);
error = "log";
if (errno != 0)
#ifdef Rel4
error = strerror (errno);
#else
error = (s_char *)sys_errlist[errno];
#endif /* Rel4 */
(void) sprintf(buf1, "%s; (%s) %s", buf, error, ctime(&now));
if ((logf = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
return;
(void) write(logf, buf1, strlen(buf1));
(void) close(logf);
errno = 0;
va_end(list);
}

45
src/lib/common/mailbox.c Normal file
View file

@ -0,0 +1,45 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* mailbox.c: Return string containing telegram file
*
* Known contributors to this file:
*
*/
#include "misc.h"
#include "tel.h"
#include <stdio.h>
s_char *
mailbox(s_char *buf, natid cn)
{
(void) sprintf(buf, "%s%d", telfil, cn);
return buf;
}

420
src/lib/common/maps.c Normal file
View file

@ -0,0 +1,420 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* maps.c: Map routines
*
* Known contributors to this file:
* Ken Stevens, 1995
* Steve McClure, 1998
*/
#include "misc.h"
#include "player.h"
#include "var.h"
#include "sect.h"
#include "xy.h"
#include "nsc.h"
#include "file.h"
#include "deity.h"
#include "nat.h"
#include "map.h"
#include "ship.h"
#include "land.h"
#include "plane.h"
#include "common.h"
#include "gen.h"
#include "subs.h"
#include "optlist.h"
int
draw_map(int bmap, s_char origin, int map_flags, struct nstr_sect *nsp, int country)
{
struct natstr *np;
struct range range;
struct nstr_item ni;
struct shpstr ship;
struct lndstr land;
struct plnstr plane;
coord x,y;
int i;
/* Note this is not re-entrant anyway, so we keep the buffers
around */
static u_char *bitmap = (u_char *)0;
static s_char *wmapbuf = (s_char *)0;
static s_char **wmap = (s_char **)0;
if (!wmapbuf)
wmapbuf = (s_char *)malloc((WORLD_Y * MAPWIDTH(1)) * sizeof(s_char));
if (!wmap) {
wmap = (s_char **)malloc(WORLD_Y * sizeof(s_char *));
if (wmap && wmapbuf) {
for (i = 0; i < WORLD_Y; i++)
wmap[i] = &wmapbuf[MAPWIDTH(1) * i];
} else if (wmap) {
free((s_char *)wmap);
wmap = (s_char **)0;
}
}
if (!bitmap)
bitmap = (u_char *)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 == EF_MAP + EF_BMAP) {
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(country);
/* zap any conditionals */
nsp->ncond = 0;
xyrelrange(np, &nsp->range, &range);
border(&range, " ", "");
blankfill((s_char *)wmapbuf, &nsp->range, 1);
if (bmap) {
register int c;
switch (bmap) {
case EF_BMAP:
while (bmnxtsct(nsp) && !player->aborted) {
if (0 != (c = player->bmap[sctoff(nsp->x, nsp->y)]))
wmap[nsp->dy][nsp->dx] = c;
}
break;
case EF_MAP:
while (bmnxtsct(nsp) && !player->aborted) {
if (0 != (c = player->map[sctoff(nsp->x, nsp->y)]))
wmap[nsp->dy][nsp->dx] = c;
}
break;
case (EF_MAP + EF_BMAP):
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 EF_NMAP:
do {
register s_char *ptr;
struct sctstr sect;
if ((!player->god || country)) {
bzero((s_char *)bitmap, (WORLD_X * WORLD_Y) / 8);
bitinit2(nsp, bitmap, country);
}
while (nxtsct(nsp, &sect) && !player->aborted) {
if ((!player->god || country) &&
!emp_getbit(nsp->x, nsp->y, bitmap)) {
if (!player->god)
continue;
}
ptr = &wmap[nsp->dy][nsp->dx];
if (sect.sct_newtype > SCT_MAXDEF) {
*ptr = '?';
} else {
*ptr = dchr[sect.sct_newtype].d_mnem;
switch (sect.sct_newtype) {
case SCT_WATER:
case SCT_RURAL:
case SCT_MOUNT:
case SCT_WASTE:
case SCT_PLAINS:
break;
default:
if (sect.sct_own != country &&
(!player->god || country)) {
if (!player->god)
*ptr = '?';
}
break;
}
}
}
} while (0);
break;
}
} else {
register s_char *ptr;
struct sctstr sect;
int changed = 0;
if ((!player->god || country)) {
bzero((s_char *)bitmap, (WORLD_X * WORLD_Y) / 8);
bitinit2(nsp, bitmap, country);
}
while (nxtsct(nsp, &sect) && !player->aborted) {
if ((!player->god || country) && !emp_getbit(nsp->x, nsp->y, bitmap)) {
if (!player->god)
continue;
}
ptr = &wmap[nsp->dy][nsp->dx];
if (sect.sct_type > SCT_MAXDEF) {
*ptr = '?';
} else {
*ptr = dchr[sect.sct_type].d_mnem;
switch (sect.sct_type) {
case SCT_WATER:
case SCT_RURAL:
case SCT_MOUNT:
case SCT_WASTE:
case SCT_PLAINS:
break;
default:
if (sect.sct_own != country &&
(!player->god || country)) {
if(!player->god)
*ptr = '?';
}
break;
}
changed += map_set(player->cnum, nsp->x, nsp->y, *ptr, 0);
}
}
if (changed)
writemap(player->cnum);
}
if (player->aborted)
return RET_OK;
if (map_flags & MAP_PLANE){
snxtitem_all(&ni, EF_PLANE);
while (nxtitem(&ni, (caddr_t)&plane)) {
if (plane.pln_own == 0)
continue;
if (plane.pln_own != player->cnum && !player->god)
continue;
if (!xyinrange(plane.pln_x, plane.pln_y, &nsp->range))
continue;
x = xnorm(plane.pln_x-nsp->range.lx);
y = ynorm(plane.pln_y-nsp->range.ly);
wmap[y][x] = (*plchr[(int)plane.pln_type].pl_name) & ~0x20;
}
}
if (map_flags & MAP_SHIP){
snxtitem_all(&ni, EF_SHIP);
while (nxtitem(&ni, (caddr_t)&ship)) {
if (ship.shp_own == 0)
continue;
if (ship.shp_own != player->cnum && !player->god)
continue;
if (!xyinrange(ship.shp_x, ship.shp_y, &nsp->range))
continue;
x = xnorm(ship.shp_x-nsp->range.lx);
y = ynorm(ship.shp_y-nsp->range.ly);
wmap[y][x] = (*mchr[(int)ship.shp_type].m_name) & ~0x20;
}
}
if (map_flags & MAP_LAND){
snxtitem_all(&ni, EF_LAND);
while (nxtitem(&ni, (caddr_t)&land)) {
if (land.lnd_own == 0)
continue;
if (land.lnd_own != player->cnum && !player->god)
continue;
if (!xyinrange(land.lnd_x, land.lnd_y, &nsp->range))
continue;
x = xnorm(land.lnd_x-nsp->range.lx);
y = ynorm(land.lnd_y-nsp->range.ly);
wmap[y][x] = (*lchr[(int)land.lnd_type].l_name) & ~0x20;
}
}
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
*/
int
bmnxtsct(register 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*/
}
void
bitinit2(struct nstr_sect *np, u_char *bitmap, int country)
{
extern int *bitmaps[];
struct sctstr sect;
int eff;
while (nxtsct(np, &sect)) {
if (sect.sct_own != country)
continue;
eff = sect.sct_effic / 20;
if (eff > 4)
eff = 4;
emp_setbitmap(np->x, np->y, bitmap, bitmaps[eff]);
}
snxtsct_rewind(np);
}
int
unit_map(int unit_type, int i, struct nstr_sect *nsp, s_char *originp)
{
struct shpstr origs;
struct lndstr origl;
struct plnstr origp;
s_char what[64];
struct natstr *np;
np = getnatp(player->cnum);
if (unit_type == EF_LAND){
if (!getland(i, &origl) ||
(origl.lnd_own != player->cnum && !player->god) ||
(origl.lnd_own == 0))
return RET_FAIL;
sprintf(what, "%d:%d,%d:%d",xrel(np,origl.lnd_x-10),
xrel(np,origl.lnd_x+10),
yrel(np,origl.lnd_y-5), yrel(np,origl.lnd_y+5));
*originp = *lchr[(int)origl.lnd_type].l_name;
} else if (unit_type == EF_PLANE){
if (!getplane(i, &origp) ||
(origp.pln_own != player->cnum && !player->god) ||
(origp.pln_own == 0))
return RET_FAIL;
sprintf(what, "%d:%d,%d:%d",xrel(np,origp.pln_x-10),
xrel(np,origp.pln_x+10),
yrel(np,origp.pln_y-5), yrel(np,origp.pln_y+5));
*originp = *plchr[(int)origp.pln_type].pl_name;
} else {
if (!getship(i, &origs) ||
(origs.shp_own != player->cnum && !player->god) ||
(origs.shp_own == 0))
return RET_FAIL;
sprintf(what, "%d:%d,%d:%d",xrel(np,origs.shp_x-10),
xrel(np,origs.shp_x+10),
yrel(np,origs.shp_y-5), yrel(np,origs.shp_y+5));
unit_type = EF_SHIP;
*originp = *mchr[(int)origs.shp_type].m_name;
}
if (!snxtsct(nsp, what))
return RET_FAIL;
return RET_OK;
}
int
bmaps_intersect(natid a, natid b)
{
s_char *mapa = ef_ptr(EF_MAP, a);
s_char *mapb = ef_ptr(EF_MAP, b);
int i;
for (i = 0; i < WORLD_X*WORLD_Y/2; ++i, ++mapa, ++mapb)
if (*mapa && *mapa != ' ' && *mapb && *mapb != ' ')
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, s_char des, s_char *from_name)
{
s_char *from_bmap = ef_ptr(EF_BMAP, from);
s_char *to_bmap = ef_ptr(EF_BMAP, to);
int n = 0;
struct sctstr sect;
s_char fromdes;
s_char todes;
s_char from_des = *from_name;
if (isalpha(from_des))
from_des &= ~0x20;
while (nxtsct(ns, &sect)) {
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;
}

75
src/lib/common/move.c Normal file
View file

@ -0,0 +1,75 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* move.c: Misc. move routines
*
* Known contributors to this file:
*
*/
#include "gamesdef.h"
#include "misc.h"
#include "xy.h"
#include "var.h"
#include "sect.h"
#include "file.h"
#include "deity.h"
#include "path.h"
#include "nat.h"
#include "common.h"
double
sector_mcost(struct sctstr *sp, int do_bonus)
{
double d;
if (!(d = dchr[sp->sct_type].d_mcst))
return -1.0;
/* Note, the best you can get is a 1.0 here. */
if (do_bonus == MOB_ROAD) {
d = d / (1.0 + ((double)sp->sct_road / 122.0));
} else if (do_bonus == MOB_RAIL) {
d = d / (1.0 + ((double)sp->sct_rail / 100.0));
} else {
if (d < 2.0)
d = 2.0;
}
if (d < 1.0)
d = 1.0;
if (dchr[sp->sct_type].d_mcst < 25)
d = (d * 100.0 - (double)sp->sct_effic) / 500.0;
/* d = (200.0 + (d - 3.0) * (double)sp->sct_effic) / 500.0;*/
else
d = (d * 10.0 - (double)sp->sct_effic) / 115;
if (d <= 0.0 || d < MIN_MOBCOST)
return MIN_MOBCOST;
return d;
}

170
src/lib/common/nat.c Normal file
View file

@ -0,0 +1,170 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* nat.c: Misc. accesses on the nation file
*
* Known contributors to this file:
* Dave Pare, 1989
*/
#include "misc.h"
#include "nat.h"
#include "file.h"
#include "optlist.h"
s_char *
cname(natid n)
{
struct natstr *np;
if ((np = getnatp(n)) == 0)
return 0;
return np->nat_cnam;
}
s_char *
relatename(struct natstr *np, natid other)
{
extern s_char *relates[];
return relates[getrel(np, other)];
}
s_char *
rejectname(struct natstr *np, natid other)
{
extern s_char *rejects[];
return rejects[getrejects(other, np)];
}
s_char *
natstate(struct natstr *np)
{
if ((np->nat_stat & STAT_INUSE) == 0)
return "FREE";
if (np->nat_stat & STAT_GOD)
return "DEITY";
if ((np->nat_stat & STAT_NORM) == 0)
return "VISITOR";
return "ACTIVE";
}
/* This returns the relations that np has with them */
int
getrel(struct natstr *np, natid them)
{
return np->nat_relate[them];
}
int
getrejects(natid them, struct natstr *np)
{
int ind;
int shift;
int reject;
ind = them / 4;
shift = 12 - ((them - ((them / 4) << 2)) * 4);
/* the 07 should *really* be 017 */
reject = (np->nat_rejects[ind] >> shift) & 0x0f;
return reject;
}
void
agecontact(struct natstr *np)
{
int them;
if (opt_LOSE_CONTACT) {
for (them = 1; them < MAXNOC; ++them) {
if (them != np->nat_cnum && np->nat_contact[them]) {
--np->nat_contact[them];
}
}
}
}
int
getcontact(struct natstr *np, natid them)
{
int contact;
if (opt_LOSE_CONTACT) {
contact = np->nat_contact[them];
} else {
int ind = them/16;
int shift = (them % 16);
contact = (np->nat_contact[ind] >> shift) & 1;
}
return contact;
}
void
putrel(struct natstr *np, natid them, int relate)
{
np->nat_relate[them] = relate;
}
void
putreject(struct natstr *np, natid them, int how, int what)
{
int shift;
int newrej;
int ind;
/* This 07 should be changed to 017 after the current game is over */
what &= 0x0f;
ind = them / 4;
shift = 12 - ((them - ((them / 4) << 2)) * 4);
newrej = np->nat_rejects[ind];
if (how)
newrej |= (what << shift);
else
newrej &= ~(what << shift);
np->nat_rejects[ind] = newrej;
}
void
putcontact(struct natstr *np, natid them, int contact)
{
if (opt_LOSE_CONTACT) {
if (np->nat_contact[them] > contact)
return;
np->nat_contact[them] = contact;
} else {
int ind = them/16;
int shift = them%16;
int new = np->nat_contact[ind];
if (contact)
contact = 1;
new &= ~(1 << shift);
new |= (contact << shift);
np->nat_contact[ind] = new;
}
}

159
src/lib/common/nstr_subs.c Normal file
View file

@ -0,0 +1,159 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* nstr.c: Compile and execute the item selections on sectors
*
* Known contributors to this file:
* Dave Pare, 1989
*/
#include <ctype.h>
#include "struct.h"
#include "misc.h"
#include "var.h"
#include "xy.h"
#include "sect.h"
#include "nsc.h"
#include "nat.h"
#include "match.h"
#include "file.h"
#include "player.h"
#include "common.h"
#include "gen.h"
/*
* return true if the conditions on this item
* are all true.
*/
int
nstr_exec(struct nscstr *conds, register int ncond, void *ptr, int type)
{
register struct nscstr *nsc;
register int op;
register int lhs;
register int rhs;
register int oper;
for (nsc=conds; --ncond >= 0; nsc++) {
oper = nsc->oper;
if (oper > 65535) {
oper = oper - 65535;
rhs = nsc->fld2;
} else
rhs = decode(player->cnum, nsc->fld2, ptr, type);
if (oper > 255) {
oper = oper - 255;
lhs = nsc->fld1;
} else
lhs = decode(player->cnum, nsc->fld1, ptr, type);
op = oper;
if ((op == '<' && lhs >= rhs) ||
(op == '=' && lhs != rhs) ||
(op == '>' && lhs <= rhs) ||
(op == '#' && lhs == rhs))
return 0;
}
return 1;
}
int
decode(natid cnum, long int code, void *addr, int type)
{
register int val;
register int nsc_code;
struct natstr *np;
long code_type = (code & NSC_TMASK);
val = (code & ~NSC_MASK) & 0xffff;
/* handle negative numbers properly */
/* this assumes a binary two's complement number representation */
if (val>=0x8000) val -= 0x10000;
nsc_code = code & NSC_CMASK;
if (nsc_code == NSC_VAR) {
val = getvar(val, addr, type);
} else if (nsc_code == NSC_OFF) {
/*
* add offset to value
*/
addr = (s_char *)addr + val;
switch (code_type) {
case NSC_TIME:
val = *((time_t *)addr);
break;
case NSC_CHAR:
val = *((s_char *) addr);
break;
case NSC_UCHAR:
val = (int) *((unsigned char *) addr);
break;
case NSC_SHORT:
val = *((short *) addr);
break;
case NSC_USHORT:
val = *((u_short *) addr);
break;
case NSC_INT:
val = *((int *) addr);
break;
case NSC_LONG:
val = *((long *) addr);
break;
case NSC_XCOORD:
val = *((short *) addr);
np = getnatp(cnum);
val = xrel(np, val);
break;
case NSC_YCOORD:
val = *((short *) addr);
np = getnatp(cnum);
val = yrel(np, val);
break;
default:
logerror("bad type in decode: %x!\n",
code & NSC_TMASK);
val = 0;
break;
}
}
if (code & NSC_ROUND)
val = roundintby(val, 10);
return val;
}
s_char *
decodep(long int code, void *addr)
{
addr = (char *)addr + ((code & ~NSC_MASK) & 0xffff);
if ((code & NSC_TMASK) == NSC_CHARP)
return *(s_char **)addr?*((s_char **)addr):(s_char *)"";
return addr;
}

541
src/lib/common/path.c Normal file
View file

@ -0,0 +1,541 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* path.c: Empire/A* Interface code. Provides callbacks for A* code and
* a sector cache to speed things up. Define BP_STATS for sector
* cache statistics, AS_STATS for A* statistics.
*
* Known contributors to this file:
* Phil Lapsley, 1991
* Dave Pare, 1991
* Thomas Ruschak, 1993
* Steve McClure, 1997
*/
#include <stdio.h>
#include <stdlib.h>
#include "../as/as.h"
#include "misc.h"
#include "path.h"
#include "xy.h"
#include "sect.h"
#include "file.h"
#include "common.h"
#include "gen.h"
#include "optlist.h"
/* STM - The server is now reliant on the sector file being
* memory mapped for other things. So, this code has been
* setup to have the sector hashing #ifdef'd instead so that
* we don't have to do runtime checking. If someone moves
* the sector file to me non-memory mapped, they have larger
* problems than this, and can just turn this back on. Then
* again, their performance will be so bad going to a file
* all the time, it won't matter. */
/*#define DO_EFF_MEM_CHECKING*/
/* XXX won't need sector hash when sect file is memory mapped */
#define BP_SCTHASHSIZE 128 /* sector cache hash table size */
#define BP_ASHASHSIZE 128 /* A* queue hash table size */
#define BP_NEIGHBORS 6 /* max number of neighbors */
struct sctcache {
coord x, y;
struct sctstr *sp;
struct sctcache *next;
};
struct bestp {
struct sctcache *sctcachetab[BP_SCTHASHSIZE];
int sctcache_hits;
int sctcache_misses;
int bp_mobtype;
struct as_data *adp;
};
#ifdef DO_EFF_MEM_CHECKING
static struct sctstr *bp_getsect(struct bestp *bp, coord x, coord y);
static struct sctstr *bp_sctcache_get(struct bestp *bp, coord x, coord y);
static void bp_sctcache_set(struct bestp *bp, coord x, coord y, struct sctstr *sp);
static void bp_sctcache_zap(struct bestp *bp);
#endif /* DO_EFF_MEM_CHECKING */
static int bp_path(struct as_path *pp, s_char *buf);
static int bp_neighbors(struct as_coord c, struct as_coord *cp, s_char *pp);
static double bp_lbcost(struct as_coord from, struct as_coord to, s_char *pp);
static double bp_realcost(struct as_coord from, struct as_coord to, s_char *pp);
static double bp_seccost(struct as_coord from, struct as_coord to, s_char *pp);
static int bp_coord_hash(struct as_coord c);
struct empfile *ep;
/* We use this for caching neighbors. It never changes except
* at reboot time (maybe) so we never need to free it */
struct sctstr **neighsects = (struct sctstr **)0;
s_char *
bp_init(void)
{
struct bestp *bp;
ep = &empfile[EF_SECTOR];
bp = (struct bestp *) malloc(sizeof(*bp));
bzero((s_char *)bp, sizeof(*bp));
bp->adp = as_init(BP_NEIGHBORS, BP_ASHASHSIZE, bp_coord_hash,
bp_neighbors, bp_lbcost, bp_realcost,
bp_seccost, (s_char *)bp);
if (bp->adp == NULL)
return NULL;
if (neighsects == (struct sctstr **)0)
neighsects = (struct sctstr **)calloc(1, (sizeof(struct sctstr *) *
((WORLD_X * WORLD_Y)/2)*6));
return (s_char *) bp;
}
/*
* Find the best path from sector to to sector, and put the Empire movement
* string in path. Return 0 on success, -1 on error.
*/
int
best_path(struct sctstr *from, struct sctstr *to, s_char *path, int mob_type)
{
static struct bestp *mybestpath;
struct as_data *adp;
struct as_path *ap;
if (mybestpath == 0)
mybestpath = (struct bestp *)bp_init();
adp = mybestpath->adp;
#ifdef DO_EFF_MEM_CHECKING
bp_sctcache_zap(mybestpath);
#endif
ap = as_find_cachepath(from->sct_x, from->sct_y, to->sct_x, to->sct_y);
if (ap == NULL) {
adp->from.x = from->sct_x;
adp->from.y = from->sct_y;
adp->to.x = to->sct_x;
adp->to.y = to->sct_y;
mybestpath->bp_mobtype = mob_type;
if (as_search(adp) < 0)
return -1;
ap = adp->path;
}
if (bp_path(ap, path) < 0)
return -1;
#ifdef AS_STATS
as_stats(adp, stderr);
#endif /* AS_STATS */
#ifdef BP_STATS
fprintf(stderr, "best path %s\n", path);
fprintf(stderr, "cache hits/misses: %d/%d\n",
bp->sctcache_hits, bp->sctcache_misses);
#endif /* BP_STATS */
return 0;
}
/*
* Translate an A* path into an empire movement string. Return 0 on
* success, -1 on failure.
*/
static int
bp_path(struct as_path *pp, s_char *buf)
{
struct as_path *np;
s_char *cp = buf;
int dx, dy;
int n;
np = pp->next;
while (np) {
dx = np->c.x - pp->c.x;
/* deal with wraparound from non-neg coords */
if (dx < -2)
dx += WORLD_X;
else if (dx > 2)
dx -= WORLD_X;
dy = np->c.y - pp->c.y;
if (dy < -1)
dy += WORLD_Y;
else if (dy > 1)
dy -= WORLD_Y;
for (n=1;n<=6;n++)
if (dx == diroff[n][0] && dy == diroff[n][1])
break;
if (n > 6)
return -1;
*cp++ = dirch[n];
pp = np;
np = np->next;
}
*cp = '\0';
return 0;
}
/*
* Find coords neighboring this sector; return number of such
* coords, and coordinartes themselves in an array pointed
* to by *cpp.
* XXX need to check ownership, sector types, etc.
*/
static int
bp_neighbors(struct as_coord c, struct as_coord *cp, s_char *pp)
{
#ifdef DO_EFF_MEM_CHECKING
struct bestp *bp = (struct bestp *) pp;
#endif /* DO_EFF_MEM_CHECKING */
coord x, y;
coord nx, ny;
int n = 0, q;
struct sctstr *sp, *from, **ssp;
/* Six pointers, just in case our cache isn't there */
struct sctstr *tsp[] = { 0, 0, 0, 0, 0, 0 };
int sx, sy, offset;
x = c.x;
y = c.y;
#ifdef DO_EFF_MEM_CHECKING
if ((ep->flags & EFF_MEM) == 0) {
from = bp_getsect(bp, x, y);
} else {
#endif /* DO_EFF_MEM_CHECKING */
sx = XNORM(x);
sy = YNORM(y);
offset = (sy * WORLD_X + sx) / 2;
from = (struct sctstr *) (ep->cache + ep->size * offset);
#ifdef DO_EFF_MEM_CHECKING
}
#endif /* DO_EFF_MEM_CHECKING */
if (neighsects == (struct sctstr **)0)
ssp = (struct sctstr **)&tsp[0];
else
ssp = (struct sctstr **)&neighsects[offset * 6];
for (q = 1; q <= 6; q++, ssp++) {
if (*ssp == (struct sctstr *)0) {
/* We haven't cached this neighbor yet */
nx = x + diroff[q][0];
ny = y + diroff[q][1];
sx = XNORM(nx);
sy = YNORM(ny);
#ifdef DO_EFF_MEM_CHECKING
if ((ep->flags & EFF_MEM) == 0) {
sp = bp_getsect(bp, nx, ny);
} else {
#endif /* DO_EFF_MEM_CHECKING */
offset = (sy * WORLD_X + sx) / 2;
sp = (struct sctstr *) (ep->cache + ep->size * offset);
/* We can only save in our neighbor cache if the
sector file is in memory */
*ssp = sp;
#ifdef DO_EFF_MEM_CHECKING
}
#endif /* DO_EFF_MEM_CHECKING */
} else {
sp = *ssp;
sx = XNORM(sp->sct_x);
sy = YNORM(sp->sct_y);
}
/* No need to calculate cost each time, just make sure we can
move through it. We calculate it later. */
if (dchr[sp->sct_type].d_mcst == 0)
continue;
if (sp->sct_own != from->sct_own)
continue;
cp[n].x = sx;
cp[n].y = sy;
n++;
}
return (n);
}
/*
* Compute a lower-bound on the cost from "from" to "to".
*/
/*ARGSUSED*/
static double
bp_lbcost(struct as_coord from, struct as_coord to, s_char *pp)
{
struct bestp *bp = (struct bestp *) pp;
struct sctstr *ts;
float cost;
int x, y, sx, sy, offset;
#ifdef DO_EFF_MEM_CHECKING
if ((ep->flags & EFF_MEM) == 0) {
ts = bp_getsect(bp, (coord)to.x, (coord)to.y);
} else {
#endif /* DO_EFF_MEM_CHECKING */
x = to.x;
y = to.y;
sx = XNORM(x);
sy = YNORM(y);
offset = (sy * WORLD_X + sx) / 2;
ts = (struct sctstr *)(ep->cache + ep->size * offset);
#ifdef DO_EFF_MEM_CHECKING
}
#endif /* DO_EFF_MEM_CHECKING */
cost = sector_mcost(ts, bp->bp_mobtype);
return (cost);
}
/*
* Compute the real cost to move from "from" to "to".
*/
static double
bp_realcost(struct as_coord from, struct as_coord to, s_char *pp)
{
return (bp_lbcost(from, to, pp));
}
/*
* Tie breaker secondary metric (only used when lower bound costs
* are equal).
*/
/*ARGSUSED*/
static double
bp_seccost(struct as_coord from, struct as_coord to, s_char *pp)
{
return ((double) mapdist((coord)from.x, (coord)from.y,
(coord)to.x, (coord)to.y));
}
#ifdef DO_EFF_MEM_CHECKING
/*
* Get a sector from the cache. If it's not in the cache,
* get it from disk and add it to the cache.
*/
static struct sctstr *
bp_getsect(struct bestp *bp, coord x, coord y)
{
struct sctstr *sp;
sp = bp_sctcache_get(bp, x, y);
if (sp == NULL) {
sp = (struct sctstr *) malloc(sizeof(*sp));
getsect(x, y, sp);
bp_sctcache_set(bp, x, y, sp);
bp->sctcache_misses++;
} else {
bp->sctcache_hits++;
}
return (sp);
}
/*
* Get a sector from the cache; return NULL if it's not there.
*/
static struct sctstr *
bp_sctcache_get(struct bestp *bp, coord x, coord y)
{
int hashval;
struct as_coord c;
struct sctcache *hp;
c.x = x;
c.y = y;
hashval = bp_coord_hash(c) % BP_SCTHASHSIZE;
for (hp = bp->sctcachetab[hashval]; hp; hp = hp->next) {
if (hp->x == x && hp->y == y)
return (hp->sp);
}
return (NULL);
}
/*
* Put a sector in the cache.
*/
static void
bp_sctcache_set(struct bestp *bp, coord x, coord y, struct sctstr *sp)
{
int hashval;
struct as_coord c;
struct sctcache *hp;
hp = (struct sctcache *) calloc(1, sizeof(*hp));
hp->x = x;
hp->y = y;
hp->sp = sp;
c.x = x;
c.y = y;
hashval = bp_coord_hash(c) % BP_SCTHASHSIZE;
hp->next = bp->sctcachetab[hashval];
bp->sctcachetab[hashval] = hp;
}
/*
* Zap the cache and reset statistics.
*/
static void
bp_sctcache_zap(struct bestp *bp)
{
register struct sctcache *hp;
register struct sctcache *np;
register int i;
for (i = 0; i < BP_SCTHASHSIZE; i++) {
for (hp = bp->sctcachetab[i]; hp; hp = np) {
np = hp->next;
free(hp->sp);
free(hp);
}
bp->sctcachetab[i] = NULL;
}
bp->sctcache_hits = 0;
bp->sctcache_misses = 0;
}
#endif /* DO_EFF_MEM_CHECKING */
/*
* Hash a coordinate into an integer.
*/
static int
bp_coord_hash(struct as_coord c)
{
return ((abs(c.x) + 1) << 3) ^ abs(c.y);
}
void
bp_enable_cachepath()
{
as_enable_cachepath();
}
void
bp_disable_cachepath()
{
as_disable_cachepath();
}
void
bp_clear_cachepath()
{
as_clear_cachepath();
}
double
pathcost(struct sctstr *start, s_char *path, int mob_type)
{
register int o;
register int cx, cy;
double cost = 0.0;
struct sctstr *sp;
int sx, sy, offset;
cx = start->sct_x;
cy = start->sct_y;
while (*path) {
if (*path == 'h') {
path++;
continue;
}
o = dirindex[(int)((*path) - 'a')];
cx += diroff[o][0];
cy += diroff[o][1];
sx = XNORM(cx);
sy = YNORM(cy);
offset = (sy * WORLD_X + sx) / 2;
sp = (struct sctstr *)(ep->cache + ep->size * offset);
cost += sector_mcost(sp, mob_type);
path++;
}
return cost;
}
s_char *
BestDistPath(s_char *path,
struct sctstr *from,
struct sctstr *to,
double *cost,
int mob_type)
{
return BestLandPath(path, from, to, cost, mob_type);
}
s_char *
BestLandPath(s_char *path,
struct sctstr *from,
struct sctstr *to,
double *cost,
int mob_type)
{
int length;
*path = 0;
*cost = 0.0;
if (best_path(from, to, path, mob_type) < 0)
return (s_char *)0;
*cost = pathcost(from, path, mob_type);
length = strlen(path);
path[length] = 'h';
path[length + 1] = '\0';
return path;
}
s_char *
BestShipPath(s_char *path,
int fx,
int fy,
int tx,
int ty,
int owner)
{
s_char *map;
/* need to make sector database available to bestpath */
map = ef_ptr(EF_BMAP, owner);
return (bestownedpath(path, map, fx, fy, tx, ty, ".=h", owner));
}
s_char *
BestAirPath(s_char *path,
int fx,
int fy,
int tx,
int ty)
{
return (bestownedpath(path, 0, fx, fy, tx, ty, "", -1));
/* return (bestpath(path, fx, fy, tx, ty, ""));*/
}

71
src/lib/common/res_pop.c Normal file
View file

@ -0,0 +1,71 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* res_pop.c: Get maximum pop of a sector
*
* Known contributors to this file:
* Ken Stevens, 1995
* Steve McClure, 1998
*/
#include <math.h>
#include "misc.h"
#include "var.h"
#include "sect.h"
#include "nat.h"
#include "item.h"
#include "news.h"
#include "file.h"
#include "xy.h"
#include "optlist.h"
#include "common.h"
int
max_pop(float research, struct sctstr *sp)
{
int maxpop = 999;
if (opt_RES_POP) {
maxpop = (((50.0+4.0*research)/(200.0+3.0*research))*600.0) + 400;
if (maxpop > 999)
maxpop = 999;
}
if (opt_BIG_CITY) {
if (sp && dchr[sp->sct_type].d_pkg == UPKG)
maxpop = (int)(maxpop * ((9.0 * sp->sct_effic) / 100 + 1));
}
if (sp) {
if (sp->sct_type == SCT_MOUNT)
maxpop /= 10;
else if (sp->sct_type == SCT_PLAINS)
maxpop /= 20;
}
return maxpop;
}

141
src/lib/common/sectdamage.c Normal file
View file

@ -0,0 +1,141 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* sectdamage.c: Damage a sector
*
* Known contributors to this file:
* Dave Pare, 1989
* Steve McClure, 1996
*/
#include "misc.h"
#include "var.h"
#include "sect.h"
#include "ship.h"
#include "land.h"
#include "plane.h"
#include "nuke.h"
#include "xy.h"
#include "nsc.h"
#include "file.h"
#include "nat.h"
#include "optlist.h"
#include "damage.h"
#include "common.h"
#include "gen.h"
#include "subs.h"
#include "lost.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((int)sp->sct_effic, dam);
sp->sct_road = damage((int)sp->sct_road, dam);
sp->sct_rail = damage((int)sp->sct_rail, dam);
sp->sct_defense = damage((int)sp->sct_defense, dam);
if (!opt_DEFENSE_INFRA)
sp->sct_defense = sp->sct_effic;
eff = dam;
if (sp->sct_mobil > 0)
sp->sct_mobil = damage((int)sp->sct_mobil, dam);
sp->sct_nv = vl_damage(dam,
sp->sct_vtype, sp->sct_vamt,
(int)sp->sct_nv);
if (opt_EASY_BRIDGES == 0) {
if (sp->sct_effic < 20 && sp->sct_type == SCT_BHEAD)
bridgefall(sp, list);
} else {
if (sp->sct_effic < 20 && sp->sct_type == SCT_BSPAN)
knockdown(sp, list);
}
putsect(sp);
return eff;
}
int
sectdamage(struct sctstr *sp, int dam, struct emp_qelem *list)
{
extern double unit_damage;
struct nstr_item ni;
struct lndstr land;
struct plnstr plane;
double real_dam;
int eff;
double sector_strength();
/* Some sectors are harder/easier to kill.. */
/* Average sector has a dstr of 1, so adjust */
/* the damage accordingly. Makes forts a pain */
/* real_dam = (double)dam * (1.0/((((double)(dchr[sp->sct_type].d_dstr - 1))*(sp->sct_effic/100.0)) + 1.0));*/
real_dam = (double)dam * (1.0/sector_strength(sp));
dam = ldround(real_dam,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,(s_char *)&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, (s_char *)&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;
}

View file

@ -0,0 +1,156 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* snxtit_subs.c: arrange item selection using one of many criteria.
*
* Known contributors to this file:
* Dave Pare, 1989
*/
#include "misc.h"
#include "var.h"
#include "xy.h"
#include "sect.h"
#include "nsc.h"
#include "file.h"
#include "common.h"
void
snxtitem_area(register struct nstr_item *np, int type, struct range *range)
{
bzero((s_char *)np, sizeof(*np));
np->cur = -1;
np->type = type;
np->sel = NS_AREA;
np->index = -1;
np->range = *range;
np->read = ef_read;
np->flags = ef_flags(type);
xysize_range(&np->range);
ef_zapcache(type);
}
void
snxtitem_dist(register struct nstr_item *np, int type, int cx, int cy, int dist)
{
struct range range;
bzero((s_char *)np, sizeof(*np));
xydist_range(cx, cy, dist, &range);
np->cur = -1;
np->type = type;
np->sel = NS_DIST;
np->cx = cx;
np->cy = cy;
np->index = -1;
np->range = range;
np->dist = dist;
np->read = ef_read;
np->flags = ef_flags(type);
#if 0
/* This is no longer proper. */
/* It did the wrong thing for small, hitech worlds. */
xysize_range(&np->range);
#endif
ef_zapcache(type);
}
void
snxtitem_xy(register struct nstr_item *np, int type, coord x, coord y)
{
bzero((s_char *)np, sizeof(*np));
np->cur = -1;
np->type = type;
np->sel = NS_XY;
np->cx = xnorm(x);
np->cy = ynorm(y);
np->index = -1;
np->dist = 0;
np->read = ef_read;
np->flags = ef_flags(type);
ef_zapcache(type);
}
void
snxtitem_all(register struct nstr_item *np, int type)
{
bzero((s_char *)np, sizeof(*np));
np->cur = -1;
np->sel = NS_ALL;
np->type = type;
np->index = -1;
np->read = ef_read;
np->flags = ef_flags(type);
xysize_range(&np->range);
ef_zapcache(type);
}
void
snxtitem_group(register struct nstr_item *np, int type, s_char group)
{
if (group == '~')
group = ' ';
bzero((s_char *)np, sizeof(*np));
np->cur = -1;
np->sel = NS_GROUP;
np->group = group;
np->type = type;
np->index = -1;
np->read = ef_read;
np->flags = ef_flags(type);
xysize_range(&np->range);
ef_zapcache(type);
}
void
snxtitem_rewind(struct nstr_item *np)
{
np->cur = -1;
np->index = -1;
ef_zapcache(np->type);
}
int
snxtitem_list(register struct nstr_item *np, int type, int *list, int len)
{
int i;
bzero((s_char *)np, sizeof(*np));
np->cur = -1;
np->type = type;
np->sel = NS_LIST;
np->index = -1;
np->read = ef_read;
np->flags = ef_flags(type);
if (len <= 0 || len > NS_LSIZE)
return 0;
for (i=0; i<len; i++)
np->list[i] = list[i];
np->size = len;
ef_zapcache(type);
return 1;
}

View file

@ -0,0 +1,159 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* snxtsct_subs.c: arrange sector selection using either distance or area
*
* Known contributors to this file:
* Dave Pare, 1989
*/
/*
* XXX we can *almost* treat sectors as items, but not quite.
* Items are retrieved using id's, and sectors still use x,y.
*/
#include "misc.h"
#include "var.h"
#include "xy.h"
#include "sect.h"
#include "nsc.h"
#include "file.h"
#include "common.h"
#include "optlist.h"
void
snxtsct_all(struct nstr_sect *np)
{
struct range worldrange;
worldrange.lx = -WORLD_X/2;
worldrange.ly = -WORLD_Y/2;
worldrange.hx = WORLD_X/2;
worldrange.hy = WORLD_Y/2;
worldrange.width = worldrange.height = 0;
snxtsct_area(np, &worldrange);
}
void
snxtsct_area(register struct nstr_sect *np, struct range *range)
{
bzero((s_char *)np, sizeof(*np));
np->range = *range;
np->ncond = 0;
np->type = NS_AREA;
np->read = ef_read;
np->x = np->range.lx - 1;
np->y = np->range.ly;
np->dx = -1;
np->dy = 0;
xysize_range(&np->range);
ef_zapcache(EF_SECTOR);
}
void
snxtsct_rewind(struct nstr_sect *np)
{
np->x = np->range.lx - 1;
np->y = np->range.ly;
np->dx = -1;
np->dy = 0;
np->id = -1;
ef_zapcache(EF_SECTOR);
}
void
snxtsct_dist(register struct nstr_sect *np, coord cx, coord cy, int dist)
{
bzero((s_char *)np, sizeof(*np));
xydist_range(cx, cy, dist, &np->range);
np->cx = cx;
np->cy = cy;
np->ncond = 0;
np->dist = dist;
np->type = NS_DIST;
np->read = ef_read;
np->x = np->range.lx - 1;
np->y = np->range.ly;
np->dx = -1;
np->dy = 0;
#if 0
/* This function is now done elsewhere. */
/* It was not doing the right thing when the world was small */
xysize_range(&np->range);
#endif
ef_zapcache(EF_SECTOR);
}
void
xysize_range(register struct range *rp)
{
if (rp->lx >= rp->hx)
rp->width = WORLD_X + rp->hx - rp->lx;
else
rp->width = rp->hx - rp->lx;
#ifndef HAY
/* This is a necessary check for small, hitech worlds. */
if (rp->width > WORLD_X)
rp->width = WORLD_X;
#endif
if (rp->ly >= rp->hy)
rp->height = WORLD_Y + rp->hy - rp->ly;
else
rp->height = rp->hy - rp->ly;
#ifndef HAY
/* This is a necessary check for small, hitech worlds. */
if (rp->height > WORLD_Y)
rp->height = WORLD_Y;
#endif
}
/* This is called also called in snxtitem.c */
void
xydist_range(coord x, coord y, register int dist, struct range *rp)
{
if (dist < WORLD_X/4) {
rp->lx = xnorm((coord)(x - 2 * dist));
rp->hx = xnorm((coord)(x + 2 * dist) + 1);
rp->width = 4 * dist + 1;
} else {
/* Range is larger than the world */
/* Make sure we get lx in the right place. */
rp->lx = xnorm((coord)(x - WORLD_X/2));
rp->hx = xnorm((coord)(rp->lx + WORLD_X - 1));
rp->width = WORLD_X;
}
if (dist < WORLD_Y/2) {
rp->ly = ynorm((coord)(y - dist));
rp->hy = ynorm((coord)(y + dist) + 1);
rp->height = 2 * dist + 1;
} else {
/* Range is larger than the world */
rp->ly = ynorm((coord)(y - WORLD_Y/2));
rp->hy = ynorm((coord)(rp->ly + WORLD_Y - 1));
rp->height = WORLD_Y;
}
}

82
src/lib/common/stmtch.c Normal file
View file

@ -0,0 +1,82 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* stmtch.c: Matching operations on structures and commands
*
* Known contributors to this file:
*
*/
/*
* XXX These routines gamble that structures are all longword-aligned.
* If this is not true, they will BREAK!
*/
#include "misc.h"
#include "match.h"
#include "common.h"
/*
* find a matching string from a member string pointer
* in a structure "str". Pointer is incremented by
* the (passed) size of the structure.
*/
int
stmtch(register s_char *obj, s_char *base, int off, int size)
{
register s_char *str;
register int stat2;
register int i;
register int n;
stat2 = M_NOTFOUND;
str = base + off;
for (i=0; *(s_char **)str; i++, str += size) {
if ((n = mineq(obj, *(s_char **)str)) == ME_MISMATCH)
continue;
if (n == ME_EXACT)
return i;
if (stat2 != M_NOTFOUND)
return M_NOTUNIQUE;
stat2 = i;
}
return stat2;
}
/*
* do partial match comparison.
*/
int
mineq(register s_char *a, register s_char *b)
{
do {
if (*a++ != *b++)
return ME_MISMATCH;
} while (*b != ' ' && *a != 0);
if (*a == 0 && (*b == ' ' || *b == 0))
return ME_EXACT;
return ME_PARTIAL;
}

89
src/lib/common/tfact.c Normal file
View file

@ -0,0 +1,89 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* tfact.c: return tech fact given multiplier
*
* Known contributors to this file:
* Yannick Trembley
*/
#include "misc.h"
#include "nat.h"
#include "file.h"
extern float fire_range_factor;
double
tfact(natid cn, double mult)
{
double tlev;
struct natstr *np;
np = getnatp(cn);
tlev = np->nat_level[NAT_TLEV];
tlev = (50.0 + tlev) / (200.0 + tlev);
return mult * tlev;
}
double
tfactfire(natid cn, double mult)
{
double tlev;
struct natstr *np;
np = getnatp(cn);
tlev = np->nat_level[NAT_TLEV];
tlev = (50.0 + tlev) / (200.0 + tlev);
return mult * tlev * fire_range_factor;
}
double
techfact(int level, double mult)
{
return mult * ((50.0 + level) / (200.0 + level));
}
/*
* added so that firing range can be different to other ranges
*/
double
techfactfire(int level, double mult)
{
return mult * ((50.0 + level) / (200.0 + level)) * fire_range_factor;
}
/*
* figure out relative difference between two tech levels
*/
double
reltech(int level1, int level2, double mult)
{
int diff;
diff = level1 - level2;
return (1.0 + ((diff + 50.0) / (level1 + 50.0))) * mult;
}

101
src/lib/common/type.c Normal file
View file

@ -0,0 +1,101 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* type.c: typename to array offset translation
*
* Known contributors to this file:
* Dave Pare, 1989
* Steve McClure, 2000
*/
#ifdef Rel4
#include <string.h>
#endif /* Rel4 */
#include "misc.h"
#include "ship.h"
#include "land.h"
#include "plane.h"
#include "sect.h"
#include "nuke.h"
#include "file.h"
#include "common.h"
int
typematch(s_char *buf, int type)
{
register int n;
int len;
len = strlen(buf);
switch (type) {
case EF_SECTOR: {
register struct dchrstr *dcp;
if (!buf[0] || buf[1])
return -1;
for (dcp=dchr,n=0; dcp->d_name; n++,dcp++)
if (dcp->d_mnem == *buf)
return n;
}
break;
case EF_SHIP: {
register struct mchrstr *mcp;
for (mcp=mchr,n=0; *mcp->m_name; n++,mcp++)
if (strncmp(mcp->m_name, buf, len) == 0)
return n;
}
break;
case EF_LAND: {
register struct lchrstr *lcp;
for (lcp=lchr,n=0; *lcp->l_name; n++,lcp++)
if (strncmp(lcp->l_name, buf, len) == 0)
return n;
}
break;
case EF_PLANE: {
register struct plchrstr *pcp;
for (pcp=plchr,n=0; *pcp->pl_name; n++,pcp++)
if (strncmp(pcp->pl_name, buf, len) == 0)
return n;
}
break;
case EF_NUKE: {
register struct nchrstr *ncp;
for (ncp=nchr,n=0; *ncp->n_name; n++,ncp++)
if (strncmp(ncp->n_name, buf, len) == 0)
return n;
}
break;
default:
break;
}
return -1;
}

284
src/lib/common/vlist.c Normal file
View file

@ -0,0 +1,284 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* vlist.c: manage variable lists
*
* Known contributors to this file:
* Dave Pare, 1989
*/
#include "misc.h"
#include "var.h"
#include "sect.h"
#include "ship.h"
#include "land.h"
#include "product.h"
#include "optlist.h"
#include "common.h"
#include "gen.h"
static int freeslot(u_char *vec, register u_char *end);
int
vl_find(register int vtype, u_char *typevec, u_short *amtvec, int nelem)
{
register u_char *vp;
register u_short *ap;
register u_char *endp;
if (vtype < 0 || vtype > V_MAX)
return -1;
vp = typevec;
ap = amtvec;
endp = vp + nelem;
for ( ; vp < endp; vp++, ap++) {
if (*vp == vtype)
return (int) *ap;
}
return 0;
}
int
vl_set(register int vtype, u_int amt, u_char *typevec, u_short *amtvec, u_char *nvp, int max)
{
register u_char *vp;
register u_char *endp;
register u_short *ap;
int n;
if (vtype < 0 || vtype > V_MAX)
return 0;
if (amt > 65536) {
logerror("vl_set: bad amt %d (%x), vtype %d\n", (int)amt, amt,
vtype);
return 0;
}
vp = typevec;
ap = amtvec;
endp = vp + *nvp;
for ( ; vp < endp; vp++, ap++) {
if (*vp == vtype)
break;
}
if (vp == endp) {
if (amt == 0) {
/* deleting, but not present */
return 0;
}
if (*nvp == max) {
if (isdel(vtype) || isdist(vtype))
return -1;
/* replace any del or dst entries */
if ((n = freeslot(typevec, endp)) < 0)
return -1;
vp = &typevec[n];
ap = &amtvec[n];
} else {
/* add at end */
(*nvp)++;
}
*vp = vtype;
*ap = amt;
} else {
if (amt != 0) {
/* altering; just change value */
*ap = amt;
return 1;
}
(*nvp)--;
if (vp < endp-1) {
/* if not last element, copy last to current */
*ap = amtvec[*nvp];
*vp = typevec[*nvp];
}
}
return 1;
}
int
vl_damage(register int pct, register u_char *typevec, register u_short *amtvec, register int nelem)
{
register int i;
register int lose;
extern double people_damage;
if (pct >= 100)
return 0;
if (pct <= 0)
return nelem;
for (i=0; i<nelem; i++) {
if (!isitem(typevec[i]))
continue;
if (opt_SUPER_BARS && typevec[i] == V_BAR)
continue;
lose = roundavg((double)amtvec[i] * pct * 0.01);
if (typevec[i] == V_CIVIL ||
typevec[i] == V_MILIT ||
typevec[i] == V_UW)
lose = ldround(people_damage * lose, 1);
if ((amtvec[i] -= lose) + 1 == 0) {
nelem--;
if (i == nelem)
break;
typevec[i] = typevec[nelem];
amtvec[i] = amtvec[nelem];
i--;
}
}
return nelem;
}
/*
* extract all "mask" items from the variable list
* caller must pass a pointer to an aray of I_MAX+1,
* or else bad things will happen.
*/
int
vl_getvec(register u_char *src_type, register u_short *src_amt, register int src_nv, register int class, register int *dst_amt)
{
register int n;
int count;
int item;
for (n=0; n<I_MAX+1; n++)
dst_amt[n] = 0;
for (count=0, n=0; n<src_nv; n++) {
if ((src_type[n] & VT_TYPE) != class)
continue;
item = src_type[n] & ~VT_TYPE;
if (item > I_MAX) {
logerror("vl_getvec: bad I-type %d (vtype %d)\n",
item, src_type[n]);
continue;
}
dst_amt[item] = src_amt[n];
count++;
}
return count;
}
/*
* Copy the vec into the variable list. All items zero in
* the vec will be deleted from the vlist, and all items
* present in the vec will be added to the vlist.
*/
int
vl_setvec(register u_char *type, register u_short *amt, u_char *nvp, int max, register int class, register int *vec)
{
register int nv;
register int n;
register int vec_n;
nv = *nvp;
vec_n = 1;
n = 0;
while (n < nv) {
if ((type[n] & VT_TYPE) != class) {
n++;
continue;
}
/* find non-zero vec entry to overwrite current slot */
for ( ; vec_n <= I_MAX; vec_n++)
if (vec[vec_n] != 0)
break;
if (vec_n > I_MAX) {
/* no more elements left; delete */
nv--;
if (n < nv) {
/* copy last entry over current entry */
type[n] = type[nv];
amt[n] = amt[nv];
}
} else {
/* use new (unused) entry */
type[n] = vec_n | class;
amt[n] = vec[vec_n];
vec_n++;
n++;
}
}
*nvp = nv;
if (n >= nv && vec_n > I_MAX)
return 1;
/* free slots at end; copy rest of vec into the vlist */
for ( ; vec_n <= I_MAX && nv < max; vec_n++) {
if (vec[vec_n] == 0)
continue;
type[nv] = vec_n | class;
amt[nv] = vec[vec_n];
nv++;
}
*nvp = nv;
if (vec_n <= I_MAX && (class == VT_ITEM || class == VT_COND)) {
/*
* still stuff left; make free slots out of deliveries
* and distributes and stuff 'em in (only for item or cond)
*/
for ( ; vec_n <= I_MAX; vec_n++) {
if (vec[vec_n] == 0)
continue;
if ((n = freeslot(type, &type[max])) < 0) {
logerror("vl_setvec: no free slots left\n");
return 0;
}
logerror("vl_setvec: replacing type %d amt %d\n",
type[n], amt[n]);
type[n] = vec_n | class;
amt[n] = vec[vec_n];
}
}
if (nv == max) {
/* checking for overflow */
while (vec_n <= I_MAX) {
if (vec[vec_n])
break;
}
if (vec_n <= I_MAX) {
logerror("vl_setvec: no space for i-type #%d (%d)\n",
vec_n, vec[vec_n]);
return 0;
}
}
return 1;
}
/*
* make a free slot; deliveries and distributions
* are fair game for us.
*/
static
int
freeslot(u_char *vec, register u_char *end)
{
register u_char *vp;
for (vp=vec; vp < end; vp++) {
if (isdel(*vp) || isdist(*vp))
return vp - vec;
}
return -1;
}

399
src/lib/common/wantupd.c Normal file
View file

@ -0,0 +1,399 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* wantupd.c: Check to se if an update is wanted and/or allowed.
*
* Known contributors to this file:
* Doug Hay, 1990
*/
#include <stdio.h>
#if !defined(_WIN32)
#include <unistd.h>
#endif
#include "misc.h"
#include "nat.h"
#include "file.h"
#include "keyword.h"
#include "wantupd.h"
#include "optlist.h"
#include "common.h"
#include <sys/types.h>
#include <fcntl.h>
#if defined(Rel4) || defined(_WIN32)
#include <time.h>
#else /* Rel4 */
#include <sys/time.h>
#endif /* Rel4 */
void
update_policy_check(void)
{
extern int update_policy,update_demandpolicy;
extern int update_wantmin,blitz_time;
if (update_policy < 0) update_policy = UDP_DEFAULT;
if (update_policy > UDP_MAX) update_policy = UDP_DEFAULT;
if (update_demandpolicy < 0) update_demandpolicy = UDDEM_DEFAULT;
if (update_demandpolicy > UDDEM_MAX)
update_demandpolicy = UDDEM_DEFAULT;
if (update_wantmin < 0) update_wantmin = 0;
if (update_wantmin > MAXNOC) update_wantmin = MAXNOC;
if (blitz_time < 0) blitz_time = 0;
}
static int
demand_update_time(time_t *now)
{
struct tm *tm;
s_char *p;
int curtime;
int hour[2];
extern s_char *update_demandtimes;
tm = localtime(now);
curtime = tm->tm_min + tm->tm_hour * 60;
p=update_demandtimes;
if (*p == 0) return(1);
while (NULL != (p = kw_parse(CF_TIMERANGE, p, &hour[0]))) {
if (curtime >= hour[0] && curtime < hour[1])
return(1);
}
return(0);
}
/* When is the next regularly scheduled update from now. */
static void
regular_update_time(time_t *now, time_t *tim, time_t *delta)
{
extern int s_p_etu;
extern int etu_per_update;
extern int adj_update;
s_char *p;
time_t tw;
int secs_per_update;
tw = *now + adj_update;
secs_per_update = etu_per_update * s_p_etu;
*delta = secs_per_update - (tw % secs_per_update);
*tim = *now + *delta;
}
/* Is this a valid time for a scheduled update. */
static int
scheduled_update_time(time_t *now, int *which)
{
struct tm *tm;
s_char *p, *p1;
int curtime;
int hour;
extern int hourslop;
extern s_char *update_times;
*which = -1;
p=update_times;
if (*p == 0) return(0);
tm = localtime(now);
curtime = tm->tm_min + tm->tm_hour * 60;
while (NULL != (p = kw_parse(CF_TIME, p, &hour))) {
(*which) ++;
if (curtime >= hour &&
curtime < hour+hourslop)
return(1);
}
return 0;
}
static int
next_scheduled_time(time_t *now, time_t *tim, time_t *delta)
{
struct tm *tm;
s_char *p;
int curtime;
int hour;
int mintime;
extern s_char *update_times;
p=update_times;
if (*p == 0) return(0);
tm = localtime(now);
curtime = tm->tm_min + tm->tm_hour * 60; /* now - in minutes */
mintime = curtime + 24*60+1; /* start with now + 1 day */
while (NULL != (p = kw_parse(CF_TIME, p, &hour))) {
if (hour <= curtime)
hour += 24 * 60; /* this must be tomorrow */
if (hour < mintime)
mintime = hour; /* this is best bet so far */
}
*delta = 60*(mintime - curtime);
*tim = *now + *delta - tm->tm_sec;
return(1);
}
int
demand_update_want(int *want, int *pop, int which)
{
natid cn;
struct natstr *natp;
int totpop;
int totwant;
int whichwants;
whichwants = totpop = totwant = 0;
for (cn = 1; 0 != (natp = getnatp(cn)); cn++) {
/* Only countries which are normal. */
/* Should probably include sanctuaries ..... */
if (((natp->nat_stat & NORM) == NORM) &&
((natp->nat_stat & GOD) != GOD)) {
totpop++;
if ((natp->nat_update & WUPD_WANT) == WUPD_WANT) {
totwant++;
if (which == cn)
whichwants++;
}
}
}
*want = totwant;
*pop = totpop;
return(whichwants);
}
static int
demand_check(void)
{
extern int update_wantmin,update_missed;
struct natstr *natp;
int want, pop, cn, veto;
time_t now;
time_t cur;
extern long last_demand_update;
time(&cur);
/*
if (last_demand_update == 0){
natp=getnatp(0);
last_demand_update = natp->nat_reserve;
}
logerror("last_demand_update = %d\n",last_demand_update);
logerror("update_between = %d\n",update_between());
logerror("now = %d\n",cur);
diff = (cur-(last_demand_update + update_between()));
logerror("diff = %d\n",diff);
if (diff >= 0){
logerror("Forced update!\n");
last_demand_update = cur;
for (cn = 1; natp = getnatp(cn); cn++){
if (((natp->nat_stat & NORM) == NORM) &&
((natp->nat_stat & GOD) != GOD)){
natp->nat_missed = 0;
}
}
return(1);
}
logerror("No forced update!\n");
*/
if (0 == update_wantmin) {
logerror("no demand update allowed, wantmin = 0");
return(0);
}
demand_update_want(&want, &pop, 0);
if (want < update_wantmin) {
logerror("no demand update, want = %d, min = %d",
want, update_wantmin);
return(0);
}
time(&now);
if (!demand_update_time(&now)) {
logerror("no demand update, not within hours allowed.");
return(0);
}
veto=0;
for (cn = 1; 0 != (natp = getnatp(cn)); cn++){
if (((natp->nat_stat & NORM) == NORM) &&
((natp->nat_stat & GOD) != GOD)){
if (natp->nat_missed >= update_missed)
veto=cn+1;
}
}
if (veto){
logerror("no demand update, %d has missed more than %d updates",
veto-1, update_missed);
return(0);
}
last_demand_update = cur;
natp=getnatp(0);
/* A dumb way to do it, but simple */
last_demand_update = natp->nat_reserve;
return(1);
}
/* Check if enough countries want an update,
* and if demand updates are allowed now.
*/
int
demandupdatecheck(void)
{
extern int update_demandpolicy;
if (UDDEM_COMSET != update_demandpolicy) {
logerror("no demand update, not policy.");
return(0);
}
return(demand_check());
}
/* Is it time for a regular or scheduled update?
* As well, if none of the above, check to see if
* a demand update can occur.
*/
int
updatetime(time_t *now)
{
extern int update_policy;
int which;
if (opt_BLITZ && update_policy == UDP_BLITZ) {
logerror("BLITZ Update.");
return(1);
}
if (UDP_NORMAL == update_policy) {
logerror("Regular update, etu type.");
return(1);
}
if (UDP_TIMES == update_policy) {
if (scheduled_update_time(now, &which)) {
logerror("Scheduled update, %d.", which);
return(1);
}
}
if (opt_DEMANDUPDATE) {
if (demand_check()) {
logerror("Demand update, at check time.");
return(1);
}
}
return(0);
}
/* Return the time, and delta seconds, of the next update.
* If the policy is no regular updates, return the time of
* the next possible check.
*/
void
next_update_time(time_t *now, time_t *tim, time_t *delta)
/* From when */
/* Time of next update */
/* Seconds till next update */
{
extern int update_policy;
time_t stim, sdelta;
extern int blitz_time;
switch (update_policy) {
case UDP_NORMAL:
regular_update_time(now, tim, delta);
break;
case UDP_TIMES:
if (!next_scheduled_time(now, tim, delta))
regular_update_time(now, tim, delta);
break;
case UDP_BLITZ:
*delta = (blitz_time * 60) - (*now % (blitz_time * 60));
*tim = *now + *delta;
break;
case UDP_NOREG:
default:
regular_update_time(now, tim, delta);
if (next_scheduled_time(now, &stim, &sdelta)) {
if (*delta > sdelta) {
*delta = sdelta;
*tim = stim;
}
}
break;
}
}
void
next_update_check_time(time_t *now, time_t *tim, time_t *delta)
/* From when */
/* Time of next update */
/* Seconds till next update check */
{
extern int update_policy;
time_t stim, sdelta;
extern int blitz_time;
switch (update_policy) {
case UDP_NORMAL:
regular_update_time(now, tim, delta);
break;
case UDP_BLITZ:
*delta = (blitz_time * 60) - (*now % (blitz_time * 60));
*tim = *now + *delta;
break;
case UDP_TIMES:
case UDP_NOREG:
default:
regular_update_time(now, tim, delta);
if (next_scheduled_time(now, &stim, &sdelta)) {
if (*delta > sdelta) {
*delta = sdelta;
*tim = stim;
}
}
}
}
int
updates_disabled(void)
{
extern s_char *disablefil;
int fd;
if ((fd = open(disablefil, O_RDONLY, 0)) < 0)
return 0;
close(fd);
return 1;
}

212
src/lib/common/xy.c Normal file
View file

@ -0,0 +1,212 @@
/*
* Empire - A multi-player, client/server Internet based war game.
* Copyright (C) 1986-2000, 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.
*
* ---
*
* xy.c: x-y related conversion routines
*
* Known contributors to this file:
* Dave Pare, 1989
*/
#include <ctype.h>
#include <stdarg.h>
#include "misc.h"
#include "xy.h"
#include "nat.h"
#include "sect.h"
#include "deity.h"
#include "file.h"
#include <stdio.h>
#include "common.h"
#include "optlist.h"
/*
* return pointer to a string containing the x,y
* coords as desired by a particular target country.
*/
s_char *
xyas(coord x, coord y, natid country)
{
struct natstr *np;
np = getnatp(country);
return prbuf("%d,%d", xrel(np, x), yrel(np, y));
}
s_char *
ownxy(struct sctstr *sp)
{
return xyas(sp->sct_x, sp->sct_y, sp->sct_own);
}
coord
xrel(struct natstr *np, coord absx)
{
coord x;
if ((np->nat_stat & STAT_ABS) == 0) {
x = XNORM(absx - np->nat_xorg);
} else {
x = XNORM(absx);
}
if (x >= WORLD_X/2)
x -= WORLD_X;
else if (x < -WORLD_X/2)
x += WORLD_X;
return x;
}
coord
yrel(struct natstr *np, coord absy)
{
coord y;
if ((np->nat_stat & STAT_ABS) == 0) {
y = YNORM(absy - np->nat_yorg);
} else {
y = YNORM(absy);
}
if (y >= WORLD_Y/2)
y -= WORLD_Y;
else if (y < -WORLD_Y/2)
y += WORLD_Y;
return y;
}
void
xyrelrange(struct natstr *np, struct range *src, struct range *dst)
{
dst->lx = xrel(np, src->lx);
dst->hx = xrel(np, src->hx);
dst->ly = yrel(np, src->ly);
dst->hy = yrel(np, src->hy);
dst->width = src->width;
dst->height = src->height;
}
void
xyabsrange(struct natstr *np, struct range *src, struct range *dst)
{
dst->lx = xabs(np, src->lx);
dst->hx = xabs(np, src->hx);
dst->ly = yabs(np, src->ly);
dst->hy = yabs(np, src->hy);
dst->width = src->width;
dst->height = src->height;
}
void
inputxy(coord *xp, coord *yp, natid cn)
{
struct natstr *np;
np = getnatp(cn);
*xp = xabs(np, *xp);
*yp = yabs(np, *yp);
}
coord
xabs(struct natstr *np, coord relx)
{
if ((np->nat_stat & STAT_ABS) == 0)
relx += np->nat_xorg;
return XNORM(relx);
}
coord
yabs(struct natstr *np, coord rely)
{
if ((np->nat_stat & STAT_ABS) == 0)
rely += np->nat_yorg;
return YNORM(rely);
}
int
sctoff(coord x, coord y)
{
if ((x + y) & 01) {
logerror("%d,%d is an invalid sector specification!\n", x, y);
return -1;
}
return (YNORM(y) * WORLD_X + XNORM(x))/2;
}
coord
xnorm(register coord x)
{
if (x < 0)
x = WORLD_X - (-x % WORLD_X);
return x % WORLD_X;
}
coord
ynorm(register coord y)
{
if (y < 0)
y = WORLD_Y - (-y % WORLD_Y);
return y % WORLD_Y;
}
int
xyinrange(coord x, coord y, struct range *rp)
{
if (rp->lx < rp->hx) {
/* xrange doesn't wrap */
if (x < rp->lx || x > rp->hx)
return 0;
} else {
if (x < rp->lx && x > rp->hx)
return 0;
}
if (rp->ly < rp->hy) {
/* yrange doesn't wrap */
if (y < rp->ly || y > rp->hy)
return 0;
} else {
if (y < rp->ly && y > rp->hy)
return 0;
}
return 1;
}
s_char *
prbuf(s_char *format, ...)
{
static int nbuf = -1;
static s_char buf[20][1024];
va_list ap;
if (++nbuf > 19)
nbuf = 0;
va_start(ap, format);
(void) vsprintf(buf[nbuf], format, ap);
va_end(ap);
return buf[nbuf];
}