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

62
src/lib/player/Makefile Normal file
View file

@ -0,0 +1,62 @@
#
# 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/libplayer.a
NTLIB = $(SRCDIR)\lib\libplayer.lib
OBJS = accept.o dispatch.o empdis.o empmod.o init_nats.o login.o nat.o \
player.o recvclient.o
NTOBJS = accept.obj dispatch.obj empdis.obj empmod.obj init_nats.obj \
login.obj nat.obj player.obj recvclient.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

268
src/lib/player/accept.c Normal file
View file

@ -0,0 +1,268 @@
/*
* 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.
*
* ---
*
* accept.c: Keep track of people logged in
*
* Known contributors to this file:
* Dave Pare, 1994
*/
#include "prototypes.h"
#include "misc.h"
#include "bit.h"
#include "proto.h"
#include "empthread.h"
#include "player.h"
#include "file.h"
#include "io_mask.h"
#include "empio.h"
#include "power.h"
#include "common.h"
#include "gen.h"
#include "optlist.h"
#if !defined(_WIN32)
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <unistd.h>
#else
#include <winsock.h>
#endif
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
struct emp_qelem Players;
void
player_init(void)
{
emp_initque(&Players);
init_player_commands();
}
struct player *
player_new(int s, struct sockaddr_in *sin)
{
struct player *lp;
struct hostent *hostp;
lp = (struct player *) calloc(1, sizeof(struct player));
bzero((s_char *)lp, sizeof(struct player));
if (sin) {
/* update uses dummy player */
/* so does the market updater */
emp_insque(&lp->queue, &Players);
strcpy(lp->hostaddr, inet_ntoa(sin->sin_addr));
#ifdef RESOLVE_IPADDRESS
if (NULL != (hostp = gethostbyaddr((char *) &sin->sin_addr, sizeof(sin->sin_addr), AF_INET)))
strcpy(lp->hostname, hostp->h_name);
#endif /* RESOLVE_IPADDRESS */
lp->cnum = 255;
lp->curid = -1;
time(&lp->curup);
lp->iop = io_open(s, IO_READ|IO_WRITE|IO_NBLOCK,
IO_BUFSIZE, 0, 0);
}
return lp;
}
struct player *
player_delete(struct player *lp)
{
struct player *back;
back = (struct player *) lp->queue.q_back;
if (back)
emp_remque(&lp->queue);
if (lp->iop) {
/* it's a real player */
io_close(lp->iop);
lp->iop = 0;
}
free((s_char *)lp);
/* XXX may need to free bigmap here */
return back;
}
struct player *
player_next(struct player *lp)
{
if (lp == 0)
lp = (struct player *)Players.q_forw;
else
lp = (struct player *)lp->queue.q_forw;
if (&lp->queue == &Players)
return 0;
return lp;
}
struct player *
player_prev(struct player *lp)
{
if (lp == 0)
lp = (struct player *)Players.q_back;
else
lp = (struct player *)lp->queue.q_back;
if (&lp->queue == &Players)
return 0;
return lp;
}
struct player *
getplayer(natid cnum)
{
register struct emp_qelem *qp;
for (qp = Players.q_forw; qp != &Players; qp = qp->q_forw)
if (((struct player *)qp)->cnum == cnum)
return (struct player *)qp;
return 0;
}
struct player *
player_find_other(struct player *us, register natid cnum)
{
register struct emp_qelem *qp;
for (qp = Players.q_forw; qp != &Players; qp = qp->q_forw)
if (((struct player *)qp)->cnum == cnum &&
((struct player *)qp != us) &&
(((struct player *)qp)->state == PS_PLAYING))
return (struct player *)qp;
return 0;
}
void
player_wakeup_all(natid cnum)
{
register struct player *lp;
if (NULL != (lp = getplayer(cnum)))
player_wakeup(lp);
}
void
player_wakeup(struct player *pl)
{
if (pl->waiting)
empth_wakeup(pl->proc);
}
/*ARGSUSED*/
void
player_accept(void *argv)
{
extern s_char *loginport;
extern int errno;
struct sockaddr_in sin;
struct servent *sp;
int s;
short port;
int val;
int maxfd;
struct player *np;
int len;
int ns;
int set = 1;
int stacksize;
char buf[128];
player_init();
sp = getservbyname("empire", "tcp");
if (sp == 0)
port = htons(atoi(loginport));
else
port = sp->s_port;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = port;
sin.sin_family = AF_INET;
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
logerror("inet socket create");
exit(1);
}
val = 1;
#if !(defined(__linux__) && defined(__alpha__))
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)) < 0) {
logerror("inet socket setsockopt SO_REUSEADDR (%d)", errno);
exit(1);
}
#else
logerror("Alpha/Linux? You don't support SO_REUSEADDR yet, do you?\n");
#endif
if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
logerror("inet socket bind");
exit(1);
}
#ifdef LISTENMAXCONN /* because someone in linux world didn't want to use
* SOMAXCONN as defined in the header files... */
if (listen(s, LISTENMAXCONN) < 0) {
logerror("inet socket listen");
exit(1);
}
#else
if (listen(s, SOMAXCONN) < 0) {
logerror("inet socket listen");
exit(1);
}
#endif
maxfd = getfdtablesize() - 1;
while (1) {
empth_select(s, EMPTH_FD_READ);
len = sizeof(sin);
ns = accept(s, (struct sockaddr *) &sin, &len);
if (ns < 0) {
logerror("new socket accept");
continue;
}
(void) setsockopt(ns, SOL_SOCKET, SO_KEEPALIVE,
(char *) &set, sizeof(set));
if (ns >= maxfd) {
logerror("new fd %d, max %d, no fd's left for new user",
ns, maxfd);
close(ns);
continue;
}
np = player_new(ns, &sin);
/* XXX may not be big enough */
stacksize = 100000
/* budget */ + max(WORLD_X*WORLD_Y/2 * sizeof(int) * 7,
/* power */ MAXNOC * sizeof(struct powstr));
sprintf(buf, "Player (fd #%d)", ns);
empth_create(PP_PLAYER, player_login, stacksize,
0, buf, "Empire player", np);
}
}

114
src/lib/player/dispatch.c Normal file
View file

@ -0,0 +1,114 @@
/*
* 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.
*
* ---
*
* dispatch.c: Actually execute the command given
*
* Known contributors to this file:
* Dave Pare, 1994
* Steve McClure, 1998
*/
#include "prototypes.h"
#include "misc.h"
#include "player.h"
#include "com.h"
#include "user.h"
#include "match.h"
#include "nat.h"
#include "file.h"
#include "proto.h"
#include "empio.h"
#include "optlist.h"
#include "subs.h"
#include "common.h"
int
dispatch(s_char *buf, s_char *redir)
{
extern struct cmndstr player_coms[];
extern int update_pending;
extern int max_btus;
struct natstr *np;
struct cmndstr *command;
int cmd;
cmd = comtch(player->argp[0], player_coms,
player->ncomstat, player->god);
if (cmd < 0) {
if (cmd == M_NOTUNIQUE)
pr("\"%s\" is ambiguous -- ", buf);
else if (cmd == M_IGNORE)
return 0;
else {
pr("\"%s\" is not a legal command ", buf);
if (player->nstat != player->ncomstat)
pr("now ");
pr("\n");
}
return -1;
}
command = &player_coms[cmd];
np = getnatp(player->cnum);
if (np->nat_btu < command->c_cost && command->c_cost > 0) {
if (player->god || opt_BLITZ)
np->nat_btu = max_btus;
else {
pr("You don't have the BTU's, bozo\n");
return 0;
}
}
if (command->c_addr == 0) {
pr("Command not implemented\n");
return 0;
}
if (update_pending) {
pr("Update in progress...command failed\n");
return 0;
}
if (redir) {
prredir(redir);
pr("%s\n", buf);
}
player->command = command;
switch (command->c_addr()) {
case RET_OK:
player->btused += command->c_cost;
break;
case RET_FAIL:
pr("command failed\n");
player->btused += command->c_cost;
break;
case RET_SYN:
pr("Usage: %s\n", command->c_form);
break;
default:
logerror("%s: returned bad value", command->c_form);
break;
}
player->command = 0;
return 0;
}

234
src/lib/player/empdis.c Normal file
View file

@ -0,0 +1,234 @@
/*
* 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.
*
* ---
*
* empdis.c: Empire dispatcher stuff
*
* Known contributors to this file:
* Dave Pare, 1994
* Steve McClure, 2000
*/
#include "prototypes.h"
#include <stdio.h>
#include "misc.h"
#include "player.h"
#include "nat.h"
#include "tel.h"
#include "proto.h"
#include "com.h"
#include "deity.h"
#include "keyword.h"
#include "file.h"
#include "empio.h"
#include "subs.h"
#include "common.h"
#include <fcntl.h>
#ifdef Rel4
#include <time.h>
#endif /* Rel4 */
#if !defined(_WIN32)
#include <sys/time.h>
#include <unistd.h>
#endif
#include <signal.h>
#define KEEP_COMMANDS 50
s_char player_commands[KEEP_COMMANDS][1024 + 8];
int player_commands_index = 0;
int
getcommand(s_char *combufp)
{
struct natstr *natp;
s_char buf[1024];
/* Note this now assumes a 1024 byte buffer is being passed in */
natp = getnatp(player->cnum);
if (++player_commands_index >= KEEP_COMMANDS)
player_commands_index = 0;
sprintf(player_commands[player_commands_index], "%3d %3d [prompt]",
player_commands_index, player->cnum);
do {
prprompt(natp->nat_minused, natp->nat_btu);
buf[0] = 0;
if (recvclient(buf, 1024) < 0) {
return -1;
}
} while (buf[0] == 0);
if (++player_commands_index >= KEEP_COMMANDS)
player_commands_index = 0;
sprintf(player_commands[player_commands_index], "%3d %3d %s",
player_commands_index, player->cnum, buf);
copy(buf, combufp);
return (strlen(combufp));
}
void
init_player_commands(void)
{
int i;
for (i = 0; i < KEEP_COMMANDS; ++i)
*player_commands[i] = 0;
}
void
log_last_commands(void)
{
int i;
logerror("Most recent player commands:");
for (i = player_commands_index; i >=0; --i)
if (*player_commands[i])
logerror("%s", player_commands[i]+4);
for (i = KEEP_COMMANDS - 1; i > player_commands_index; --i)
if (*player_commands[i])
logerror("%s", player_commands[i]+4);
}
int
explain(void)
{
extern struct cmndstr player_coms[];
register s_char *format;
register int i;
pr("\t\tCurrent EMPIRE Command List\n");
pr("\t\t------- ------ ------- ----\n");
pr("Initial number is cost in B.T.U. units.\n");
pr("Next 2 chars (if present) are:\n");
pr("$ - must be non-broke\tc -- must have capital\n");
pr("Args in [brackets] are optional.\n");
if (player->nstat > 4) {
pr("All-caps args in <angle brackets>");
pr(" have the following meanings:\n");
pr(" <NUM> :: a number in unspecified units\n");
pr(" <COMM> :: a commodity such as `food', `guns', etc\n");
pr(" <VAR> :: a commodity such as `food', `guns', etc\n");
pr(" <TYPE> :: an item type such as `ship', `plane', etc\n");
}
for (i = 0; (format = player_coms[i].c_form) != 0; i++) {
if ((player_coms[i].c_permit & player->ncomstat) == player_coms[i].c_permit){
pr("%2d ", player_coms[i].c_cost);
if ((player_coms[i].c_permit & MONEY) == MONEY)
pr("$");
else
pr(" ");
if ((player_coms[i].c_permit & CAP) == CAP)
pr("c");
else
pr(" ");
pr(" %s\n", format);
}
}
pr("For further info on command syntax see \"info Syntax\".\n");
return RET_OK;
}
/*
* returns true if down
*/
int
gamedown(void)
{
extern s_char *downfil;
int downf;
struct telstr tgm;
s_char buf[1024];
if (player->god)
return 0;
#if !defined(_WIN32)
if ((downf = open(downfil, O_RDONLY, 0)) < 0)
#else
if ((downf = open(downfil, O_RDONLY|O_BINARY, 0)) < 0)
#endif
return 0;
if (read(downf, (s_char *) &tgm, sizeof(tgm)) != sizeof(tgm)) {
logerror("bad header on login message (downfil)");
close(downf);
return 1;
}
if (read(downf, buf, tgm.tel_length) != tgm.tel_length) {
logerror("bad length %d on login message", tgm.tel_length);
close(downf);
return 1;
}
if (tgm.tel_length >= (long)sizeof(buf))
tgm.tel_length = sizeof(buf)-1;
buf[tgm.tel_length] = 0;
pr(buf);
pr("\nThe game is down\n");
(void) close(downf);
return 1;
}
void
daychange(time_t now)
{
struct natstr *natp;
struct tm *tm;
natp = getnatp(player->cnum);
tm = localtime(&now);
if ((tm->tm_yday % 128) != natp->nat_dayno) {
natp->nat_dayno = tm->tm_yday % 128;
natp->nat_minused = 0;
}
}
int
getminleft(time_t now, int *hour, int *mpd)
{
s_char *bp;
struct tm *tm;
int nminleft;
int curtime;
struct natstr *natp;
int n;
tm = localtime(&now);
curtime = tm->tm_min + tm->tm_hour * 60;
if (NULL != (bp = kw_find("minutes")))
kw_parse(CF_VALUE, bp, mpd);
natp = getnatp(player->cnum);
nminleft = *mpd - natp->nat_minused;
if (NULL != (bp = kw_find("hours"))) {
/*
* assume hours has already been set; just verify
* that it is present
*/
n = hour[1] - curtime;
if (n < nminleft)
nminleft = n;
}
n = 60*24 - (tm->tm_min + tm->tm_hour*60);
if (n < nminleft)
nminleft = n;
return nminleft;
}

433
src/lib/player/empmod.c Normal file
View file

@ -0,0 +1,433 @@
/*
* 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.
*
* ---
*
* empmod.c: List all commands for Empire
*
* Known contributors to this file:
* Dave Pare, 1986
* Jeff Bailey
* Thomas Ruschak, 1992
* Ken Stevens, 1995
* Steve McClure, 1996-2000
*/
#include "misc.h"
#include "com.h"
#include "nat.h"
#include "file.h"
extern int add();
extern int anti();
extern int assa();
extern int atta();
extern int boar();
extern int bdes();
extern int bomb();
extern int buil();
extern int chan();
extern int coas();
extern int comm();
extern int coun();
extern int decl();
extern int deli();
extern int show();
extern int show_motd(void);
extern int desi();
extern int diss();
extern int drop();
extern int echo(void);
extern int enli();
extern int fire();
extern int flee();
extern int fly();
extern int force();
extern int info();
extern int apro();
extern int load();
extern int look();
extern int map();
extern int mine();
extern int move();
extern int nati();
extern int navi();
extern int head(), news();
extern int nuke();
extern int offs();
extern int para();
extern int path();
extern int payo();
extern int powe();
extern int rada();
extern int rea();
extern int real();
extern int reco();
extern int rout();
extern int sona();
extern int spy();
extern int tele();
extern int tend();
extern int torp();
extern int tran();
extern int trea();
extern int turn();
extern int vers();
/*
* new commands
*/
extern int repo();
extern int laun();
extern int new();
extern int shoo();
extern int thre();
extern int dist();
extern int sct();
extern int plan();
extern int arm();
extern int hard();
extern int upgr();
extern int surv();
extern int capi();
extern int orig();
extern int conv();
extern int leve();
extern int cuto();
extern int prod();
extern int wai();
extern int carg();
extern int terr();
extern int sate();
extern int give();
extern int edit();
extern int wipe();
extern int dump();
extern int ldump();
extern int ndump();
extern int pdump();
extern int pboa();
extern int sdump();
extern int lost();
extern int explore();
extern int reso();
extern int scra();
extern int rela();
extern int brea();
extern int upda();
extern int hidd();
extern int orde();
extern int qorde();
extern int sorde();
extern int reje();
extern int acce();
extern int sabo();
extern int scut();
extern int grin();
extern int shar();
extern int sail(); /* Forsman's hacks */
extern int foll(); /**/
extern int mobq(); /**/
extern int name();
extern int range();
extern int zdon();
extern int fuel();
extern int multifire();
extern int retr();
extern int budg();
extern int wire();
extern int stop();
extern int start();
extern int land();
extern int supp();
extern int lboa();
extern int lcarg();
extern int lload();
extern int army();
extern int lrange();
extern int morale();
extern int lretr();
extern int landmine();
extern int fort();
extern int march();
extern int llook();
extern int mission();
extern int work();
extern int ltend();
extern int cede();
extern int best();
extern int newe();
extern int starve();
extern int setres();
extern int setsector();
extern int disa();
extern int enab();
/*
* Undeclared functions
*/
extern int quit(void);
extern int cens();
extern int demo();
extern int shi();
extern int wing();
extern int execute(void);
extern int explain(void);
extern int set();
extern int flash(void);
extern int wall();
extern int shut();
extern int togg();
extern int stre();
extern int skyw();
extern int play();
extern int swaps();
extern int trad();
extern int mark();
extern int buy();
extern int mult();
extern int sell();
extern int rese();
extern int repa();
extern int fina();
extern int coll();
extern int cons();
extern int ledg();
extern int shark();
extern int offe();
extern int mobupdate();
extern int sinfra();
extern int improve();
extern int lstats();
extern int pstat();
extern int sstat();
struct cmndstr player_coms[] = {
/* command form cost addr permit */
{ "accept [as-COUNTRY]", 0, acce, C_MOD, NORM },
{ "add <NAT> <NAME> <REP> <STATUS> <c|w|i>",0, add, C_MOD, GOD },
{ "announce {message}", 0, tele, C_MOD, VIS },
{ "anti <SECT>", 3, anti, C_MOD, NORM+MONEY+CAP },
{ "apropos <topic>", 0, apro, 0, VIS },
{ "arm <PLANE> <NUKETYPE> <airburst?>", 3, arm, C_MOD, NORM+MONEY+CAP },
{ "army <ARMY> <UNITS>", 0, army, C_MOD, NORM },
{ "assault <to-SECT> <from-SHIP> [<forts?> <ships?> <arty?> <planes?>]",3,assa,C_MOD, NORM+MONEY+CAP },
{ "attack <SECT> [<forts?> <ships?> <arty?> <planes?>]",3,atta,C_MOD, NORM+MONEY+CAP },
{ "bdes <SECTS> <type>", 0, bdes, C_MOD, NORM },
{ "bestpath <SECTS> <SECTS>", 0, best, 0, NORM },
{ "bestdistpath <SECTS> <SECTS>", 0, best, 0, NORM },
{ "bmap <SECTS|UNIT> [s|l|p|r|t*]", 0, map, C_MOD, NORM },
{ "board <to-SHIP> [<from-SHIP>|<from-sector>]", 3, boar, C_MOD, NORM+MONEY+CAP },
{ "bomb <bomber-PLANES> <fighter-PLANES> <pin|strat> <ap-SECT> <PATH|DESTINATION>",2,bomb,C_MOD, NORM+MONEY+CAP },
{ "break {sanctuary}", 1, brea, C_MOD, SANCT },
{ "budget [<sector type|P|S|L|A|M|N|C> <PRIORITY|~>]",1,budg,0, NORM },
{ "build <s|l|b|p|n|t> <SECTS> <type|dir> [<number> <tech> <sure?>]",1, buil, C_MOD, NORM+MONEY+CAP },
{ "buy <COMM> <LOT#> <BID/UNIT> <DEST>", 1, buy, C_MOD, CAP+NORM+MONEY },
{ "bye {log-off}", 0, quit, 0, VIS },
{ "capital <SECT>", 0, capi, C_MOD, NORM },
{ "cargo <SHIPS>", 0, carg, 0, NORM },
#ifdef CEDE_IS_ALLOWED
{ "cede <SECTS|SHIPS> <COUNTRY> [se|sh]", 639, cede, C_MOD, NORM },
#endif /* CEDE_IS_ALLOWED */
{ "census <SECTS>", 0, cens, 0, VIS },
{ "change <country|representative> <NAME>",0, chan, C_MOD, VIS },
{ "coastwatch <SECTS>", 1, coas, C_MOD, NORM+CAP },
{ "collect <LOAN> <SECT>", 2, coll, C_MOD, NORM+MONEY+CAP },
{ "commodity <SECTS>", 0, comm, 0, VIS },
{ "consider <loan|treaty> <LOAN/TREATY> <acc|decl|post>",1,cons,C_MOD, NORM+CAP },
{ "convert <SECTS> <NUM> [sure?]", 2, conv, C_MOD, NORM+MONEY+CAP },
{ "country <NATS>", 0, coun, 0, NORM },
{ "cutoff <SECTS>", 0, cuto, C_MOD, NORM },
{ "declare <all|friend|neut|hos|war> <NATS>", 2, decl, C_MOD, NORM+CAP },
{ "deliver <COMM> <SECTS> [q|<THRESH>] [<DIR>]",1, deli, C_MOD, NORM },
{ "demobilize <SECTS> <NUM> <active-reserve?> [sure?]",1, demo, C_MOD, NORM+CAP },
{ "designate <SECTS> <type> [sure?]", 1, desi, C_MOD, NORM },
{ "disable", 0, disa, C_MOD, GOD },
{ "disarm <PLANE>", 2, arm, C_MOD, NORM+MONEY+CAP },
{ "dissolve <really dissove?>", 0, diss, C_MOD, GOD },
{ "distribute <SECTS> <DISTSECT|.|h>", 1, dist, C_MOD, NORM },
{ "drop <cargo-PLANES> <fighter-PLANES> <ap-SECT> <PATH|DESTINATION> <COMM>",1,drop,C_MOD, NORM+MONEY+CAP },
{ "dump <SECTS> [<fields>]", 0, dump, 0, NORM },
{ "echo [<string>]", 0, echo, 0, NORM },
{ "edit <country|land|unit|ship|plane|nuke>", 0, edit, C_MOD, GOD },
{ "enable", 0, enab, C_MOD, GOD },
{ "enlist <SECTS> <NUM>", 2, enli, C_MOD, NORM+MONEY+CAP },
{ "execute <INPUT FILE>", 0, execute,0, VIS },
{ "explore <c|m> <SECT> <NUM> <PATH|DESTINATION>",1,explore, C_MOD, NORM+MONEY+CAP },
{ "financial", 0, fina, 0, NORM },
{ "fire <land, ship or sect> <from-SECTS | SHIPS | UNITS> [TO-SECT | SHIP]",1,multifire,C_MOD, NORM+MONEY+CAP },
{ "flash <COUNTRY> [<message>]", 0, flash, 0, VIS },
{ "fleetadd <FLEET> <SHIPS>", 0, flee, C_MOD, NORM },
{ "fly <cargo-PLANES> <fighter-PLANES> <ap-SECT> <PATH|DESTINATION> <COM>",2,fly,C_MOD, NORM+MONEY+CAP },
{ "follow <leader> <SHIPS>", 1, foll, C_MOD, NORM+CAP },
{ "force <delay time>", 0, force, C_MOD, GOD },
{ "fortify <UNITS> <MOB>", 1, fort, C_MOD, NORM },
{ "fuel <s|l> <SHIP/FLEET | UNIT/ARMY> <AMOUNT> [<OILER>]", 1, fuel, C_MOD, NORM },
{ "give <COMM> <SECT> <NUM>", 0, give, C_MOD, GOD },
{ "grind <SECT> <NUM>", 1, grin, C_MOD, NORM+MONEY+CAP },
{ "harden <PLANES> <NUM>", 2, hard, C_MOD, NORM+MONEY+CAP },
{ "help <topic>", 0, info, 0, VIS },
{ "headlines [days]", 0, head, C_MOD, VIS },
{ "hidden <SECTS>", 0, hidd, 0, GOD },
{ "improve <road|rail|defense> <SECTS> <NUM>",1, improve,C_MOD, NORM+MONEY+CAP },
{ "info <topic>", 0, info, 0, VIS },
{ "land <UNITS>", 0, land, C_MOD, NORM },
{ "launch <PLANES>", 3, laun, C_MOD, NORM+MONEY+CAP },
{ "lboard <to-LAND> [<from-sector>]", 3, lboa, C_MOD, NORM+MONEY+CAP },
{ "lcargo <UNITS>", 0, lcarg, 0, NORM },
{ "ledger <LOANS>", 0, ledg, 0, NORM },
{ "level <SECTS>", 0, leve, 0, NORM },
{ "list of commands", 0, explain,0, VIS },
{ "lbmap <SECTS|UNIT> [s|l|p|*]", 0, map, C_MOD, NORM },
{ "ldump <UNITS> [<fields>]", 0, ldump, 0, NORM },
{ "lload <COMM|\"land\"|\"plane\"> <UNITS> <NUM|UNITS|PLANES>",1, lload, C_MOD, NORM+CAP },
{ "llookout <UNITS>", 1, llook, 0, NORM+CAP },
{ "lmap <SECTS|UNIT> [s|l|p|*]", 0, map, C_MOD, NORM },
{ "lmine <UNITS>", 2, landmine,C_MOD, NORM+MONEY+CAP },
{ "load <COMM|\"land\"|\"plane\"> <SHIPS> <NUM|UNITS|PLANES>",1,load,C_MOD, NORM+CAP },
{ "lookout <SHIPS>", 1, look, 0, NORM+CAP },
{ "lost", 0, lost, 0, NORM },
{ "lradar <UNITS | SECTS>", 1, rada, 0, NORM+CAP },
{ "lrange <UNITS> <range>", 1, lrange, C_MOD, NORM+CAP },
{ "lretreat <UNITS|ARMY> <PATH> [i|h|b|c]", 1, lretr, C_MOD, NORM+CAP },
{ "lstats <UNITS>", 0, lstats, C_MOD, NORM },
{ "ltend <COMM> <tender-SHIPS> <NUM> <UNITS>",1, ltend, C_MOD, NORM+CAP },
{ "lunload <COMM|\"land\"|\"plane\"> <UNITS> <NUM|UNITS|PLANES>",1,lload, C_MOD, NORM+CAP },
{ "market [COMM]", 0, mark, 0, VIS },
{ "map <SECTS|SHIP>", 0, map, C_MOD, VIS },
{ "march <UNITS> <PATH|DESTINATION>", 1, march, C_MOD, NORM+CAP },
{ "mine <SHIPS>", 2, mine, C_MOD, NORM+MONEY+CAP },
{ "mission <type> <PLANES|SHIPS|UNITS> <mission type> <op sect> [<radius>]", 2,mission,C_MOD, NORM+CAP },
{ "mobupdate <MINUTES|check>", 0, mobupdate, C_MOD, GOD },
{ "morale <UNITS> <retreat%>", 1, morale, C_MOD, NORM+CAP },
{ "motd", 0, show_motd, C_MOD, VIS },
{ "move <c|m|s|g|p|i|o|b|f|r|u> <SECT> <NUM> <PATH|DESTINATION>",1,move,C_MOD, NORM+CAP },
{ "mquota <SHIPS> <value>", 2, mobq, C_MOD, NORM+CAP },
{ "mult [COUNTRY]", 1, mult, C_MOD, GOD },
{ "name <SHIPS> <NAME>", 0, name, C_MOD, NORM },
{ "nation", 0, nati, 0, VIS },
{ "navigate <SHIPS> <PATH|DESTINATION>", 1, navi, C_MOD, NORM+CAP },
{ "ndump <SECTS>", 0, ndump, 0, NORM },
{ "newcap <NAT> [<SECTOR>]", 0, new, C_MOD, GOD },
{ "neweff <SECTS>", 0, newe, C_MOD, NORM },
{ "newspaper [days]", 0, news, 0, VIS },
{ "nmap <SECTS|SHIP>", 0, map, C_MOD, VIS },
{ "nuke <SECTS>", 0, nuke, 0, NORM },
{ "offer <loan|treaty> <NAT> [<NUM> <DAYS> <IRATE>]",1,offe,C_MOD, NORM+MONEY+CAP },
{ "offset <SECT|NAT>", 0, offs, C_MOD, GOD },
{ "order <SHIPS> <c|s|r|d|l> ", 1, orde, C_MOD, NORM+CAP },
{ "origin <SECT>", 1, orig, C_MOD, NORM },
{ "paradrop <cargo-PLANES> <fighter-PLANES> <ap-SECT> <PATH|DESTINATION>",3,para,C_MOD, NORM+MONEY+CAP },
{ "path <SECT>", 0, path, 0, NORM },
{ "payoff <SHIPS>", 0, payo, C_MOD, NORM },
{ "pbmap <SECTS|UNIT> [s|l|p|*]", 0, map, C_MOD, NORM },
{ "pboard <PLANES>", 3, pboa, C_MOD, NORM+MONEY+CAP },
{ "pdump <PLANES> [<fields>]", 0, pdump, 0, NORM },
{ "plane <SECTS>", 0, plan, 0, NORM },
{ "players", 0, play, 0, VIS },
{ "pmap <SECTS|UNIT> [s|l|p|*]", 0, map, C_MOD, NORM },
{ "power [[\"new\" [<NUMBER OF COUNTRIES>]] | [\"country\" <COUNTRY NUMBER>]]", 0, powe, C_MOD, VIS },
{ "pray", 0, tele, C_MOD, NORM },
{ "production <SECTS>", 0, prod, 0, NORM },
{ "pstat <PLANES>", 0, pstat, 0, NORM },
{ "qorder <SHIPS>", 0, qorde, C_MOD, NORM+CAP },
{ "quit", 0, quit, 0, VIS },
{ "radar <SHIPS | SECTS>", 1, rada, 0, NORM+CAP },
{ "range <PLANES> <range>", 1, range, C_MOD, NORM+CAP },
{ "read", 0, rea, C_MOD, VIS },
{ "realm <number> [<SECTS>]", 0, real, C_MOD, NORM },
{ "recon <spy-PLANES> <fighter-PLANES> <ap-SECT> <PATH|DESTINATION>",3,reco,C_MOD, NORM+MONEY+CAP },
{ "retreat <SHIPS|FLEET> <PATH> [i|t|s|h|b|d|u|c]", 1,retr, C_MOD, NORM+CAP },
{ "relations [as-COUNTRY]", 0, rela, 0, VIS },
{ "reject <reject|accept> <announcements|mail|treaties|loans> <NAT>",2,reje,C_MOD, NORM },
{ "repay <LOAN> <NUM>", 1, repa, C_MOD, NORM+MONEY+CAP },
{ "report <NATS>", 0, repo, 0, VIS },
{ "reset <lot #> <0|price>", 1, rese, C_MOD, NORM+CAP },
{ "resource <SECTS>", 0, reso, 0, NORM },
{ "route <COMM> <SECTS>", 1, rout, 0, NORM },
{ "sabotage <UNITS>", 1, sabo, C_MOD, NORM+MONEY+CAP },
{ "sail <SHIPS> <PATH>", 1, sail, C_MOD, NORM+CAP },
{ "satellite <PLANE> [<se|sh|l> [?cond&cond&...]]",1, sate, 0, NORM+MONEY+CAP },
{ "sbmap <SECTS|UNIT> [s|l|p|*]", 0, map, C_MOD, NORM },
{ "scrap <s|p|l> <SHIPS|PLANES|UNITS>", 2, scra, C_MOD, NORM+MONEY+CAP },
{ "scuttle <s|p|l> <SHIPS|PLANES|UNITS>", 5, scut, C_MOD, NORM+CAP },
{ "sdump <SHIPS> [<fields>]", 0, sdump, 0, NORM },
{ "sect <SECTS>", 0, sct, 0, NORM },
{ "sell <COMM> <SECTS> <NUM> <NUM>", 1, sell, C_MOD, NORM+CAP },
{ "set <TYPE> <LIST> <PRICE>", 1, set, C_MOD, NORM+CAP },
{ "setsector <TYPE> <SECTS> <NUM>", 0, setsector,C_MOD, GOD },
{ "setresource <TYPE> <SECTS> <NUM>", 0, setres, C_MOD, GOD },
{ "shark <LOAN>", 25, shark, C_MOD, NORM+MONEY+CAP },
{ "sharebmap <CNUM/CNAME> <SECTS> [<des>]", 0, shar, C_MOD, NORM },
{ "ship <SHIPS>", 0, shi, 0, NORM },
{ "shoot <c|u> <SECTS> <NUMBER>", 3, shoo, C_MOD, NORM+MONEY+CAP },
{ "show <TYPE> <\"build\"|\"stats\"|\"cap\"> [<tech>]", 0,show, 0, VIS },
{ "shutdown [<minutes>] <disable update?>", 0, shut, 0, GOD },
{ "sinfrastructure <SECTS>", 0, sinfra, 0, VIS },
{ "skywatch <SECTS>", 1, skyw, C_MOD, NORM+CAP },
{ "smap <SECTS|UNIT> [s|l|p|*]", 0, map, C_MOD, NORM },
{ "sonar <SHIPS> <brief?>", 1, sona, C_MOD, NORM+CAP },
{ "sorder <SHIPS>", 0, sorde, C_MOD, NORM+CAP },
{ "spy <SECTS>", 1, spy, C_MOD, NORM+CAP },
{ "sstat <SHIPS>", 0, sstat, 0, NORM },
{ "start <SECTS>", 1, start, C_MOD, NORM+CAP },
{ "starvation [<SECTS>|l <UNITS>|s <SHIPS>]", 0, starve, 0, NORM },
{ "stop <SECTS>", 1, stop, C_MOD, NORM+CAP },
{ "strength <SECTS>", 1, stre, C_MOD, NORM },
{ "supply <LAND UNITS>", 1, supp, C_MOD, NORM+CAP },
{ "survey <COMM|VAR> <SECTS>", 0, surv, 0, NORM+CAP },
{ "swapsector <SECT> <SECT>", 0, swaps, C_MOD, GOD },
{ "sweep <sweep-PLANES> <fighter-PLANES> <ap-SECT> <PATH|DESTINATION>",3,reco,C_MOD, NORM+MONEY+CAP },
{ "telegram <NAT>", 0, tele, C_MOD, NORM },
{ "tend <COMM|\"land\"> <tender-SHIPS> <NUM|UNIT> <dest-SHIPS>",1,tend, C_MOD, NORM+CAP },
{ "territory <SECTS> <NUMBER> [<FIELD>]", 0, terr, C_MOD, NORM },
{ "test <c|m|s|g|p|i|o|b|f|r|u> <SECT> <NUM> <PATH|DESTINATION>",1,move,0, NORM+CAP },
{ "threshold <COMM> <SECTS> <THRESH>", 1, thre, C_MOD, NORM },
{ "toggle [inform|flash|beep|coastwatch|sonar|techlists] [on|off]", 0, togg, C_MOD, VIS },
{ "torpedo <submarine-SHIPS> <target-SHIP>",3, torp, C_MOD, NORM+MONEY+CAP },
{ "trade", 1, trad, C_MOD, NORM+CAP+MONEY },
{ "transport <\"nuke\"|\"plane\"> <SECT|PLANES> [<NUKETYPE> <number>] <PATH|DESTINATION>",1,tran,C_MOD, NORM+CAP },
{ "treaty <TREATIES>", 0, trea, 0, NORM+MONEY+CAP },
{ "turn <\"on\"|\"off\"|\"mess\">", 0, turn, C_MOD, GOD },
{ "unload <COMM|\"land\"|\"plane\"> <SHIPS> <NUM|UNIT|PLANE>",1,load,C_MOD, NORM+CAP },
{ "unsail <SHIPS>", 1, sail, C_MOD, NORM+CAP },
{ "update", 0, upda, 0, VIS },
{ "upgrade <SHIPS|LAND UNITS|PLANES>", 1, upgr, C_MOD, NORM+MONEY+CAP },
{ "version", 0, vers, 0, VIS },
{ "wait", 0, wai, C_MOD, GOD },
{ "wall [<message>]", 0, wall, C_MOD, NORM },
{ "wingadd <WING> <PLANES>", 1, wing, C_MOD, NORM },
{ "wipe <SECTS>", 1, wipe, C_MOD, NORM },
{ "wire [yes|no|<days>]", 0, rea, C_MOD, VIS },
{ "work <LAND UNITS> <AMOUNT>", 1, work, C_MOD, NORM+MONEY+CAP },
{ "zdone <y|n|c>", 0, zdon, C_MOD, NORM },
{ 0, 0, 0, 0, 0 }
};

133
src/lib/player/init_nats.c Normal file
View file

@ -0,0 +1,133 @@
/*
* 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.
*
* ---
*
* init_nats.c: Initialize country and nation file stuff
*
* Known contributors to this file:
* Dave Pare, 1994
* Steve McClure, 2000
*/
#include "prototypes.h"
#include "misc.h"
#include "player.h"
#include "var.h"
#include "sect.h"
#include "nat.h"
#include "file.h"
#include "deity.h"
#include "optlist.h"
#include "common.h"
#include "gen.h"
int
init_nats(void)
{
struct natstr *np;
if ((np = getnatp(player->cnum)) == 0)
return -1;
player->nstat = np->nat_stat;
player->god = np->nat_stat & STAT_GOD;
player->map = ef_ptr(EF_MAP, player->cnum);
player->bmap = ef_ptr(EF_BMAP, player->cnum);
if (opt_HIDDEN) {
putcontact(np, player->cnum, FOUND_SPY);
}
if (np->nat_money <= 0)
player->broke = 1;
else {
player->nstat |= MONEY;
player->broke = 0;
}
if (nat_cap(np->nat_btu) < 0)
return -1;
return 0;
}
int
nat_cap(int btu)
{
extern int s_p_etu;
extern int max_btus;
extern float btu_build_rate;
struct sctstr sect;
struct natstr *np;
double d;
double civ;
int delta;
np = getnatp(player->cnum);
if (!getsect(np->nat_xcap, np->nat_ycap, &sect)) {
logerror("can't read %s's cap @ %d,%d",
np->nat_cnam, np->nat_xcap, np->nat_ycap);
return -1;
}
if ((player->nstat & NORM) == NORM) {
if (player->owner && (sect.sct_type == SCT_CAPIT ||
sect.sct_type == SCT_MOUNT ||
sect.sct_type == SCT_SANCT))
player->nstat |= CAP;
else
player->nstat &= ~CAP;
/* Ok, has the country owner reset his capital yet after it was sacked? */
if (np->nat_flags & NF_SACKED)
player->nstat &= ~CAP; /* No capital yet */
}
delta = 0;
if ((player->nstat & CAP) || player->god) {
d = (double) (player->curup - np->nat_last_login) / s_p_etu;
if (d > 336.0)
d = 336.0;
civ = getvar(V_CIVIL, (caddr_t)&sect, EF_SECTOR);
if (civ > 999)
civ = 999;
if ((sect.sct_effic) && (sect.sct_type != SCT_MOUNT))
delta=roundavg(d*civ*sect.sct_effic*btu_build_rate);
else /* Assume 1/2% efficiency minimum */
delta=roundavg(d*civ*btu_build_rate/2.0);
if (player->god)
delta = max_btus - btu;
if (delta + btu > max_btus)
delta = max_btus - btu;
if (btu > max_btus)
delta = max_btus - btu;
if (opt_BLITZ)
delta = max_btus - btu;
if (delta > 0) {
/* set date if BTUs made */
np->nat_btu += delta;
}
if (btu > max_btus)
np->nat_btu = max_btus;
}
if (np->nat_stat == VIS)
np->nat_btu = max_btus;
putnat(np);
return 0;
}

327
src/lib/player/login.c Normal file
View file

@ -0,0 +1,327 @@
/*
* 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.
*
* ---
*
* login.c: Allow the player to login
*
* Known contributors to this file:
* Dave Pare, 1994
* Steve McClure, 2000
*/
#ifdef Rel4
#include <string.h>
#endif /* Rel4 */
#include "prototypes.h"
#include "misc.h"
#include "proto.h"
#include "player.h"
#include "com.h"
#include "empthread.h"
#include "empio.h"
#include "nsc.h"
#include "nat.h"
#include "optlist.h"
#include "file.h"
#include "subs.h"
#include "common.h"
#include "gen.h"
#ifdef aix
#include <unistd.h>
#endif /* aix */
#if !defined(_WIN32)
#include <netinet/in.h>
#endif
#include <errno.h>
struct cmndstr login_coms[];
/*ARGSUSED*/
void
player_login(void *ud)
{
s_char buf[128];
s_char space[512];
s_char *av[64];
int ac;
int cmd;
player->proc = empth_self();
pr_id(player, C_INIT, "Empire server ready\n");
while (!io_eof(player->iop) && !io_error(player->iop)) {
io_output(player->iop, IO_WAIT);
if (io_gets(player->iop, buf, sizeof(buf)) < 0) {
io_input(player->iop, IO_WAIT);
continue;
}
ac = parse(buf, av, 0, space, 0);
cmd = comtch(av[0], login_coms, 0, 0);
if (cmd < 0) {
pr_id(player, C_BADCMD, "Command %s not found\n", av[0]);
continue;
}
switch (login_coms[cmd].c_addr(player, ac, av)) {
case RET_OK:
break;
case RET_FAIL:
break;
case RET_SYN:
pr_id(player, C_BADCMD, "Usage %s\n", login_coms[cmd].c_form);
break;
default:
break;
}
if (player->state >= PS_SHUTDOWN)
break;
}
player->state = PS_SHUTDOWN;
if (!io_eof(player->iop)) {
(void) pr_player(player, C_EXIT, "so long...\n");
io_noblocking(player->iop, 0);
while (io_output(player->iop, IO_WAIT) > 0)
;
}
player_delete(player);
empth_exit();
/*NOTREACHED*/
}
int
client_cmd(struct player *player, int ac, char **av)
{
int i;
if (ac < 1 || av[1] == '\0')
return RET_SYN;
for (i = 1; i < ac; ++i) {
if (i > 1)
(void) strncat(player->client, " ", sizeof(player->client)-1);
(void) strncat(player->client, av[i], sizeof(player->client)-1);
}
player->client[sizeof(player->client)-1] = '\0';
pr_id(player, C_CMDOK, "talking to %s\n", player->client);
return RET_OK;
}
int
user_cmd(struct player *player, int ac, char **av)
{
if (ac < 1 || av[1] == '\0')
return RET_SYN;
(void) strncpy(player->userid, av[1], sizeof(player->userid)-1);
player->userid[sizeof(player->userid)-1] = '\0';
pr_id(player, C_CMDOK, "hello %s\n", player->userid);
return RET_OK;
}
int
sanc_cmd(struct player *player, int ac, char **av)
{
struct nstr_item ni;
struct natstr nat;
int first = 1;
if (!opt_BLITZ) {
pr_id(player, C_BADCMD, "Command %s not found\n", av[0]);
return RET_FAIL;
}
snxtitem_all(&ni, EF_NATION);
while (nxtitem(&ni, (s_char *)&nat)) {
if (nat.nat_stat != (STAT_INUSE|STAT_SANCT))
continue;
if (first) {
pr_id(player, C_DATA, "The following countries are still in sanctuary:\n");
first = 0;
}
pr_id(player, C_DATA, "%s\n", nat.nat_cnam);
}
if (first)
pr_id(player, C_CMDOK, "There are no countries in sanctuary\n");
else
pr_id(player, C_CMDOK, "\n");
return RET_OK;
}
int
coun_cmd(struct player *player, int ac, char **av)
{
natid cnum;
if (ac < 1 || av[1] == '\0')
return RET_SYN;
if (natbyname(av[1], &cnum) < 0) {
pr_id(player, C_CMDERR, "country %s does not exist\n",av[1]);
return 0;
}
player->cnum = cnum;
player->validated = 0;
pr_id(player, C_CMDOK, "country name %s\n", av[1]);
return 0;
}
int
pass_cmd(struct player *player, int ac, char **av)
{
if (ac < 1 || av[1] == '\0')
return RET_SYN;
if (player->cnum == 255) {
pr_id(player, C_CMDERR, "need country first\n");
return RET_FAIL;
}
if (!natpass(player->cnum, av[1])) {
pr_id(player, C_CMDERR, "password bad, logging entry\n");
logerror("%s tried country #%d with %s",
praddr(player), player->cnum, av[1]);
return RET_FAIL;
}
player->validated++;
pr_id(player, C_CMDOK, "password ok\n");
logerror("%s using country #%d", praddr(player), player->cnum);
return RET_OK;
}
/*ARGSUSED*/
int
play_cmd(struct player *player, int ac, char **av)
{
extern char *banfil;
struct player *other;
natid cnum;
struct natstr *natp;
if (ac == 4) {
(void) strncpy(player->userid, av[1], sizeof(player->userid)-1);
player->userid[sizeof(player->userid)-1] = '\0';
player->validated = 0;
if (natbyname(av[2], &cnum) < 0) {
pr_id(player, C_CMDERR, "country %s does not exist\n", av[2]);
return 0;
}
if (!natpass(cnum, av[3])) {
pr_id(player, C_CMDERR, "password bad, logging entry\n");
logerror("%s tried country #%d with %s",
praddr(player), cnum, av[3]);
return RET_FAIL;
}
player->cnum = cnum;
player->validated++;
}
if (player->cnum == 255 || !player->validated) {
pr_id(player, C_CMDERR, "need country and password\n");
return RET_FAIL;
}
if ((other = player_find_other(player, (natid)player->cnum)) != 0) {
natp = getnatp(player->cnum);
if (natp->nat_stat != VIS) {
pr_id(player, C_EXIT, "country in use by %s\n",
praddr(other));
} else {
pr_id(player, C_EXIT, "country in use\n");
}
return RET_FAIL;
}
if (match_user(banfil, player)) {
logerror("Attempted login by BANNED host %s",
praddr(player));
pr("Your login has been banned from this game\n");
io_shutdown(player->iop, IO_READ);
return RET_FAIL;
}
player_main(player);
player->state = PS_SHUTDOWN;
return RET_OK;
}
/*ARGSUSED*/
int
kill_cmd(struct player *player, int ac, char **av)
{
struct player *other;
if (player->cnum == 255 || !player->validated) {
pr_id(player, C_CMDERR, "need country and password\n");
return RET_FAIL;
}
/* XXX find cnum other than us */
if ((other = player_find_other(player, player->cnum)) == 0) {
pr_id(player, C_EXIT, "country not in use\n");
return RET_FAIL;
}
io_shutdown(other->iop, IO_READ|IO_WRITE);
pr_id(player, C_EXIT, "closed socket of offending job\n");
return RET_OK;
}
/*ARGSUSED*/
int
list_cmd(struct player *player, int ac, char **av)
{
struct player *lp;
int first = 1;
if (player->cnum != 0 || !player->validated) {
pr_id(player, C_CMDERR, "Permission denied\n");
return 0;
}
for (lp = player_next(0); lp != 0; lp = player_next(lp)) {
if (first) {
pr_id(player, C_DATA, "user@host\tcountry\tpid\n");
first = 0;
}
pr_id(player, C_DATA, "%s\t%d\n", praddr(lp), lp->cnum);
}
if (first == 0)
pr_id(player, C_DATA, "\n");
return 0;
}
/*ARGSUSED*/
int
quit_cmd(struct player *player, int ac, char **av)
{
pr_id(player, C_EXIT, "so long\n");
io_shutdown(player->iop, IO_READ);
return RET_OK;
}
struct cmndstr login_coms[] = {
{ "list", 0, list_cmd, 0, 0 },
{ "client clientname [version info]", 0, client_cmd, 0, 0 },
{ "user username", 0, user_cmd, 0, 0 },
{ "sanc", 0, sanc_cmd, 0, 0 },
{ "coun countryname", 0, coun_cmd, 0, 0 },
{ "pass password", 0, pass_cmd, 0, 0 },
{ "play [user country pass]", 0, play_cmd, 0, 0 },
{ "quit ", 0, quit_cmd, 0, 0 },
{ "kill {self}", 0, kill_cmd, 0, 0 },
{ 0, 0, 0, 0, 0 }
};

68
src/lib/player/nat.c Normal file
View file

@ -0,0 +1,68 @@
/*
* 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: Get nation stuff
*
* Known contributors to this file:
* Dave Pare, 1994
*/
#include "prototypes.h"
#include "misc.h"
#include "nat.h"
#include "file.h"
#include "player.h"
#include <fcntl.h>
int
natbyname(s_char *name, natid *result)
{
struct natstr *np;
int i;
for (i=0; NULL != (np = getnatp(i)); i++) {
if (strcmp(np->nat_cnam, name) == 0) {
*result = i;
return 0;
}
}
*result = 255;
return -1;
}
int
natpass(int cn, s_char *pass)
{
struct natstr *np;
np = getnatp((natid)cn);
if (np->nat_stat == VIS)
return 1;
if (strcmp(np->nat_pnam, pass) == 0)
return 1;
return 0;
}

426
src/lib/player/player.c Normal file
View file

@ -0,0 +1,426 @@
/*
* 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.
*
* ---
*
* player.c: Main command loop for a player
*
* Known contributors to this file:
* Steve McClure, 2000
*
*/
#include "prototypes.h"
#include <string.h>
#include "gamesdef.h"
#include "misc.h"
#include "player.h"
#include "proto.h"
#include "var.h"
#include "com.h"
#include "nat.h"
#include "sect.h"
#include "deity.h"
#include "file.h"
#include "proto.h"
#include "empio.h"
#include "empthread.h"
#include "tel.h"
#include "gen.h"
#include "subs.h"
#include "common.h"
#if !defined(_WIN32)
#include <unistd.h>
#include <sys/time.h>
#endif
#include <stdio.h>
#include <fcntl.h>
struct player *player;
extern int m_m_p_d;
void
player_main(struct player *p)
{
extern s_char *authfil;
struct natstr *natp;
int hour[2];
int secs;
s_char buf[128];
p->state = PS_PLAYING;
player = p;
time(&player->lasttime);
(void) time(&player->curup);
showvers(CLIENTPROTO);
show_motd();
if (init_nats() < 0)
return;
natp = getnatp(player->cnum);
if (player->god &&
!match_user(authfil, player)) {
logerror("NON-AUTHed Login attempted by %s",
praddr(player));
pr("You're not a deity!\n");
return;
}
if (!gamehours(player->curup, hour)) {
pr("Empire hours restriction in force\n");
if ((natp->nat_stat & STAT_GOD) == 0)
return;
}
daychange(player->curup);
if ((player->minleft = getminleft(player->curup, hour, &m_m_p_d)) <= 0){
pr("Time exceeded today\n");
return;
}
if ((*natp->nat_hostaddr &&
*player->hostaddr &&
strcmp(natp->nat_hostaddr, player->hostaddr)) ||
(*natp->nat_userid &&
*player->userid &&
strcmp(natp->nat_userid, player->userid))) {
if (natp->nat_stat != VIS) {
pr("Last connection from: %s", ctime(&natp->nat_last_login));
pr(" to: %s", natp->nat_last_login <
natp->nat_last_logout ? ctime(&natp->nat_last_logout):"?");
pr(" by: %s@%s\n",
*natp->nat_userid?natp->nat_userid : (s_char *)"nobody",
*natp->nat_hostname?natp->nat_hostname:
*natp->nat_hostaddr?natp->nat_hostaddr:(s_char *)"nowhere");
}
}
if (*player->userid)
strcpy(natp->nat_userid, player->userid);
else
strcpy(natp->nat_userid, "nobody");
if (*player->hostname)
strcpy(natp->nat_hostname, player->hostname);
else
strcpy(natp->nat_hostname, "nowhere");
if (*player->hostaddr)
strcpy(natp->nat_hostaddr, player->hostaddr);
time(&natp->nat_last_login);
natp->nat_connected = 1;
putnat(natp);
if (natp->nat_flags & NF_INFORM &&
natp->nat_tgms > 0) {
if (natp->nat_tgms == 1)
pr("You have a new telegram waiting ...\n");
else
pr("You have %s new telegrams waiting ...\n",
numstr(buf, natp->nat_tgms));
natp->nat_tgms = 0;
}
while (status()) {
if (command() == 0 && !player->aborted)
break;
player->aborted = 0;
}
/* #*# I put the following line in to prevent server crash -KHS */
natp = getnatp(player->cnum);
/*
* randomly round up to the nearest minute,
* charging at least 15 seconds.
*/
time(&natp->nat_last_logout);
secs = max(natp->nat_last_logout - player->lasttime, 15);
natp->nat_minused += secs / 60;
secs = secs % 60;
if (chance(secs / 60.0))
natp->nat_minused += 1;
natp->nat_connected = 0;
putnat(natp);
pr("Bye-bye\n");
}
int
command(void)
{
register unsigned int x;
s_char *redir;
int kill_player();
s_char scanspace[1024];
if (getcommand(player->combuf) < 0)
return 0;
if (parse(player->combuf, player->argp, &player->condarg,
scanspace, &redir) < 0) {
pr("See \"info Syntax\"?\n");
} else {
/* XXX don't use alarm; use a scavenger thread */
/* DONT USE IT!!!! alarm and sleep may and dont work
together -- Sasha */
/* alarm((unsigned int)60*60); 1 hour */
if (player->condarg != (s_char *)0)
for(x=0;x<strlen(player->condarg);x++)
if (isupper(*(player->condarg+x)))
*(player->condarg+x) = tolower(*(player->condarg+x));
if (dispatch(player->combuf, redir) < 0)
pr("Try \"list of commands\" or \"info\"\n");
}
return 1;
}
int
status(void)
{
struct natstr *natp;
int minute;
struct sctstr sect;
int hour[2];
s_char buf[128];
if (player->state == PS_SHUTDOWN)
return 0;
natp = getnatp(player->cnum);
if (io_error(player->iop) || io_eof(player->iop)) {
putnat(natp);
return 0;
}
player->visitor = (natp->nat_stat & (STAT_NORM|STAT_GOD)) == 0;
if (player->dolcost != 0.0) {
if (player->dolcost > 100.0)
pr("That just cost you $%.2f\n", player->dolcost);
else if (player->dolcost < -100.0)
pr("You just made $%.2f\n", -player->dolcost);
if (natp->nat_money < player->dolcost && !player->broke) {
player->broke = 1;
player->nstat &= ~MONEY;
pr("You are now broke; industries are on strike.\n");
} else if (player->broke && natp->nat_money - player->dolcost > 0) {
player->broke = 0;
player->nstat |= MONEY;
pr("You are no longer broke!\n");
}
natp->nat_money -= roundavg(player->dolcost);
player->dolcost = 0.0;
} else {
if (natp->nat_money < 0.0 && !player->broke) {
player->broke = 1;
player->nstat &= ~MONEY;
pr("You are now broke; industries are on strike.\n");
}
if (player->broke && natp->nat_money > 0) {
player->broke = 0;
player->nstat |= MONEY;
pr("You are no longer broke!\n");
}
}
getsect(natp->nat_xcap, natp->nat_ycap, &sect);
if ((sect.sct_type == SCT_CAPIT || sect.sct_type == SCT_MOUNT ||
sect.sct_type == SCT_SANCT) &&
sect.sct_own == player->cnum)
player->nstat |= CAP;
else
player->nstat &= ~CAP;
/* Ok, has the country owner reset his capital yet after it was sacked? */
if (natp->nat_flags & NF_SACKED)
player->nstat &= ~CAP; /* No capital yet */
player->ncomstat = player->nstat;
(void) time(&player->curup);
minute = (player->curup - player->lasttime) / 60;
if (minute > 0) {
player->minleft -= minute;
if (player->minleft <= 0) {
/*
* countdown timer "player->minleft" has expired.
* either day change, or hours restriction
*/
daychange(player->curup);
if (!gamehours(player->curup, hour)) {
pr("Empire hours restriction in force\n");
if ((natp->nat_stat & STAT_GOD) == 0) {
putnat(natp);
return 0;
}
}
player->minleft = getminleft(player->curup, hour, &m_m_p_d);
}
player->lasttime += minute * 60;
natp->nat_minused += minute;
}
if ((player->nstat & NORM) && natp->nat_minused > m_m_p_d) {
pr("Max minutes per day limit exceeded.\n");
player->ncomstat = VIS;
}
if (player->btused) {
natp->nat_btu -= player->btused;
player->btused = 0;
}
if (natp->nat_tgms > 0) {
if (!(natp->nat_flags & NF_INFORM)) {
if (natp->nat_tgms == 1)
pr("You have a new telegram waiting ...\n");
else
pr("You have %s new telegrams waiting ...\n",
numstr(buf, natp->nat_tgms));
natp->nat_tgms = 0;
}
}
if (natp->nat_ann > 0) {
if (natp->nat_ann == 1)
pr("You have a new announcement waiting ...\n");
else
pr("You have %s new announcements waiting ...\n",
numstr(buf, natp->nat_ann));
natp->nat_ann = 0;
}
if (!player->visitor && !player->god && (player->nstat & CAP) == 0)
pr("You lost your capital... better designate one\n");
putnat(natp);
if (gamedown() && !player->god) {
pr("gamedown\n");
return 0;
}
return 1;
}
/*
* actually a command; redirection and piping ignored.
* XXX This whole mess should be redone; execute block should
* start with "exec start", and should end with "exec end".
* We'll wait until 1.2 I guess.
*/
int
execute(void)
{
s_char buf[512];
int abort;
s_char *p;
s_char *redir;
s_char scanspace[1024];
abort = 0;
redir = 0;
p = getstarg (player->argp[1], "File? ", buf);
if (p == (s_char *) 0 || p == '\0')
return RET_SYN;
prexec(player->argp[1]);
while (!abort && status()) {
if (recvclient(buf, sizeof(buf)) < 0)
break;
if (parse(buf, player->argp, &player->condarg,
scanspace, &redir) < 0) {
abort = 1;
continue;
}
if (redir == 0)
pr("\nExecute : %s\n", buf);
if (dispatch(buf, redir) < 0)
abort = 1;
}
if (abort) {
while (recvclient(buf, sizeof(buf)) >= 0)
;
}
if (redir == 0)
pr("Execute : %s\n", abort ? "aborted" : "terminated");
return RET_OK;
}
int
show_motd(void)
{
extern s_char *upfil;
int upf;
struct telstr tgm;
s_char buf[MAXTELSIZE];
#if !defined(_WIN32)
if ((upf = open(upfil, O_RDONLY, 0)) < 0)
#else
if ((upf = open(upfil, O_RDONLY|O_BINARY, 0)) < 0)
#endif
return RET_FAIL;
if (read(upf, (s_char *) &tgm, sizeof(tgm)) != sizeof(tgm)) {
logerror("bad header on login message (upfil)");
close(upf);
return RET_FAIL;
}
if (read(upf, buf, tgm.tel_length) != tgm.tel_length) {
logerror("bad length %d on login message", tgm.tel_length);
close(upf);
return RET_FAIL;
}
if (tgm.tel_length >= (long)sizeof(buf))
tgm.tel_length = sizeof(buf)-1;
buf[tgm.tel_length] = 0;
pr(buf);
(void) close(upf);
return RET_OK;
}
int match_user(char *file, struct player *player)
{
FILE *fp;
int match = 0;
s_char host[256];
s_char user[256];
if ((fp = fopen(file, "r")) == NULL) {
/*logerror("Cannot find file %s", file);*/
return 0;
}
match = 0;
while (!feof(fp) && !match) {
if (fgets(host, sizeof(host)-1, fp) == NULL)
break;
if (host[0] == '#') continue;
if (fgets(user, sizeof(user)-1, fp) == NULL)
break;
host[strlen(host)-1] = '\0';
user[strlen(user)-1] = '\0';
if (strstr(player->userid, user) &&
(strstr(player->hostaddr, host) ||
strstr(player->hostname, host)))
++match;
}
fclose(fp);
return match;
}
int
quit(void)
{
player->state = PS_SHUTDOWN;
return RET_OK;
}
s_char *
praddr(struct player *player)
{
return prbuf("%s@%s", player->userid,
*player->hostname?player->hostname:player->hostaddr);
}

View file

@ -0,0 +1,72 @@
/*
* 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.
*
* ---
*
* recvclient.c: Send and receive commands from the client
*
* Known contributors to this file:
* Dave Pare, 1986
*/
#include "prototypes.h"
#include <stdio.h>
#include "misc.h"
#include "bit.h"
#include "empio.h"
#include "player.h"
#include "empthread.h"
#include <errno.h>
int
recvclient(s_char *cmd, int size)
{
extern int errno;
int count;
if (player->aborted)
return -2;
count = io_gets(player->iop, cmd, size);
while (!player->aborted && count < 0) {
io_output_all(player->iop);
io_input(player->iop, IO_WAIT);
if (io_error(player->iop))
player->aborted++;
else if (io_eof(player->iop))
return -1;
else
count = io_gets(player->iop, cmd, size);
}
if (count > 0) {
if (strcmp(cmd, "ctld") == 0)
return -1;
if (strcmp(cmd, "aborted") == 0)
player->aborted = 1;
}
if (player->aborted)
return -2;
return count;
}