DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T s

⟦da10988fa⟧ TextFile

    Length: 18229 (0x4735)
    Types: TextFile
    Names: »subdaemon.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/X/Xtrek/subdaemon.c« 

TextFile

static char sccsid[] = "@(#)subdaemon.c	1.1";
#ifndef lint
static char *rcsid_daemon_c = "$Header: /uraid2/riedl/src/xceltrek/RCS/subdaemon.c,v 1.1 88/04/18 16:10:46 riedl Exp Locker: riedl $";
#endif	lint
/* Copyright (c) 1986 	Chris Guthrie */

#include <X11/Xlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <setjmp.h>
#include "defs.h"
#include "data.h"
extern long isin[], icos[];
#include "planets.h"

#define fuse(X) ((udcounter % (X)) == 0)
/* Run the game */

double sqrt();
double pow();
double hypot();

static int debug = 0;
static int plfd;

/*
 * subdaemon - allocate memory and initialize subdaemon
 */
subdaemon()
{
    register int i;
    int move();
    int reaper();

    for (i = 0; i < MAXPLAYER; i++)
	players[i].p_status = PFREE;

    plfd = open(PLFILE, O_RDWR, 0777);
    if (plfd < 0) {
	fprintf(stderr, "No planet file.  Restarting galaxy\n");
	bcopy(pdata, planets, sizeof(pdata));
    }
    else {
	if (read(plfd, planets, sizeof(pdata)) != sizeof(pdata)) {
	    fprintf(stderr, "Planet file wrong size.  Restarting galaxy\n");
	    bcopy(pdata, planets, sizeof(pdata));
	    for (i = 0; i < 40; i++) {
		if (planets[i].pl_flags & PLHOME)
		    planets[i].pl_flags |= (PLREPAIR|PLFUEL);
		if (random() % 4 == 0)
		    planets[i].pl_flags |= PLREPAIR;
		if (random() % 2 == 0)
		    planets[i].pl_flags |= PLFUEL;
	    }
	}
    }

    status->active = 0;
}

#ifdef notdef
exitgame(p, status)
struct player	*p;
int status;
{
  if (!copilot) savestats(p);
  exit(status);
}
#endif

save_planets() {
  if (plfd > 0) {
    lseek(plfd, 0, 0);
    write(plfd, planets, sizeof(pdata));
  }
}

/* These specify how often special actions will take place in
   UPDATE units (0.20 seconds, currently.)
*/

#define PLAYERFUSE	1
#define TORPFUSE	1
#define PHASERFUSE	1
#define TEAMFUSE	3
#define PLFIGHTFUSE	2
#define BEAMFUSE	5
#define PLANETFUSE	301
#define REFRESHFUSE	1
#define ROBOTFUSE	1

move()
{
	register int		i;
	register struct player	*p;

	for (i = 0, p = &players[0]; i < MAXPLAYER; i++, p++) {
		if (fuse(PLAYERFUSE) && (p->p_status != PFREE)) {
			udplayer(p);
		}
		if (fuse(BEAMFUSE) && (p->p_status == PALIVE)) {
			beam(p);
		}
	}

	/* Per tick things...one time for all players */
	if (fuse(TORPFUSE)) {
		udtorps();
	}
	if (fuse(PHASERFUSE)) {
		udphaser();
	}
	if (fuse(TEAMFUSE)) {
		teamtimers();
	}
	if (fuse(PLFIGHTFUSE)) {
		plfight();	/* Planet fire */
	}
	if (fuse(PLANETFUSE)) {
		udplanets();
	}

	/* Remaining player things... */
	for (i = 0, p = &players[0]; i < MAXPLAYER; i++, p++) {
		if (fuse(ROBOTFUSE) &&
		    (p->p_status == PALIVE) &&
		    (p->p_flags & PFROBOT)) {
			udrobot(p);
		}
		if (fuse(REFRESHFUSE) &&
		    (p->p_status == PALIVE || p->p_status == PEXPLODE) &&
		    (p->p_flags & PFROBOT) == 0) {
			redraw(p);
		}
	}
}

udplayer(j)
register struct player *j;
{
    tcount[FED] = tcount[ROM] = tcount[KLI] = tcount[ORI] = 0;
	auto_features(j);
      switch (j->p_status) {
      case PDEAD:
	if (--j->p_explode <= 0 && j->p_ntorp <= 0) {
	  j->p_status = PFREE;

	    XSync(j->display, 1);
	    j->redrawall = 1;
	}
	break;
      case PEXPLODE:
	j->p_updates++;
	j->p_flags &= ~PFCLOAK;
	if (j->p_explode == PEXPTIME)
	  blowup(j);		/* damage everyone else around */
	if (--j->p_explode <= 0) {
		if (j->p_stats.st_maxkills < j->p_kills)
			j->p_stats.st_maxkills = j->p_kills;
		j->p_stats.st_kills += j->p_kills;
		death(j);
	}
	break;
      case PALIVE:
#ifdef notdef
	status->active += (1<<i);
#endif
	tcount[j->p_team]++;
	j->p_updates++;

	/* cool weapons */
	cool_weapons(j);

	/* cool engine */
	cool_engines(j);

	/* Add fuel */
	add_fuel(j);

	/* repair shields */
	repair_shields(j);

	/* repair damage */
	repair_damage(j);

	/* Charge for cloaking */
	cloak_charge(j);

	/* Move Player in orbit */
	player_orbit(j);

	/* Move player through space */
	space_move(j);

	/* Set player's alert status */
	adjust_alert(j);
	break;
      }				/* end switch */
}

udtorps()
{
    register int i;
    register struct torp *j;

    for (i = 0, j = &torps[i]; i < MAXPLAYER * MAXTORP; i++, j++) {
	switch (j->t_status) {
	    case TFREE:
		continue;
	    case TMOVE:
	    case TSTRAIGHT:
		j->t_x += (j->t_speed * icos[j->t_dir] * WARP1) >> TRIGSCALE;
		if (j->t_x < 0) {
		    j->t_x = 0;
		    explode(j);
		    break;
		}
		else if (j->t_x > GWIDTH) {
		    j->t_x = GWIDTH;
		    explode(j);
		    break;
		}
		j->t_y += (j->t_speed * isin[j->t_dir] * WARP1) >> TRIGSCALE;
		if (j->t_y < 0) {
		    j->t_y = 0;
		    explode(j);
		    break;
		}
		else if (j->t_y > GWIDTH) {
		    j->t_y = GWIDTH;
		    explode(j);
		    break;
		}

		/* Make sure that player torps wobble */
		if (j->t_status == TMOVE)
		    j->t_dir += (random() % 3) - 1;

		if (near(j) || (j->t_fuse-- <= 0)) {
 		    explode(j);
		}
		break;
	    case TDET:
		j->t_x += (j->t_speed * icos[j->t_dir] * WARP1) >> TRIGSCALE;
		if (j->t_x < 0)
		    j->t_x += GWIDTH;
		else if (j->t_x > GWIDTH)
		    j->t_x -= GWIDTH;
		j->t_y += (j->t_speed * isin[j->t_dir] * WARP1) >> TRIGSCALE;
		if (j->t_y < 0)
		    j->t_y += GWIDTH;
		else if (j->t_y > GWIDTH)
		    j->t_y -= GWIDTH;
		explode(j);
		break;
	    case TEXPLODE:
		if (j->t_fuse-- <= 0) {
		    j->t_status = TFREE;
		    players[j->t_owner].p_ntorp--;
		}
		break;
	    case TOFF:
		j->t_status = TFREE;
		players[j->t_owner].p_ntorp--;
		break;
	}
    }
}

/* See if there is someone close enough to explode for */
near(torp)
struct torp *torp;
{
    register int i;
    int dx, dy;
    register struct player *j;

    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
       if (!(j->p_status == PALIVE))
	  continue;
       if (torp->t_owner == j->p_no)
	  continue;
       if ((!(torp->t_war & j->p_team)) &&
	   (!(torp->t_team & (j->p_swar | j->p_hostile))))
	  continue;
       dx = torp->t_x - j->p_x;
       dy = torp->t_y - j->p_y;
       if (ABS(dx) > EXPDIST || ABS(dy) > EXPDIST)
	  continue;
       if (dx * dx + dy * dy < EXPDIST * EXPDIST)
	  return 1;
    }
    return 0;
}

    

/* Do damage to all surrounding players */

explode(torp)
struct torp *torp;
{
    register int i;
    int dx, dy, dist;
    int damage;
    register struct player *j;

    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
	if (!(j->p_status == PALIVE))
	    continue;
	if (torp->t_owner == j->p_no)
	    continue;
	dx = torp->t_x - j->p_x;
	dy = torp->t_y - j->p_y;
	if (ABS(dx) > TDAMDIST || ABS(dy) > TDAMDIST)
	    continue;
	dist = dx * dx + dy * dy;
	if (dist > TDAMDIST * TDAMDIST)
	    continue;
	if (dist > EXPDIST * EXPDIST) {
	    damage = torp->t_damage * (TDAMDIST - sqrt((double) dist)) /
		(TDAMDIST - EXPDIST);
	}
	else {
	    damage = torp->t_damage;
	}
	if (damage > 0) {
	    /* First, check to see if torp owner has started a war */
	    if (players[torp->t_owner].p_hostile & j->p_team) {
		players[torp->t_owner].p_swar |= j->p_team;
	    }
	    /* Note that if a player is at peace with the victim, then
	       the torp has caused damage either accidently, or because
	       the victim was at war with, or hostile to, the player.
	       In either case, we don't consider the damage to be
	       an act of war. */

	    if (j->p_flags & PFSHIELD) {
		j->p_shield -= damage;
		if (j->p_shield < 0) {
		    j->p_damage -= j->p_shield;
		    j->p_shield = 0;
		}
	    }
	    else {
		j->p_damage += damage;
	    }
	    if (j->p_damage >= 100) {
		j->p_status = PEXPLODE;
		j->p_explode = PEXPTIME;
		/* no points for killing yourself! */
		if (torp->t_owner != j->p_no)
		  players[torp->t_owner].p_kills += 1.0
			+ j->p_armies * 0.1 + j->p_kills * 0.1;
		killmess(j, &players[torp->t_owner]);
		j->p_stats.st_losses++;
		j->p_whydead = KTORP;
		j->p_whodead = torp->t_owner;
	    }
	}
    }
    torp->t_status = TEXPLODE;
    torp->t_fuse = TEXPTIME;
}

udplanets()
{
    register int i;
    register struct planet *l;

    for (i = 0, l = &planets[i]; i < MAXPLANETS; i++, l++) {
	if (l->pl_armies == 0)
	    continue;
	if ((random() % 3000) < l->pl_armies)
	    l->pl_armies -= (random() % l->pl_armies);
	if ((l->pl_armies < 4) && ((random() % 20) == 0)) {
	    l->pl_armies++;
	    continue;
	}
	if ((random() % 10) == 0)
	    l->pl_armies += (random() % 3) + 1;
	    
    }
}

udphaser()
{
    register int i;
    register struct phaser *j;
    register struct player *victim;

    for (i = 0, j = &phasers[i]; i < MAXPLAYER; i++, j++) {
	switch (j->ph_status) {
	    case PHFREE:
		continue;
	    case PHMISS:
		if (j->ph_fuse-- == 1)
		    j->ph_status = PHFREE;
		break;
	    case PHHIT:
		if (j->ph_fuse-- == PFIRETIME) {
		    victim = &players[j->ph_target];
		    /* the victim may have been killed by a torp already */
		    if (victim->p_status != PALIVE) continue;

		    if (victim->p_flags & PFSHIELD) {
			victim->p_shield -= j->ph_damage;
			if (victim->p_shield < 0) {
			    victim->p_damage -= victim->p_shield;
			    victim->p_shield = 0;
			}
		    }
		    else {
			victim->p_damage += j->ph_damage;
		    }
		    if (victim->p_damage >= 100) {
			victim->p_status = PEXPLODE;
			victim->p_explode = PEXPTIME;
			players[i].p_kills += 1.0
			    + victim->p_armies * 0.1 + victim->p_kills * 0.1;
			killmess(victim, &players[i]);
			victim->p_stats.st_losses++;
			victim->p_whydead = KPHASER;
			victim->p_whodead = i;
		    }
		}
		if (j->ph_fuse == 0)
		    j->ph_status = PHFREE;
		break;
	}
    }
}

int pl_warning[MAXPLANETS];	/* To keep planets shut up for awhile */
int tm_robots[MAXTEAM + 1];		/* To limit the number of robots */
int tm_coup[MAXTEAM + 1];		/* To allow a coup */

teamtimers()
{
    register int i;
    for (i = 0; i <= MAXTEAM; i++) {
	if (tm_robots[i] > 0)
	    tm_robots[i]--;
	if (tm_coup[i] > 0)
	    tm_coup[i]--;
    }
}

plfight()
{
    register int h, i;
    register struct player *j;
    register struct planet *l;
    int dx, dy;
    int damage;
    int dist;
    int rnd;
    char buf[80];
    char buf1[80];

    for (h = 0, l = &planets[h]; h < MAXPLANETS; h++, l++) {
	if (l->pl_flags & PLCOUP) {
	    l->pl_flags &= ~PLCOUP;
	    l->pl_owner = (l->pl_flags & ALLTEAM);
	}
	l->pl_flags &= ~PLREDRAW;
	if (pl_warning[h] > 0)
	    pl_warning[h]--;
	for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
	    switch (j->p_status) {
		case PFREE:
		case PDEAD:
		case PEXPLODE:
		    continue;
		case PALIVE:
		    /* Do damage by planets */
			dx = ABS(l->pl_x - j->p_x);
			dy = ABS(l->pl_y - j->p_y);
			if (dx < 3 * PFIREDIST && dy < 3 * PFIREDIST)
			    l->pl_flags |= PLREDRAW;
			if (dx > PFIREDIST || dy > PFIREDIST)	/*XXX*/
			    continue;
			dist = (int) hypot((double) dx, (double) dy);
			if (dist > PFIREDIST)
			    continue;
		    if ((j->p_swar | j->p_hostile) & l->pl_owner) {
			if (l->pl_armies > 0)
			    damage = l->pl_armies / 10 + 2;
			else
			    damage = 0;
			if (damage > 0) {
			    if (j->p_flags & PFSHIELD) {
				j->p_shield -= damage;
				if (j->p_shield < 0) {
				    j->p_damage -= j->p_shield;
				    j->p_shield = 0;
				}
			    }
			    else {
				j->p_damage += damage;
			    }
			    if (j->p_damage >= 100) {
			    j->p_explode = PEXPTIME;
			    j->p_status = PEXPLODE;
			    j->p_stats.st_losses++;
			    sprintf(buf, "%s (%c%x) killed by %s (%c)",
				j->p_name,
				teamlet[j->p_team],
				j->p_no,
				l->pl_name,
				teamlet[l->pl_owner]);
			    pmessage(buf, 0, MALL, "GOD->ALL");
			    j->p_whydead = KPLANET;
			    j->p_whodead = h;
			    }
			}
		    }
		    /* do bombing */
		    if ((!(j->p_flags & PFORBIT)) || (!(j->p_flags & PFBOMB)))
			continue;
		    if (j->p_planet != l->pl_no)
			continue;
		    if (!((j->p_swar | j->p_hostile) & l->pl_owner))
			continue;
		    if (l->pl_armies < 5)
			continue;

			/* Warn owning team */
		    if (pl_warning[h] <= 0) {
			pl_warning[h] = 50/PLFIGHTFUSE; 
			sprintf(buf, "We are under attack.  Please send aid");
			sprintf(buf1, "%-3s->%-3s",
			    l->pl_name, teamshort[l->pl_owner]);
			pmessage(buf, l->pl_owner, MTEAM, buf1);
		    }

		    rnd = random() % 100;
		    if (rnd < 50) {
			continue;
		    }
		    else if (rnd < 80) {
			l->pl_armies -= 1;
			j->p_kills += 0.02;
			j->p_stats.st_armsbomb++;
		    }
		    else if (rnd < 90) {
			l->pl_armies -= 2;
			j->p_kills += 0.04;
			j->p_stats.st_armsbomb += 2;
		    }
		    else  {
			l->pl_armies -= 3;
			j->p_kills += 0.06;
			j->p_stats.st_armsbomb += 3;
		    }

		    /* Send in a robot if there are no other defenders 
			and the planet is in the team's home space */

		    if ((tcount[l->pl_owner] == 0) && 
			(l->pl_flags & l->pl_owner) &&
			    tm_robots[l->pl_owner] == 0) {
				startrobot(l->pl_owner, PFRSTICKY | PFRHARD);
	
			tm_robots[l->pl_owner] = (60 + 
				    (random() % 60)) /
				    TEAMFUSE;
		    }

	    }
	}
    }
}

/* udrobot - Check if any of the robots in the player list deserve
 * their chance to execute this tick.  Note that hard robots 
 * get to recalculate more often.  In order not to kill the game
 * they only recalculate every other call; the other times they just
 * fire an additional torp.
 */
udrobot(j)
register struct player *j;
{
	if (j->p_flags & PFRHARD) { /* hard robots recalculate more often */
	    if (udcounter % 2 == j->p_no % 2) rmove(j);
	} else {
	    if (udcounter % 10 == j->p_no % 10) rmove(j);
	}
}

beam(j)
register struct player *j;
{
    register int h, i;
    register struct planet *l;
    char buf[80];

	/* do beaming */
	if (!(j->p_flags & PFORBIT))
		return;

      for (h = 0, l = &planets[h]; h < MAXPLANETS; h++, l++) {
		    if (j->p_planet != l->pl_no)
			continue;
		    if (j->p_flags & PFBEAMUP) {
			if (l->pl_armies < 5)
			    continue;
			if (j->p_armies == j->p_ship.s_maxarmies)
			    continue;
			/* XXX */
			if (j->p_armies == floor(j->p_kills * 2.0))
			    continue;
			if (j->p_team != l->pl_owner)
			    continue;
			j->p_armies++;
			l->pl_armies--;
		    }
		    if (j->p_flags & PFBEAMDOWN) {
			if (j->p_armies == 0)
			    continue;
			if (j->p_team != l->pl_owner) {
			    j->p_armies--;
			    if (l->pl_armies) {
				l->pl_armies--;
				j->p_kills += 0.02;
				j->p_stats.st_armsbomb++;
			    }
			    else { 	/* planet taken over */
				l->pl_armies++;
				l->pl_owner = j->p_team;
				j->p_stats.st_planets++;
				j->p_kills += 0.25;
				checkwin(j);
				sprintf(buf, "%s taken over by %s (%c%x)",
				    l->pl_name,
				    j->p_name,
				    teamlet[j->p_team],
				    j->p_no);
				pmessage(buf, 0, MALL, "GOD->ALL");
			    }
			}
			else {
			    j->p_armies--;
			    l->pl_armies++;
			}
		    }

	}
}

blowup(sh)
struct player *sh;
{
    register int i;
    int dx, dy, dist;
    int damage;
    register struct player *j;

    for (i = 0, j = &players[i]; i < MAXPLAYER; i++, j++) {
	if (j->p_status == PFREE || j->p_status == PDEAD || j->p_status == PEXPLODE)
	    continue;
	if (sh == j)
	    continue;
	dx = sh->p_x - j->p_x;
	dy = sh->p_y - j->p_y;
	if (ABS(dx) > TDAMDIST || ABS(dy) > TDAMDIST)
	    continue;
	dist = dx * dx + dy * dy;
	if (dist > TDAMDIST * TDAMDIST)
	    continue;
	if (dist > EXPDIST * EXPDIST) {
	    damage = 100 * (TDAMDIST - sqrt((double) dist)) /
		(TDAMDIST - EXPDIST);
	}
	else {
	    damage = 100;
	}
	if (damage > 0) {
	    if (j->p_flags & PFSHIELD) {
		j->p_shield -= damage;
		if (j->p_shield < 0) {
		    j->p_damage -= j->p_shield;
		    j->p_shield = 0;
		}
	    }
	    else {
		j->p_damage += damage;
	    }
	    if (j->p_damage >= 100) {
		j->p_status = PEXPLODE;
		j->p_explode = PEXPTIME;
		sh->p_kills += 1.0 + j->p_armies * 0.1 + j->p_kills * 0.1;
		killmess(j, sh);
		j->p_stats.st_losses++;
		j->p_whydead = KSHIP;
		j->p_whodead = sh->p_no;
	    }
	}
    }
}

/* This function is called when a planet has been taken over.
   It checks all the planets to see if the victory conditions
   are right.  If so, it blows everyone out of the game and
   resets the galaxy
*/
checkwin(winner)
struct player *winner;
{
    register int i, h;
    register struct planet *l;
    register struct player *j;
    int team[MAXTEAM + 1];

    for (i = 0; i < 4; i++)
	team[1<<i] = 0;
    
    for (i = 0, l = &planets[i]; i < MAXPLANETS; i++, l++)
	team[l->pl_owner]++;

    for (i = 0; i < 4; i++) {
	if (team[1<<i] == MAXPLANETS) {
	    /* We have a winning team */
	    for (h = 0, j = &players[0]; h < MAXPLAYER; h++, j++) {
		j->p_status = PDEAD;
		j->p_whydead = KWINNER;
		j->p_whodead = winner->p_no;
		j->p_ntorp = 0;
		j->p_team = (FED|ROM|KLI|ORI);	/* Allow them to repick any team */
	    }
	    winner->p_stats.st_conqs++;
	    bcopy(pdata, planets, sizeof(pdata));
	    for (i = 0; i < 40; i++) {
		if (random() % 4 == 0)
		    planets[i].pl_flags |= PLREPAIR;
		if (random() % 2 == 0)
		    planets[i].pl_flags |= PLFUEL;
	    }
	    save_planets();
	}
    }
}

killmess(victim, killer)
struct player *victim, *killer;
{
    char buf[80];

    sprintf(buf, "%s (%c%x) was kill %0.2f for %s (%c%x)",
	victim->p_name,
	teamlet[victim->p_team],
	victim->p_no,
	killer->p_kills,
	killer->p_name,
	teamlet[killer->p_team],
	killer->p_no);
	pmessage(buf, 0, MALL, "GOD->ALL");
}

dumpmessages()
{
    register int i;
    register struct message *j;

    for (i = 0, j = &messages[0]; i < MAXMESSAGE; i++, j++)
	if (j->m_flags & MVALID)
	    printf("%d, %s\n", i, j->m_data);
}

startrobot(team, flags)
int team;
int flags;
{
    register struct player	*p;
    int rpno, tno;
    extern char *rnames[4];

    if ((rpno = findslot()) >= MAXPLAYER) return;
    switch (team) {
    case FED: tno = 0; break;
    case ROM: tno = 1; break;
    case KLI: tno = 2; break;
    case ORI: tno = 3; break;
    }
    p = &players[rpno];
    enter(tno, "Nowhere", rpno);
    p->p_status = PALIVE;
    p->p_flags |= PFROBOT | PFCOPILOT;		/* Mark as a robot */
    strncpy(p->p_login, "Robot", strlen("Robot"));
    p->p_login[strlen("Robot")] = NULL;
    strncpy(p->p_name, rnames[tno], strlen(rnames[tno]));
    p->p_name[strlen(rnames[tno])] = NULL;
    p->p_ship.s_phasercost = 0;
    p->p_ship.s_torpcost = 0;
    /* Set robot difficulty */
    p->p_flags |= flags;
    if (p->p_flags & PFRHOSTILE)
	p->p_hostile |= team;
}