1 // Emacs style mode select -*- C++ -*-
2 //---------------------------------------------------------------------------
3 //
4 // $Id: swinit.c,v 1.5.2.2 2003/06/08 18:16:38 fraggle Exp $
5 //
6 // Copyright(C) 1984-2000 David L. Clark
7 // Copyright(C) 2001-2003 Simon Howard
8 //
9 // This program is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License as published by the
11 // Free Software Foundation; either version 2 of the License, or (at your
12 // option) any later version. This program is distributed in the hope that
13 // it will be useful, but WITHOUT ANY WARRANTY; without even the implied
14 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 // the GNU General Public License for more details. You should have
16 // received a copy of the GNU General Public License along with this
17 // program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 // Place - Suite 330, Boston, MA 02111-1307, USA.
19 //
20 //---------------------------------------------------------------------------
21 //
22 //        swinit   -      SW initialization
23 //
24 //---------------------------------------------------------------------------
25 
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <time.h>
30 #include <SDL.h>
31 
32 #include "pcsound.h"
33 #include "timer.h"
34 #include "video.h"
35 
36 #include "sw.h"
37 #include "swasynio.h"
38 #include "swcollsn.h"
39 #include "swconf.h"
40 #include "swdisp.h"
41 #include "swend.h"
42 #include "swinit.h"
43 #include "swgames.h"
44 #include "swground.h"
45 #include "swgrpha.h"
46 #include "swmain.h"
47 #include "swmisc.h"
48 #include "swmove.h"
49 #include "swobject.h"
50 #include "swsound.h"
51 #include "swsymbol.h"
52 #include "swtitle.h"
53 #include "swutil.h"
54 
55 static int savescore;		/* save players score on restart  */
56 static BOOL ghost;		/* ghost display flag             */
57 static int starting_level = 0;
58 static int conf_explosions = 1;
59 
60 static char helptxt[] =
61 "\n"
62 "SDL Sopwith " VERSION "\n"
63 "Copyright (C) 1984-2000 David L. Clark\n"
64 "Copyright (C) 2001 Simon Howard\n"
65 "Copyright (C) 2012 Jesse Smith\n"
66 "\n"
67 "Usage:  sopwith [options]\n"
68 "The options are:\n"
69 "        -n :  novice single player\n"
70 "        -s :  single player\n"
71 "        -c :  single player against computer\n"
72 "        -x :  enable missiles\n"
73 "        -q :  begin game with sound off (default)\n"
74 "        -p :  turn sound on\n"
75 "        -g#:  start at level #\n"
76 "        -e :  turn off big explosions\n"
77 "\n"
78 "Video:\n"
79 "        -f :  fullscreen\n"
80 "        -2 :  double scale window\n"
81 "\n"
82 #ifdef TCPIP
83 "Networking: \n"
84 "        -l :  listen for connection\n"
85 " -j <host> :  connect to a listening host\n"
86 #endif
87 ;
88 
89 // old options
90 // "        -m :  multiple players on a network\n"
91 //"        -a :  2 players over asynchrounous communications line\n"
92 //"              (Only one of -n, -s, -c, -a may be specified)\n"
93 //"        -k :  keyboard only\n"
94 //"        -j :  joystick and keyboard\n"
95 //"              (Only one of -k and -j  may be specified)\n"
96 ////        "        -i :  IBM PC keyboard\n"
97 //  "        -r :  resets the multiuser communications file after an abnormal"
98 //  "                  end of a game"
99 //  "        -d*:  overrides the default drive C as the device containing the"
100 //  "                  communications file"
101 //"        -p#:  overrides asynchronous port 1 as the asynchrounous port\n"
102 //"                  to use\n"
103 
initwobj()104 static void initwobj()
105 {
106 	int x;
107 	OBJECTS *ob;
108 	OLDWDISP *ow;
109 
110 	ow = wdisp;
111 	ob = nobjects;
112 	for (x = 0; x < MAX_OBJS; ++x, ow++, ob++)
113 		ow->ow_xorplot = ob->ob_drwflg = ob->ob_delflg = 0;
114 
115 	for (x = 0; x < MAX_TARG; ++x) {
116 		ob = targets[x];
117 		if (ob && ob->ob_state != FINISHED)
118 			dispwobj(ob);
119 	}
120 
121 }
122 
123 
124 // sdh 28/10/2001: moved auxdisp graphic functions into swgrpha.c
125 
initobjs()126 static void initobjs()
127 {
128 	OBJECTS *ob;
129 	int o;
130 
131 	topobj.ob_xnext = topobj.ob_next = &botobj;
132 	botobj.ob_xprev = botobj.ob_prev = &topobj;
133 	topobj.ob_x = -32767;
134 	botobj.ob_x = 32767;
135 
136 	objbot = objtop = deltop = delbot = NULL;
137 	objfree = ob = nobjects;
138 
139 	for (o = 0; o < MAX_OBJS; ++o) {
140 		ob->ob_next = ob + 1;
141 		(ob++)->ob_index = o;
142 	}
143 
144 	(--ob)->ob_next = NULL;
145 }
146 
147 
initgrnd()148 static void initgrnd()
149 {
150 	// sdh 16/11/200; removed movmem
151 
152 	memcpy(ground, orground, sizeof(GRNDTYPE) * MAX_X);
153 }
154 
initseed()155 static void initseed()
156 {
157 	srand(clock());
158 	explseed = rand() % 65536;
159 
160 	// sdh 28/4/2002: removed atari and ibm code
161 }
162 
163 
164 
165 //
166 // status bar code
167 //
168 
initscore()169 static void initscore()
170 {
171 	if (savescore) {
172 		nobjects[0].ob_score = savescore;
173 		savescore = 0;
174 	}
175 
176 	dispscore(&nobjects[0]);
177 	if (playmode == PLAYMODE_ASYNCH)
178 		dispscore(&nobjects[1]);
179 }
180 
181 
182 
183 
dispgge(int x,int cury,int maxy,int clr)184 static void dispgge(int x, int cury, int maxy, int clr)
185 {
186 	int y;
187 
188 	if (ghost)
189 		return;
190 
191 	cury = cury * 10 / maxy - 1;
192 	if (cury > 9)
193 		cury = 9;
194 	for (y = 0; y <= cury; ++y)
195 		Vid_PlotPixel(x, y, clr);
196 	for (; y <= 9; ++y)
197 		Vid_PlotPixel(x, y, 0);
198 }
199 
200 // sdh 26/10/2001: merged guage functions into a single function
201 
dispguages(OBJECTS * ob)202 void dispguages(OBJECTS *ob)
203 {
204 	int x = GUAGEX;
205 	int sep = conf_missiles ? 3 : 5;
206 
207 	// crashes/lives
208 
209 	dispgge(x += sep, maxcrash - ob->ob_crashcnt, maxcrash, ob->ob_clr);
210 
211 	// fuel
212 
213 	dispgge(x += sep, ob->ob_life >> 4, MAXFUEL >> 4, ob->ob_clr);
214 
215 	// bombs
216 
217 	dispgge(x += sep, ob->ob_bombs, MAXBOMBS, 3 - ob->ob_clr);
218 
219 	// bullets
220 
221  	dispgge(x += sep, ob->ob_rounds, MAXROUNDS, 3);
222 
223 	if (conf_missiles) {
224 
225 		// missiles
226 
227 		dispgge(x += sep, ob->ob_missiles, MAXMISSILES, ob->ob_clr);
228 
229 // starburst (flares)
230 
231 		dispgge(x += sep, ob->ob_bursts, MAXBURSTS, 3 - ob->ob_clr);
232 	}
233 }
234 
235 
dispworld()236 static void dispworld()
237 {
238 	int x, y, dx, maxh, sx;
239 
240 	dx = 0;
241 	sx = SCR_CENTR;
242 
243 	maxh = 0;
244 	y = 0;
245 
246 	// draw ground
247 
248 	for (x = 0; x < MAX_X; ++x) {
249 
250 		if (ground[x] > maxh)
251 			maxh = ground[x];
252 
253 		if ((++dx) == WRLD_RSX) {
254 			maxh /= WRLD_RSY;
255 			if (maxh == y)
256 				Vid_PlotPixel(sx, maxh, 7);
257 			else if (maxh > y)
258 				for (++y; y <= maxh; ++y)
259 					Vid_PlotPixel(sx, y, 7);
260 			else
261 				for (--y; y >= maxh; --y)
262 					Vid_PlotPixel(sx, y, 7);
263 			y = maxh;
264 			Vid_PlotPixel(sx, 0, 11);
265 			++sx;
266 			dx = maxh = 0;
267 		}
268 	}
269 
270 	// map border
271 
272 	maxh = MAX_Y / WRLD_RSY;
273 	for (y = 0; y <= maxh; ++y) {
274 		Vid_PlotPixel(SCR_CENTR, y, 11);
275 		Vid_PlotPixel(sx, y, 11);
276 	}
277 
278 	// border of status bar
279 
280 	for (x = 0; x < SCR_WDTH; ++x)
281 		Vid_PlotPixel(x, (SCR_MNSH + 2), 7);
282 
283 	Vid_Update();
284 }
285 
286 
287 
initdisp(BOOL reset)288 void initdisp(BOOL reset)
289 {
290 	OBJECTS *ob;
291 	OBJECTS ghostob;
292 
293 	splatox = oxsplatted = 0;
294 	if (!reset) {
295 		clrdispa();
296 		setadisp();
297 		dispworld();
298 		swtitlf();
299 		ghost = FALSE;
300 	}
301 	movedisp();
302 	setvdisp();
303 	initwobj();
304 	initscore();
305 
306 	ob = &nobjects[player];
307 	if (ghost) {
308 		ghostob.ob_type = DUMMYTYPE;
309 		//ghostob.ob_symhgt = ghostob.ob_symwdt = 8;
310 		ghostob.ob_clr = ob->ob_clr;
311 		ghostob.ob_newsym = symbol_ghost;     // sdh 27/6/2002
312 		swputsym(GHOSTX, 12, &ghostob);
313 	} else {
314 		// sdh 26/10/2001: merged guages into a single function
315 
316 		dispguages(ob);
317 	}
318 	dispinit = TRUE;
319 }
320 
321 
322 //
323 // object creation
324 //
325 
326 
327 // static int inits[2] = { 0, 7 };
328 static int inits[4] = { 0, 7, 1, 6 };
329 static int initc[4] = { 0, 7, 1, 6 };
330 static int initm[8] = { 0, 7, 3, 4, 2, 5, 1, 6 };
331 
332 // plane
333 
initpln(OBJECTS * obp)334 OBJECTS *initpln(OBJECTS * obp)
335 {
336 	OBJECTS *ob;
337 	int x, height, minx, maxx, n;
338 
339 	if (!obp)
340 		ob = allocobj();
341 	else
342 		ob = obp;
343 
344 	switch (playmode) {
345 	case PLAYMODE_SINGLE:
346 	case PLAYMODE_NOVICE:
347 		n = inits[ob->ob_index];
348 		break;
349 	case PLAYMODE_ASYNCH:
350 		n = initm[ob->ob_index];
351 		break;
352 	case PLAYMODE_COMPUTER:
353 		n = initc[ob->ob_index];
354 		break;
355 	default:
356 		return NULL;
357 	}
358 
359 	ob->ob_type = PLANE;
360 
361 	ob->ob_x = currgame->gm_x[n];
362 	minx = ob->ob_x;
363 	maxx = ob->ob_x + 20;
364 	height = 0;
365 	for (x = minx; x <= maxx; ++x)
366 		if (ground[x] > height)
367 			height = ground[x];
368 	ob->ob_y = height + 13;
369 	ob->ob_lx = ob->ob_ly = ob->ob_speed = ob->ob_flaps = ob->ob_accel
370 	    = ob->ob_hitcount = ob->ob_bdelay = ob->ob_mdelay
371 	    = ob->ob_bsdelay = 0;
372 	setdxdy(ob, 0, 0);
373 	ob->ob_orient = currgame->gm_orient[n];
374 	ob->ob_angle = (ob->ob_orient) ? (ANGLES / 2) : 0;
375 	ob->ob_target = ob->ob_firing = ob->ob_mfiring = NULL;
376 	ob->ob_bombing = ob->ob_bfiring = ob->ob_home = FALSE;
377 	ob->ob_newsym = symbol_plane[ob->ob_orient][0]; // sdh 27/6/2002
378 	//ob->ob_symhgt = SYM_HGHT;
379 	//ob->ob_symwdt = SYM_WDTH;
380 	ob->ob_athome = TRUE;
381 	if (!obp || ob->ob_state == CRASHED
382 	    || ob->ob_state == GHOSTCRASHED) {
383 		ob->ob_rounds = MAXROUNDS;
384 		ob->ob_bombs = MAXBOMBS;
385 		ob->ob_missiles = MAXMISSILES;
386 		ob->ob_bursts = MAXBURSTS;
387 		ob->ob_life = MAXFUEL;
388 	}
389 	if (!obp) {
390 		ob->ob_score = ob->ob_updcount = ob->ob_crashcnt
391 		    = endsts[ob->ob_index] = 0;
392 		compnear[ob->ob_index] = NULL;
393 		insertx(ob, &topobj);
394 	} else {
395 		deletex(ob);
396 		insertx(ob, ob->ob_xnext);
397 	}
398 
399 	if (playmode == PLAYMODE_ASYNCH && ob->ob_crashcnt >= maxcrash) {
400 		ob->ob_state = GHOST;
401 		if (ob->ob_index == player)
402 			ghost = TRUE;
403 	} else
404 		ob->ob_state = FLYING;
405 
406 	return (ob);
407 }
408 
409 
410 
411 // player
412 
initplyr(OBJECTS * obp)413 void initplyr(OBJECTS * obp)
414 {
415 	OBJECTS *ob;
416 	OBJECTS *initpln();
417 
418 	ob = initpln(obp);
419 	if (!obp) {
420 		ob->ob_drawf = dispplyr;
421 		ob->ob_movef = moveplyr;
422 		ob->ob_clr = ob->ob_index % 2 + 1;
423 		ob->ob_owner = ob;
424 		oobjects[ob->ob_index] = *ob;  // sdh 16/11: removed movmem
425 		goingsun = FALSE;
426 		endcount = 0;
427 	}
428 
429 	displx = ob->ob_x - SCR_CENTR;
430 
431 	swflush();
432 }
433 
434 // computer opponent
435 
initcomp(OBJECTS * obp)436 void initcomp(OBJECTS * obp)
437 {
438 	OBJECTS *ob;
439 	OBJECTS *initpln();
440 
441 	ob = initpln(obp);
442 	if (!obp) {
443 		ob->ob_drawf = dispcomp;
444 		ob->ob_movef = movecomp;
445 		ob->ob_clr = 2;
446 		if (playmode != PLAYMODE_ASYNCH)
447 			ob->ob_owner = &nobjects[1];
448 		else if (ob->ob_index == 1)
449 			ob->ob_owner = ob;
450 		else
451 			ob->ob_owner = ob - 2;
452 		oobjects[ob->ob_index] = *ob;  // sdh 16/11: removed movmem
453 	}
454 	if (playmode == PLAYMODE_SINGLE || playmode == PLAYMODE_NOVICE) {
455 		ob->ob_state = FINISHED;
456 		deletex(ob);
457 	}
458 }
459 
460 
isrange(int x,int y,int ax,int ay)461 static int isrange(int x, int y, int ax, int ay)
462 {
463 	int dx, dy, t;
464 
465 	dy = abs(y - ay);
466 	dy += dy >> 1;
467 	dx = abs(x - ax);
468 
469 	if (dx > 100 || dy > 100)
470 		return -1;
471 
472 	if (dx < dy) {
473 		t = dx;
474 		dx = dy;
475 		dy = t;
476 	}
477 
478 	return (7 * dx + 4 * dy) / 8;
479 }
480 
481 // bullet
482 
initshot(OBJECTS * obop,OBJECTS * targ)483 void initshot(OBJECTS * obop, OBJECTS * targ)
484 {
485 	OBJECTS *ob, *obo = obop;
486 	int nangle, nspeed, dx, dy, r, bspeed, x, y;
487 
488 	if (!targ && !compplane && !obo->ob_rounds)
489 		return;
490 
491 	ob = allocobj();
492 
493 	if (!ob)
494 		return;
495 
496 	obo = obop;
497 	if (playmode != PLAYMODE_NOVICE)
498 		--obo->ob_rounds;
499 
500 	bspeed = BULSPEED + gamenum;
501 
502 	if (targ) {
503 		x = targ->ob_x + (targ->ob_dx << 2);
504 		y = targ->ob_y + (targ->ob_dy << 2);
505 		dx = x - obo->ob_x;
506 		dy = y - obo->ob_y;
507 
508 		r = isrange(x, y, obo->ob_x, obo->ob_y);
509 		if (r < 1) {
510 			deallobj(ob);
511 			return;
512 		}
513 		ob->ob_dx = (dx * bspeed) / r;
514 		ob->ob_dy = (dy * bspeed) / r;
515 		ob->ob_ldx = ob->ob_ldy = 0;
516 	} else {
517 		nspeed = obo->ob_speed + bspeed;
518 		nangle = obo->ob_angle;
519 		setdxdy(ob, nspeed * COS(nangle), nspeed * SIN(nangle));
520 	}
521 
522 	ob->ob_type = SHOT;
523 	ob->ob_x = obo->ob_x + SYM_WDTH / 2;
524 	ob->ob_y = obo->ob_y - SYM_HGHT / 2;
525 	ob->ob_lx = obo->ob_lx;
526 	ob->ob_ly = obo->ob_ly;
527 
528 	ob->ob_life = BULLIFE;
529 	ob->ob_owner = obo;
530 	ob->ob_clr = obo->ob_clr;
531 	ob->ob_newsym = &symbol_pixel;                 // sdh 27/6/2002
532 	//ob->ob_symhgt = ob->ob_symwdt = 1;
533 	ob->ob_drawf = NULL;
534 	ob->ob_movef = moveshot;
535 	ob->ob_speed = 0;
536 
537 	insertx(ob, obo);
538 
539 }
540 
541 // bomb
542 
initbomb(OBJECTS * obop)543 void initbomb(OBJECTS * obop)
544 {
545 	OBJECTS *ob, *obo = obop;
546 	int angle;
547 
548 	if ((!compplane && !obo->ob_bombs) || obo->ob_bdelay)
549 		return;
550 
551 	ob = allocobj();
552 	if (!ob)
553 		return;
554 
555 	if (playmode != PLAYMODE_NOVICE)
556 		--obo->ob_bombs;
557 
558 	obo->ob_bdelay = 10;
559 
560 	ob->ob_type = BOMB;
561 	ob->ob_state = FALLING;
562 	ob->ob_dx = obo->ob_dx;
563 	ob->ob_dy = obo->ob_dy;
564 
565 	if (obo->ob_orient)
566 		angle = (obo->ob_angle + (ANGLES / 4)) % ANGLES;
567 	else
568 		angle = (obo->ob_angle + (3 * ANGLES / 4)) % ANGLES;
569 
570 	ob->ob_x = obo->ob_x + ((COS(angle) * 10) >> 8) + 4;
571 	ob->ob_y = obo->ob_y + ((SIN(angle) * 10) >> 8) - 4;
572 	ob->ob_lx = ob->ob_ly = ob->ob_ldx = ob->ob_ldy = 0;
573 
574 	ob->ob_life = BOMBLIFE;
575 	ob->ob_owner = obo;
576 	ob->ob_clr = obo->ob_clr;
577 	ob->ob_newsym = symbol_bomb[0];           // sdh 27/6/2002
578 	//ob->ob_symhgt = ob->ob_symwdt = 8;
579 	ob->ob_drawf = dispbomb;
580 	ob->ob_movef = movebomb;
581 
582 	insertx(ob, obo);
583 
584 }
585 
586 // missile
587 
initmiss(OBJECTS * obop)588 void initmiss(OBJECTS * obop)
589 {
590 	OBJECTS *ob, *obo = obop;
591 	int angle, nspeed;
592 
593 	if (obo->ob_mdelay || !obo->ob_missiles || !conf_missiles)
594 		return;
595 
596 	ob = allocobj();
597 	if (!ob)
598 		return;
599 
600 	if (playmode != PLAYMODE_NOVICE)
601 		--obo->ob_missiles;
602 
603 	obo->ob_mdelay = 5;
604 
605 	ob->ob_type = MISSILE;
606 	ob->ob_state = FLYING;
607 
608 	angle = ob->ob_angle = obo->ob_angle;
609 	ob->ob_x = obo->ob_x + (COS(angle) >> 4) + 4;
610 	ob->ob_y = obo->ob_y + (SIN(angle) >> 4) - 4;
611 	ob->ob_lx = ob->ob_ly = 0;
612 	ob->ob_speed = nspeed = gmaxspeed + (gmaxspeed >> 1);
613 	setdxdy(ob, nspeed * COS(angle), nspeed * SIN(angle));
614 
615 	ob->ob_life = MISSLIFE;
616 	ob->ob_owner = obo;
617 	ob->ob_clr = obo->ob_clr;
618 	ob->ob_newsym = symbol_missile[0];           // sdh 27/6/2002
619 	//ob->ob_symhgt = ob->ob_symwdt = 8;
620 	ob->ob_drawf = dispmiss;
621 	ob->ob_movef = movemiss;
622 	ob->ob_target = obo->ob_mfiring;
623 	ob->ob_orient = ob->ob_accel = ob->ob_flaps = 0;
624 
625 	insertx(ob, obo);
626 
627 }
628 
629 
630 // starburst
631 
initburst(OBJECTS * obop)632 void initburst(OBJECTS * obop)
633 {
634 	OBJECTS *ob, *obo = obop;
635 	int angle;
636 
637 	if (obo->ob_bsdelay || !obo->ob_bursts || !conf_missiles)
638 		return;
639 
640 	ob = allocobj();
641 	if (!ob)
642 		return;
643 
644 	ob->ob_bsdelay = 5;
645 
646 	if (playmode != PLAYMODE_NOVICE)
647 		--obo->ob_bursts;
648 
649 	ob->ob_type = STARBURST;
650 	ob->ob_state = FALLING;
651 
652 	if (obo->ob_orient)
653 		angle = (obo->ob_angle + (3 * ANGLES / 8)) % ANGLES;
654 	else
655 		angle = (obo->ob_angle + (5 * ANGLES / 8)) % ANGLES;
656 
657 	setdxdy(ob, gminspeed * COS(angle), gminspeed * SIN(angle));
658 	ob->ob_dx += obo->ob_dx;
659 	ob->ob_dy += obo->ob_dy;
660 
661 	ob->ob_x = obo->ob_x + ((COS(angle) * 10) >> 10) + 4;
662 	ob->ob_y = obo->ob_y + ((SIN(angle) * 10) >> 10) - 4;
663 	ob->ob_lx = ob->ob_ly = 0;
664 
665 	ob->ob_life = BURSTLIFE;
666 	ob->ob_owner = obo;
667 	ob->ob_clr = obo->ob_clr;
668 	ob->ob_newsym = symbol_burst[0];             // sdh 27/6/2002
669 	//ob->ob_symhgt = ob->ob_symwdt = 8;
670 	ob->ob_drawf = dispburst;
671 	ob->ob_movef = moveburst;
672 
673 	insertx(ob, obo);
674 
675 }
676 
677 // building/target
678 
inittarg()679 static void inittarg()
680 {
681 	OBJECTS *ob;
682 	int x, i;
683 	int *tx, *tt;
684 	int minh, maxh, aveh, minx, maxx;
685 
686 	tx = currgame->gm_xtarg;
687 	tt = currgame->gm_ttarg;
688 
689 	if (playmode != PLAYMODE_ASYNCH) {
690 		numtarg[0] = 0;
691 		numtarg[1] = MAX_TARG - 3;
692 	} else {
693 		numtarg[0] = numtarg[1] = MAX_TARG / 2;
694 	}
695 
696 	for (i = 0; i < MAX_TARG; ++i, ++tx, ++tt) {
697 		targets[i] = ob = allocobj();
698 		minx = ob->ob_x = *tx;
699 		maxx = ob->ob_x + 15;
700 		minh = 999;
701 		maxh = 0;
702 		for (x = minx; x <= maxx; ++x) {
703 			if (ground[x] > maxh)
704 				maxh = ground[x];
705 			if (ground[x] < minh)
706 				minh = ground[x];
707 		}
708 		aveh = (minh + maxh) / 2;
709 
710 		while ((ob->ob_y = aveh + 16) >= MAX_Y)
711 			--aveh;
712 
713 		for (x = minx; x <= maxx; ++x)
714 			ground[x] = aveh;
715 
716 		ob->ob_dx = ob->ob_dy = ob->ob_lx = ob->ob_ly = ob->ob_ldx
717 		    = ob->ob_ldy = ob->ob_angle = ob->ob_hitcount = 0;
718 		ob->ob_type = TARGET;
719 		ob->ob_state = STANDING;
720 		ob->ob_orient = *tt;
721 		ob->ob_life = i;
722 
723 		if (playmode != PLAYMODE_ASYNCH)
724 			ob->ob_owner =
725 				&nobjects[(i < MAX_TARG / 2
726 					   && i > MAX_TARG / 2 - 4)
727 						? 0 : 1];
728 		else
729 			ob->ob_owner = &nobjects[i >= (MAX_TARG / 2)];
730 		ob->ob_clr = ob->ob_owner->ob_clr;
731 		ob->ob_newsym = symbol_targets[0];      // sdh 27/6/2002
732 		//ob->ob_symhgt = ob->ob_symwdt = 16;
733 		ob->ob_drawf = disptarg;
734 		ob->ob_movef = movetarg;
735 
736 		insertx(ob, &topobj);
737 	}
738 }
739 
740 // explosion
741 
initexpl(OBJECTS * obop,int small)742 void initexpl(OBJECTS * obop, int small)
743 {
744 	OBJECTS *ob, *obo = obop;
745 	int i, ic, speed;
746 	// int life;
747 	int obox, oboy, obodx, obody, oboclr;
748 	obtype_t obotype;
749 	BOOL mansym;
750 	int orient;
751 
752 	obox = obo->ob_x + (obo->ob_newsym->w / 2);
753 	oboy = obo->ob_y + (obo->ob_newsym->h / 2);
754 	obodx = obo->ob_dx >> 2;
755 	obody = obo->ob_dy >> 2;
756 	oboclr = obo->ob_clr;
757 
758 	obotype = obo->ob_type;
759 	if (obotype == TARGET && obo->ob_orient == 2) {
760 		ic = 1;
761                 // adding in option here for large oil tank explosions
762                 // - Jesse
763                 if (conf_explosions)
764                    speed = gminspeed * 4 / 3;
765                 else
766 		   speed = gminspeed;
767 	} else {
768 		ic = small ? 6 : 2;
769 		speed = gminspeed >> ((explseed & 7) != 7);
770 	}
771 	mansym = obotype == PLANE
772 		 && (obo->ob_state == FLYING || obo->ob_state == WOUNDED);
773 
774 	for (i = 1; i <= 15; i += ic) {
775 		ob = allocobj();
776 		if (!ob)
777 			return;
778 
779 		ob->ob_type = EXPLOSION;
780 
781 		setdxdy(ob, COS(i) * speed, SIN(i) * speed);
782 		ob->ob_dx += obodx;
783 		ob->ob_dy += obody;
784 
785 		ob->ob_x = obox + ob->ob_dx;
786 		ob->ob_y = oboy + ob->ob_dy;
787 		explseed *= ob->ob_x * ob->ob_y;
788 		explseed += 7491;
789 		if (!explseed)
790 			explseed = 74917777;
791 
792 		ob->ob_life = EXPLLIFE;
793 		orient = ob->ob_orient = (explseed & 0x01C0) >> 6;
794 		if (mansym && (!orient || orient == 7)) {
795 			mansym = orient = ob->ob_orient = 0;
796 			ob->ob_dx = obodx;
797 			ob->ob_dy = -gminspeed;
798 		}
799 
800 		ob->ob_lx = ob->ob_ly = ob->ob_hitcount = ob->ob_speed = 0;
801 		ob->ob_owner = obo;
802 		ob->ob_clr = oboclr;
803 		ob->ob_newsym = symbol_debris[0];            // sdh 27/6/2002
804 		//ob->ob_symhgt = ob->ob_symwdt = 8;
805 		ob->ob_drawf = dispexpl;
806 		ob->ob_movef = moveexpl;
807 
808 		if (orient)
809 			initsound(ob, S_EXPLOSION);
810 
811 		insertx(ob, obo);
812 	}
813 }
814 
815 // smoke from falling plane
816 
initsmok(OBJECTS * obop)817 void initsmok(OBJECTS * obop)
818 {
819 	OBJECTS *ob, *obo=obop;
820 
821 	ob = allocobj();
822 	if (!ob)
823 		return;
824 
825 	ob->ob_type = SMOKE;
826 
827 	ob->ob_x = obo->ob_x + 8;
828 	ob->ob_y = obo->ob_y - 8;
829 	ob->ob_dx = obo->ob_dx;
830 	ob->ob_dy = obo->ob_dy;
831 	ob->ob_lx = ob->ob_ly = ob->ob_ldx = ob->ob_ldy = 0;
832 	ob->ob_life = SMOKELIFE;
833 	ob->ob_owner = obo;
834 	ob->ob_drawf = NULL;
835 	ob->ob_movef = movesmok;
836 	ob->ob_clr = obo->ob_clr;
837 }
838 
839 
840 
841 
842 
843 // birds
844 
initflck()845 static void initflck()
846 {
847 	static int ifx[] =
848 		{ MINFLCKX, MINFLCKX + 1000, MAXFLCKX - 1000, MAXFLCKX };
849 	static int ify[] = { MAX_Y - 1, MAX_Y - 1, MAX_Y - 1, MAX_Y - 1 };
850 	static int ifdx[] = { 2, 2, -2, -2 };
851 	OBJECTS *ob;
852 	int i, j;
853 
854 	// sdh 28/10/2001: option to disable animals
855 
856 	if (playmode == PLAYMODE_NOVICE || !conf_animals)
857 		return;
858 
859 	for (i = 0; i < MAX_FLCK; ++i) {
860 
861 		ob = allocobj();
862 		if (!ob)
863 			return;
864 
865 		ob->ob_type = FLOCK;
866 		ob->ob_state = FLYING;
867 		ob->ob_x = ifx[i];
868 		ob->ob_y = ify[i];
869 		ob->ob_dx = ifdx[i];
870 		ob->ob_dy = ob->ob_lx = ob->ob_ly = ob->ob_ldx =
871 		    ob->ob_ldy = 0;
872 		ob->ob_orient = 0;
873 		ob->ob_life = FLOCKLIFE;
874 		ob->ob_owner = ob;
875 		ob->ob_newsym = symbol_flock[0];            // sdh 27/6/2002
876 		//ob->ob_symhgt = ob->ob_symwdt = 16;
877 		ob->ob_drawf = dispflck;
878 		ob->ob_movef = moveflck;
879 		ob->ob_clr = 9;
880 		insertx(ob, &topobj);
881 		for (j = 0; j < MAX_BIRD; ++j)
882 			initbird(ob, 1);
883 	}
884 }
885 
886 // single bird
887 
initbird(OBJECTS * obop,int i)888 void initbird(OBJECTS * obop, int i)
889 {
890 	OBJECTS *ob, *obo = obop;
891 	static int ibx[] = { 8, 3, 0, 6, 7, 14, 10, 12 };
892 	static int iby[] = { 16, 1, 8, 3, 12, 10, 7, 14 };
893 	static int ibdx[] = { -2, 2, -3, 3, -1, 1, 0, 0 };
894 	static int ibdy[] = { -1, -2, -1, -2, -1, -2, -1, -2 };
895 
896 	ob = allocobj();
897 	if (!ob)
898 		return;
899 
900 	ob->ob_type = BIRD;
901 
902 	ob->ob_x = obo->ob_x + ibx[i];
903 	ob->ob_y = obo->ob_y - iby[i];
904 	ob->ob_dx = ibdx[i];
905 	ob->ob_dy = ibdy[i];
906 	ob->ob_orient = ob->ob_lx = ob->ob_ly = ob->ob_ldx = ob->ob_ldy =
907 	    0;
908 	ob->ob_life = BIRDLIFE;
909 	ob->ob_owner = obo;
910 	ob->ob_newsym = symbol_bird[0];                // sdh 27/6/2002
911 	//ob->ob_symhgt = 2;
912 	//ob->ob_symwdt = 4;
913 	ob->ob_drawf = dispbird;
914 	ob->ob_movef = movebird;
915 	ob->ob_clr = obo->ob_clr;
916 	insertx(ob, obo);
917 }
918 
919 // oxen
920 
initoxen()921 static void initoxen()
922 {
923 	OBJECTS *ob;
924 	int i;
925 	static int iox[] = { 1376, 1608 };
926 	static int ioy[] = { 80, 91 };
927 
928 	// sdh 28/10/2001: option to disable animals
929 
930 	if (playmode == PLAYMODE_NOVICE || !conf_animals) {
931 		for (i = 0; i < MAX_OXEN; ++i)
932 			targets[MAX_TARG + i] = NULL;
933 		return;
934 	}
935 
936 	for (i = 0; i < MAX_OXEN; ++i) {
937 		ob = allocobj();
938 		if (!ob)
939 			return;
940 
941 		targets[MAX_TARG + i] = ob;
942 
943 		ob->ob_type = OX;
944 		ob->ob_state = STANDING;
945 		ob->ob_x = iox[i];
946 		ob->ob_y = ioy[i];
947 		ob->ob_orient = ob->ob_lx = ob->ob_ly = ob->ob_ldx =
948 		    ob->ob_ldy = ob->ob_dx = ob->ob_dy = 0;
949 		ob->ob_owner = ob;
950 		//ob->ob_symhgt = 16;
951 		//ob->ob_symwdt = 16;
952 		ob->ob_newsym = symbol_ox[0];             // sdh 27/6/2002
953 		ob->ob_drawf = NULL;
954 		ob->ob_movef = moveox;
955 		ob->ob_clr = 1;
956 		insertx(ob, &topobj);
957 	}
958 }
959 
960 
961 
962 
initgdep()963 static void initgdep()
964 {
965 	gmaxspeed = MAX_SPEED + gamenum;
966 	gminspeed = MIN_SPEED + gamenum;
967 
968 	targrnge = 150;
969 	if (gamenum < 6)
970 		targrnge -= 15 * (6 - gamenum);
971 	targrnge *= targrnge;
972 }
973 
974 // sdh 27/10/2001: created
975 
swinitlevel()976 void swinitlevel()
977 {
978 	if (playmode == PLAYMODE_ASYNCH)
979 		init1asy();
980 
981 	// sdh 16/11/2001: this needs to be reset with each new game
982 	// to keep netgames in sync if we have already played
983 
984 	countmove = 0;
985 
986 	// sdh: dont carry hud splats forward from previous games
987 
988 	splatox = splatbird = shothole = 0;
989 
990 	initsndt();
991 	initgrnd();
992 	initobjs();
993 
994 	if (keydelay == -1)
995 		keydelay = 1;
996 
997 	if (playmode == PLAYMODE_ASYNCH) {
998 		maxcrash = MAXCRASH * 2;
999 		init2asy();
1000 	} else {
1001 		maxcrash = MAXCRASH;
1002 		currgame = &swgames[0];
1003 
1004 		// single player
1005 
1006 		initplyr(NULL);
1007 		initcomp(NULL);
1008 		initcomp(NULL);
1009 		initcomp(NULL);
1010 	}
1011 
1012 	inittarg();
1013 
1014 	if (currgame->gm_specf)
1015 		(*currgame->gm_specf) ();
1016 
1017 	initdisp(NO);
1018 	initflck();
1019 	initoxen();
1020 	initgdep();
1021 
1022 	inplay = TRUE;
1023 }
1024 
swrestart()1025 void swrestart()
1026 {
1027 	OBJECTS *ob;
1028 	int inc;
1029 	int time;
1030 
1031 	if (endsts[player] == WINNER) {
1032 		ob = &nobjects[player];
1033 		inc = 0;
1034 		while (ob->ob_crashcnt++ < maxcrash) {
1035 			ob->ob_score += (inc += 25);
1036 			setvdisp();
1037 			dispguages(ob);
1038 			dispscore(ob);
1039 
1040 			Vid_Update();
1041 
1042 			// sdh 27/10/2001: use new time code for delay
1043 
1044 			time = Timer_GetMS();
1045 			while(Timer_GetMS() < time + 200);
1046 		}
1047 		++gamenum;
1048 		savescore = ob->ob_score;
1049 	} else {
1050 		// gamenum = 0;
1051                 // allow variable start level -- Jesse
1052                 gamenum = starting_level;
1053 		savescore = 0;
1054 
1055 		// sh 28/10/2001: go back to the title screen
1056 
1057 		playmode = PLAYMODE_UNSET;
1058 	}
1059 
1060 	// sdh 27/10/2001: moved all level init stuff into swinitlevel
1061 
1062 	longjmp(envrestart, 0);
1063 }
1064 
1065 // global argv/argc
1066 
1067 int g_argc;
1068 char **g_argv;
1069 
1070 // init game
1071 
swinit(int argc,char * argv[])1072 void swinit(int argc, char *argv[])
1073 {
1074 	BOOL n = FALSE;
1075 	BOOL s = FALSE;
1076 	BOOL c = FALSE;
1077 	BOOL a = FALSE;
1078 	BOOL k = FALSE;
1079 	int modeset = 0, keyset;
1080 	int i;
1081 
1082 	// store global argc/argv
1083 
1084 	g_argc = argc;
1085 	g_argv = argv;
1086 
1087 #if 0
1088 	// old getflags code
1089 	if (getflags(&argc, &argv,
1090 		       /*---- 96/12/27------
1091                         "n&s&c&m&a&k&i&j&q&h*v*r&d*f*n*t#w&y#e&g#x&:",
1092                         &n, &s, &c, &m, &a, &k, &ibmkeybd, &joystick, &soundflg,
1093                         &histout, &histin, &reset, &device,
1094                         &multfile, &cmndfile, &multtick, &hires, &keydelay,
1095                         &repflag, &gamenum, &missok )
1096                         ------ 96/12/27----*/
1097 			/*---- 99/01/24------
1098                         "n&s&c&m&a&k&j&q&h*v*r&d*f*t#w&y#e&g#x&:",
1099                         &n, &s, &c, &m, &a, &k, &joystick, &soundflg,
1100                         &histout, &histin, &reset, &device,
1101                         &multfile, &multtick, &hires, &keydelay,
1102                         &repflag, &gamenum, &missok )
1103                         ------ 99/01/24----*/
1104 		     "n&s&c&a&k&j&q&x&:",
1105 		     &n, &s, &c, &a, &k, &joystick, &soundflg,
1106 		     &missok) || ((modeset = n + s + c + a) > 1)
1107 	    || ((keyset = joystick + k) > 1)) {
1108 		disphelp(helptxt);
1109 		exit(1);
1110 	}
1111 #endif
1112 
1113 	// sdh 29/10/2001: load config from configuration file
1114 
1115         soundflg = 1;      // assume off by default
1116 	swloadconf();
1117 
1118 	for (i=1; i<argc; ++i) {
1119 		if (!strcasecmp(argv[i], "-n"))
1120 			n = 1;
1121 		else if (!strcasecmp(argv[i], "-s"))
1122 			s = 1;
1123 		else if (!strcasecmp(argv[i], "-c"))
1124 			c = 1;
1125 		else if (!strcasecmp(argv[i], "-f"))
1126 			vid_fullscreen = 1;
1127                 else if (!strncasecmp(argv[i], "-g", 2))
1128                 {
1129                     sscanf(& (argv[i][2]), "%d", &starting_level);
1130                     gamenum = starting_level;
1131                 }
1132 		else if (!strcasecmp(argv[i], "-2"))
1133 			vid_double_size = 1;
1134 		else if (!strcasecmp(argv[i], "-q"))
1135 			soundflg = 1;
1136                 else if (!strcasecmp(argv[i], "-p"))
1137                         soundflg = 0;
1138 		else if (!strcasecmp(argv[i], "-x"))
1139 			conf_missiles = 1;
1140                 else if (!strcasecmp(argv[i], "-e"))
1141                         conf_explosions = 0;
1142 		else
1143 #ifdef TCPIP
1144 			if (!strcasecmp(argv[i], "-l")) {
1145 			a = 1;
1146 			asynmode = ASYN_LISTEN;
1147 		} else if (!strcasecmp(argv[i], "-j")) {
1148 			if (++i < argc) {
1149 				a = 1;
1150 				asynmode = ASYN_CONNECT;
1151 				strcpy(asynhost, argv[i]);
1152 			} else {
1153 				fprintf(stderr, "insufficient arguments to -j\n");
1154 				exit(-1);
1155 			}
1156 		} else
1157 #endif
1158 		{
1159 			puts(helptxt);
1160 			exit(0);
1161 		}
1162 	}
1163 
1164 	modeset = n | s | c | a;
1165 	keyset = joystick + k;
1166 
1167 	soundflg = !soundflg;
1168 	if (modeset && keyset)
1169 		titleflg = TRUE;
1170 
1171 	movemax = 15;
1172 	initseed();
1173 
1174 	// sdh 27/6/2002: generate symbol objects
1175 
1176 	symbol_generate();
1177 
1178 	// initialise video
1179 
1180 	Vid_Init();
1181 	Vid_SetBuf();
1182 
1183 	// dont init speaker if started with -q (quiet)
1184 	if (soundflg)
1185 		Speaker_Init();		// init pc speaker
1186 
1187 	//        explseed = histinit( explseed );
1188 	initsndt();
1189 	initgrnd();           // needed for title screen
1190 
1191 	// sdh 26/03/2002: remove swinitgrph
1192 
1193 	// set playmode if we can, from command line options
1194 
1195 	playmode =
1196 		n ? PLAYMODE_NOVICE :
1197 		s ? PLAYMODE_SINGLE :
1198 		c ? PLAYMODE_COMPUTER :
1199 		a ? PLAYMODE_ASYNCH :
1200 		PLAYMODE_UNSET;
1201 
1202 	// sdh 28/10/2001: moved getmode into swmain
1203 	// sdh 27/10/2001: moved all level init stuff into swinitlevel
1204 
1205         // make mouse disappear
1206         SDL_ShowCursor(SDL_DISABLE);
1207 }
1208 
1209 //---------------------------------------------------------------------------
1210 //
1211 // $Log: swinit.c,v $
1212 // Revision 1.5.2.2  2003/06/08 18:16:38  fraggle
1213 // Fix networking and some compile bugs
1214 //
1215 // Revision 1.5.2.1  2003/06/08 17:08:17  fraggle
1216 // Fix variable declared in wrong place
1217 //
1218 // Revision 1.5  2003/06/04 17:13:26  fraggle
1219 // Remove disprx, as it is implied from displx anyway.
1220 //
1221 // Revision 1.4  2003/06/04 15:33:53  fraggle
1222 // Store global argc/argv for gtk_init
1223 //
1224 // Revision 1.3  2003/04/05 22:44:04  fraggle
1225 // Remove some useless functions from headers, make them static if they
1226 // are not used by other files
1227 //
1228 // Revision 1.2  2003/04/05 22:31:29  fraggle
1229 // Remove PLAYMODE_MULTIPLE and swnetio.c
1230 //
1231 // Revision 1.1.1.1  2003/02/14 19:03:13  fraggle
1232 // Initial Sourceforge CVS import
1233 //
1234 //
1235 // sdh 14/2/2003: change license header to GPL
1236 // sdh 27/06/2002: move symbols to new sopsym_t format,
1237 //                 remove references to symwdt, symhgt
1238 // sdh 27/03/2002: move old drawing functions to new ones (pntsym, pntcol)
1239 // sdh 26/03/2002: change CGA_ to Vid_
1240 // sdh 16/11/2001: TCPIP #define to disable TCP/IP support
1241 // sdh 16/11/2001: fix out of sync error
1242 // sdh 29/10/2001: load game options from config file
1243 // sdh 28/10/2001: extra game options
1244 // sdh 28/10/2001: game init restructured: swinitlevel now initialises the
1245 //                 level, getmode is called from main
1246 // sdh 26/10/2001: merge guages into a single function
1247 // sdh 24/10/2001: fix auxdisp buffer
1248 // sdh 23/10/2001: fixed arguments help list and rewrote argument checking
1249 //                 to support new network features
1250 // sdh 21/10/2001: use new obtype_t and obstate_t
1251 // sdh 21/10/2001: rearranged headers, added cvs tags
1252 // sdh 21/10/2001: reformatted with indent, adjusted some code by hand
1253 //                 to be more readable
1254 // sdh 19/10/2001: removed all extern definitions, these are now in headers
1255 //                 shuffled some functions around to shut up compiler
1256 // sdh 18/10/2001: converted all functions in this file to ANSI-style
1257 // 		   arguments from k&r
1258 //
1259 // 2000-10-29      Copyright update.
1260 //                 Comment out multiplayer selection on startup.
1261 // 99-01-24        1999 copyright.
1262 //                 Disable network support.
1263 // 96-12-26        New network version.
1264 //                 Remove keyboard prompts. Speed up game a bit.
1265 // 87-04-09        Fix to initial missile path.
1266 //                 Delay between starbursts
1267 // 87-04-06        Computer plane avoiding oxen.
1268 // 87-04-05        Less x-movement in explosions
1269 // 87-04-04        Missile and starburst support
1270 // 87-03-31        Less x-movement in explosions
1271 // 87-03-31        Missiles
1272 // 87-03-30        Novice player.
1273 // 87-03-12        Wounded airplanes.
1274 // 87-03-11        Smaller fuel tank explosions.
1275 // 87-03-09        Microsoft compiler.
1276 // 87-01-09        BMB standard help text.
1277 //                 Multiple serial ports.
1278 // 85-10-31        Atari
1279 // 84-02-02        Development
1280 //
1281 //---------------------------------------------------------------------------
1282 
1283