|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 18229 (0x4735) Types: TextFile Names: »subdaemon.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/X/Xtrek/subdaemon.c«
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; }