billr@saab.CNA.TEK.COM (Bill Randle) (06/02/90)
Submitted-by: VANCLEEF@mps.ohio-state.edu Posting-number: Volume 10, Issue 2 Archive-name: gb3/Part02 Supersedes: GB2: Volume 7, Issue 44-51 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 2 (of 14)." # Contents: Docs/zoom.doc server/GB_server.c server/doship.c # Wrapped by billr@saab on Fri Jun 1 11:53:31 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Docs/zoom.doc' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Docs/zoom.doc'\" else echo shar: Extracting \"'Docs/zoom.doc'\" \(1194 characters\) sed "s/^X//" >'Docs/zoom.doc' <<'END_OF_FILE' XZOOM Galactic Bloodshed ZOOM X X XNAME X [0] zoom -- declare zoom values X XSYNTAX X zoom (amount) <x,y> X XDESCRIPTION X X This command allows users to alter the scale used in an orbit display. XThe lower the number, the larger the display will be. X X ``Amount'' can be specified in one of two ways: a floating-point format, Xin which case the amount will be the amount given, or an i/j format, in Xwhich case the amount will be the numerator (i) divided by the denominator (j). X X The optional argument changes the ``lastx,lasty'' coordinates to the specified Xcoordinates, in case the player desires a closeup of an area he has not explored Xyet. X X At a zoom scale of 1.0, the display will be equal to the screen size. At Xa scale of greater than 1.0, the display will be smaller than the screen; Xsmaller than 1.0, and the screen will zoom in to the displayed map. X X Display is centered around the current ``lastx,lasty'' coordinates (see Xorbit). X X At game start, the zoom value is declared as 1.0. X X There are two zoom factors, one for 'star' level, and one for 'universe' level. You can Xspecify the 'lastx, lasty' for the universe level with the 'center <star>' command. X XSEE ALSO X orbit END_OF_FILE if test 1194 -ne `wc -c <'Docs/zoom.doc'`; then echo shar: \"'Docs/zoom.doc'\" unpacked with wrong size! fi # end of 'Docs/zoom.doc' fi if test -f 'server/GB_server.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'server/GB_server.c'\" else echo shar: Extracting \"'server/GB_server.c'\" \(33670 characters\) sed "s/^X//" >'server/GB_server.c' <<'END_OF_FILE' X/* X * Galactic Bloodshed, copyright (c) 1989 1990 by Robert P. Chansky, X * smq@ucscb.ucsc.edu, Univ of Ca Santa Cruz. X * You may copy, alter and distribute this game as you please as X * long as these notices remain intact. No duplication for X * commercial purposes without permission of the author. X * X * Version 1.1 mods by: X * Garrett Van Cleef, Ph.D X * Dept. of Physics X * Ohio State University X * V1.1 playtesting by: X * Hanan Baddar X * Ken Bloch X * John Davis X * Robert Jones X * Menelaos Kafkaladis X * Brett Lowry X * Paul Murphy X * Garrett van Cleef X * Wolfgang Wenzel X * and X * tons of people X * at U.C. Santa Cruz X * X * X * GB_server.c -- X * main loop X */ X X#include "TinyMUD_copyright.h" X/* Copyright for the original TinyMUD interface which was used for the networking */ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/file.h> X#include <sys/time.h> X#include <signal.h> X#include <sys/ioctl.h> X#include <sys/wait.h> X#include <fcntl.h> X#include <sys/errno.h> X#include <ctype.h> X#include <sys/socket.h> X#include <netinet/in.h> X#include <netdb.h> X X/*#include <time.h> /* included by <sys/time.h> with bsd */ X#include <sys/timeb.h> X X#include <curses.h> X#include <sys/stat.h> Xstruct stat sbuf; X#include <signal.h> X#include <strings.h> X#include <pwd.h> Xstruct passwd *passwd; Xint i; X X/* GB headers */ X#define EXTERN X#include "vars.h" X#include "ships.h" X#include "races.h" X#include "power.h" X#include "doturn.h" X X#include "config.h" X#include "interface.h" X#include "buffers.h" X X/* For BSD 4.2 systems. */ X#ifndef FD_ZERO X#define OLD_BSD_FDSETS X#include "ultrix_cpt.h" X#endif X Xextern int errno; Xint shutdown_flag = 0; X Xstruct tm *update_tm; /* keeps track of the last update */ Xstruct tm *current_tm;/* for watching for next update */ Xlong clk; Xchar start_buf[128]; Xchar update_buf[128]; X Xstatic const char *connect_fail = "Connection refused.\n"; Xstatic const char *create_fail = "Connection refused.\n"; Xstatic const char *flushed_message = "<Output Flushed>\n"; Xstatic const char *shutdown_message = "Shutdown ordered by deity - Bye\n"; Xstatic const char *already_on = "Connection refused.\n"; X Xint errno; X Xstruct text_block { X int nchars; X struct text_block *nxt; X char *start; X char *buf; X}; X Xstruct text_queue { X struct text_block *head; X struct text_block **tail; X}; X Xstruct descriptor_data { X int descriptor; X int connected; X int Playernum; X char *output_prefix; X char *output_suffix; X int output_size; X struct text_queue output; X struct text_queue input; X char *raw_input; X char *raw_input_at; X long last_time; X int quota; X struct descriptor_data *next; X struct descriptor_data **prev; X} *descriptor_list = 0; X Xstatic int sock; Xstatic int ndescriptors = 0; X Xvoid panic(); Xvoid process_commands(); Xvoid shovechars(); Xvoid shutdownsock(); Xstruct descriptor_data *initializesock(); Xvoid make_nonblocking(); Xvoid freeqs(); Xvoid welcome_user(); Xvoid check_connect(); Xvoid close_sockets(); Xconst char *addrout (); Xvoid dump_users(); Xvoid set_signals(); Xstruct descriptor_data *new_connection(); Xvoid parse_connect (); Xvoid set_userstring (); Xint do_command (); Xchar *strsave (); Xint make_socket(); Xint queue_string(); Xint queue_write(); Xint process_output(); Xint process_input(); Xint bailout(); Xstruct timeval update_quotas(); X X#define MALLOC(result, type, number) do { \ X if (!((result) = (type *) malloc ((number) * sizeof (type)))) \ X panic("Out of memory"); \ X } while (0) X X#define FREE(x) (free(x)) X Xchar *Desnames[] = { X "ocean", X "land", X "mountainous", X "gaseous", X "ice", X "plated", X "error in des type!", /* (illegal values) */ X "err in des type!" X}; X Xint server_racedata; X#ifdef BSD4_2 Xint min_west; Xextern char *timezone(); X#endif X Xvoid main(argc, argv) Xint argc; Xchar **argv; X{ Xint maim_stardata, s; Xint i, j, dummy; X#ifdef BSD4_2 Xchar zone[16]; Xstruct timeval tp; Xstruct timezone tzp; X#endif X X /* go do it */ Xclk = time(0); Xcurrent_tm = localtime(&clk); X#ifdef BSD4_2 X/* all this because BSD 4.2 derived systems don't have X * tm_zone in the tm struct X */ Xgettimeofday(&tp, &tzp); Xmin_west = tzp.tz_minuteswest; Xstrcpy(zone, timezone(min_west, current_tm->tm_isdst)); X#else Xstrcpy(zone, current_tm->tm_zone); X#endif X Xsprintf(start_buf, "Server started: %2d/%2d/%d %02d:%02d:%02d %s\n", X current_tm->tm_mon+1, current_tm->tm_mday, X current_tm->tm_year, current_tm->tm_hour, current_tm->tm_min, X current_tm->tm_sec, zone); X X srandom(getpid()); X printf("*** Galactic Bloodshed ver %s ***\n\n", VERS); X printf(" The update password is '%s'.\n", DAEMON_PASSWORD); X/* compute powers of 2 for bit operations */ X Two[0]=1; X for(i=1;i<32;i++) X Two[i]=2*Two[i-1]; X X reload_star_data_base(); /* get star data */ X Getpower(Power); /* get power report from disk */ X Getblock(Blocks); /* get alliance block data */ Xfor(i=1; i<=MAXPLAYERS; i++) { X setbit(Blocks[i-1].invite, i); X setbit(Blocks[i-1].pledge, i); X } X Putblock(Blocks); X XNum_races = Numraces(); X/* compute alliance block power */ Xsprintf(Power_blocks.time, "%2d/%2d/%d %02d:%02d:%02d %s", X current_tm->tm_mon+1, current_tm->tm_mday, X current_tm->tm_year, current_tm->tm_hour, X current_tm->tm_min, current_tm->tm_sec, zone); X for (i=1; i<=Num_races; i++) { X dummy=(Blocks[i-1].invite & Blocks[i-1].pledge); X Power_blocks.members[i-1] = 0; X Power_blocks.sectors_owned[i-1] = 0; X Power_blocks.popn[i-1] = 0; X Power_blocks.ships_owned[i-1] = 0; X Power_blocks.planets_owned[i-1] = 0; X Power_blocks.resource[i-1] = 0; X Power_blocks.fuel[i-1] = 0; X Power_blocks.destruct[i-1] = 0; X Power_blocks.VPs[i-1] = 0; X for(j=1; j<=Num_races; j++) X if(isset(dummy, j)){ X Power_blocks.members[i-1] += 1; X Power_blocks.sectors_owned[i-1] += Power[j-1].sectors_owned; X Power_blocks.popn[i-1] += Power[j-1].popn; X Power_blocks.ships_owned[i-1] += Power[j-1].ships_owned; X Power_blocks.planets_owned[i-1] += Power[j-1].planets_owned; X Power_blocks.resource[i-1] += Power[j-1].resource; X Power_blocks.fuel[i-1] += Power[j-1].fuel; X Power_blocks.destruct[i-1] += Power[j-1].destruct; X Power_blocks.VPs[i-1] += Blocks[j-1].VPs; X } X } X X X X shovechars (argc==1 ? GB_PORT : atoi (argv[1]) ); X close_sockets (); Xprintf("Going down.\n"); X exit (0); X} X X Xint notify(Playernum, msg) Xint Playernum; Xchar *msg; X{ X struct descriptor_data *d; X X for (d = descriptor_list; d; d = d->next) { X if (d->connected && d->Playernum == Playernum) { X queue_string (d, msg); X return(1); X } X } Xreturn(0); X} X Xstruct timeval timeval_sub(now, then) Xstruct timeval now; Xstruct timeval then; X{ X now.tv_sec -= then.tv_sec; X now.tv_usec -= then.tv_usec; X if (now.tv_usec < 0) { X now.tv_usec += 1000000; X now.tv_sec--; X } X return now; X} X Xint msec_diff(now, then) Xstruct timeval now; Xstruct timeval then; X{ X return ((now.tv_sec - then.tv_sec) * 1000 X + (now.tv_usec - then.tv_usec) / 1000); X} X Xstruct timeval msec_add(t, x) Xstruct timeval t; Xint x; X{ X t.tv_sec += x / 1000; X t.tv_usec += (x % 1000) * 1000; X if (t.tv_usec >= 1000000) { X t.tv_sec += t.tv_usec / 1000000; X t.tv_usec = t.tv_usec % 1000000; X } X return t; X} X Xvoid shovechars(port) Xint port; X{ X fd_set input_set, output_set; X long now; X struct timeval last_slice, current_time; X struct timeval next_slice; X struct timeval timeout, slice_timeout; X int maxd; X struct descriptor_data *d, *dnext; X struct descriptor_data *newd; X int avail_descriptors; X X sock = make_socket (port); X maxd = sock+1; X gettimeofday(&last_slice, (struct timezone *) 0); X X avail_descriptors = getdtablesize() - 4; X X while (shutdown_flag == 0) { X gettimeofday(¤t_time, (struct timezone *) 0); X last_slice = update_quotas(last_slice, current_time); X X process_commands(); X X if (shutdown_flag) X break; X timeout.tv_sec = 1000; X timeout.tv_usec = 0; X next_slice = msec_add (last_slice, COMMAND_TIME_MSEC); X slice_timeout = timeval_sub (next_slice, current_time); X X FD_ZERO (&input_set); X FD_ZERO (&output_set); X if (ndescriptors < avail_descriptors) X FD_SET (sock, &input_set); X for (d = descriptor_list; d; d=d->next) { X if (d->input.head) X timeout = slice_timeout; X else X FD_SET (d->descriptor, &input_set); X if (d->output.head) X FD_SET (d->descriptor, &output_set); X } X X if (select (maxd, &input_set, &output_set, X (fd_set *) 0, &timeout) < 0) { X if (errno != EINTR) { X perror ("select"); X return; X } X } else { X (void) time (&now); X if (FD_ISSET (sock, &input_set)) { X if (!(newd = new_connection (sock))) { X if (errno != EINTR && errno != EMFILE) { X perror ("new_connection"); X return; X } X } else { X if (newd->descriptor >= maxd) X maxd = newd->descriptor + 1; X } X } X for (d = descriptor_list; d; d = dnext) { X dnext = d->next; X if (FD_ISSET (d->descriptor, &input_set)) { X d->last_time = now; X if (!process_input (d)) { X shutdownsock (d); X continue; X } X } X if (FD_ISSET (d->descriptor, &output_set)) { X if (!process_output (d)) { X shutdownsock (d); X } X } X } X } X } X} X Xint make_socket(port) Xint port; X{ X int s; X struct sockaddr_in server; X int opt; X X s = socket (AF_INET, SOCK_STREAM, 0); X if (s < 0) { X perror ("creating stream socket"); X exit (3); X } X opt = 1; X if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, X (char *) &opt, sizeof (opt)) < 0) { X perror ("setsockopt"); X exit (1); X } X server.sin_family = AF_INET; X server.sin_addr.s_addr = INADDR_ANY; X server.sin_port = htons (port); X if (bind (s, (struct sockaddr *) & server, sizeof (server))) { X perror ("binding stream socket"); X close (s); X exit (4); X } X listen (s, 5); X return s; X} X Xstruct timeval update_quotas(last, current) Xstruct timeval last; Xstruct timeval current; X{ X int nslices; X struct descriptor_data *d; X X nslices = msec_diff (current, last) / COMMAND_TIME_MSEC; X X if (nslices > 0) { X for (d = descriptor_list; d; d = d -> next) { X d -> quota += COMMANDS_PER_TIME * nslices; X if (d -> quota > COMMAND_BURST_SIZE) X d -> quota = COMMAND_BURST_SIZE; X } X } X return msec_add (last, nslices * COMMAND_TIME_MSEC); X} X Xstruct descriptor_data *new_connection(sock) Xint sock; X{ X int newsock; X struct sockaddr_in addr; X int addr_len; X X addr_len = sizeof (addr); X newsock = accept (sock, (struct sockaddr *) & addr, &addr_len); X if (newsock <= 0) { X return 0; X } else { X fprintf (stderr, "ACCEPT from %s(%d) on descriptor %d\n", addrout (ntohl (addr.sin_addr.s_addr)), ntohs (addr.sin_port), newsock); X return initializesock (newsock); X } X} X Xconst char *addrout(a) Xlong a; X{ X static char outbuf[1024]; X X sprintf (outbuf, "%d.%d.%d.%d", (a >> 24) & 0xff, (a >> 16) & 0xff, X (a >> 8) & 0xff, a & 0xff); X return outbuf; X} X Xvoid clearstrings(d) Xstruct descriptor_data *d; X{ X if (d->output_prefix) { X free(d->output_prefix); X d->output_prefix = 0; X } X if (d->output_suffix) { X free(d->output_suffix); X d->output_suffix = 0; X } X} X Xvoid shutdownsock(d) Xstruct descriptor_data *d; X{ X if (d->connected) { X fprintf (stderr, "DISCONNECT descriptor %d Playernum(%d)\n", X d->descriptor, d->Playernum); X } else { X fprintf (stderr, "DISCONNECT descriptor %d never connected\n", X d->descriptor); X } X clearstrings (d); X shutdown (d->descriptor, 2); X close (d->descriptor); X freeqs (d); X *d->prev = d->next; X if (d->next) X d->next->prev = d->prev; X free(d); X ndescriptors--; X} X Xstruct descriptor_data *initializesock(s) Xint s; X{ X struct descriptor_data *d; X X ndescriptors++; X MALLOC(d, struct descriptor_data, 1); X d->descriptor = s; X d->connected = 0; X make_nonblocking (s); X d->output_prefix = 0; X d->output_suffix = 0; X d->output_size = 0; X d->output.head = 0; X d->output.tail = &d->output.head; X d->input.head = 0; X d->input.tail = &d->input.head; X d->raw_input = 0; X d->raw_input_at = 0; X d->quota = COMMAND_BURST_SIZE; X d->last_time = 0; X if (descriptor_list) X descriptor_list->prev = &d->next; X d->next = descriptor_list; X d->prev = &descriptor_list; X descriptor_list = d; X X welcome_user (d); X return d; X} X Xstruct text_block *make_text_block(s, n) Xconst char *s; Xint n; X{ X struct text_block *p; X X MALLOC(p, struct text_block, 1); X MALLOC(p->buf, char, n); X bcopy (s, p->buf, n); X p->nchars = n; X p->start = p->buf; X p->nxt = 0; X return p; X} X Xvoid free_text_block (t) Xstruct text_block *t; X{ X free(t->buf); X free((char *) t); X} X Xvoid add_to_queue(q, b, n) Xstruct text_queue *q; Xconst char *b; Xint n; X{ X struct text_block *p; X X if (n == 0) return; X X p = make_text_block (b, n); X p->nxt = 0; X *q->tail = p; X q->tail = &p->nxt; X} X Xint flush_queue(q, n) Xstruct text_queue *q; Xint n; X{ X struct text_block *p; X int really_flushed = 0; X X n += strlen(flushed_message); X X while (n > 0 && (p = q->head)) { X n -= p->nchars; X really_flushed += p->nchars; X q->head = p->nxt; X free_text_block (p); X } X p = make_text_block(flushed_message, strlen(flushed_message)); X p->nxt = q->head; X q->head = p; X if (!p->nxt) X q->tail = &p->nxt; X really_flushed -= p->nchars; X return really_flushed; X} X Xint queue_write(d, b, n) Xstruct descriptor_data *d; Xconst char *b; Xint n; X{ X int space; X X space = MAX_OUTPUT - d->output_size - n; X if (space < 0) X d->output_size -= flush_queue(&d->output, -space); X add_to_queue (&d->output, b, n); X d->output_size += n; X return n; X} X Xint queue_string(d, s) Xstruct descriptor_data *d; Xconst char *s; X{ X return queue_write (d, s, strlen (s)); X} X Xint process_output(d) Xstruct descriptor_data *d; X{ X struct text_block **qp, *cur; X int cnt; X X for (qp = &d->output.head; cur = *qp;) { X cnt = write (d->descriptor, cur -> start, cur -> nchars); X if (cnt < 0) { X if (errno == EWOULDBLOCK) X return 1; X return 0; X } X d->output_size -= cnt; X if (cnt == cur -> nchars) { X if (!cur -> nxt) X d->output.tail = qp; X *qp = cur -> nxt; X free_text_block (cur); X continue; /* do not adv ptr */ X } X cur -> nchars -= cnt; X cur -> start += cnt; X break; X } X return 1; X} X Xvoid make_nonblocking(s) Xint s; X{ X if (fcntl (s, F_SETFL, FNDELAY) == -1) { X perror ("make_nonblocking: fcntl"); X panic ("FNDELAY fcntl failed"); X } X} X Xvoid freeqs(d) Xstruct descriptor_data *d; X{ X struct text_block *cur, *next; X X cur = d->output.head; X while (cur) { X next = cur -> nxt; X free_text_block (cur); X cur = next; X } X d->output.head = 0; X d->output.tail = &d->output.head; X X cur = d->input.head; X while (cur) { X next = cur -> nxt; X free_text_block (cur); X cur = next; X } X d->input.head = 0; X d->input.tail = &d->input.head; X X if (d->raw_input) X free(d->raw_input); X d->raw_input = 0; X d->raw_input_at = 0; X} X Xvoid welcome_user(d) Xstruct descriptor_data *d; X{ X FILE *f; X char buf[BUFFER_LEN]; X char *p; X X sprintf(buf, "*** Welcome to Galactic Bloodshed ver %s ***\n", VERS); X queue_string(d, buf); X X if((f = fopen(WELCOME_FILE, "r")) != NULL) { X while(fgets(buf, sizeof buf, f)) { X for(p = buf; *p; p++) if(*p == '\n') { X *p = '\0'; X break; X } X queue_string(d, buf); X queue_string(d, "\n"); X } X fclose(f); X } X X/* if((f = fopen(NEWS_FILE, "r")) != NULL) { X while(fgets(buf, sizeof buf, f)) { X for(p = buf; *p; p++) if(*p == '\n') { X *p = '\0'; X break; X } X queue_string(d, buf); X queue_string(d, "\n"); X } X fclose(f); X } */ X X} X Xvoid goodbye_user(d) Xstruct descriptor_data *d; X{ X write (d->descriptor, LEAVE_MESSAGE, strlen (LEAVE_MESSAGE)); X} X Xchar *strsave (s) Xconst char *s; X{ X char *p; X X MALLOC (p, char, strlen(s) + 1); X X if (p) X strcpy (p, s); X return p; X} X Xvoid save_command (d, command) Xstruct descriptor_data *d; Xconst char *command; X X{ X add_to_queue (&d->input, command, strlen(command)+1); X} X Xint process_input (d) Xstruct descriptor_data *d; X{ X int got; X char *p, *pend, *q, *qend; X X got = read (d->descriptor, buf, sizeof buf); X if (got <= 0) X return 0; X if (!d->raw_input) { X MALLOC(d->raw_input,char,MAX_COMMAND_LEN); X d->raw_input_at = d->raw_input; X } X p = d->raw_input_at; X pend = d->raw_input + MAX_COMMAND_LEN - 1; X for (q=buf, qend = buf + got; q < qend; q++) { X if (*q == '\n') { X *p = '\0'; X if (p > d->raw_input) X save_command (d, d->raw_input); X p = d->raw_input; X } else if (p < pend && isascii (*q) && isprint (*q)) { X *p++ = *q; X } X } X if (p > d->raw_input) { X d->raw_input_at = p; X } else { X free(d->raw_input); X d->raw_input = 0; X d->raw_input_at = 0; X } X return 1; X} X Xvoid set_userstring (userstring, command) Xchar **userstring; Xconst char *command; X{ X if (*userstring) { X free(*userstring); X *userstring = 0; X } X while (*command && isascii (*command) && isspace (*command)) X command++; X if (*command) X *userstring = strsave (command); X} X X#ifdef __STDC__ Xvoid process_commands(void) X#else Xvoid process_commands() X#endif X{ X int nprocessed; X struct descriptor_data *d, *dnext; X struct text_block *t; X X do { X nprocessed = 0; X for (d = descriptor_list; d; d = dnext) { X dnext = d->next; X if (d -> quota > 0 && (t = d -> input.head)) { X d -> quota--; X nprocessed++; X X if (!do_command (d, t -> start)) { X shutdownsock (d); X } else { X d -> input.head = t -> nxt; X if (!d -> input.head) X d -> input.tail = &d -> input.head; X free_text_block (t); X } X X } X } X } while (nprocessed > 0); X X} X Xint do_command (d, command) Xstruct descriptor_data *d; Xchar *command; X{ Xracetype *r; Xchar *string; Xint parse_exit=0, argn=0, i; Xchar args[MAXARGS][COMMANDSIZE]; X X/* Main processing loop. When command strings are sent from the client, X they are processed here. Responses are sent back to the client via notify. X The client will then process the strings in whatever manner is expected. */ X X/* check to see if there are a few words typed out, usually for the help command */ X string=command; X while (!parse_exit) { X i=0; X while ( !isspace(*string) && (*string!='\0') && (i<COMMANDSIZE) ) X args[argn][i++]=(*string++); X args[argn][i]='\0'; X /*printf("arg %d |%s|\n",argn,args[argn]);*/ X while ((*string)==' ') string++; X if ( (*string=='\0') || (argn>=MAXARGS)) parse_exit=1; X argn++; X } X for (i=argn; i<MAXARGS; i++) X args[i][0]='\0'; X X if (!strcmp (args[0], QUIT_COMMAND)) { X if(d->connected) { X X openracedata(&server_racedata); X getrace(server_racedata, &r, d->Playernum); X close_file(server_racedata); X X sprintf(buf, "%s (%d) logged out.\n", r->name, d->Playernum); X for(i=1; i<=Numraces(); i++) X if(!Dir[i-1].gag) X notify(i, buf); X } X goodbye_user (d); X return 0; X } else if (!strcmp (args[0], WHO_COMMAND)) { X dump_users (d); X } else if (!strcmp (args[0], HELP_COMMAND)) { X help(d, argn, args); X } else { X if (d->connected) { X process_command (d->Playernum, command); /* GB command parser */ X } else { X check_connect (d, command); /* Logs player into the game, connects X if the password given by *command is a player's */ X if(!d->connected) { X goodbye_user(d); X } X else { X check_for_telegrams(d->Playernum); X process_command (d->Playernum, "cs"); /* set the scope to home upon login */ X } X } X } X return 1; X} X Xvoid check_connect (d, msg) Xstruct descriptor_data *d; Xconst char *msg; X{ X char password[MAX_COMMAND_LEN]; X reg int i; X int Playernum, Num_races; X racetype *r; X struct descriptor_data *d0, *dnext; X#ifdef BSD4_2 X char zone[16]; X#endif X X parse_connect (msg, password); X XNum_races = Numraces(); X/* daemon wants an update */ Xif(!strcmp(password, DAEMON_PASSWORD)) { X Xfor (i=1; i<=Num_races; i++) X notify(i, "DOING UPDATE...\n"); X X X clk = time(0); X update_tm=localtime(&clk); X#ifdef BSD4_2 X strcpy(zone, timezone(min_west, update_tm->tm_isdst)); X#else X strcpy(zone, update_tm->tm_zone); X#endif Xsprintf(Power_blocks.time, "%2d/%2d/%d %02d:%02d:%02d %s", X update_tm->tm_mon+1, update_tm->tm_mday, X update_tm->tm_year, update_tm->tm_hour, X update_tm->tm_min, update_tm->tm_sec, zone); Xsprintf(update_buf, "Last update : %2d/%2d/%d %02d:%02d:%02d %s\n", X update_tm->tm_mon+1, update_tm->tm_mday, X update_tm->tm_year, update_tm->tm_hour, X update_tm->tm_min, update_tm->tm_sec, zone); X do_turn(); X return; X } X X X i = Getracenum(password); X X if (!i) { X queue_string (d, connect_fail); X fprintf (stderr, "FAILED CONNECT %s on descriptor %d\n", X password, d->descriptor); X } else { X X openracedata(&server_racedata); X getrace(server_racedata, &r, i); X close_file(server_racedata); X X Playernum = r->Playernum; X X/* check to see if this player is already connect, if so, nuke the descriptor */ X for (d0 = descriptor_list; d0; d0 = dnext) { X dnext = d0->next; X if(d0->connected && d0->Playernum == Playernum) { X queue_string (d, already_on); X return; X } X } X X fprintf (stderr, "CONNECTED %s(%d) on descriptor %d\n", X r->name, Playernum, d->descriptor); X d->connected = 1; X d->Playernum = Playernum; X X sprintf(buf,"\nLogged in as %s (%d).\n",r->name,Playernum); X notify(Playernum, buf); X X sprintf(buf, "%s (%d) logged on.\n", r->name, Playernum); X for(i=1; i<=Numraces(); i++) X if(i != Playernum && !Dir[i-1].gag) notify(i, buf); X X GB_time(Playernum); X if (r->Gov_ship==0) { X sprintf(buf,"You have no Governmental Center. No action points will be produced\nuntil you build one and designate a capital.\n"); X notify(Playernum, buf); X } else { X sprintf(buf,"Government Center #%d is active.\n", r->Gov_ship); X notify(Playernum, buf); X } X } X} X Xvoid parse_connect (msg, pass) Xconst char *msg; Xchar *pass; X{ X char *p; X X while (*msg && isascii(*msg) && isspace (*msg)) X msg++; X p = pass; X while (*msg && isascii(*msg) && !isspace (*msg)) X *p++ = *msg++; X *p = '\0'; X} X X#ifdef __STDC__ Xvoid close_sockets(void) X#else Xvoid close_sockets() X#endif X{ X struct descriptor_data *d, *dnext; X X for (d = descriptor_list; d; d = dnext) { X dnext = d->next; X write (d->descriptor, shutdown_message, strlen (shutdown_message)); X if (shutdown (d->descriptor, 2) < 0) X perror ("shutdown"); X close (d->descriptor); X } X close (sock); X} X X#ifdef __STDC__ Xvoid emergency_shutdown(void) X#else Xvoid emergency_shutdown() X#endif X{ X close_sockets(); X} X X#ifdef __STDC__ Xint bailout(int sig, int code, struct sigcontext *scp) X#else Xint bailout(sig, code, scp) Xint sig, code; Xstruct sigcontext *scp; X#endif X{ X char message[1024]; X X sprintf (message, "BAILOUT: caught signal %d code %d", sig, code); X panic(message); X _exit (7); X return 0; X} X X#ifdef __STDC__ Xint dump_status(void) X#else Xint dump_status() X#endif X{ X struct descriptor_data *d; X long now; X racetype *r; X X (void) time (&now); X fprintf (stderr, "STATUS REPORT:\n"); Xopenracedata(&server_racedata); X for (d = descriptor_list; d; d = d->next) { X if (d->connected) { X getrace(server_racedata, &r, d->Playernum); X fprintf (stderr, "PLAYING descriptor %d Playernum %s(%d)", X d->descriptor, r->name, d->Playernum); X X if (d->last_time) X fprintf (stderr, " idle %d seconds\n", X now - d->last_time); X else X fprintf (stderr, " never used\n"); X } else { X fprintf (stderr, "CONNECTING descriptor %d", d->descriptor); X if (d->last_time) X fprintf (stderr, " idle %d seconds\n", X now - d->last_time); X else X fprintf (stderr, " never used\n"); X } X } Xclose_file(server_racedata); X return 0; X} X Xvoid dump_users(e) Xstruct descriptor_data *e; X{ X struct descriptor_data *d; X long now; X racetype *r; X X (void) time (&now); X queue_string (e, "Current Players:\n"); Xopenracedata(&server_racedata); X for (d = descriptor_list; d; d = d->next) { X if (d->connected) { X getrace(server_racedata, &r, d->Playernum); X X if (d->last_time) X sprintf (buf, "%20s (%3d) seconds idle %d\n", r->name, X d->Playernum, now - d->last_time); X else X sprintf (buf, "%20s (%3d) idle forever\n", r->name, d->Playernum); X queue_string (e, buf); X } X } Xclose_file(server_racedata); X} X Xvoid process_command(Playernum, command) X/* locate and parse the command for processing */ Xint Playernum; Xchar *command; X{ Xint i,argn=0; Xboolean parse_exit=0; Xchar args[MAXARGS][COMMANDSIZE]; Xchar *string, *announcement, *dummy; X Xopenracedata(&server_racedata); Xfree(Race); Xgetrace(server_racedata, &Race, Playernum); Xclose_file(server_racedata); X X string=command; /* make pointers the same */ X X while (!parse_exit) { X i=0; X while ( !isspace(*string) && (*string!='\0') && (i<COMMANDSIZE) ) X args[argn][i++]=(*string++); X args[argn][i]='\0'; X /*printf("arg %d |%s|\n",argn,args[argn]);*/ X while ((*string)==' ') string++; X if ( (*string=='\0') || (argn>=MAXARGS)) parse_exit=1; X argn++; X } X for (i=argn; i<MAXARGS; i++) X args[i][0]='\0'; X X if (args[0][0]=='\0') /* just pressed return */ X return; /* go back and wait again */ X i=strlen(args[0]); X X/*determine which routine to go to and what action to take */ X/* target routine is specified by the first substring, other options X are the substrings which follow */ X X if (!strncmp(args[0],"announce",i)) X announce(Playernum,0,argn,args, 0); X else if (!strncmp(args[0],"allocate",i)) allocateAPs(Playernum,0, argn, args); X else if (!strncmp(args[0],"assault",i)) land(Playernum,1,argn,args,1); X else if (!strncmp(args[0], "autoreport",i)) autoreport(Playernum, 0, argn, args); X else if (!strncmp(args[0],"build",i)) build(Playernum,1,argn,args); X else if (!strncmp(args[0], "broadcast", i)) announce(Playernum, 5*(!Race->God), argn, args, 1); X else if (!strncmp(args[0], "block", i)) block(Playernum, 0, argn, args); X else if (!strncmp(args[0],"capitol",i)) capitol(Playernum,50,argn,args); X else if (!strncmp(args[0],"capture",i)) capture(Playernum,1,argn,args); X else if (!strncmp(args[0], "center", i)) center(Playernum, 0, argn, args); X else if (!strncmp(args[0],"cs",i)) cs(Playernum,0,argn,args); X else if (!strncmp(args[0],"declare",i)) declare(Playernum,1,argn,args); X else if (!strncmp(args[0],"dock",i)) land(Playernum,0,argn,args,0); X else if (!strncmp(args[0],"enslave",i)) enslave(Playernum,2,argn,args); X else if (!strncmp(args[0],"examine",i)) examine(Playernum,0,argn,args); X else if (!strncmp(args[0],"explore",i)) exploration(Playernum,0,argn,args); X else if (!strncmp(args[0],"fire",i)) fire(Playernum,1,argn,args); X else if (!strncmp(args[0], "gag", i)) Dir[Playernum-1].gag = !Dir[Playernum-1].gag; X else if (!strncmp(args[0],"give",i)) give(Playernum,5,argn,args); X else if (!strncmp(args[0], "identify", i)) whois(Playernum, 0, argn, args); X else if (!strncmp(args[0], "invite", i)) invite(Playernum, 0, argn, args, 1); X else if (!strncmp(args[0],"land",i)) land(Playernum,1,argn,args,0); X else if (!strncmp(args[0],"launch",i)) launch(Playernum,1,argn,args); X else if (!strncmp(args[0], "list", i) && Race->God) list(Playernum); X else if (!strncmp(args[0],"load",i)) load(Playernum,0,argn,args); X else if (!strncmp(args[0],"map",i)) map(Playernum,0,argn,args); X else if (!strncmp(args[0],"mobilize",i)) mobilize(Playernum,1,argn,args); X else if (!strncmp(args[0],"move",i)) move_popn(Playernum,1,argn,args); X else if (!strncmp(args[0],"make", i)) make_mod(Playernum, 0, argn, args, 0); X else if (!strncmp(args[0],"modify", i)) make_mod(Playernum, 0, argn, args, 1); X else if (!strncmp(args[0],"name",i)) name(Playernum,1*(!Race->God),argn,args); X else if (!strncmp(args[0],"object",i)) rst(Playernum,0,argn,args,4); X else if (!strncmp(args[0],"orbit",i)) orbit(Playernum,0,argn,args); X else if (!strncmp(args[0],"order",i)) order(Playernum,1,argn,args); X else if (!strncmp(args[0],"page",i)) page(Playernum, 1*(!Race->God), argn, args); X else if (!strncmp(args[0],"colonies",i)) colonies(Playernum,0,argn,args); X else if (!strncmp(args[0], "pledge", i)) pledge(Playernum, 0, argn, args, 1); X else if (!strncmp(args[0],"power",i)) power(Playernum,0,argn,args); X else if (!strncmp(args[0],"profile",i)) profile(Playernum,0,argn,args); X else if (!strncmp(args[0],"relation",i)) relation(Playernum,0,argn,args); X else if (!strncmp(args[0],"read",i)) read_messages(Playernum,0,argn,args); X else if (!strncmp(args[0],"reset", i) && Race->God) reload_star_data_base(); X else if (!strncmp(args[0],"report",i)) rst(Playernum,0,argn,args,0); X else if (!strncmp(args[0],"@@shutdown",i) && Race->God) { X shutdown_flag = 1; X notify(Playernum, "Doing shutdown.\n"); X } else if (!strncmp(args[0],"stock",i)) rst(Playernum,0,argn,args,1); X else if (!strncmp(args[0],"ship",i)) rst(Playernum,0,argn,args,3); X else if (!strncmp(args[0],"survey",i)) survey(Playernum,0,argn,args); X else if (!strncmp(args[0], "send", i)) send_message(Playernum, 1*(!Race->God), argn, args); X else if (!strncmp(args[0],"scrap",i)) scrap(Playernum,1,argn,args); X else if(!strncmp(args[0],"tactical",i)) rst(Playernum,0,argn,args,2); X/* else if (!strncmp(args[0],"telegram",i)) telegram(Playernum,0,argn,args); */ X else if(!strncmp(args[0],"technology",i)) technology(Playernum,1,argn,args); X else if (!strncmp(args[0],"toggle",i)) toggle(Playernum,0,argn,args); X else if(!strncmp(args[0],"toxicity",i)) toxicity(Playernum,1,argn,args); X else if (!strncmp(args[0],"transfer",i)) transfer(Playernum,1,argn,args); X else if (!strncmp(args[0],"unload",i)) load(Playernum,0,argn,args); X else if (!strncmp(args[0],"undock",i)) launch(Playernum,0,argn,args); X else if (!strncmp(args[0], "uninvite", i)) invite(Playernum, 0, argn, args, 0); X else if (!strncmp(args[0], "unpledge", i)) pledge(Playernum, 0, argn, args, 0); X else if (!strncmp(args[0],"time",i)) GB_time(Playernum); X else if (!strncmp(args[0],"zoom",i)) zoom(Playernum,0,argn,args); X /* only owning player can use fix */ X else { X sprintf(buf,"'%s':illegal command error(%d).\n",args[0],*args[0]); X notify(Playernum, buf); X } X X/* send the prompt to the player */ X sprintf(buf, "%s", Dir[Playernum-1].prompt); X notify(Playernum, buf); X X} X Xvoid panic(message) Xconst char *message; X{ X FILE *f; X int i; X X fprintf(stderr, "PANIC: %s\n", message); X X /* turn off signals */ X for(i = 0; i < NSIG; i++) { X signal(i, SIG_IGN); X } X X /* shut down interface */ X emergency_shutdown(); X X /* dump panic file */ X} X Xreload_star_data_base() X{ Xint maim_stardata; Xint s, t; X X/* get star database */ X openstardata(&maim_stardata); X getsdata(maim_stardata,&Sdata); X for (s=0; s<Sdata.numstars; s++) { X getstar(maim_stardata,&(Stars[s]),s); X } X close_file(maim_stardata); X/* initialize zoom factors */ X for(i=1; i<=Numraces(); i++) { X Dir[i-1].zoom[0] = 1.0; X Dir[i-1].zoom[1] = 0.5; X Dir[i-1].lastx[0] = Dir[i-1].lastx[1] = 0.0; X Dir[i-1].lasty[0] = Dir[i-1].lasty[1] = 0.0; X } X} X X Xstr_cat(s1, s2) Xchar *s1,*s2; X{ X strcat(s1, s2); X} X XGB_time(Playernum) /* report back the update status */ Xint Playernum; X{ X#ifdef BSD4_2 X char zone[16]; X#endif X X clk = time(0); X current_tm=localtime(&clk); X#ifdef BSD4_2 X strcpy(zone, timezone(min_west, current_tm->tm_isdst)); X#else X strcpy(zone, current_tm->tm_zone); X#endif Xsprintf(buf,"\nCurrent time : %2d/%2d/%d %02d:%02d:%02d %s\n", X current_tm->tm_mon+1, current_tm->tm_mday, X current_tm->tm_year, current_tm->tm_hour, X current_tm->tm_min, current_tm->tm_sec, zone); Xnotify(Playernum, buf); Xif(update_tm != NULL) X notify(Playernum, update_buf); Xelse X notify(Playernum, "No updates since the server was started.\n"); X /* can happen if you have just started the game up */ Xnotify(Playernum, start_buf); X} X Xhelp(e, argn,args) Xstruct descriptor_data *e; Xint argn; Xchar args[MAXARGS][COMMANDSIZE]; X{ X char s[MAXCOMMSTRSIZE]; X X if (argn==1) { X sprintf(buf,"usage: help [topic]\n"); X queue_string(e, buf); X sprintf(buf," valid topics are:\n CONCEPTS:\n%s", X "help scope actionpoints explore colony\n" ); X queue_string(e, buf); X sprintf(buf,"daemon races blocks quit info\n"); X queue_string(e, buf); X sprintf(buf,"\n COMMANDS:\n"); X queue_string(e, buf); X sprintf(buf,"cs map survey orbit zoom autoreport\n"); X queue_string(e, buf); X sprintf(buf,"toggle gag capitol allocate\n\n"); X queue_string(e, buf); X sprintf(buf, "announce page who time quit\n"); X queue_string(e, buf); X sprintf(buf,"build ship stock report tactical order examine\n"); X queue_string(e, buf); X sprintf(buf,"land launch dock undock load assault scrap\n\n"); X queue_string(e, buf); X sprintf(buf,"assault capture fire give move enslave\n\n"); X queue_string(e, buf); X sprintf(buf,"declare profile relation power explore\n"); X queue_string(e, buf); X sprintf(buf,"colonies name mobilize technology toxicity transfer\n"); X queue_string(e, buf); X sprintf(buf, "make modify\n"); X queue_string(e, buf); X X } else { X X FILE *f; X char file[1024]; X char *p; X X sprintf(file,"%s/%s.doc", DOCS, args[1] ); X if((f = fopen(file, "r")) != 0) { X while(fgets(buf, sizeof buf, f)) { X for(p = buf; *p; p++) if(*p == '\n') { X *p = '\0'; X break; X } X strcat(buf, "\n"); X queue_string(e, buf); X } X fclose(f); X } else X queue_string(e, "Help on that subject unavailable.\n"); X X } X X} X Xcheck_for_telegrams(Playernum) Xint Playernum; X{ Xsprintf(buf, "%s.%d", TELEGRAMFL, Playernum); Xstat(buf, &sbuf); Xif(sbuf.st_size) Xnotify(Playernum, "You have telegram(s) waiting. Use 'read' to read them.\n"); X} END_OF_FILE if test 33670 -ne `wc -c <'server/GB_server.c'`; then echo shar: \"'server/GB_server.c'\" unpacked with wrong size! fi # end of 'server/GB_server.c' fi if test -f 'server/doship.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'server/doship.c'\" else echo shar: Extracting \"'server/doship.c'\" \(16262 characters\) sed "s/^X//" >'server/doship.c' <<'END_OF_FILE' X/* X * Galactic Bloodshed, copyright (c) 1989 by Robert P. Chansky, X * smq@ucscb.ucsc.edu, mods by people in GB_copyright.h. X * Restrictions in GB_copyright.h. X * doship -- do one ship turn. X */ X X#include "GB_copyright.h" X#define EXTERN extern X#include "vars.h" X#include "ships.h" X#include "races.h" X#include "doturn.h" X#include "power.h" X#include "buffers.h" X#include <math.h> X#include <strings.h> X X Xdoship(shipno,ship) Xint shipno; Xshiptype *ship; X{ X int sh,sh2,j,shfdata; X boolean trigger; X X/*ship is active */ X ship->active = 1; X X if (ship->is_alive) { X X/* for debugging */ X if(ship->popn > Max_crew(ship)) X ship->popn = Max_crew(ship); X if(ship->destruct > Max_destruct(ship)) X ship->destruct = Max_destruct(ship); X if(ship->fuel > (float)Max_fuel(ship)) X ship->fuel = (float)Max_fuel(ship); X X/* compute the mass of the ship (there is a wierd bug that changes X mass the wrong way) */ Xship->mass = ship->popn*races[ship->owner-1]->mass + ship->resource*MASS_RESOURCE X + ship->fuel*MASS_FUEL + ship->destruct*MASS_DESTRUCT X + Mass(ship); X X /* repair radiation */ X if (ship->rad) { X ship->active = 1; X /* irradiated ships are immobile.. */ X /* kill off some people */ X /* check to see if ship is active */ X if(int_rand(1,100) <= ship->rad) X ship->active = 0; X ship->popn = round_rand(ship->popn * .80); X if (ship->rad >= (int)REPAIR_RATE) X ship->rad -= int_rand(0,(int)REPAIR_RATE); X else X ship->rad -= int_rand(0,ship->rad); X } else X ship->active = 1; X X if(!ship->popn && Max_crew(ship) > 0 X && !ship->is_docked) { X ship->whatdest = LEVEL_UNIV; X } X X if (ship->whatorbits>LEVEL_UNIV && Stars[ship->storbits]->nova_stage>0) { X /* damage ships from supernovae */ X ship->damage += 50.0/Armor(ship); X if (ship->damage >= 100) { X kill_ship(ship); X return; X } X } X X if(ship->active) X Moveship(shipno, ship); X X X X if(ship->whatorbits != LEVEL_UNIV) { X/* printf("checking #%d\n",shipno); */ X StarsInhab[ship->storbits] = 1; X setbit(Stars[ship->storbits]->inhabited, ship->owner); X setbit(Stars[ship->storbits]->explored, ship->owner); X if(ship->whatorbits == LEVEL_PLAN) { X planets[ship->storbits][ship->pnumorbits]->info[ship->owner-1].explored = 1; X } X } X/* just making sure */ X X X /* add ships, popn to total count to add AP's */ X Power[ship->owner-1].ships_owned++; X Power[ship->owner-1].resource += ship->resource; X Power[ship->owner-1].fuel += ship->fuel; X Power[ship->owner-1].destruct += ship->destruct; X Power[ship->owner-1].popn += ship->popn; X X if (ship->whatorbits==LEVEL_UNIV) { X Sdatanumships[ship->owner-1]++; X Sdatapopns[ship->owner] += ship->popn; X } else { X starnumships[ship->storbits][ship->owner-1]++; X /* add popn of ships to popn */ X starpopns[ship->storbits][ship->owner-1] += ship->popn; X /* set inhabited for ship */ X StarsInhab[ship->storbits] = 1; X setbit(Stars[ship->storbits]->inhabited, ship->owner); X setbit(Stars[ship->storbits]->explored, ship->owner); X } X X X X X if (ship->active) { X X /* bombard the planet */ X if (can_bombard(ship) && ship->bombard X && ship->whatorbits==LEVEL_PLAN X && ship->whatdest==LEVEL_PLAN X && ship->deststar== ship->storbits X && ship->destpnum== ship->pnumorbits) { X /* ship bombards planet */ X Stinfo[ship->storbits][ship->pnumorbits].inhab = 1; X } X X X X /* repair ship by the amount of crew it has */ X /* industrial complexes can repair (robot ships can't repair) */ X if (ship->damage && (ship->popn || ship->type==OTYPE_FACTORY)) { X reg int drep,cost; X reg float maxrep; X maxrep = REPAIR_RATE; X /* stations repair for free, and ships docked with them */ X if ((ship->type==STYPE_STATION || !Max_resource(ship)) || X (ship->is_docked && ship->whatdest==LEVEL_SHIP && X ships[ship->destshipno]->type==STYPE_STATION)) X { X cost = 0.0; X } else { X maxrep *= (float)ship->popn / (float)Max_crew(ship); X cost = 0.005 * maxrep * Cost(ship); X } X X if (cost > ship->resource) X { X drep = (int)maxrep * ship->resource / cost; X ship->resource = 0; X } else { X ship->resource -= cost; X drep = (int)maxrep; X } X X ship->mass -= cost * MASS_RESOURCE; X X if (drep > ship->damage) ship->damage = 0; X else X ship->damage -= drep; X/* printf("rep = %d\n",drep); */ X } X X X switch (ship->type) { X X case OTYPE_CANIST: X if (ship->whatorbits == LEVEL_PLAN && !ship->is_docked) { short *t; X if (--ship->object.number) { X if ( Stinfo[ship->storbits][ship->pnumorbits].temp_add < -90 ) X Stinfo[ship->storbits][ship->pnumorbits].temp_add = -100; X else X Stinfo[ship->storbits][ship->pnumorbits].temp_add -= 10; X } else { /* timer expired; destroy canister */ X reg int j=0; X X kill_ship(ship); X sprintf(telegram_buf,"Notice from /%s/%s\n\n", X Stars[ship->storbits]->name, X Stars[ship->storbits]->pnames[ship->pnumorbits]); X sprintf(buf, "Canister of dust previously covering this planet has dissipated.\n"); X str_cat(telegram_buf, buf); X for (j=1; j<=Num_races; j++) X if (planets[ship->storbits][ship->pnumorbits]->info[j-1].numsectsowned) X push_message(TELEG_PLAYER_AUTO, j, telegram_buf); X } X } X break; X X case STYPE_MINE: X /* check around and see if we should explode. */ X if (ship->on) { X int rad=0; int dam=0; double xd,yd,range; int p; X if (ship->whatorbits==LEVEL_STAR) X sh = Stars[ship->storbits]->ships; X else if (ship->whatorbits==LEVEL_PLAN) X sh = planets[ship->storbits][ship->pnumorbits]->ships; X else X sh = Sdata.ships; X sh2 = sh; X /* traverse the list, look for ships that X are closer than the trigger radius... */ X/*printf("found mine sh = %d rad = %d\n",sh,rad);*/ X while (sh && !rad) { X xd = ships[sh]->xpos - ship->xpos; X yd = ships[sh]->ypos - ship->ypos; X range = sqrt(xd*xd + yd*yd); X if ( !isset(races[ship->owner-1]->allied, ships[sh]->owner) && X (ships[sh]->owner != ship->owner) && X ( range <= (float)ship->object.number) ) X rad = 1; X else { X sh = ships[sh]->nextship; X } X } X X/*printf("rad = %d\n",rad);*/ X if (rad) { X char telegram_not[1000]; X kill_ship(ship); X sprintf(telegram_buf, "BULLETIN!\n mine #%d triggered at %s\n", X shipno,prin_ship_orbits(ship)); X X /* I have made the blast radius equal to the trigger radius.*/ X /* -R. */ X X sh = sh2 ; /* Make sh start from beginning of the list */ X while (sh) { X X xd = ships[sh]->xpos - ship->xpos; X yd = ships[sh]->ypos - ship->ypos; X range = sqrt(xd*xd + yd*yd); X trigger = (int_rand(1,100) X <= 2 * Size(ships[sh])); X X if (range <= ship->object.number && trigger) { X X if (!ship->mine.mode) { X int totalrad; X /* radiation mine */ X X rad = round_rand(ship->destruct * X (1./(float)Size(ships[sh])) * X (800/(range + 1.)) ); X X rad = MIN(int_rand(0,rad),100); X X totalrad = ships[sh]->rad + rad; X if (totalrad > 100 ) totalrad = 100; X ships[sh]->rad = totalrad; X X if (rad) { X sprintf(telegram_not, "BULLETIN!\n %s #%d irradiated by mine #%d\n", Shipnames[ships[sh]->type], sh, shipno); X sprintf(buf," at %s - dosage %d%%",prin_ship_orbits(ships[sh]), rad); X str_cat(telegram_not, buf); X push_message(TELEG_PLAYER_AUTO, ships[sh]->owner, telegram_not); X sprintf(buf,"%s #%d [%d] received %d%% dosage\n", X Shipnames[ships[sh]->type], sh, X ships[sh]->owner, rad); X str_cat(telegram_buf, buf); X } X X } else { X int totaldam; X /* explosive mine */ X rad = round_rand(ship->destruct * X (1./(float)Size(ships[sh])) * X (800.0/(range + 1.)) ); X X dam = MIN(100,int_rand(0,rad)); X totaldam = ships[sh]->damage+dam; X if (totaldam > 100 ) totaldam = 100; X if (dam>0) { X ships[sh]->damage = totaldam; X sprintf(telegram_not, "BULLETIN!\n %s #%d damaged by mine #%d\n", X Shipnames[ships[sh]->type], sh, shipno); X sprintf(buf," at %s - %d %% damage", prin_ship_orbits(ship), dam); X str_cat(telegram_not, buf); X sprintf(buf,"%s #%d [%d] received %d%% damage\n", X Shipnames[ships[sh]->type], sh, X ships[sh]->owner, rad); X str_cat(telegram_buf, buf); X if (ships[sh]->damage >= 100) { X kill_ship(ships[sh]); X sprintf(buf, " %s #%d DESTROYED",Shipnames[ships[sh]->type],sh); X str_cat(telegram_not, buf); X sprintf(buf,"\t--DESTROYED\n"); X str_cat(telegram_buf, buf); X } X push_message(TELEG_PLAYER_AUTO, ships[sh]->owner, telegram_not); X } X } X X } X X sh = ships[sh]->nextship; X } X } X push_message(TELEG_PLAYER_AUTO, ship->owner, telegram_buf); X } X break; X X case STYPE_MIRROR: X switch (ship->aimed_at.level) { X case LEVEL_SHIP: /* ship aimed at is a legal ship now */ X /* if in the same system */ X if ( (ship->whatorbits==LEVEL_STAR || ship->whatorbits==LEVEL_PLAN) X && (ships[ship->aimed_at.shipno]!=NULL) X && (ships[ship->aimed_at.shipno]->whatorbits==LEVEL_STAR || X ships[ship->aimed_at.shipno]->whatorbits==LEVEL_PLAN) X && ship->storbits == ships[ship->aimed_at.shipno]->storbits X && ships[ship->aimed_at.shipno]->is_alive ) { X shiptype *s; X reg int i; X float range; X s = ships[ship->aimed_at.shipno]; X range = sqrt(Distsq(ship->xpos, ship->ypos,s->xpos,s->ypos)); X i = int_rand(0,round_rand((2./((float)Size(s))) X *(float)ship->aimed_at.intensity/(range/PLORBITSIZE+1.0))); X sprintf(telegram_buf, "Space Mirror #%d %s [owner %d] aimed at ", X shipno, ship->name, ship->owner); X str_cat(telegram_buf, buf); X sprintf(buf, "%s #%d %s [owner %d] !\n",Shipnames[s->type], X ship->aimed_at.shipno, s->name, s->owner); X str_cat(telegram_buf, buf); X s->damage += i; X if(i) { X sprintf(buf, "\n%d%% damage done.\n",i); X str_cat(telegram_buf, buf); X } X if (s->damage >= 100) { X sprintf(buf, "%s #%d DESTROYED!!!\n",Shipnames[s->type], X ship->aimed_at.shipno); X kill_ship(s); X } X X push_message(TELEG_PLAYER_AUTO, s->owner, telegram_buf); X push_message(TELEG_PLAYER_AUTO, ship->owner, telegram_buf); X } X break; X case LEVEL_PLAN: { reg short *t; X reg int i; X float range; X range = sqrt(Distsq(ship->xpos, ship->ypos, X Stars[ship->storbits]->xpos X +planets[ship->storbits][ship->pnumorbits]->xpos, X Stars[ship->storbits]->ypos X +planets[ship->storbits][ship->pnumorbits]->ypos)); X X if ( range > PLORBITSIZE ) X i = PLORBITSIZE * ship->aimed_at.intensity/range; X else X i = ship->aimed_at.intensity; X X i = round_rand(.01*(100.0-(float)ship->damage)*(float)i); X Stinfo[ship->storbits][ship->aimed_at.pnum].temp_add += i; X X } break; X X case LEVEL_STAR: { float range; X /* have to be in the same system as the star; otherwise X it's not too fair.. */ X if (ship->aimed_at.snum>0 && X ship->aimed_at.snum < Sdata.numstars && X ship->whatorbits > LEVEL_UNIV && X ship->aimed_at.snum == ship->storbits) X Stars[ship->aimed_at.snum]->stability += random()&01; X } break; X case LEVEL_UNIV: X break; X } X break; X case STYPE_GOD: X /* gods have infinite power.... heh heh heh */ X ship->fuel = Max_fuel(ship); X ship->popn = Max_crew(ship); X ship->destruct = Max_destruct(ship); X ship->resource = Max_resource(ship); X break; X X case OTYPE_AP: /* atmospheric processor */ X /* if landed on planet, change conditions to be like race */ X if (ship->is_docked && ship->whatdest==LEVEL_PLAN && ship->on) { X int j,d,a;planettype *p; X p = planets[ship->storbits][ship->pnumorbits]; X if (ship->fuel >= 3.0) { X ship->fuel -= 3.0; X for (j=RTEMP+1; j<=OTHER; j++) { X if ( (d = races[ship->owner-1]->conditions[j] - X p->conditions[j]) != 0) { X X a = sgn(d)*int_rand(-1, X round_rand(MIN(3,d*sgn(d)) X *(float)ship->popn/(float)Shipdata[OTYPE_AP][ABIL_MAXCREW])); X if (p->conditions[j] + a < 0) X p->conditions[j] = 0; X else if (p->conditions[j] + a > 100) X p->conditions[j] = 100; X else p->conditions[j] += a; X } X } X } else if (!ship->notified) { X ship->notified = 1; X msg_OOF(ship, shipno, telegram_buf); X } X } X break; X X case OTYPE_VN: /* Von Neumann machine */ X do_VN(ship,shipno); X break; X X case OTYPE_BERS: /* Berserker */ X /* (turn done in doplanet() ) */ X break; X X case STYPE_ASS: X /* "indimidate" the planet below, for enslavement purposes. */ X if (ship->whatorbits==LEVEL_PLAN) X Stinfo[ship->storbits][ship->pnumorbits].intimidated = 1; X break; X X case OTYPE_OMCL: X /* orbital mind control laser */ X if (ship->aimed_at.level==LEVEL_PLAN && ship->on && X ship->speed==1) { X planets[ship->aimed_at.snum][ship->aimed_at.pnum] X ->is_sheep = 1; X } X break; X X case STYPE_HABITAT:{ reg int add; X /* habitats multiply some resources inside them. */ X add = ship->resource * X ((float)ship->popn / Shipdata[STYPE_HABITAT][ABIL_MAXCREW]) X * (100 - ship->damage) * 0.0005; X if (ship->resource+add > Shipdata[STYPE_HABITAT][ABIL_CARGO]) X add = Shipdata[STYPE_HABITAT][ABIL_CARGO] - ship->resource; X ship->resource += add; X ship->mass += add * MASS_RESOURCE; X add = ship->popn * races[ship->owner-1]->birthrate * X (100 - ship->damage) * 0.002; X if (ship->popn+add > Shipdata[STYPE_HABITAT][ABIL_MAXCREW]) X add = Shipdata[STYPE_HABITAT][ABIL_MAXCREW] - ship->popn; X ship->popn += add; X ship->mass += add * races[ship->owner-1]->mass; X } break; X X case STYPE_POD: X if (ship->notified) { X /* we just arrived at this system -- explode */ X /* or, we are floating in space with no fuel -- just die */ X reg int i,f; X X f = -1; X kill_ship(ship); X if (ship->whatorbits==LEVEL_STAR) { X X i = int_rand(0,Stars[ship->storbits]->numplanets - 1); X X if(int_rand(1,4)==1) X f = i; X X sprintf(telegram_buf, "Bulletin\n\nSpore pod #%d has warmed and exploded.\n",shipno); X if (f != -1) { X sprintf(buf,"A spore has landed on planet %s.\n",Stars[ship->storbits]->pnames[f]); X Stinfo[ship->storbits][f].Thing_add = ship->owner; X /* so doplanet does not pass over it */ X StarsInhab[ship->storbits] = 1; X setbit(Stars[ship->storbits]->inhabited,ship->owner); X setbit(Stars[ship->storbits]->explored, ship->owner); X planets[ship->storbits][f]->info[ship->owner-1].explored = 1; X } else { X sprintf(buf,"No spores have survived.\n"); X } X str_cat(telegram_buf, buf); X push_message(TELEG_PLAYER_AUTO, ship->owner, telegram_buf); X sprintf(telegram_buf,"BULLETIN!\n\n A spore pod has exploded in system /%s.\n", X Stars[ship->storbits]->name); X sprintf(buf, "Spores may have drifted to planets here.\n"); X str_cat(telegram_buf, buf); X for (i=1; i<=Num_races; i++) X if (i!=ship->owner && isset(Stars[ship->storbits]->inhabited,i)) X push_message(TELEG_PLAYER_AUTO, i, telegram_buf); X X } X } X break; X X default: X break; X } X X } X X } else if (!ship->is_alive && !ship->notified) { X /* ship is dead -- add to shipfree file, remove from all lists. */ X /* if notified, this means it's already been deleted and written. */ X/* printf("destroyed ship #%d\n",shipno);*/ X if (ship->type == OTYPE_VN || ship->type==OTYPE_BERS) { X X /* add ship to VN shit list */ X X if (ship->object.number2>0 && ship->object.number2<=Num_races X && ship->object.number2 != ship->owner) { X Sdata.VN_hitlist[ship->object.number2-1] ++; X X /* keep track of where these VN's were shot up */ X X if (Sdata.VN_index1[ship->object.number2]== 255) X /* there's no star in the first index */ X Sdata.VN_index1[ship->object.number2] = ship->storbits; X else if (Sdata.VN_index2[ship->object.number2]== 255) X /* there's no star in the second index */ X Sdata.VN_index2[ship->object.number2] = ship->storbits; X else { X /* pick an index to supplant */ X if (random()&01) X Sdata.VN_index1[ship->object.number2] = ship->storbits; X else X Sdata.VN_index2[ship->object.number2] = ship->storbits; X } X printf("\t-- added %d ships, player %d\n", X ship->object.number, ship->object.number2); X } X } X ship->notified = 1; X makeshipdead(shipno); X } X X} END_OF_FILE if test 16262 -ne `wc -c <'server/doship.c'`; then echo shar: \"'server/doship.c'\" unpacked with wrong size! fi # end of 'server/doship.c' fi echo shar: End of archive 2 \(of 14\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 14 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0