Mercurial > ~darius > hgwebdir.cgi > paradise_server
diff src/conquer.c @ 2:2719a89505ba
First entry of Paradise Server 2.9 patch 10 Beta
author | darius |
---|---|
date | Sat, 06 Dec 1997 04:37:01 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/conquer.c Sat Dec 06 04:37:01 1997 +0000 @@ -0,0 +1,578 @@ +/*-------------------------------------------------------------------------- +NETREK II -- Paradise + +Permission to use, copy, modify, and distribute this software and its +documentation, or any derivative works thereof, for any NON-COMMERCIAL +purpose and without fee is hereby granted, provided that this copyright +notice appear in all copies. No representations are made about the +suitability of this software for any purpose. This software is provided +"as is" without express or implied warranty. + + Xtrek Copyright 1986 Chris Guthrie + Netrek (Xtrek II) Copyright 1989 Kevin P. Smith + Scott Silvey + Paradise II (Netrek II) Copyright 1993 Larry Denys + Kurt Olsen + Brandon Gillespie +--------------------------------------------------------------------------*/ + + +#include "config.h" +#include <sys/time.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <setjmp.h> +#include <time.h> + +#include "defs.h" +#include "struct.h" +#include "data.h" +#include "daemonII.h" +#include "misc.h" +#include "shmem.h" +#include "path.h" + + + +/*----------------------------NUMBER DEFINES-------------------------------*/ +#define SURRSTART 4 /* # planets where surrender starts */ +#define SURREND 7 /* # planets where surrender stops */ +#define SURRLENGTH 25 /* give them 30 minutes to sustain empire */ +/*-------------------------------------------------------------------------*/ + + + + + + +/*----------------------------MODULE VARIABLES-----------------------------*/ + +/* used to store players found with the displayBest function */ +typedef struct playerlist +{ + char name[16]; /* player's name */ + char mapchars[2]; /* player's map window image */ + int planets, armies; /* planets taken and armies bombed */ + int resources, dooshes; /* resources bombed and armies dooshed */ +} Players; + +/*-------------------------------------------------------------------------*/ + + + + + + +extern int enemy_admiral(); +extern void perror(); +extern void cause_kaboom(); +extern void gen_planets(); +extern void endtourn(); +extern void stoptimer(); +extern char *twoletters(); +void checkwin(); +void displayBest(); + +static void +swap(a, b) + int *a, *b; +{ + int t = *a; + *a = *b; + *b = t; +} + + +/*----------------------------INTERNAL FUNCTIONS---------------------------*/ + +/*-----------------------------------GENOCIDE------------------------------*/ +/* + * This function checks for a genocide. It also returns the two teams with + * the most players. It first goes through the four teams and finds the two + * teams with the greatest number of players. These two teams are returned + * in the parameters team1 and team2. If one of the teams does not have at + * least one planet then a 1 is returned. Otherwise a zero is returned. + */ + +int +genocide(team1, team2) + int *team1; /* where to put first team */ + int *team2; /* where to put second team */ +{ + int t1, t2; /* to hold two teams */ + int n1, n2; /* to hold number of ships on teams */ + int t; /* temp var */ + int i; /* looping var */ + + t1 = FED; /* set first team */ + n1 = realNumShips(FED); /* get players on it */ + t2 = ROM; /* set second team */ + n2 = realNumShips(ROM); /* get players on it */ + if (n1 < n2) + { /* place team with least players in t2 */ + swap(&n1, &n2); + swap(&t1, &t2); + } + if (realNumShips(KLI) > n2) + { /* check the klingons */ + t2 = KLI; + n2 = realNumShips(KLI); + } + if (n1 < n2) + { /* place team with least players in t2 */ + swap(&n1, &n2); + swap(&t1, &t2); + } + if (realNumShips(ORI) > n2) + { /* check the orions */ + t2 = ORI; + n2 = realNumShips(ORI); + } + /* no longer necessarily in order */ + *team1 = t1; /* pass back team 1 */ + *team2 = t2; /* pass back team 2 */ + t = 0; /* no genocide detected yet */ + for (i = 0; i < NUMPLANETS; i++) + { /* see if team 1 has a planet */ + if (planets[i].pl_owner == t1) + { /* do they own this */ + t++; /* inc t andd then get out of loop */ + break; + } + } + for (i = 0; i < NUMPLANETS; i++) + { /* see if team 2 has a planet */ + if (planets[i].pl_owner == t2) + { /* do they own this */ + t++; /* inc t andd then get out of loop */ + break; + } + } + if (t != 2) /* if both teams do not have planets then */ + return (1); /* return that genocide has occured */ + else /* else genocide has not occured */ + return (0); +} + + + + +/*------------------------------CHECKSURRENDER-----------------------------*/ +/* + * This function is called when a teams surrender status may have changed. It + * takes a team and uses the s_plcount in the teams structure to check + * whether a team has prevented surrender or the surrender process should + * begin. + */ + +void +checksurrender(team, otherplanets) + int team; /* the team to check */ + int otherplanets; +{ + char buf[80]; /* to sprintf into */ + + if ((teams[team].s_surrender > 0) && /* surrender timer running? */ + ((teams[team].s_plcount >= SURREND) || + (teams[team].s_plcount * 2 > otherplanets))) + { /* and enough planets */ + pmessage("", 0, MALL, ""); + sprintf(buf, "The %s %s prevented collapse of the empire.", + teams[team].name, teamVerbage[team]); + pmessage(buf, 0, MALL, MSERVA); /* message to all */ + pmessage("", 0, MALL, ""); + teams[team].s_surrender = 0;/* stop surrender clock */ + } + else if ((teams[team].s_surrender == 0) && /* start surrender ? */ + (teams[team].s_plcount <= SURRSTART) && + (teams[team].s_plcount * 2 <= otherplanets) && + (realNumShips(team) >= configvals->tournplayers) && + (teams[team].s_plcount < teams[team].s_plcountold)) + { + teams[team].s_surrender = SURRLENGTH; + sprintf(buf, "The %s %s %d minutes before the empire collapses.", + teams[team].name, teamVerbage[team], SURRLENGTH); + pmessage("", 0, MALL, ""); + pmessage(buf, 0, MALL, MSERVA); + sprintf(buf, "%d planets are needed to sustain the empire.", + SURREND); + pmessage(buf, 0, MALL, MSERVA); + pmessage("", 0, MALL, ""); + } +} + +/*-------------------------------------------------------------------------*/ + + + + + + + +/*------------------------------VISIBLE PROCEDURES-------------------------*/ + +/*---------------------------------UDSURRENDER-----------------------------*/ +/* + * This function updates the surender stuff. There is also stuff for + * updating the ship construction timers here. + */ + +void +udsurrend() +{ + register int i, t; /* looping vars */ + char buf[80]; + struct planet *l; + struct player *j; + + /* TC's termination of players not on a t-mode team */ + for (i = 0, j = &players[0]; i < MAXPLAYER; i++, j++) + { + if ((j->p_status == PALIVE) && + !(j->p_flags & PFROBOT) && (j->p_team != NOBODY) && + (realNumShips(j->p_team) < configvals->tournplayers) && + (lrand48() % 5 == 0)) + rescue(TERMINATOR, j->p_no, -1); + } + for (t = 0; t <= MAXTEAM; t++) + { /* go through all teams */ + if ((teams[t].s_surrender == 0) || + (realNumShips(t) < configvals->tournplayers)) + continue; /* suspend if no t-mode */ + if (teams[t].s_plcount > SURRSTART) /* suspend timer if they have */ + continue; /* enough planets */ + teams[t].s_surrender--; /* dec the surrender timer */ + if (teams[t].s_surrender <= 0) + { /* if timer ran out then */ + teams[t].s_surrender = -1;/* set it so it isnt 0 (otherwise it + * announces surrender again) (BG) */ + sprintf(buf, "The %s %s surrendered.", teams[t].name, + teamVerbage[t]); /* print surrender message */ + pmessage("", 0, MALL, ""); + pmessage(buf, 0, MALL, MSERVA); + pmessage("", 0, MALL, ""); + for (i = 0, l = &planets[i]; i < NUMPLANETS; i++, l++) + { + if (l->pl_owner == t) + { /* neutralize and zero the */ + l->pl_owner = NOBODY; /* armies on all loser's planets */ + l->pl_armies = 0; + } + } + checkwin(enemy_admiral(t)); /* go check the win */ + } + else if ((teams[t].s_surrender % 5) == 0 || + (teams[t].s_surrender < 4)) + { + sprintf(buf, "The %s %s %d minutes remaining.", + teams[t].name, teamVerbage[t], teams[t].s_surrender); + pmessage("", 0, MALL, "");/* blank line */ + pmessage(buf, 0, MALL, MSERVA); /* printf counting down */ + sprintf(buf, "%d planets will sustain the empire. ", SURREND); + pmessage(buf, 0, MALL, MSERVA); + sprintf(buf, "%d or half enemy suspends countdown.", SURRSTART + 1); + pmessage(buf, 0, MALL, MSERVA); + pmessage("", 0, MALL, "");/* blank line */ + } + } /* end for team */ +} + + +/*------------------------------CONQUERMESSAGE-----------------------------*/ +/* + * This function is called after a race is genocided. It lists the players + * on the winning and losing teams. The reason should be either GENOCIDE or + * SURRENDER. The list is written to the conquer file. + */ + +void +conquerMessage(winners, losers, pno) + int winners; + int losers; + int pno; +/* the losing and winning teams */ +/* the person who won it */ +{ + char buf[80]; /* to sprintf into */ + FILE *conqfile; /* to open conquer file */ + time_t curtime; /* to get current time */ + char *paths; /* to hold path to directory */ + + paths = build_path(CONQFILE); + conqfile = fopen(paths, "a"); /* open the conquer file */ + if (!conqfile) + { + perror(""); + fprintf(stderr, "failed to open file %s\n", paths); + } +#ifdef LEAGUE_SUPPORT +#define OUT pmessage(buf, 0, MALL | MGENO, " "); \ + if (conqfile) fprintf(conqfile, " %s\n", buf); \ + tlog_conquerline(buf); +#else +#define OUT pmessage(buf, 0, MALL | MGENO, " "); \ + if (conqfile) fprintf(conqfile, " %s\n", buf); +#endif + + time(&curtime); /* get current time */ + strcpy(buf, "\nConquer! "); /* this is a genocide */ + strcat(buf, ctime(&curtime)); /* cat on current time */ + if (conqfile) + fprintf(conqfile, " %s\n", buf); /* write it to conquer file */ + pmessage("***********************************************************", + 0, MALL | MGENO, " "); /* print enclosure to messages */ + + if (pno >= 0) + { + sprintf(buf, "The galaxy has been conquered by %s and the %s!!!!", + players[pno].p_name, teams[winners].name); + } + else + { + sprintf(buf, "Stalemate."); + } + OUT; + + sprintf(buf, +#ifdef LEAGUE_SUPPORT + status2->league ? "The %s(%s):" : +#endif + "The %s:", + teams[winners].name +#ifdef LEAGUE_SUPPORT + ,((winners == (1 << status2->home.index)) ? + (&status2->home) : + (&status2->away))->name +#endif + ); + OUT; + displayBest(conqfile, winners); /* go display team 1 */ + sprintf(buf, +#ifdef LEAGUE_SUPPORT + status2->league ? "The %s(%s):" : +#endif + "The %s:", + teams[losers].name +#ifdef LEAGUE_SUPPORT + ,((losers == (1 << status2->home.index)) ? + (&status2->home) : + (&status2->away))->name +#endif + ); + OUT; + displayBest(conqfile, losers);/* go display team 2 */ + pmessage("***********************************************************", + 0, MALL | MGENO, " "); /* printf the enclosure */ + if (conqfile) + { + fprintf(conqfile, "\n"); /* space between conquering */ + fclose(conqfile); /* close conquer file */ + } +} + + +void +refresh_team_planetcounts() +{ + int i; + register struct planet *l; /* to point to planets */ + + for (i = 0; i <= MAXTEAM; i++) + { /* zero out each teams planet count */ + teams[i].s_plcountold = teams[i].s_plcount; /* save last planet count */ + teams[i].s_plcount = 0; + } + for (i = 0, l = &planets[i]; i < NUMPLANETS; i++, l++) /* recompute */ + teams[l->pl_owner].s_plcount++; /* planet counts for teams */ +} + +/* blow everyone up, print the conquer assessments, figure out who won. */ +void +endgame_effects(t1, t2, pno) + int t1; + int t2; + int pno; +{ + int i; + struct player *j; + + refresh_team_planetcounts(); + + if (teams[t1].s_plcount < teams[t2].s_plcount) + { + int i; + i = t1; + t1 = t2; + t2 = i; /* t1 is the winners */ + } + if (pno >= 0 && players[pno].p_team != t1) + pno = -1; /* he can't win the game! */ + + if (pno < 0) + pno = enemy_admiral(t2); + + if (teams[t1].s_plcount == teams[t2].s_plcount) + { + /* tie, nobody wins */ + pno = -1; + } + status->genocides++; /* inc number of genocides */ + conquerMessage(t1, t2, pno); /* print conquer message */ + + for (i = 0, j = &players[0]; i < MAXPLAYER; i++, j++) + { + if (j->p_status == PFREE) /* if player not in game */ + continue; /* ignore him */ + if (status->tourn) /* only inc genos if t-mode */ + j->p_stats.st_genocides++;/* inc player's genocides */ + j->p_whydead = KWINNER; /* because someone won */ + j->p_whodead = pno; /* set who won the game */ + j->p_status = POUTFIT; /* send them immediately to outfit screen */ + /* + * cause_kaboom (j); + */ + j->p_ntorp = 0; /* no torps shot */ + j->p_nplasmatorp = 0; /* no plasmas shot */ + } +} + + + +/*-------------------------------CHECKWIN---------------------------------*/ +/* + * This function is called when a planet is taken or beamed to zero. It + * recalculates s_plcount for each team. It then finds the two teams that + * are in t-mode. If either of them has just sustained the empire from + * collapse or should start the surrender procedure then that is done. If a + * team has been genocided then the genocide message is printed and the game + * is reset. + */ + +void +checkwin(pno) + int pno; +{ + int g; /* to hold whether genocide occured */ + int t1, t2; /* to hold the t-mode teams */ + + refresh_team_planetcounts(); + g = genocide(&t1, &t2); /* check genocide */ + if (teams[t1].s_plcount < teams[t2].s_plcount) + { + int i; + i = t1; + t1 = t2; + t2 = i; /* t1 is the winners */ + } + checksurrender(t1, teams[t2].s_plcount); /* check for change in */ + checksurrender(t2, teams[t1].s_plcount); /* surrender status */ + if (!g) /* if genocide did not occur */ + return; /* then return from func */ + teams[t1].s_surrender = 0; /* stop the surrender clock */ + teams[t2].s_surrender = 0; + + stoptimer(); + +#ifdef LEAGUE_SUPPORT + if (status2->league) + { + endtourn(); /* calls endgame_effects */ + } + else +#endif + endgame_effects(t1, t2, pno); +#if 0 + gen_planets(); /* generate new galaxy */ + + longjmp(env, 0); /* restart */ +#else + status->gameup = 0; /* exit the daemon */ + status->count = 0; + save_planets(); + sleep(2); + blast_shmem(); + exit(0); +#endif +} + + + + + + + +/*-------------------------------DISPLAYBEST-------------------------------*/ +/* + * This function is used to get a list of players on a team after a genocide. + * It goes through the players and selects the ones that have inflicted the + * most damage. They are then printed to the message window and to the + * conquer file. They are arranged according to how much damage the players + * have inflicted on the enemy, with one planet taken counting as thirty + * armies bombed. A resource counts as 8 armies bombed and a army dooshed + * counts as five armies bombed. + */ + +void +displayBest(conqfile, team) + FILE *conqfile; /* the opened conquer file */ + int team; /* the winning team */ +{ + register int i, k, l; /* looping vars */ + register struct player *j; /* to point to players */ + int planets, armies; /* # planets and armies for player */ + int resources, dooshes; /* resources bombed, armies dooshed */ + Players winners[MAXPLAYER + 1]; /* to hold player's stats */ + char buf[100]; /* to sprintf into */ + int number; /* to hold # players found */ + + number = 0; /* number of players found */ + for (i = 0, j = &players[0]; i < MAXPLAYER; i++, j++) + { + if ((j->p_team != team) || (j->p_status == PFREE)) /* player wrong race */ + continue; /* or not here, then forget him */ + planets = j->p_planets; /* get all planets and armies for */ + armies = j->p_armsbomb; /* entire game */ + resources = j->p_resbomb; /* get resources and armies dooshed */ + dooshes = j->p_dooshes; + for (k = 0; k < number; k++) + { /* go find postion in current list */ + if (30 * winners[k].planets + winners[k].armies + 8 * winners[k].resources + + 5 * winners[k].dooshes < + 30 * planets + armies + 8 * resources + 5 * dooshes) + { + break; /* break when position found */ + } + } + for (l = number; l >= k; l--) /* move other players to make room */ + winners[l + 1] = winners[l]; /* for new player */ + number++; /* we have found one more player */ + winners[k].planets = planets; /* record his planets and armies */ + winners[k].armies = armies; + winners[k].resources = resources; + winners[k].dooshes = dooshes; + strncpy(winners[k].mapchars, twoletters(j), 2); + strncpy(winners[k].name, j->p_name, 16); /* get his name */ + winners[k].name[15] = 0; /* `Just in case' paranoia */ + } + for (k = 0; k < number; k++) + { /* go through all players found */ + if (winners[k].planets != 0 || winners[k].armies != 0) + { /* damage done? */ + sprintf(buf, " %16s (%2.2s) %d planets %d armies %d resources %d dooshes", + winners[k].name, winners[k].mapchars, winners[k].planets, + winners[k].armies, winners[k].resources, winners[k].dooshes); + OUT; + } + } +} + +/*-------------------------------------------------------------------------*/ + + + + + + +/*-----------END OF FILE-----*/