1 /***************************************************************************
2                           main.cpp  -  description
3                              -------------------
4     begin                : Tue Sep 19 17:16:48 PDT 2000
5     copyright            : (C) 2000 by Michael Bridak
6     email                : michael.bridak@verizon.net
7 $Id: main.cpp,v 1.28 2003/07/18 03:50:00 mbridak Exp $
8  ***************************************************************************/
9 
10 /***************************************************************************
11  *                                                                         *
12  *   This program is free software; you can redistribute it and/or modify *
13  *   it under the terms of the GNU General Public License as published by  *
14  *   the Free Software Foundation; either version 2 of the License.     *
15  *    .                                   *
16  *                                                                         *
17  ***************************************************************************/
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21 
22 /*Feeling left out? Get included!*/
23 #include <iostream>
24 #include <list>
25 #include <string.h>
26 #include <string>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <math.h>
30 #include <time.h>
31 #include <unistd.h>
32 #include <SDL.h>
33 #include <SDL/SDL.h>
34 #include <SDL/SDL_image.h>
35 #include <SDL/SDL_thread.h>
36 #include "dfont.h"
37 #include "draw.h"
38 #include "gameclock.h"
39 #include "submarine.h"
40 #include "towedarray.h"
41 #include "targetmotionanalysis.h"
42 #include "menu.h"
43 #include "message.h"
44 #include "mission.h"
45 #include "sonar.h"
46 #include "radar.h"
47 #include "files.h"
48 #include "esm.h"
49 #include "control.h"
50 #include "helicopter.h"
51 #include "main.h"
52 #include "sound.h"
53 #include "map.h"
54 #include "winfunctions.h"
55 #include <fstream>
56 #include <cstdlib>
57 #include <iomanip>
58 using namespace std;
59 
60 MAP *my_map = NULL;
61 
62 //#######GRAPHIC PRIMITIVES#############
SetupScreen(bool full_screen)63 void SetupScreen(bool full_screen){
64 	//Initialize the screen and some default colors
65 
66 	if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO) < 0 ) {
67 		cerr << "Couldn't initialize SDL: " << SDL_GetError() << endl;
68 		exit(1);
69 	}
70 	atexit(SDL_Quit);
71 	SDL_InitSubSystem(SDL_INIT_TIMER);
72 	if(full_screen){
73 		//Create main screen surface
74 		screen = SDL_SetVideoMode(1024, 768, 16, SDL_FULLSCREEN);
75 	}else{
76 		screen = SDL_SetVideoMode(1024, 768, 16, SDL_SWSURFACE);
77 	}
78 
79 	if ( screen == NULL ) {
80 		cerr << "Couldn't set video mode..." << endl
81 		<< "OpenSSN requires 1024x768 @ 16 bpp" << endl
82 		<< SDL_GetError() << endl;
83 		exit(1);
84 	}
85 	SDL_WM_SetCaption("OpenSSN http://openssn.sf.net", "OpenSSN");
86 
87 	//define some standard colors
88 	textcolor = SDL_MapRGB(screen->format, 192, 255, 6);
89 	black = SDL_MapRGB(screen->format, 0, 0, 0);
90 	white = SDL_MapRGB(screen->format, 255, 255, 255);
91 	red = SDL_MapRGB(screen->format, 255, 99, 20);
92         dark_red = SDL_MapRGB(screen->format, 140, 80, 10);
93 	green = SDL_MapRGB(screen->format, 0, 255, 0);
94         dark_green = SDL_MapRGB(screen->format, 0, 120, 0);
95 	yellow = SDL_MapRGB(screen->format, 216, 255, 0);
96         brown = SDL_MapRGB(screen->format, 120, 140, 0);
97         grey = SDL_MapRGB(screen->format, 180, 180, 180);
98         dark_grey = SDL_MapRGB(screen->format, 100, 100, 100);
99 	// mapcolor = SDL_MapRGB(screen->format, 130, 201, 225);
100         mapcolor = SDL_MapRGB(screen->format, 10, 10, 100);
101         // Init_Audio();
102 }
103 
MapIcon(int x,int y,int ShipType,int Friend,Uint32 color)104 void MapIcon(int x, int y, int ShipType, int Friend, Uint32 color){
105   // Display NTDS symbols according to the following Legend
106   // Hostile:  Submarine = Red Bottom Half Diamond, Surface = Red Full Diamond,
107   //           Aircraft = Red Top Half Diamond
108 
109   // Friendly: Submarine = green Bottom SemiCircle, Surface = green Circle,
110   //           Aircraft = green Top SemiCircle
111 
112   // Unknown:  Submarine = grey Bottom Half Box, Surface = grey Box,
113   //           Aircraft = grey Top Half Box
114 
115   // Neutral: Submarine = Yellow Bottom Half box, Surface = Yellow box,
116   //           Aircraft = Yellow Top Half box
117 
118   // Is it a submarine?
119   if(ShipType == TYPE_SUB) {
120     switch(Friend){
121     case 0: //Foe??
122       DrawDiamond(screen, x-2, y+2, 7, 'B', black);  //Bottom Half Diamond
123       DrawDiamond(screen, x, y, 7, 'B', color);  //Bottom Half Diamond
124       break;
125     case 1: //Friend??
126       DrawArc(screen, x-2,y+2, 7, 180, 360, black); //Bottom SemiCircle
127       DrawArc(screen, x-2, y+3, 7, 180, 360, black); // thickness
128       DrawArc(screen, x ,y, 7, 180, 360, color); //Bottom SemiCircle
129       DrawArc(screen, x, y + 1, 7, 180, 360, color); // thickness
130       break;
131     case 2://Unknown??
132       DrawBox(screen, x-2 ,y+2, 7, 'B', black); //Bottom Half Box
133       DrawBox(screen, x ,y, 7, 'B', color); //Bottom Half Box
134       break;
135     default: //Neutral
136        DrawBox(screen, x-2 ,y+2, 7, 'B', black); //Bottom Half Box
137        DrawBox(screen, x ,y, 7, 'B', color); //Bottom Half Box
138     }
139   }
140  // Is it a surface ship?
141     else if(ShipType == TYPE_SHIP) {
142    switch(Friend){
143    case 0: //Foe??
144      DrawDiamond(screen, x-2 ,y+2, 7, 'F', black); //Diamond
145      DrawDiamond(screen, x ,y, 7, 'F', color); //Diamond
146      break;
147    case 1: //Friend??
148      DrawCircle(screen, x-2, y+2, 7, black); //Circle
149      DrawCircle(screen, x, y, 7, color); //Circle
150      break;
151    case 2: //Unknown??
152       DrawBox(screen, x-2 ,y+2, 7, 'F', black); //Box
153       DrawBox(screen, x ,y, 7, 'F', color); //Box
154       break;
155    default: //Neutral
156      DrawBox(screen, x-2 ,y+2, 7, 'F', black); //Cross
157      DrawBox(screen, x ,y, 7, 'F', color); //Cross
158     }
159   }
160 
161   // Is it an airplane or Helo?
162   else if(ShipType == TYPE_HELICOPTER) {
163     switch(Friend){
164     case 0: //Foe??
165       DrawDiamond(screen, x, y, 7, 'T', color);  //Top Half Diamond
166       break;
167     case 1: //Friend??
168       DrawArc(screen, x ,y, 7, 0, 180, color); //Top SemiCircle
169       break;
170     case 2: //Unknown??
171       DrawBox(screen, x ,y, 7, 'T', color); //Top Half Box
172       break;
173     default: //Neutral
174       DrawBox(screen, x ,y, 7, 'T', color); //Top Half Cross
175     }
176   }
177   else if (ShipType == TYPE_TORPEDO)
178   {
179       DrawDiamond(screen, x, y, 7, 'B', color);
180       DrawLine(screen, x, y-5, x, y, color);
181   }
182   else if (ShipType == TYPE_NOISEMAKER)
183   {
184       DrawBox(screen, x, y, 7, 'B', color);
185   }
186 }
187 
188 
DirectionalPointer(int x,int y,int heading,int speed,Uint32 color)189 void DirectionalPointer(int x, int y, int heading, int speed,Uint32 color){
190 	//Draws a directional vane on a ships map icon.
191 	//the length will vary depending on the speed.
192 
193 	double var1; //just a place to hold a value so we don't have to calc it twice.
194 	double destinationx; //the dest x&y point for
195 	double destinationy; //the drawn line.
196 
197 	if((speed > 1) || (speed < -1)) speed=speed/2; //allow for 0 speed.
198 	var1 = heading * 0.017453; //convert degrees to radians.
199 	destinationx = (sin(var1) * speed) + x;
200 	destinationy = (-1) * (cos(var1) * speed) + y;
201 	DrawLine(screen, x, y, (int)destinationx, (int)destinationy, color);
202 }
203 
LoadScreen(int item)204 void LoadScreen(int item){
205 	//Loads a PN file into an SDL surface then
206 	//blits it to the display surface.
207 	//then deletes the temporary surface.
208 
209 
210 	SDL_Surface *IMGFile=NULL; // Get our selfs a surface to work with..
211 	SDL_Rect dest; //A rectangle structure to define a blit area
212 	switch (item)
213 	{
214 	case 0:
215 		IMGFile = Load_Image("images/tittle.png"); //fill the surface w/ the bmp
216 		break;
217 	case 1:
218 		IMGFile = Load_Image("images/Sonarscreen.png"); //fill the surface w/ the bmp
219 		break;
220 	case 2:
221 		IMGFile = Load_Image("images/Mapscreen.png"); //fill the surface w/ the bmp
222 		break;
223 	case 3:
224 		IMGFile = Load_Image("images/Mapscreen.png"); //fill the surface w/ the bmp
225 		break;
226 	case 4:
227 		IMGFile = Load_Image("images/ControlScreen.png"); //fill the surface w/ the bmp
228 		break;
229 	case 5:
230 		IMGFile = Load_Image("images/RadarScreen.png"); //fill the surface w/ the bmp
231 		break;
232 	case 6:
233 		IMGFile = Load_Image("images/ESMScreen.png"); //fill the surface w/ the bmp
234 		break;
235         case 7:
236                 IMGFile = Load_Image("images/sub_surfacing.png"); break;
237         case 8:
238                 IMGFile = Load_Image("images/sub_rising.png"); break;
239         case 9:
240                 IMGFile = Load_Image("images/sub_menu.png"); break;
241 	default:
242 		cerr << "Unknown screen item" << endl;
243 		break;
244 	}
245 	if ( IMGFile == NULL ) { // Are we screwed??
246 		cerr << "Function LoadScreen()" << endl
247 				<< "Couldn't load screen item# " << item <<endl
248 				<< "SDL Error: " << SDL_GetError() << endl;
249 		SDL_Quit();
250 		exit(0);
251 		return; // Whine Snivel and Bail..
252 	}
253 	dest.x = 0; // Blit destination x&y to the upper left
254 	dest.y = 0;
255 	dest.w = IMGFile->w; // Height and width equal to the
256 	dest.h = IMGFile->h;  // source images....
257 	SDL_BlitSurface(IMGFile, NULL, screen, &dest); // Do the actual Blit
258 	SDL_UpdateRects(screen, 1, &dest); //Show the screen...
259 	SDL_FreeSurface(IMGFile); //Free up the surface memory..
260 	return;
261 }
262 
LoadWidgets()263 void LoadWidgets(){
264 	SDL_Surface *temp;
265 
266 	temp = Load_Image("images/mapup.png");
267 	if(temp != NULL) navbuttonup = SDL_DisplayFormat(temp);
268 	if ( navbuttonup == NULL ) { // Are we screwed??
269 		cerr<<"Function LoadWidgets()" << endl
270 		<< SDL_GetError() << endl;
271 		SDL_Quit();
272 		exit(0);
273 	}
274 	SDL_FreeSurface(temp);
275 
276 	temp = Load_Image("images/mapdown.png");
277 	if(temp != NULL) navbuttondown = SDL_DisplayFormat(temp);
278 	if ( navbuttondown == NULL ) { // Are we screwed??
279 		cerr<<"Function LoadWidgets()" << endl
280 		<< SDL_GetError() << endl;
281 		SDL_Quit();
282 		exit(0);
283 	}
284 	SDL_FreeSurface(temp);
285 
286 	temp = Load_Image("images/tmaup.png");
287 	if(temp != NULL) tmabuttonup = SDL_DisplayFormat(temp);
288 	if ( tmabuttonup == NULL ) { // Are we screwed??
289 		cerr<<"Function LoadWidgets()" << endl
290 		<< SDL_GetError() << endl;
291 		SDL_Quit();
292 		exit(0);
293 	}
294 	SDL_FreeSurface(temp);
295 
296 	temp = Load_Image("images/tmadown.png");
297 	if(temp != NULL) tmabuttondown = SDL_DisplayFormat(temp);
298 	if ( tmabuttondown == NULL ) { // Are we screwed??
299 		cerr<<"Function LoadWidgets()" << endl
300 		<< SDL_GetError() << endl;
301 		SDL_Quit();
302 		exit(0);
303 	}
304 	SDL_FreeSurface(temp);
305 
306 	temp = Load_Image("images/shipcontrolup.png");
307 	if(temp != NULL) shipcontrolbuttonup = SDL_DisplayFormat(temp);
308 	if ( shipcontrolbuttonup == NULL ) { // Are we screwed??
309 
310 		cerr<<"Function LoadWidgets()" << endl
311 		<< SDL_GetError() << endl;
312 		SDL_Quit();
313 		exit(0);
314 	}
315 	SDL_FreeSurface(temp);
316 
317 	temp = Load_Image("images/shipcontroldown.png");
318 	if(temp != NULL) shipcontrolbuttondown = SDL_DisplayFormat(temp);
319 	if ( shipcontrolbuttondown == NULL ) { // Are we screwed??
320 		cerr<<"Function LoadWidgets()" << endl
321 		<< SDL_GetError() << endl;
322 		SDL_Quit();
323 		exit(0);
324 	}
325 	SDL_FreeSurface(temp);
326 
327 	temp = Load_Image("images/esmup.png");
328 	if(temp != NULL) esmbuttonup = SDL_DisplayFormat(temp);
329 	if ( esmbuttonup == NULL ) { // Are we screwed??
330 		cerr<<"Function LoadWidgets()" << endl
331 		<< SDL_GetError() << endl;
332 		SDL_Quit();
333 		exit(0);
334 	}
335 	SDL_FreeSurface(temp);
336 
337 	temp = Load_Image("images/esmdown.png");
338 	if(temp != NULL) esmbuttondown = SDL_DisplayFormat(temp);
339 	if ( esmbuttondown == NULL ) { // Are we screwed??
340 		cerr<<"Function LoadWidgets()" << endl
341 		<< SDL_GetError() << endl;
342 		SDL_Quit();
343 		exit(0);
344 	}
345 	SDL_FreeSurface(temp);
346 
347 	temp = Load_Image("images/radarup.png");
348 	if(temp != NULL) radarbuttonup = SDL_DisplayFormat(temp);
349 	if ( radarbuttonup == NULL ) { // Are we screwed??
350 		cerr<<"Function LoadWidgets()" << endl
351 		<< SDL_GetError() << endl;
352 		SDL_Quit();
353 		exit(0);
354 	}
355 	SDL_FreeSurface(temp);
356 
357 	temp = Load_Image("images/radardown.png");
358 	if(temp != NULL) radarbuttondown = SDL_DisplayFormat(temp);
359 	if ( radarbuttondown == NULL ) { // Are we screwed??
360 		cerr<<"Function LoadWidgets()" << endl
361 		<< SDL_GetError() << endl;
362 		SDL_Quit();
363 		exit(0);
364 	}
365 	SDL_FreeSurface(temp);
366 
367 	temp = Load_Image("images/quitbuttonup.png");
368 	if(temp != NULL) quitbuttonup = SDL_DisplayFormat(temp);
369 	if ( quitbuttonup == NULL ) { // Are we screwed??
370 		cerr<<"Function LoadWidgets()" << endl
371 		<< SDL_GetError() << endl;
372 		SDL_Quit();
373 		exit(0);
374 	}
375 	SDL_FreeSurface(temp);
376 
377 	temp = Load_Image("images/quitbuttondown.png");
378 	if(temp != NULL) quitbuttondown = SDL_DisplayFormat(temp);
379 	if ( quitbuttondown == NULL ) { // Are we screwed??
380 		cerr<<"Function LoadWidgets()" << endl
381 		<< SDL_GetError() << endl;
382 		SDL_Quit();
383 		exit(0);
384 	}
385 	SDL_FreeSurface(temp);
386 
387 	temp = Load_Image("images/plusbuttonup.png");
388 	if(temp != NULL) plusbuttonup = SDL_DisplayFormat(temp);
389 	if ( quitbuttonup == NULL ) { // Are we screwed??
390 
391 		cerr<<"Function LoadWidgets()" << endl
392 		<< SDL_GetError() << endl;
393 		SDL_Quit();
394 		exit(0);
395 	}
396 	SDL_FreeSurface(temp);
397 
398 	temp = Load_Image("images/plusbuttondown.png");
399 	if(temp != NULL) plusbuttondown = SDL_DisplayFormat(temp);
400 	if ( quitbuttondown == NULL ) { // Are we screwed??
401 		cerr<<"Function LoadWidgets()" << endl
402 		<< SDL_GetError() << endl;
403 		SDL_Quit();
404 		exit(0);
405 	}
406 	SDL_FreeSurface(temp);
407 
408 	temp = Load_Image("images/minusbuttonup.png");
409 	if(temp != NULL) minusbuttonup = SDL_DisplayFormat(temp);
410 	if ( minusbuttonup == NULL ) { // Are we screwed??
411 		cerr<<"Function LoadWidgets()" << endl
412 		<< SDL_GetError() << endl;
413 		SDL_Quit();
414 		exit(0);
415 	}
416 	SDL_FreeSurface(temp);
417 
418 	temp = Load_Image("images/minusbuttondown.png");
419 	if(temp != NULL) minusbuttondown = SDL_DisplayFormat(temp);
420 	if ( minusbuttondown == NULL ) { // Are we screwed??
421 		cerr<<"Function LoadWidgets()" << endl
422 		<< SDL_GetError() << endl;
423 		SDL_Quit();
424 		exit(0);
425 	}
426 	SDL_FreeSurface(temp);
427 
428 	temp = Load_Image("images/centerbuttondown.png");
429 	if(temp != NULL) centerbuttondown = SDL_DisplayFormat(temp);
430 	if ( centerbuttondown == NULL ) { // Are we screwed??
431 		cerr<<"Function LoadWidgets()" << endl
432 		<< SDL_GetError() << endl;
433 		SDL_Quit();
434 		exit(0);
435 	}
436 	SDL_FreeSurface(temp);
437 
438 	temp = Load_Image("images/centerbuttonup.png");
439 	if(temp != NULL) centerbuttonup = SDL_DisplayFormat(temp);
440 	if ( centerbuttonup == NULL ) { // Are we screwed??
441 		cerr<<"Function LoadWidgets()" << endl
442 		<< SDL_GetError() << endl;
443 		SDL_Quit();
444 		exit(0);
445 	}
446 	SDL_FreeSurface(temp);
447 
448 	temp = Load_Image("images/upbuttondown.png");
449 	if(temp != NULL) upbuttondown = SDL_DisplayFormat(temp);
450 	if ( upbuttondown == NULL ) { // Are we screwed??
451 		cerr<<"Function LoadWidgets()" << endl
452 		<< SDL_GetError() << endl;
453 		SDL_Quit();
454 		exit(0);
455 	}
456 	SDL_FreeSurface(temp);
457 
458 	temp = Load_Image("images/upbuttonup.png");
459 	if(temp != NULL) upbuttonup = SDL_DisplayFormat(temp);
460 	if ( upbuttonup == NULL ) { // Are we screwed??
461 		cerr<<"Function LoadWidgets()" << endl
462 		<< SDL_GetError() << endl;
463 		SDL_Quit();
464 		exit(0);
465 	}
466 	SDL_FreeSurface(temp);
467 
468 	temp = Load_Image("images/downbuttondown.png");
469 	if(temp != NULL) downbuttondown = SDL_DisplayFormat(temp);
470 	if ( centerbuttondown == NULL ) { // Are we screwed??
471 		cerr<<"Function LoadWidgets()" << endl
472 		<< SDL_GetError() << endl;
473 		SDL_Quit();
474 		exit(0);
475 	}
476 	SDL_FreeSurface(temp);
477 
478 	temp = Load_Image("images/downbuttonup.png");
479 	if(temp != NULL) downbuttonup = SDL_DisplayFormat(temp);
480 	if ( downbuttonup == NULL ) { // Are we screwed??
481 		cerr<<"Function LoadWidgets()" << endl
482 		<< SDL_GetError() << endl;
483 		SDL_Quit();
484 		exit(0);
485 	}
486 	SDL_FreeSurface(temp);
487 
488 	temp = Load_Image("images/leftbuttondown.png");
489 	if(temp != NULL) leftbuttondown = SDL_DisplayFormat(temp);
490 	if ( leftbuttondown == NULL ) { // Are we screwed??
491 		cerr<<"Function LoadWidgets()" << endl
492 		<< SDL_GetError() << endl;
493 		SDL_Quit();
494 		exit(0);
495 	}
496 	SDL_FreeSurface(temp);
497 
498 	temp = Load_Image("images/leftbuttonup.png");
499 	if(temp != NULL) leftbuttonup = SDL_DisplayFormat(temp);
500 	if ( leftbuttonup == NULL ) { // Are we screwed??
501 		cerr<<"Function LoadWidgets()" << endl
502 		<< SDL_GetError() << endl;
503 		SDL_Quit();
504 		exit(0);
505 	}
506 	SDL_FreeSurface(temp);
507 
508 	temp = Load_Image("images/rightbuttondown.png");
509 	if(temp != NULL) rightbuttondown = SDL_DisplayFormat(temp);
510 	if ( rightbuttondown == NULL ) { // Are we screwed??
511 		cerr<<"Function LoadWidgets()" << endl
512 		<< SDL_GetError() << endl;
513 		SDL_Quit();
514 		exit(0);
515 	}
516 	SDL_FreeSurface(temp);
517 
518 	temp = Load_Image("images/rightbuttonup.png");
519 	if(temp != NULL) rightbuttonup = SDL_DisplayFormat(temp);
520 	if ( rightbuttonup == NULL ) { // Are we screwed??
521 		cerr<<"Function LoadWidgets()" << endl
522 		<< SDL_GetError() << endl;
523 		SDL_Quit();
524 		exit(0);
525 	}
526 	SDL_FreeSurface(temp);
527 
528         temp = Load_Image("images/noisemaker.png");
529         if (temp)
530         {
531            noisemaker_image = SDL_DisplayFormat(temp);
532            if (! noisemaker_image)
533              cerr << "Error loading noisemaker image." << endl;
534            SDL_FreeSurface(temp);
535         }
536 
537         temp = Load_Image("images/torpedo.png");
538         if (temp)
539         {
540            torpedo_image = SDL_DisplayFormat(temp);
541            if (! noisemaker_image)
542              cerr << "Error loading torpedo image." << endl;
543            SDL_FreeSurface(temp);
544         }
545 
546 }
547 
548 
549 
UnLoadWidgets()550 void UnLoadWidgets(){
551 
552 	//free the surfaces
553 
554 	SDL_FreeSurface(sonarbuttonup);
555 	SDL_FreeSurface(sonarbuttondown);
556 	SDL_FreeSurface(navbuttonup);
557 	SDL_FreeSurface(navbuttondown);
558 	SDL_FreeSurface(tmabuttonup);
559 	SDL_FreeSurface(tmabuttondown);
560 	SDL_FreeSurface(quitbuttonup);
561 	SDL_FreeSurface(quitbuttondown);
562 	SDL_FreeSurface(plusbuttonup);
563 	SDL_FreeSurface(plusbuttondown);
564 	SDL_FreeSurface(minusbuttonup);
565 	SDL_FreeSurface(minusbuttondown);
566         SDL_FreeSurface(torpedo_image);
567         SDL_FreeSurface(noisemaker_image);
568 }
569 
DisplayNavigationWidgets()570 void DisplayNavigationWidgets(){
571 	if (navwidget){ // is the nav button down?
572 		destination_rectangle.x = 280; //upper left corner to
573 		destination_rectangle.y = 710; //place the button.
574 		destination_rectangle.h = navbuttondown->h; //height &
575 		destination_rectangle.w = navbuttondown->w;//width of button.
576 		SDL_BlitSurface(navbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
577 		SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
578 		if(mapcenter){
579 			destination_rectangle.x = 225; //upper left corner to
580 			destination_rectangle.y = 269; //place the button.
581 			destination_rectangle.h = centerbuttondown->h; //height &
582 			destination_rectangle.w = centerbuttondown->w;//width of button.
583 			SDL_BlitSurface(centerbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
584 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
585 		}else{
586 			destination_rectangle.x = 225; //upper left corner to
587 			destination_rectangle.y = 269; //place the button.
588 			destination_rectangle.h = centerbuttonup->h; //height &
589 			destination_rectangle.w = centerbuttonup->w;//width of button.
590 			SDL_BlitSurface(centerbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
591 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
592 		}
593 		 	destination_rectangle.x = 225; //upper left corner to
594 			destination_rectangle.y = 219; //place the button.
595 			destination_rectangle.h = upbuttonup->h; //height &
596 			destination_rectangle.w = upbuttonup->w;//width of button.
597 			SDL_BlitSurface(upbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
598 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
599 		 	destination_rectangle.x = 225; //upper left corner to
600 			destination_rectangle.y = 319; //place the button.
601 			destination_rectangle.h = downbuttonup->h; //height &
602 			destination_rectangle.w = downbuttonup->w;//width of button.
603 			SDL_BlitSurface(downbuttonup, NULL, screen, &destination_rectangle); // Do the Blit
604 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen..
605 		 	destination_rectangle.x = 175; //upper left corner to
606 			destination_rectangle.y = 269; //place the button.
607 			destination_rectangle.h = leftbuttonup->h; //height &
608 			destination_rectangle.w = leftbuttonup->w;//width of button.
609 			SDL_BlitSurface(leftbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
610 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
611 		 	destination_rectangle.x = 275; //upper left corner to
612 			destination_rectangle.y = 269; //place the button.
613 			destination_rectangle.h = rightbuttonup->h; //height &
614 			destination_rectangle.w = rightbuttonup->w;//width of button.
615 			SDL_BlitSurface(rightbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
616 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
617 		 	destination_rectangle.x = 175; //upper left corner to
618 			destination_rectangle.y = 359; //place the button.
619 			destination_rectangle.h = plusbuttonup->h; //height &
620 			destination_rectangle.w = plusbuttonup->w;//width of button.
621 			SDL_BlitSurface(plusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
622 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
623 		 	destination_rectangle.x = 275; //upper left corner to
624 			destination_rectangle.y = 359; //place the button.
625 			destination_rectangle.h = minusbuttonup->h; //height &
626 			destination_rectangle.w = minusbuttonup->w;//width of button.
627 			SDL_BlitSurface(minusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
628 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
629 	}else{ // our button must be up...
630  		destination_rectangle.x = 280; //upper left corner to
631 		destination_rectangle.y = 710; //place the button.
632 		destination_rectangle.h = navbuttonup->h; //height &
633 		destination_rectangle.w = navbuttonup->w;//width of button.
634 		SDL_BlitSurface(navbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
635 		SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
636 	}
637 }
638 
DisplayTMAWidgets()639 void DisplayTMAWidgets(){
640 	if (tmawidget){ // is the TMA button down?
641 	 	destination_rectangle.x = 380; //upper left corner to
642 		destination_rectangle.y = 710; //place the button.
643 		destination_rectangle.h = tmabuttondown->h; //height &
644 		destination_rectangle.w = tmabuttondown->w;//width of button.
645 		SDL_BlitSurface(tmabuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
646 		SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
647 		if(Tma.centerGeoPlot){
648 			destination_rectangle.x = 225; //upper left corner to
649 			destination_rectangle.y = 269; //place the button.
650 			destination_rectangle.h = centerbuttondown->h; //height &
651 			destination_rectangle.w = centerbuttondown->w;//width of button.
652 			SDL_BlitSurface(centerbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
653 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
654 		}else{
655 			destination_rectangle.x = 225; //upper left corner to
656 			destination_rectangle.y = 269; //place the button.
657 			destination_rectangle.h = centerbuttonup->h; //height &
658 			destination_rectangle.w = centerbuttonup->w;//width of button.
659 			SDL_BlitSurface(centerbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
660 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
661 		}
662 		 	destination_rectangle.x = 225; //upper left corner to
663 			destination_rectangle.y = 219; //place the button.
664 			destination_rectangle.h = upbuttonup->h; //height &
665 			destination_rectangle.w = upbuttonup->w;//width of button.
666 			SDL_BlitSurface(upbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
667 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
668 		 	destination_rectangle.x = 225; //upper left corner to
669 			destination_rectangle.y = 319; //place the button.
670 			destination_rectangle.h = downbuttonup->h; //height &
671 			destination_rectangle.w = downbuttonup->w;//width of button.
672 			SDL_BlitSurface(downbuttonup, NULL, screen, &destination_rectangle); // Do the Blit
673 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen..
674 		 	destination_rectangle.x = 175; //upper left corner to
675 			destination_rectangle.y = 269; //place the button.
676 			destination_rectangle.h = leftbuttonup->h; //height &
677 			destination_rectangle.w = leftbuttonup->w;//width of button.
678 			SDL_BlitSurface(leftbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
679 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
680 		 	destination_rectangle.x = 275; //upper left corner to
681 			destination_rectangle.y = 269; //place the button.
682 			destination_rectangle.h = rightbuttonup->h; //height &
683 			destination_rectangle.w = rightbuttonup->w;//width of button.
684 			SDL_BlitSurface(rightbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
685 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
686 		 	destination_rectangle.x = 175; //upper left corner to
687 			destination_rectangle.y = 359; //place the button.
688 			destination_rectangle.h = plusbuttonup->h; //height &
689 			destination_rectangle.w = plusbuttonup->w;//width of button.
690 			SDL_BlitSurface(plusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
691 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
692 		 	destination_rectangle.x = 275; //upper left corner to
693 			destination_rectangle.y = 359; //place the button.
694 			destination_rectangle.h = minusbuttonup->h; //height &
695 			destination_rectangle.w = minusbuttonup->w;//width of button.
696 			SDL_BlitSurface(minusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
697 			SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
698 	}else{ // our button must be up...
699 		destination_rectangle.x = 380; //upper left corner to
700 		destination_rectangle.y = 710; //place the button.
701 		destination_rectangle.h = tmabuttonup->h; //height &
702 		destination_rectangle.w = tmabuttonup->w;//width of button.
703 		SDL_BlitSurface(tmabuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
704 		SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
705 	}
706 }
707 
DisplayESMWidgets()708 void DisplayESMWidgets(){
709  	destination_rectangle.x = 580; //upper left corner to
710 	destination_rectangle.y = 710; //place the button.
711 
712 	if (esmwidget){ // is the nav button down?
713 		destination_rectangle.h =esmbuttondown->h; //height &
714 		destination_rectangle.w = esmbuttondown->w;//width of button.
715 		SDL_BlitSurface(esmbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
716 	}else{ // our button must be up...
717 		destination_rectangle.h = esmbuttonup->h; //height &
718 		destination_rectangle.w = esmbuttonup->w;//width of button.
719 		SDL_BlitSurface(esmbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
720 	}
721 	SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
722 }
723 
DisplayRADARWidgets()724 void DisplayRADARWidgets(){
725  	destination_rectangle.x = 680; //upper left corner to
726 	destination_rectangle.y = 710; //place the button.
727 
728 	if (radarwidget){ // is the nav button down?
729 		destination_rectangle.h =radarbuttondown->h; //height &
730 		destination_rectangle.w = radarbuttondown->w;//width of button.
731 		SDL_BlitSurface(radarbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
732 	}else{ // our button must be up...
733 		destination_rectangle.h = radarbuttonup->h; //height &
734 		destination_rectangle.w = radarbuttonup->w;//width of button.
735 		SDL_BlitSurface(radarbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
736 	}
737 	SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
738 }
739 
DisplayShipControlWidgets()740 void DisplayShipControlWidgets(){
741  	destination_rectangle.x = 480; //upper left corner to
742 	destination_rectangle.y = 710; //place the button.
743 
744 	if (shipcontrolwidget){ // is the nav button down?
745 		destination_rectangle.h = shipcontrolbuttondown->h; //height &
746 		destination_rectangle.w = shipcontrolbuttondown->w;//width of button.
747 		SDL_BlitSurface(shipcontrolbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
748 	}else{ // our button must be up...
749 		destination_rectangle.h = shipcontrolbuttonup->h; //height &
750 		destination_rectangle.w = shipcontrolbuttonup->w;//width of button.
751 		SDL_BlitSurface(shipcontrolbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
752 	}
753 	SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
754 }
DisplayWidgets()755 void DisplayWidgets(){
756 	SonarStation.DisplaySonarWidgets();
757 	DisplayNavigationWidgets();
758 	DisplayTMAWidgets();
759 	DisplayShipControlWidgets();
760 	DisplayESMWidgets();
761 	DisplayRADARWidgets();
762 
763 	destination_rectangle.x = 780; //upper left corner to
764 	destination_rectangle.y = 710; //place the button.
765 	if (quitwidget){ // is the quit button down?
766 		destination_rectangle.h = quitbuttondown->h; //height &
767 		destination_rectangle.w = quitbuttondown->w;//width of button.
768 		SDL_BlitSurface(quitbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
769 	}else{ // our button must be up...
770 		destination_rectangle.h = quitbuttonup->h; //height &
771 		destination_rectangle.w = quitbuttonup->w;//width of button.
772 		SDL_BlitSurface(quitbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
773 	}
774 	SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
775 
776 	destination_rectangle.x = 880; //upper left corner to
777 	destination_rectangle.y = 710; //place the button.
778 	destination_rectangle.h = plusbuttonup->h; //height &
779 	destination_rectangle.w = plusbuttonup->w;//width of button.
780 	SDL_BlitSurface(plusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
781 	SDL_UpdateRects(screen, 1, &destination_rectangle); //Show button on the screen...
782 	destination_rectangle.x = 970; //upper left corner to
783 	destination_rectangle.y = 710; //place the button.
784 	destination_rectangle.h = minusbuttonup->h; //height &
785 	destination_rectangle.w = minusbuttonup->w;//width of button.
786 	SDL_BlitSurface(minusbuttonup, NULL, screen, &destination_rectangle); // Do the Blit.
787 	SDL_UpdateRects(screen, 1, &destination_rectangle); //Show button on the screen...
788 
789 }
790 
791 
792 
793 // This function adds a torpedo to the linked-list of torpedoes
794 // The returned value is the new linked-list pointer, in case
795 // the new_torpedo is the first in the list.
Add_Ship(Submarine * all_torp,Submarine * new_torp)796 Submarine *Add_Ship(Submarine *all_torp, Submarine *new_torp)
797 {
798    Submarine *my_torp;
799 
800    // we do not have a torpedo to add
801    if (! new_torp)
802      return all_torp;
803 
804    // empty list
805    if (! all_torp)
806        return new_torp;
807 
808    // add one to an existing list
809    my_torp = all_torp;
810    while (my_torp->next)
811       my_torp = my_torp->next;
812 
813    // add to end of list
814    my_torp->next = new_torp;
815 
816    return all_torp;
817 }
818 
819 
820 // This function removes a torpedo from the list of all
821 // torpedoes. It returns the first item in the torpedo linked-list.
Remove_Ship(Submarine * all_torpedoes,Submarine * old_torpedo)822 Submarine *Remove_Ship(Submarine *all_torpedoes, Submarine *old_torpedo)
823 {
824    Submarine *my_torp, *previous;
825 
826    if (! all_torpedoes)
827       return NULL;
828    if (! old_torpedo)
829       return all_torpedoes;
830 
831    my_torp = all_torpedoes;
832    previous = NULL;
833    while (my_torp)
834    {
835       // found match and it is the first in the list
836       if ( (my_torp == old_torpedo) && (! previous) )
837       {
838           previous = my_torp->next;
839           delete my_torp;
840           return previous;
841       }
842       // found a match and it isn't the first in the list
843       else if (my_torp == old_torpedo)
844       {
845          previous->next = my_torp->next;
846          delete my_torp;
847          return all_torpedoes;
848       }
849       // this one does not match, go to next node
850       else
851       {
852           previous = my_torp;
853           my_torp = my_torp->next;
854       }
855 
856    }
857    // item wasn't found, just return the complete list
858    return all_torpedoes;
859 }
860 
861 
862 
Add_Helicopter(Helicopter * all_helicopters,Helicopter * new_helicopter)863 Helicopter *Add_Helicopter(Helicopter *all_helicopters, Helicopter *new_helicopter)
864 {
865    Helicopter *current;
866 
867    if (! new_helicopter)
868       return all_helicopters;
869    if (! all_helicopters)
870       return new_helicopter;
871 
872    current = all_helicopters;
873    while (current->next)
874       current = current->next;
875    current->next = new_helicopter;
876 
877   return all_helicopters;
878 }
879 
880 
881 
Remove_Helicopter(Helicopter * all_helicopters,Helicopter * old_helicopter)882 Helicopter *Remove_Helicopter(Helicopter *all_helicopters, Helicopter *old_helicopter)
883 {
884    Helicopter *current, *previous = NULL;
885 
886    if (! all_helicopters)
887       return NULL;
888    if (! old_helicopter)
889       return all_helicopters;
890 
891    current = all_helicopters;
892    while (current)
893    {
894        // first in list
895        if ( (current == old_helicopter) && (! previous) )
896        {
897           previous = current->next;
898           delete current;
899           return previous;
900        }
901        // not first in list
902        else if (current == old_helicopter)
903        {
904           previous->next = current->next;
905           delete current;
906           return all_helicopters;
907        }
908        // this is not our node
909        else
910        {
911           previous = current;
912           current = current->next;
913        }
914    }
915    return all_helicopters;
916 }
917 
918 
919 
920 
921 
922 //######################################
ShipHandeling()923 void ShipHandeling(){
924        Submarine *my_torp, *temp_torp;
925        int status;
926        Submarine *ship;
927        Helicopter *helicopter;
928 
929        // see if we can use radar, esm, etc
930        if (player->Depth > PERISCOPE_DEPTH)
931        {
932            EsmStation.LowerMast();
933            RadarStation.LowerMast();
934            player->using_radar = FALSE;
935        }
936        // if array is out, limit speed
937        if (TB16.GetLength() > 0)
938        {
939             int max_speed = Subs->MaxSpeed / 2;
940             if (Subs->Speed > max_speed)
941                Subs->Speed = max_speed;
942        }
943 
944         ship = Subs;
945 	while (ship)
946         {
947 		ship->UpdateLatLon();	//Move all the ships
948                 // see what the AI wants to do
949                 if (ship != Subs)
950                 {
951                   /*
952                   if (ship->ShipType == TYPE_SUB)
953                     torpedoes = ship->Sub_AI(Subs, torpedoes);
954                   else if (ship->ShipType == TYPE_SHIP)
955                     torpedoes = ship->Ship_AI(Subs, torpedoes);
956                   */
957                    torpedoes = ship->Sub_AI(Subs, torpedoes, helicopters);
958                 }
959 		ship->Handeling();	//Steer, Change Depth etc...
960 
961                 // we were pinging, but it fades quickly
962                 if (ship->pinging > 0)
963                    ship->pinging--;
964                 ship = ship->next;
965 	}
966         helicopter = helicopters;
967         while (helicopter)
968         {
969              helicopter->UpdateLatLon();
970              torpedoes = helicopter->Helicopter_AI(Subs, torpedoes);
971              #ifdef DEBUG_HELICOPTER
972              printf("Course: %d\nSpeed: %d\nHeight: %d\n",
973                      (int) helicopter->Heading, (int) helicopter->Speed,
974                      (int) helicopter->Depth);
975              printf("DX: %d DY: %d\nX: %d  Y: %d\n",
976                     helicopter->destination_x, helicopter->destination_y,
977                     (int) helicopter->Lat_TotalYards,
978                     (int) helicopter->Lon_TotalYards);
979              #endif
980              helicopter->Handle();
981              helicopter = helicopter->next;
982         }
983 
984 	for (int x = 0; x < MAX_SUBS; x++){
985 		Contacts[x].UpdateContact();
986 	}
987 
988         // move some torps
989         my_torp = torpedoes;
990         while (my_torp)
991         {
992            // check to see if this torpedo is chasing the player
993            if ( (my_torp->target == player) &&
994                 (my_torp->fuel_remaining == (TORPEDO_FUEL - 30)) )
995            {
996                Message.post_message("Torpedo coming our way!");
997                Message.display_message();
998            }
999            my_torp->UpdateLatLon();
1000            my_torp->Torpedo_AI(Subs);   // see where we should be going
1001            my_torp->Handeling();    // change heading and depth
1002            status = my_torp->Check_Status();  // see if we ran into something
1003                                               // or we are out of fuel
1004            if (status == OUT_OF_FUEL)
1005            {
1006                if (my_torp->ShipType == TYPE_TORPEDO)
1007                   Message.post_message("A torpedo ran out of fuel.");
1008                else
1009                   Message.post_message("Noisemaker stopped running.");
1010                temp_torp = my_torp->next;
1011                if (current_target == my_torp)
1012                  current_target = NULL;
1013                Subs->Cancel_Target(my_torp);
1014                torpedoes = Remove_Ship(torpedoes, my_torp);
1015                my_torp = temp_torp;
1016                Message.display_message();
1017            }
1018            else if (status == HIT_TARGET)
1019            {
1020                int target_status = DAMAGE_OK;
1021                // damage target
1022                // we should always have a target, but just in case...
1023                if (my_torp->target)
1024                {
1025                   if (my_torp->target == player)
1026                      Message.post_message("We have been hit!");
1027                   else
1028                      Message.post_message("A torpedo hit its target!");
1029                   // radio warning to others
1030                   if ( (my_torp->target->ShipType == TYPE_SHIP) &&
1031                        (my_torp->target->mood == MOOD_CONVOY) )
1032                   {
1033                       my_torp->target->Radio_Signal(Subs, RADIO_UNDER_ATTACK);
1034                   }
1035                   target_status = my_torp->target->Take_Damage();
1036                   if (target_status == DAMAGE_SINK)
1037                   {
1038                      if (my_torp->target == player)
1039                        player = NULL;
1040                      if (my_torp->target->mission_status == MISSION_ALIVE)
1041                         my_mission_status = MISSION_FAILED;
1042                      Remove_Inactive_Ship(my_torp->target);
1043                   }
1044                }
1045                if (current_target == my_torp)
1046                   current_target = NULL;
1047                Subs->Cancel_Target(my_torp);
1048                temp_torp = my_torp->next;
1049                torpedoes = Remove_Ship(torpedoes, my_torp);
1050                my_torp = temp_torp;
1051                // Message.post_message("A torpedo hit its target!");
1052                if (target_status == DAMAGE_SINK)
1053                   Message.post_message("Target is sinking!");
1054                Message.display_message();
1055            }
1056            else
1057               my_torp = my_torp->next;
1058         }   // end of all torpedoes
1059 
1060         // see if we can still detect the current target
1061         if (current_target)
1062         {
1063             status = player->Can_Detect(current_target);
1064             if (status < CONTACT_WEAK)
1065                current_target = NULL;
1066         }
1067 }
1068 
1069 
1070 
1071 // This function may get a little messy, we need to do a few things
1072 // to remove a ship completely from the scenario.
1073 // 1. Any torpedoes shooting at this target have to have their
1074 //    target variable set to NULL
1075 // 2. Any ships/subs who were tracking this ship need to stop
Remove_Inactive_Ship(Submarine * victim)1076 void Remove_Inactive_Ship(Submarine *victim)
1077 {
1078     Submarine *torpedo;
1079     Submarine *ship;
1080 
1081     if (! victim)   // couldn't find victim, this should never happen, quit
1082         return;
1083 
1084     // 1. Cancel torpedoes targetting this ship
1085     torpedo = torpedoes;
1086     while (torpedo)
1087     {
1088         if (torpedo->target == victim)
1089           torpedo->target = NULL;
1090         torpedo = torpedo->next;
1091     }
1092 
1093     // 2. Ships who were tracking this ship need to stop
1094     ship = Subs;
1095     while (ship)
1096     {
1097        ship->Cancel_Target(victim);
1098        ship = ship->next;
1099     }
1100 
1101     Subs->last_target = NULL;
1102     Subs = Remove_Ship(Subs, victim);
1103     if (victim == current_target)
1104        current_target = NULL;
1105 }
1106 
1107 
1108 
1109 
1110 
1111 
RelativeBearing(Submarine * observer,Submarine * target)1112 double RelativeBearing(Submarine *observer, Submarine *target){
1113 	// Returns the relative bearing of target to observer. This bearing is
1114 	//measured clockwise from on ships heading to target bearing.
1115 	double relative_bearing;
1116 	int observer_heading, bearing_to_target;
1117 	bearing_to_target = (int) observer->BearingToTarget(target );
1118 	observer_heading = (int)observer->Heading;
1119 	if(observer_heading > bearing_to_target) bearing_to_target += 360;
1120 	relative_bearing = bearing_to_target - observer_heading;
1121 	return relative_bearing;
1122 }
1123 
ReciprocalBearing(int bearing)1124 int ReciprocalBearing(int bearing){
1125 	// returns the 180 degree opposite of the bearing given to it..
1126 	int recipbearing;
1127 	if (bearing >= 180){
1128 		 recipbearing = bearing - 180;
1129 	}else{
1130 		recipbearing = bearing + 180;
1131 	}
1132 	return recipbearing;
1133 }
1134 
AngleOnBow(Submarine * observer,Submarine * target)1135 double AngleOnBow(Submarine *observer, Submarine *target){
1136 	// Returns the Angle on the Bow (AOB) of target relative to observer.
1137 	// Note: -180 < Angle on Bow < 180
1138 	// Positive AOB = Port AOB, Negative AOB = Starboard AOB
1139 	// Examples:
1140 	// target AOB port 30 -> +30
1141 	// target AOB starboard 30 -> -30
1142 	// target pointing at observer -> 0
1143 	// target pointing away from observer -> -180
1144 	double aob=0;
1145 	aob = target->Heading - observer->Heading
1146 	-	RelativeBearing(observer,target) - 180;
1147 	if (aob > 180) aob = 360 - aob;
1148 	if (aob < -180) aob = 360 + aob;
1149 	return aob;
1150 }
1151 
minimize360(int compass_bearing)1152 int minimize360 ( int compass_bearing ){
1153 	// If course is bigger than 360 degrees, then subtract 360 degrees from it
1154 	// and keep doing so until it is less than 360 degrees.
1155 	while ( compass_bearing > 360 )
1156 	{
1157 		compass_bearing -= 360;
1158 	}
1159 	return compass_bearing;
1160 }
1161 
maximize360(int compass_bearing)1162 int maximize360 ( int compass_bearing ){
1163 	// If course is negative then, then add 360 degrees to it
1164 	// and keep doing so until it is positive.
1165 	while ( compass_bearing < 0 )
1166 	{
1167 		compass_bearing += 360;
1168 	}
1169 	return compass_bearing;
1170 }
1171 
CalculateRange(Submarine * observer,Submarine * target)1172 double CalculateRange(Submarine *observer, Submarine *target){
1173 	//Calculates the distance in yards from the observer, to the target.
1174 
1175 	double latdif = 0, londif = 0; //sqrt needs doubles
1176 	LatLonDifference( observer,  target,  &latdif,  &londif );
1177 	return sqrt((latdif * latdif) + (londif * londif));
1178 }
1179 
LatLonDifference(Submarine * x,Submarine * y,double * platdif,double * plondif)1180 void LatLonDifference(Submarine *x, Submarine *y, double *platdif, double *plondif){ // CHANGE TO REFERENCES
1181 	//Returns in yards the difference between object x and object y
1182 
1183 	if (x->Lat_TotalYards > y->Lat_TotalYards){
1184 		*platdif = x->Lat_TotalYards - y->Lat_TotalYards;
1185 	}
1186 	else{
1187 		*platdif = y->Lat_TotalYards - x->Lat_TotalYards;
1188 	}
1189 
1190 	if (x->Lon_TotalYards > y->Lon_TotalYards){
1191 		*plondif = x->Lon_TotalYards - y->Lon_TotalYards;
1192 	}
1193 	else{
1194 		*plondif = y->Lon_TotalYards - x->Lon_TotalYards;
1195 	}
1196 }
1197 
CreateShips(int mission_number,MAP * map)1198 void CreateShips(int mission_number, MAP *map)
1199 {
1200   char *ship_file, *mission_name;
1201   char filename[128];
1202   char line[256], *status;
1203   // int i;
1204   FILE *my_file, *mission_file;
1205   Submarine *new_ship;
1206   Helicopter *new_helicopter;
1207   int ship_type, ship_class;
1208 
1209   #ifndef WIN32
1210   snprintf(filename, 128, "data/ships%d.dat", mission_number);
1211   #else
1212   sprintf(filename, "data/ships%d.dat", mission_number);
1213   #endif
1214 
1215   ship_file = Find_Data_File(filename);
1216   my_file = fopen(ship_file, "r");
1217   if ( (ship_file) && (ship_file != filename) )
1218      free(ship_file);
1219 
1220   // idiot check
1221   if(!my_file){
1222     printf("Create ships: file missing\n");
1223     exit(1);
1224   }
1225 
1226   #ifndef WIN32
1227   snprintf(filename, 128, "data/mission%d.dat", mission_number);
1228   #else
1229   sprintf(filename, "data/mission%d.dat", mission_number);
1230   #endif
1231   mission_name = Find_Data_File(filename);
1232   mission_file = fopen(mission_name, "r");
1233   if ( (mission_name) && (mission_name != filename) )
1234     free(mission_name);
1235 
1236 
1237   // Read in the data from the ship file
1238   // Format of ship file: 1 row of data per ship
1239   // Active flag, Ship Type, Friend flag, Speed, DesiredSpeed, Depth,
1240   // Desired depth, Heading, Desired
1241   // Heading, Rudder, Lat_TotalYards, Lon_TotalYards, PSCS
1242 
1243   // Notes: Ship Type: Sub=0, Surface=1, Aircraft=2
1244   //        Friend: Foe=0, Friend=1, Unknown=2, Neutral=3
1245   // i = 0;
1246   status = fgets(line, 256, my_file);
1247   while (status)
1248   {
1249    sscanf(line, "%d %d", &ship_type, &ship_class);
1250    if (ship_class == CLASS_HELICOPTER)
1251    {
1252          #ifdef DEBUG
1253          printf("Creating new helicopter.\n");
1254          #endif
1255          new_helicopter = new Helicopter();
1256          if (new_helicopter)
1257          {
1258              new_helicopter->map = map;
1259              sscanf(line, "%d %d %d %d %d %d %f %f %d",
1260                     &(new_helicopter->ShipType),
1261                     &(new_helicopter->ShipClass),
1262                     &(new_helicopter->Friend),
1263                     &(new_helicopter->DesiredSpeed),
1264                     &(new_helicopter->DesiredDepth),
1265                     &(new_helicopter->DesiredHeading),
1266                     &(new_helicopter->Lat_TotalYards),
1267                     &(new_helicopter->Lon_TotalYards),
1268                     &(new_helicopter->has_sonar) );
1269              // check mood
1270         #ifndef WIN32
1271         if ( strcasestr(line, "convoy") )
1272             new_helicopter->mood = MOOD_CONVOY;
1273         else if ( strcasestr(line, "passive") )
1274             new_helicopter->mood = MOOD_PASSIVE;
1275         else if ( strcasestr(line, "attack") )
1276             new_helicopter->mood = MOOD_ATTACK;
1277         #else
1278         if ( my_strcasestr(line, "convoy") )
1279             new_helicopter->mood = MOOD_CONVOY;
1280         else if ( my_strcasestr(line, "passive") )
1281             new_helicopter->mood = MOOD_PASSIVE;
1282         else if ( my_strcasestr(line, "attack") )
1283             new_helicopter->mood = MOOD_ATTACK;
1284         #endif
1285         new_helicopter->Speed = new_helicopter->DesiredSpeed;
1286         new_helicopter->Heading = new_helicopter->DesiredHeading;
1287         new_helicopter->Depth = new_helicopter->DesiredDepth;
1288              // load mission
1289         new_helicopter->Load_Mission(mission_file);
1290              // load class
1291         sprintf(filename, "ships/class%d.shp", new_helicopter->ShipClass);
1292         ship_file = Find_Data_File(filename);
1293         new_helicopter->Load_Class(ship_file);
1294         // add helicopter to list
1295         helicopters = Add_Helicopter(helicopters, new_helicopter);
1296         if ( (ship_file) && (ship_file != filename) )
1297            free(ship_file);
1298         }    // end of created a helicopter
1299 
1300    } // end of helicopter
1301 
1302    else   // all other classes
1303    {
1304    #ifdef DEBUG
1305    printf("Creating new ship\n");
1306    #endif
1307      new_ship = new Submarine();
1308      if (new_ship)
1309      {
1310         #ifdef DEBUG
1311         printf("Added new ship to list of ships.\n");
1312         #endif
1313         new_ship->Init();
1314         new_ship->map = map;
1315         #ifdef DEBUG
1316         printf("Loaded: %s", line);
1317         #endif
1318         sscanf(line, "%d %d %d %d %d %d %f %f",
1319                   &(new_ship->ShipType),
1320                   &(new_ship->ShipClass), &(new_ship->Friend),
1321                   &(new_ship->DesiredSpeed), &(new_ship->DesiredDepth),
1322                   &(new_ship->DesiredHeading), &(new_ship->Lat_TotalYards),
1323                   &(new_ship->Lon_TotalYards)); // , &(new_ship->PSCS) );
1324         // check mood
1325         #ifndef WIN32
1326         if ( strcasestr(line, "convoy") )
1327             new_ship->mood = MOOD_CONVOY;
1328         else if ( strcasestr(line, "passive") )
1329             new_ship->mood = MOOD_PASSIVE;
1330         else if ( strcasestr(line, "attack") )
1331             new_ship->mood = MOOD_ATTACK;
1332         #else
1333         if ( my_strcasestr(line, "convoy") )
1334             new_ship->mood = MOOD_CONVOY;
1335         else if ( my_strcasestr(line, "passive") )
1336             new_ship->mood = MOOD_PASSIVE;
1337         else if ( my_strcasestr(line, "attack") )
1338             new_ship->mood = MOOD_ATTACK;
1339         #endif
1340 
1341      #ifdef DEBUG
1342      printf("%d %d %d %d %d %d %f %f %d\n",
1343                   (new_ship->ShipType),
1344                   (new_ship->ShipClass), (new_ship->Friend),
1345                   (new_ship->DesiredSpeed), (new_ship->DesiredDepth),
1346                   (new_ship->DesiredHeading), (new_ship->Lat_TotalYards),
1347                   (new_ship->Lon_TotalYards), new_ship->mood);
1348                   // , (new_ship->PSCS) );
1349 
1350      #endif
1351      new_ship->Speed = new_ship->DesiredSpeed;
1352      new_ship->Depth = new_ship->DesiredDepth;
1353      new_ship->Heading = new_ship->DesiredHeading;
1354      #ifdef DEBUG
1355      printf("Set S: %f H: %f D: %f\n", new_ship->Speed,
1356             new_ship->Heading, new_ship->Depth);
1357      #endif
1358      new_ship->Load_Mission(mission_file);
1359      #ifdef DEBUG
1360      printf("Ship has mission flag: %d\n", new_ship->mission_status);
1361      #endif
1362      sprintf(filename, "ships/class%d.shp", new_ship->ShipClass);
1363      ship_file = Find_Data_File(filename);
1364      new_ship->Load_Class(ship_file);
1365      Subs = Add_Ship(Subs, new_ship);
1366      if ( (ship_file) && (ship_file != filename) )
1367         free(ship_file);
1368      // i+=1;
1369      }   // end of successfully created new ship
1370 
1371      }  // end of other classes
1372 
1373      status = fgets(line, 256, my_file);
1374   }
1375   // inClientFile.close();
1376   if (my_file)
1377      fclose(my_file);
1378   if (mission_file)
1379      fclose(mission_file);
1380 
1381   // ships = i - 1;
1382   // ships = i;
1383   // rdm 5/15/01 testing to be sure correct number of ships being read
1384   // cout << " Number of ships = " <<  i-1 << endl;
1385   if (Subs)
1386   {
1387       SonarStation.Subs = Subs;
1388       RadarStation.Subs = Subs;
1389       EsmStation.Subs = Subs;
1390       ControlStation.Subs = Subs;
1391       player = Subs;
1392   }
1393 }
1394 
UpdateSensors()1395 void UpdateSensors(){
1396 //Added code to place our boats position into a FIFO so we
1397 //can calculate where the sonar array is at any time.
1398 //the cable on the TB16 is 2600ft. wich is 866yds. The FIFO is
1399 //100 elements holding 2 double precision floats. So 866/100
1400 //Is 8.66, Which is the resolution of our placement of the array.
1401         #ifdef DEBUG
1402         printf("Updating sensors and stuff\n");
1403         #endif
1404 	static float distance_traveled;
1405 	distance_traveled += Subs->Speed * 0.555;
1406 	if(distance_traveled >= 8.66){ //if we've gone 8.66yds record our loc in the FIFO
1407 		TB16.RecordPos(Subs->Lat_TotalYards,  Subs->Lon_TotalYards);
1408 		distance_traveled = distance_traveled - 8.66;
1409 	}
1410 	TB16.OperateWinch();//extend/retract the array as needed.
1411 	SoundEnvironment(); //lets give a listen...
1412 	SonarStation.Sonar(SonarStation.GetNorthCenterState());
1413 	SonarStation.TowedSonar(SonarStation.GetNorthCenterState());
1414 }
1415 
UpdateDisplay()1416 void UpdateDisplay(){
1417 	if (drawmap){
1418                 Display_Target();
1419 		DrawMap(); // fix me to do something useful!
1420                 Draw_Depth_Meter(player, SCREEN_NAV);
1421 	}
1422 	if (drawsonar){
1423 		SonarStation.UpdateDisplay(current_target);
1424 	}
1425 	if (drawtma){
1426 		DisplayTMA();
1427 	}
1428         if (drawweapons)
1429             DisplayWeapons();
1430 	if (drawradar){
1431 		RadarStation.DisplayContacts();
1432 	}
1433 	if (drawesm){
1434 		EsmStation.DisplayContacts();
1435 	}
1436 	if (drawcontrol){
1437 		ControlStation.Display();
1438                 Draw_Depth_Meter(player, SCREEN_HELM);
1439 	}
1440 
1441 }
1442 
1443 
1444 
1445 // Show information on the currently selected target
Display_Target()1446 void Display_Target()
1447 {
1448    char buffer[256];
1449    SDL_Rect rectangle;
1450    DFont fnt("images/font.png", "data/font.dat");
1451    float range;
1452    double bearing;
1453 
1454    // if (! current_target)
1455    //   return;
1456 
1457    // make empty box to the side of the screen
1458    rectangle.x = 120;
1459    rectangle.y = 400;
1460    rectangle.w = 200;
1461    rectangle.h = 160;
1462    SDL_FillRect(screen, &rectangle, black);
1463 
1464    if (current_target)
1465    {
1466    // fill in data
1467    sprintf(buffer, "   Target");
1468    fnt.PutString(screen, 150, 400, buffer);
1469    sprintf(buffer, "Heading: %d", (int) current_target->Heading);
1470    fnt.PutString(screen, 140, 424, buffer);
1471 
1472    sprintf(buffer, "Spead: %d knots", (int) current_target->Speed);
1473    fnt.PutString(screen, 140, 436, buffer);
1474 
1475    range = Subs->DistanceToTarget(current_target);
1476    // range *= 0.000568;
1477    range *= YARDS_TO_MILES;
1478    sprintf(buffer, "Range: %2.1f miles", range);
1479    fnt.PutString(screen, 140, 448, buffer);
1480 
1481    bearing = Subs->BearingToTarget(current_target);
1482    sprintf(buffer, "Bearing: %2.0lf", bearing);
1483    fnt.PutString(screen, 140, 460, buffer);
1484 
1485    sprintf(buffer, "Depth: %d feet", (int) current_target->Depth);
1486    fnt.PutString(screen, 140, 472, buffer);
1487 
1488    sprintf(buffer, "Type: %s ", current_target->ClassName );
1489    if (current_target->ClassType[0])
1490       strcat(buffer, current_target->ClassType);
1491    fnt.PutString(screen, 140, 484, buffer);
1492    }   // end of valid target
1493    SDL_UpdateRects(screen, 1, &rectangle);
1494 }
1495 
1496 
1497 
Draw_Depth_Meter(Submarine * my_sub,int screen_number)1498 void Draw_Depth_Meter(Submarine *my_sub, int screen_number)
1499 {
1500    SDL_Rect rectangle;
1501    int y, index;
1502 
1503    if (screen_number == SCREEN_NAV)
1504    {
1505      rectangle.x = 890;
1506      rectangle.y = 145;
1507      rectangle.h = 500;
1508    }
1509    else   // helm screen
1510    {
1511      rectangle.x = 450;
1512      rectangle.y = 125;
1513      rectangle.h = 525;
1514    }
1515    rectangle.w = 10;
1516 
1517    if (! my_sub)
1518       return;
1519    SDL_FillRect(screen, &rectangle, mapcolor);
1520    if (my_sub->map)
1521    {
1522      for (index = 0; index < my_sub->map->Thermals_Between(0, MAX_DEPTH); index++)
1523      {
1524         y = my_sub->map->thermals[index];
1525         y = rectangle.y + (y / 10);
1526         FillRectangle(screen, rectangle.x, y, rectangle.x + 10, y+1, white);
1527      }
1528    }
1529    y = (my_sub->Depth / 10) + rectangle.y;
1530    FillRectangle(screen, rectangle.x, y, rectangle.x + 10, y+1, red);
1531    SDL_UpdateRects(screen, 1, &rectangle);
1532 }
1533 
1534 
DrawMap()1535 void DrawMap(){
1536 	//Future home of an actual map display routine, right now just a blank field with dots
1537 
1538 	SDL_Rect rectangle;
1539 	rectangle.x=374;
1540 	rectangle.y=145;   //define a rectangle on the screen and make it blue
1541 	rectangle.h=500;
1542 	rectangle.w=501;
1543 	SDL_FillRect(screen, &rectangle, mapcolor);
1544 
1545 	for (int x=374; x<874; x+= 10){ //Make meaningless dots grid on "Map"
1546 		for (int y=145; y<637; y+= 10){
1547 			DrawPixel(screen, x+5, y+5, white);
1548 		}
1549 	}
1550         #ifdef DEBUG
1551         printf("About to place ships.\n");
1552         #endif
1553 	PlaceShips(mapscale, 0, 0, current_target);
1554 	SDL_UpdateRects(screen, 1, &rectangle);
1555 
1556 }
1557 
PlaceShips(int scale,int change_scrollx,int change_scrolly,Submarine * current_target)1558 void PlaceShips(int scale, int change_scrollx, int change_scrolly, Submarine *current_target){
1559 	//Places all Ships onto the map. Soon to change, so only registered contacts appear.
1560 	//scale is in YDS per pixel
1561         int fresh;
1562 	int x, y; //where to place the ships
1563 	int xoffset = 374;  //offsets to move the ships to
1564 	int yoffset = 145;  //the defined place on map screen
1565 	static int scrolloffsetx=0; //offset to center map
1566 	static int scrolloffsety=0;
1567 	Uint32 color;
1568         Submarine *a_torp;
1569         Submarine *target_ship;
1570         Helicopter *a_helicopter;
1571         int layers;
1572 
1573 	scale = scale * MAP_FACTOR;
1574 	if(mapcenter){ //center map onto our own ntds symbol
1575 		scrolloffsetx = 250 - ((int)Subs->Lat_TotalYards / scale);
1576 		scrolloffsety = 250 - ((int)Subs->Lon_TotalYards / scale);
1577 	}else{
1578 		scrolloffsetx += change_scrollx;
1579 		scrolloffsety += change_scrolly;
1580 	}
1581         target_ship = Subs;
1582         #ifdef DEBUG
1583         printf("About to place ships on map.\n");
1584         #endif
1585         while (target_ship)
1586         {
1587              fresh = Subs->Can_Detect(target_ship);
1588              #ifdef DEBUG
1589              printf("Freshness factor %d\n", fresh);
1590              #endif
1591              if ( (fresh) || (target_ship == Subs) )
1592              {
1593 		x = 500 - ((int)target_ship->Lat_TotalYards / scale);
1594 		x = x - scrolloffsetx;
1595 		y = 500 - ((int)target_ship->Lon_TotalYards / scale);
1596 		y = y - scrolloffsety;
1597 		if (x>10 && x<490 && y>10 && y<490){ //are we going to fall off the damn map???
1598 			x = x + xoffset;
1599 			y = y + yoffset;
1600                         // not only do we need friend/foe, but
1601                         // also fresh/old contact
1602                         // fresh = Subs->Can_Detect(target_ship);
1603 			switch(target_ship->Friend){
1604 				case 0: //Foe??
1605                                         if (fresh >= CONTACT_SOLID)
1606 					  color = red;
1607                                         else
1608                                           color = dark_red;
1609 					break;
1610 				case 1: //Friend??
1611                                         if (fresh >= CONTACT_SOLID)
1612 					  color = green;
1613                                         else
1614                                           color = dark_green;
1615 					break;
1616 				case 2: // Neither???
1617                                         if (fresh >= CONTACT_SOLID)
1618                        			   color = yellow;
1619                                         else
1620                                            color = brown;
1621                                         break;
1622 				default: // Unknown
1623                                         if (fresh >= CONTACT_SOLID)
1624                                            color = grey;
1625                                         else
1626                                            color = dark_grey;
1627 					break;
1628 			}
1629 			if (target_ship == Subs){  // Is it me???
1630 				color = green;
1631 			}
1632                         #ifdef DEBUG
1633                         printf("Deciding if to draw clearly.\n");
1634                         #endif
1635                         if ( (fresh >= CONTACT_WEAK) || (Subs == target_ship) )
1636                         {
1637 			  MapIcon(x, y, (int)target_ship->ShipType, (int)target_ship->Friend, color); //Draw the NTDS symbol.
1638                           // check to see if we should highlight
1639                           if (current_target == target_ship)
1640                              MapIcon(x, y+1, (int)target_ship->ShipType, (int)target_ship->Friend, color);
1641 			  DirectionalPointer(x-2, y+2, (int)target_ship->Heading, (int)target_ship->Speed, black);
1642 			  DirectionalPointer(x, y, (int)target_ship->Heading, (int)target_ship->Speed, color);
1643 			// Add pointer the show heading.
1644                         }   // end of we can hear you ok
1645 		}   // end of we are on the map
1646              }    // end of able to detect
1647              target_ship = target_ship->next;
1648 	}
1649 
1650         // now place torpedoes
1651         #ifdef DEBUG
1652         printf("About to draw torpedoes on map\n");
1653         #endif
1654         a_torp = torpedoes;
1655         while (a_torp)
1656         {
1657            x = 500 - ((int)a_torp->Lat_TotalYards / scale);
1658            x = x - scrolloffsetx;
1659            y = 500 - ((int)a_torp->Lon_TotalYards / scale);
1660            y = y - scrolloffsety;
1661            if (x>10 && x<490 && y>10 && y<490)  //are we going to fall off  map??
1662            {
1663               x = x + xoffset;
1664               y = y + yoffset;
1665               switch(a_torp->Friend){
1666                  case 0: //Foe??
1667                          color = red;
1668                          break;
1669                  case 1: //Friend??
1670                          color = green;
1671                          break;
1672                  case 2: // Neither???
1673                          color = yellow;
1674                          break;
1675                  default: // Unknown
1676                           color = grey;
1677                           break;
1678                }
1679                MapIcon(x, y, (int)a_torp->ShipType, (int)a_torp->Friend, color);
1680            }   // within map limits
1681 
1682            a_torp = a_torp->next;
1683         }  // end of displaying torpedoes
1684 
1685        #ifdef DEBUG
1686        printf("About to draw helicopters on map.\n");
1687        #endif
1688        // we only draw helicopters if we are near the surface
1689        // and moving slow. This is crude, but it'll do for now
1690        layers = my_map->Thermals_Between(0, player->Depth);
1691        if ( (layers < 1) && (player->Speed < (player->MaxSpeed / 2) ) )
1692        {
1693        a_helicopter = helicopters;
1694        while (a_helicopter)
1695        {
1696            x = 500 - ((int)a_helicopter->Lat_TotalYards / scale);
1697            x = x - scrolloffsetx;
1698            y = 500 - ((int)a_helicopter->Lon_TotalYards / scale);
1699            y = y - scrolloffsety;
1700            if (x>10 && x<490 && y>10 && y<490)  // are we on the map
1701            {
1702                x = x + xoffset;
1703                y = y + yoffset;
1704                switch (a_helicopter->Friend)
1705                {
1706                   case FOE: color = red; break;
1707                   case FRIEND: color = green; break;
1708                   case NEUTRAL: color = grey; break;
1709                   case UNKNOWN:
1710                   default:  color = yellow; break;
1711                }   // end of friend/foe switch
1712                MapIcon(x, y, a_helicopter->ShipType,
1713                        a_helicopter->Friend, color);
1714            }  // within map limits
1715            a_helicopter = a_helicopter->next;
1716        }   // end of drawing helicopters
1717        }   // end of if near surface
1718 }
1719 
1720 
1721 
1722 // calls the other detection functions to see if there is
1723 // any way we can pick up the target
Any_Detection(double Range,Submarine * observer,Submarine * target)1724 float Any_Detection(double Range, Submarine *observer, Submarine *target)
1725 {
1726     float status;
1727 
1728     #ifdef DEBUG
1729     printf("Attempting all forms of detection.\n");
1730     #endif
1731     status = Radar_Detection(Range, observer, target);
1732     if (status)
1733     {
1734       // printf("I can see on radar target %d\n", target);
1735       return 2.0;
1736     }
1737     status = Esm_Detection(Range, observer, target);
1738     if (status)
1739     {
1740       // printf("I can pick up on esm target %d\n", target);
1741       return 1.0;
1742     }
1743     // this one takes the most math, so we do it last
1744     // status = Sonar_Detection(Range, observer, target);
1745     status = Sonar_Detection_New(Range, observer, target);
1746     // if (status)
1747     //   printf("I can hear target %d\n", target);
1748     return status;
1749 }
1750 
1751 
1752 // Can I see you on radar?
Radar_Detection(double Range,Submarine * observer,Submarine * target)1753 float Radar_Detection(double Range, Submarine *observer, Submarine *target)
1754 {
1755    int depth, range;
1756    bool result;
1757 
1758    depth = (int) observer->Depth;
1759    range = (int) observer->DistanceToTarget(target);
1760    result = RadarStation.isTargetVisible(target, range, depth,
1761                          SHIP_HEIGHT, DEFAULT_SEA_STATE);
1762    if (result)
1763        return 1.0;
1764    else
1765       return 0.0;
1766 }
1767 
1768 
1769 // Can I detect your radar?
Esm_Detection(double Range,Submarine * observer,Submarine * target)1770 float Esm_Detection(double Range, Submarine *observer, Submarine *target)
1771 {
1772    int depth, range;
1773    bool result;
1774 
1775    depth = (int) observer->Depth;
1776    range = (int) observer->DistanceToTarget(target);
1777    result = EsmStation.isTargetVisible(target, range, depth,
1778                        SHIP_HEIGHT, TRUE, DEFAULT_SEA_STATE);
1779    if (result)
1780      return 1.0;
1781    else
1782      return 0.0;
1783 
1784 }
1785 
1786 
1787 
1788 /// Can the observer hear the target?
Sonar_Detection_New(double Range,Submarine * observer,Submarine * target)1789 float Sonar_Detection_New(double Range, Submarine *observer, Submarine *target)
1790 {
1791 
1792         float NauticalMiles = (float)Range / 2000.0;
1793         float HisPassiveSonarCrosssection = target->PSCS;
1794         float EffectiveTargetSpeed;
1795         float AmbientNoise;
1796         float OwnShipNoise;
1797         float TotalNoise;
1798         float TargetNoise;
1799         float Gb;
1800         float Lbp;
1801         float NoiseFromSpeed;
1802         float BasisNoiseLevel;
1803         float value;
1804         float SeaState = 3.0; // Anyone want to model the weather.
1805         int thermal_layers = 0;
1806 
1807         if (target->Speed <= 5.0){
1808              EffectiveTargetSpeed = 0.0;
1809         }else{
1810              EffectiveTargetSpeed = target->Speed - 5.0;
1811         }
1812 
1813         if (target->Speed < 20.0){
1814              NoiseFromSpeed = 1.30;
1815              BasisNoiseLevel = 0.0;
1816         }else{
1817              NoiseFromSpeed = 0.65;
1818              BasisNoiseLevel = 9.75;
1819         }
1820         if (my_map)
1821            thermal_layers = my_map->Thermals_Between(observer->Depth, target->Depth);
1822         #ifdef DEBUGMAP
1823         printf("There are %d thermal layers between us.\n", thermal_layers);
1824         #endif
1825         AmbientNoise = 89.0 + (5.0 * SeaState);
1826         OwnShipNoise = observer->RadiatedNoise();
1827         TotalNoise = 10.0 * log10(pow(10.0,OwnShipNoise/10.0) + pow(10.0,AmbientNoise/10.0));
1828         Gb = (TotalNoise - AmbientNoise) / 2.9;
1829         Lbp = AmbientNoise + Gb;
1830         TargetNoise = HisPassiveSonarCrosssection +
1831         ((NoiseFromSpeed * EffectiveTargetSpeed) + BasisNoiseLevel);
1832         #ifdef DEBUGMAP
1833         printf("Old target noise: %f\n", TargetNoise);
1834         #endif
1835         if (thermal_layers)
1836             TargetNoise -= TargetNoise * (thermal_layers * THERMAL_FILTER);
1837         #ifdef DEBUGMAP
1838         printf("New target noise: %f\n", TargetNoise);
1839         #endif
1840         value = TargetNoise - (20.0 * log10(NauticalMiles) + 1.1 * NauticalMiles) - Lbp;
1841         if (!observer)
1842               SonarStation.flowandambientnoise = (Lbp - 34);
1843         if (value > -45.0){
1844                 return (value - -45.0) + 1.0;
1845         }else{
1846                 return 0.0;
1847         }
1848 }
1849 
1850 
1851 
1852 
1853 
SoundEnvironment()1854 void SoundEnvironment(){
1855 	///********************************************************************
1856 	//This will gather sound information from all platforms and place
1857 	//messages into each platforms sonar queue.
1858 	//*********************************************************************
1859 
1860 	int bearing;
1861 	double Range;
1862         Submarine *target;
1863         int line = FALSE;
1864 
1865 	//loop through each ship and let them listen
1866 	//for the other ships...
1867         #ifdef DEBUG
1868         printf("Advancing sonar.\n");
1869         #endif
1870 	Subs->AdvanceSonarHistory(); //advance sonar queue by 1/5th of a second
1871 	TB16.AdvanceSonarHistory(); //advance sonar queue by 1/5th of a second
1872 	// for (target=Subs->next; target; target = target->next){
1873         target = Subs->next;
1874         while (target)
1875         {
1876           #ifdef DEBUG
1877           printf("Checking if we can hear other ships.\n");
1878           #endif
1879 		if (! player->InBaffles(target, 1, &TB16)){ //I'm not deaf?
1880 			Range = CalculateRange(target, Subs);
1881 			float signal;
1882 			signal = Any_Detection(Range, Subs, target);
1883 			if (signal){ // Are we audible?
1884                         #ifdef DEBUG
1885                         printf("Heard you, adding to list.\n");
1886                         #endif
1887 				bearing = (int)Subs->BearingToTarget(target);  //Change me to float for better tma
1888                                 // this weird check prevents us from
1889                                 // erasing sonar data with radar/esm data
1890                                 if ( (signal == 1.0) || (signal == 2.0) )
1891                                 {
1892                                     float temp_signal;
1893                                     temp_signal = Sonar_Detection_New(Range, Subs, target);
1894 				    Subs->RegisterEvent(bearing,temp_signal,target->ShipType);
1895                                 }
1896                                 else
1897                                    Subs->RegisterEvent(bearing, signal, target->ShipType);
1898                                 // printf("Adding target %d to list.\n", target);
1899                                 Subs->Add_Target(target, signal);
1900 			}
1901                         else {
1902                           // printf("Lost target %d from list.\n", target);
1903                           Subs->Remove_Target(target);
1904                         }
1905 		}
1906 		else if (! player->InBaffles(target, 2, &TB16) && TB16.GetLength() >240){ // do the same for towed array
1907 			Range = TB16.RangeToTarget(target->Lat_TotalYards, target->Lon_TotalYards);
1908 			float signal;
1909 			// signal = Sonar_Detection(Range, 0, target);
1910                         signal = Sonar_Detection_New(Range, Subs, target);
1911 			if (signal){ // Are we audible?
1912 				bearing = (int)TB16.BearingToTarget(target->Lat_TotalYards, target->Lon_TotalYards);  //Change me to float for better tma
1913 				TB16.RegisterEvent(bearing,signal, target->ShipType);
1914                                 // printf("Adding target %d to list.\n", target);
1915                                 Subs->Add_Target(target, signal);
1916 			}
1917                         else {
1918                           // printf("Lost target %d from list.\n", target);
1919                           Subs->Remove_Target(target);
1920                         }
1921 		}
1922                 else   // can't hear target with either sonar device
1923                   Subs->Remove_Target(target);
1924 
1925             target = target->next;
1926             if ( (!target) && (! line) )
1927             {
1928                target = torpedoes;
1929                line = TRUE;
1930             }
1931 	}
1932 }
1933 
1934 /*********************************************
1935 	This function will return if a target is in
1936 	the observers Baffles and therefore not
1937 	detectable. Values for 'int sensor' are 1 for
1938 	spherical array, 2 for towed array, 3 for port
1939 	hull array and 4 for starboard hull array.
1940 
1941 	Might want to move the calculations of the
1942 	baffle angles to the Coord class so they don't
1943 	have to be calculated all the time.
1944 *********************************************/
1945 /*
1946 Moving InBaffles to the Submarine class to keep things cleaner.
1947 -- Jesse
1948 
1949 int InBaffles(Submarine *observer, Submarine *target, int sensor){
1950 	int array_heading;
1951 	int relative_bearing;
1952 	int sensordeaf=1;
1953 	int bearing_to_target;
1954 
1955 	switch(sensor){
1956 		case 1:	//Spherical
1957 			sensordeaf = 0;
1958 			array_heading = (int)observer->Heading;
1959 			bearing_to_target = (int)observer->BearingToTarget( target);
1960 			if(array_heading > bearing_to_target) bearing_to_target += 360;
1961 			relative_bearing = bearing_to_target - array_heading;
1962 			if(relative_bearing > 150 && relative_bearing < 210) sensordeaf = 1;
1963 			if(target == observer) sensordeaf = 1;
1964 			break;
1965 		case 2:	//Towed
1966 			sensordeaf = 0;
1967 			array_heading = (int)TB16.ReturnHeading();
1968 			bearing_to_target = (int)TB16.BearingToTarget(target->Lat_TotalYards, target->Lon_TotalYards);
1969 			if(array_heading > bearing_to_target) bearing_to_target += 360;
1970 			relative_bearing = bearing_to_target - array_heading;
1971 			if(relative_bearing < 30 || relative_bearing > 330) sensordeaf = 1;
1972 			break;
1973 		case 3: //port hull
1974 		case 4: //sb hull
1975 		default:
1976 			break;
1977 	}
1978 	return sensordeaf;
1979 }
1980 */
1981 
1982 
DisplayTMA(int xoffset,int yoffset)1983 void DisplayTMA(int xoffset,int yoffset){
1984  	SDL_Rect source, destination;
1985 	source.x = 0;
1986 	source.y = 0;
1987 	source.w = 500;
1988 	source.h = 500;
1989 	destination.x = 374;
1990 	destination.y = 145;
1991 	destination.w = 500;
1992 	destination.h = 500;
1993 	Tma.Lock();
1994 	Tma.our_heading = (double)Subs->Heading;
1995 	Tma.our_speed = (float)Subs->Speed;
1996 	Tma.target_heading = (double)Subs->Heading;
1997 	Tma.target_speed = (float)Subs->Speed;
1998 	Tma.DisplayGeoPlot(xoffset,yoffset);
1999 	//Tma.DisplayLOS();
2000 	SDL_BlitSurface(Tma.GeoPlotScreen, &source, screen, &destination);
2001 	SDL_UpdateRects(screen, 1, &destination);
2002 	Tma.UnLock();
2003 }
2004 
DisplayWeapons()2005 void DisplayWeapons()
2006 {
2007     SDL_Rect weapons, tubes;
2008     DFont fnt("images/font.png", "data/font.dat");
2009     char text[256];
2010     int index, y1, y2;
2011 
2012     if (! update_weapons_screen)
2013         return;
2014 
2015     weapons.x = 150;
2016     weapons.y = 145;
2017     weapons.w = 200;
2018     weapons.h = 300;
2019     tubes.x = 374;
2020     tubes.y = 145;
2021     tubes.h = 500;
2022     tubes.w = 501;
2023 
2024     SDL_FillRect(screen, &weapons, black);
2025     sprintf(text, "WEAPONS");
2026     fnt.PutString(screen, 190, 150, text);
2027     sprintf(text, "     Torpedos: %d", Subs->TorpedosOnBoard);
2028     fnt.PutString(screen, 160, 174, text);
2029     sprintf(text, "Noise Makers: %d", Subs->NoiseMakers);
2030     fnt.PutString(screen, 160, 196, text);
2031     sprintf(text, "'T' to load torpedo");
2032     fnt.PutString(screen, 160, 300, text);
2033     sprintf(text, "'N' to load noise maker");
2034     fnt.PutString(screen, 160, 312, text);
2035     sprintf(text, "'U' to unload device");
2036     fnt.PutString(screen, 160, 324, text);
2037     sprintf(text, "'F' to fire");
2038     fnt.PutString(screen, 160, 336, text);
2039     SDL_UpdateRects(screen, 1, &weapons);
2040 
2041     SDL_FillRect(screen, &tubes, black);
2042     y1 = 150; y2 = 190;
2043     for (index = 0; index < MAX_TUBES; index++)
2044     {
2045         // draw tube
2046         DrawRectangle(screen, 390, y1, 500, y2, green);
2047         // draw buttons
2048         fnt.PutString(screen, 520, y1 + 5, "  Load");
2049         fnt.PutString(screen, 520, y1 + 18, "Torpedo");
2050         DrawRectangle(screen, 520, y1, 590, y2, green);
2051         fnt.PutString(screen, 600, y1 + 5, "   Load");
2052         fnt.PutString(screen, 600, y1 + 18, "Noise Maker");
2053         DrawRectangle(screen, 600, y1, 690, y2, green);
2054         fnt.PutString(screen, 700, y1 + 10, "Unload");
2055         DrawRectangle(screen, 700, y1, 760, y2, green);
2056         fnt.PutString(screen, 770, y1 + 10, "Fire!");
2057         DrawRectangle(screen, 770, y1, 815, y2, green);
2058         y1 += 50; y2 += 50;
2059     }
2060     SDL_UpdateRects(screen, 1, &tubes);
2061 
2062     // put stuff in the tubes
2063     y1 = 151;
2064     for (index = 0; index < MAX_TUBES; index++)
2065     {
2066        tubes.x = 391;
2067        tubes.y = y1;
2068        tubes.w = 105;
2069        tubes.h = 35;
2070        if (Subs->torpedo_tube[index] == TUBE_TORPEDO)
2071           SDL_BlitSurface(torpedo_image, NULL, screen, &tubes);
2072        else if (Subs->torpedo_tube[index] == TUBE_NOISEMAKER)
2073           SDL_BlitSurface(noisemaker_image, NULL, screen, &tubes);
2074        else
2075        {
2076          SDL_FillRect(screen, &tubes, black);
2077          sprintf(text, "Tube %d", index + 1);
2078          fnt.PutString(screen, 420, y1 + 10, text);
2079        }
2080        SDL_UpdateRects(screen, 1, &tubes);
2081        y1 += 50;
2082     }
2083     update_weapons_screen = FALSE;
2084 }
2085 
2086 
2087 
RandInt(int TO)2088 inline int RandInt(int TO){ //Returns a random interger...TO is upper limit
2089 	return (rand()%TO);
2090 }
2091 
Clamp(int sample)2092 inline int Clamp(int sample){ //holds a value to be between 0 and 255
2093 	if (sample < 0){
2094 		sample = 0;
2095 	}
2096 	if (sample > 255){
2097 		sample = 255;
2098 	}
2099 	return sample;
2100 }
2101 
Clamp(double sample)2102 inline double Clamp(double sample){ //Overloaded for floats
2103 	if (sample < 0){
2104 		sample = 0.0;
2105 	}
2106 	if (sample > 255){
2107 		sample = 255.0;
2108 	}
2109 	return sample;
2110 }
2111 
ResetWidgetFlags()2112 void ResetWidgetFlags(){
2113 	//turns off all the widget redraw flags
2114 	SonarStation.sonarwidget=false;
2115 	navwidget=0;
2116 	quitwidget=0;
2117 	tmawidget=0;
2118 	esmwidget=0;
2119 	radarwidget=0;
2120 	shipcontrolwidget=0;
2121 }
2122 
ShowStation(int station)2123 void ShowStation(int station){
2124 
2125  // init everything to avoid overlap
2126  drawmap = drawweapons = drawsonar = drawradar = drawesm = drawcontrol = 0;
2127  navwidget = shipcontrolwidget = radarwidget = esmwidget = 0;
2128 	switch (station){// which station are we at?
2129 		case 1: //sonar screen
2130 			LoadScreen(1); //load in the screen for the SONAR station
2131 			ResetWidgetFlags(); //self explanitory
2132 			SonarStation.sonarwidget = true; //depress the widget
2133 			DisplayWidgets(); // display the widgets
2134 			drawsonar = 1; //tell the sonar it's ok to draw itself
2135 			break;
2136 		case 2: //nav screen
2137 			LoadScreen(2); //load in the screen for the NAV station
2138 			ResetWidgetFlags(); //self explanitory
2139 			navwidget = 1; //depress the widget
2140 			DisplayWidgets(); // display the widgets
2141 			drawmap = 1; //tell the Map it's ok to draw itself
2142 			break;
2143 		case 3: //tma screen
2144 			LoadScreen(3); //load in the screen for the TMA station
2145 			ResetWidgetFlags(); //self explanitory
2146 			// tmawidget = 1; //depress the widget
2147 			DisplayWidgets(); // display the widgets
2148 			drawweapons = 1; //Turn on TMA screen updates
2149 			break;
2150 		case 4: //shipcontrol screen
2151 			LoadScreen(4); //load in the screen for the shipcontrol station
2152 			ResetWidgetFlags(); //self explanitory
2153 			shipcontrolwidget = 1; //depress the widget
2154 			DisplayWidgets(); // display the widgets
2155 			drawcontrol = 1;
2156 			ControlStation.InitGraphics(screen, controlscreen);
2157 			break;
2158 		case 5: //RADAR screen
2159 			LoadScreen(5); //load in the screen for the RADAR station
2160 			ResetWidgetFlags(); //self explanitory
2161 			radarwidget = 1; //depress the widget
2162 			DisplayWidgets(); // display the widgets
2163 			drawradar = 1; //Turn on Radar screen updates
2164 			RadarStation.InitGraphics(screen, radarscreen);
2165 			break;
2166 		case 6: //ESM screen
2167 			LoadScreen(6); //load in the screen for the ESM station
2168 			ResetWidgetFlags(); //self explanitory
2169 			esmwidget = 1; //depress the widget
2170 			DisplayWidgets(); // display the widgets
2171 			drawesm = 1; //Turn on ESM screen updates
2172 			EsmStation.InitGraphics(screen, esmscreen);
2173 			break;
2174 	}
2175 }
2176 
2177 
2178 
2179 
2180 
2181 /**************************************************
2182 This is our callback function to handle
2183 time critical Functions
2184 **************************************************/
timerfunc(Uint32 interval,void * param)2185 Uint32 timerfunc(Uint32 interval, void *param){
2186 
2187    should_update_everything = TRUE;
2188    return interval;
2189 }
2190 
Update_Everything()2191 int Update_Everything()
2192 {
2193         // param = NULL;
2194         #ifdef DEBUG
2195         printf("In timer function\n");
2196         #endif
2197         Clock.UpdateTime();
2198         ShipHandeling();
2199         if (player)
2200         {
2201            UpdateSensors();
2202            // see if the mission is over
2203            Check_Find(Subs);
2204            Check_Alive(Subs);
2205            my_mission_status = Mission_Status(Subs, my_mission_status);
2206         }  // player is dead, we should end the mission
2207         else
2208            my_mission_status = MISSION_FAILED;
2209         return TRUE;
2210 }
2211 
2212 
2213 
2214 /***************************************************
2215 Another callback to handle the 60 second
2216 resolution TMA stuff.
2217 ****************************************************/
TmaTimer(Uint32 interval,void * param)2218 Uint32 TmaTimer(Uint32 interval, void *param){
2219 	static Uint32 tick = 0;
2220 	Tma.Lock(); //Lock Tma access mutex
2221 	param = NULL; //Quites error messages.
2222 	tick ++; //record the time of the tma record.
2223 	Tma.RecordBoatPosition(Subs->Lat_TotalYards, Subs->Lon_TotalYards, Subs->BearingToTarget(& (Subs[1])) , tick);
2224 	Tma.UnLock(); //Unlock mutex
2225 	return interval;
2226 }
2227 
HandleInput(SDL_Event & event,int & mousex,int & mousey)2228 int HandleInput(SDL_Event &event, int &mousex, int &mousey){
2229 	static string textline;
2230         int y1, y2, x_checks_out;
2231         int index;
2232 
2233 	switch (event.type){
2234 		case SDL_MOUSEBUTTONDOWN:
2235 			mousex = event.button.x;
2236 			mousey = event.button.y;
2237 			if (mousey<740 && mousey>711){
2238 				if (mousex <212 && mousex>180){   //SONAR widget
2239 					return SONAR;
2240 					break;
2241 				}
2242 				if (mousex <312 && mousex>280){  //Map Widget
2243 					return NAVMAP;
2244 					break;
2245 				}
2246 				if (mousex <412 && mousex>380){  //TMA Widget
2247 				 	return WEAPONS;
2248 					break;
2249 				}
2250 				if (mousex <512 && mousex>480){  //Ship Control Widget
2251 					return SHIPCONTROL;
2252 					break;
2253 				}
2254 				if (mousex <612 && mousex>580){  //ESM Widget
2255 					return ESM;
2256 					break;
2257 				}
2258 				if (mousex <712 && mousex>680){ //RADAR Widget
2259 					return RADAR;
2260 					break;
2261 				}
2262 				if (mousex <812 && mousex>780){ //Quit Widget
2263 					return QUIT;
2264 					break;
2265 				}
2266 				if (mousex < 908 && mousex > 884){ //Time Compression +
2267 					return COMPRESSTIME;
2268 					break;
2269 				}
2270 
2271 				if (mousex < 1000 && mousex > 972){  //Time Compression -
2272 					return UNCOMPRESSTIME;
2273 					break;
2274 				}
2275 			}
2276 			if(drawmap || drawtma){
2277 				if(mousex > 224 && mousex < 257){
2278 					if(mousey >270 && mousey < 300){
2279 						return CENTERDISPLAY;
2280 						break;
2281 					}
2282 				}
2283 				if(mousex > 224 && mousex < 257){
2284 					if(mousey >220 && mousey < 245){
2285 						return SCROLLMAPUP;
2286 						break;
2287 					}
2288 				}
2289 				if(mousex > 224 && mousex < 257){
2290 					if(mousey >320 && mousey < 345){
2291 						return SCROLLMAPDOWN;
2292 						break;
2293 					}
2294 				}
2295 				if(mousex > 175 && mousex < 210){
2296 					if(mousey >270 && mousey < 300){
2297 						return SCROLLMAPLEFT;
2298 						break;
2299 					}
2300 				}
2301 				if(mousex > 275 && mousex < 310){
2302 					if(mousey >270 && mousey < 300){
2303 						return SCROLLMAPRIGHT;
2304 						break;
2305 					}
2306 				}
2307 				if(mousex >175 && mousex < 210){
2308 					if(mousey > 360 && mousey < 390){
2309 						return INCREASEMAPSCALE;
2310 						break;
2311 					}
2312 				}
2313 				if(mousex >275 && mousex < 310){
2314 					if(mousey > 360 && mousey < 390){
2315 						return DECREASEMAPSCALE;
2316 						break;
2317 					}
2318 				}
2319 			}
2320 			// Radar events
2321 			if(drawradar){
2322 				if(mousex > 105 && mousex < 512){
2323 					if(mousey >156 && mousey < 566){
2324 					RadarStation.ShowData(screen, mousex, mousey);
2325 						break;
2326 					}
2327 				}
2328 
2329 				if(mousex > 748 && mousex < 795){
2330 					if(mousey >320 && mousey < 367){
2331 						return TOGGLER10;
2332 						break;
2333 					}
2334 				}
2335 
2336 				if(mousex > 795 && mousex < 842){
2337 					if(mousey >320 && mousey < 367){
2338 						return TOGGLER20;
2339 						break;
2340 					}
2341 				}
2342 
2343 				if(mousex > 842 && mousex < 889){
2344 					if(mousey >320 && mousey < 367){
2345 						return TOGGLER30;
2346 						break;
2347 					}
2348 				}
2349 
2350 				if(mousex > 748 && mousex < 795){
2351 					if(mousey >367 && mousey < 414){
2352 						return TOGGLER40;
2353 						break;
2354 					}
2355 				}
2356 
2357 				if(mousex > 795 && mousex < 842){
2358 					if(mousey >367 && mousey < 414){
2359 						return TOGGLER50;
2360 						break;
2361 					}
2362 				}
2363 
2364 				if(mousex > 842 && mousex < 889){
2365 					if(mousey >367 && mousey < 414){
2366 						return TOGGLER60;
2367 						break;
2368 					}
2369 				}
2370 
2371 				if(mousex > 744 && mousex < 791){
2372 					if(mousey >185 && mousey < 232){
2373 						return RADARDOWN;
2374 						break;
2375 					}
2376 				}
2377 
2378 				if(mousex > 850 && mousex < 897){
2379 					if(mousey >185 && mousey < 232){
2380 						return RADARUP;
2381 						break;
2382 					}
2383 				}
2384 
2385 				if(mousex > 749 && mousex < 796){
2386 					if(mousey >501 && mousey < 548){
2387 						return RING0;
2388 						break;
2389 					}
2390 				}
2391 
2392 				if(mousex > 796 && mousex < 843){
2393 					if(mousey >501 && mousey < 548){
2394 					  return RING5;
2395 					  break;
2396 					}
2397 				}
2398 
2399 				if(mousex > 843 && mousex < 889){
2400 				        if(mousey >501 && mousey < 548){
2401 					  return RING10;
2402 					  break;
2403 					}
2404 				}
2405 
2406 				if(mousex > 548 && mousex < 796){
2407 				        if(mousey >548 && mousey < 594){
2408 					  return RING15;
2409 					  break;
2410 					}
2411 				}
2412 
2413 				if(mousex > 796 && mousex < 843){
2414 				        if(mousey >548 && mousey < 594){
2415 					  return RING20;
2416 					  break;
2417 					}
2418 				}
2419 
2420 				if(mousex > 843 && mousex < 889){
2421 				        if(mousey >548 && mousey < 594){
2422 					  return RING25;
2423 					  break;
2424 					}
2425 				}
2426 			}
2427 
2428                         // Weapon console events
2429                         if (drawweapons)
2430                         {
2431                             x_checks_out = TRUE;
2432                             y1 = 150; y2 = 190;
2433                             // check all x1-x2 possiblities
2434                             if ( (mousex > 520) && (mousex < 590) )
2435                                tube_action = LOAD_TORPEDO;
2436                             else if ( (mousex > 600) && (mousex < 680) )
2437                                tube_action = LOAD_NOISEMAKER;
2438                             else if ( (mousex > 700) && (mousex < 760) )
2439                                tube_action = UNLOAD_TUBE;
2440                             else if ( (mousex > 770) && (mousex < 815) )
2441                                tube_action = FIRE_TUBE;
2442                             else
2443                             {
2444                                tube_action = 0;
2445                                x_checks_out = FALSE;
2446                             }
2447                             // look at all y1-y2 button possibilities
2448                             if (x_checks_out)
2449                             {
2450                                 index = 0;
2451                                 tube_to_use = -1;
2452                                 while ( (index < MAX_TUBES) &&
2453                                         (tube_to_use == -1) )
2454                                 {
2455                                     if ((mousey > y1) && (mousey < y2) )
2456                                       tube_to_use = index;
2457                                     else
2458                                     {
2459                                         index++;
2460                                         y1 += 50; y2 += 50;
2461                                     }
2462                                 }    // end of checking buttons vertically
2463                                 if (tube_to_use == -1)
2464                                    tube_action = 0;
2465                             }
2466                             else
2467                               tube_action = 0;
2468                             if ( (tube_action) && (tube_to_use > -1) )
2469                               return USE_TUBE;
2470 
2471 
2472                         }   // end of weapons screen
2473 			// ESM events
2474 			if(drawesm){
2475 				if(mousex > 744 && mousex < 791){
2476 					if(mousey >185 && mousey < 232){
2477 						return ESMDOWN;
2478 						break;
2479 					}
2480 				}
2481 
2482 				if(mousex > 850 && mousex < 897){
2483 					if(mousey >185 && mousey < 232){
2484 						return ESMUP;
2485 						break;
2486 					}
2487 				}
2488 			}
2489 
2490 			// Control events
2491 			if(drawcontrol){
2492 			       if(mousex > 158 && mousex < 347){
2493 					if(mousey >250 && mousey < 430){
2494 					ControlStation.AdjustHeading(mousex, mousey);
2495 						break;
2496 					}
2497 				}
2498 				if(mousex > 112 && mousex < 126){
2499 					if(mousey >254 && mousey < 293){
2500 					  ControlStation.AdjustDepth(mousex);
2501 						break;
2502 					}
2503 				}
2504 
2505 				if(mousex > 385 && mousex < 401){
2506 					if(mousey >257 && mousey < 296){
2507 					  ControlStation.AdjustDepth(mousex);
2508 						break;
2509 					}
2510 				}
2511 				if(mousex > 364 && mousex < 404){
2512 					if(mousey >403 && mousey < 418){
2513 						return TURNSTARBOARD;
2514 						break;
2515 					}
2516 				}
2517 
2518 				if(mousex > 108 && mousex < 147){
2519 					if(mousey >405 && mousey < 421){
2520 						return TURNPORT;
2521 						break;
2522 					}
2523 				}
2524 				if(mousex > 232 && mousex < 252){
2525 					if(mousey >581 && mousey < 607){
2526 						return ASTOP;
2527 						break;
2528 					}
2529 				}
2530 				if(mousex > 263 && mousex < 287){
2531 					if(mousey >581 && mousey < 607){
2532 						return A13;
2533 						break;
2534 					}
2535 				}
2536 				if(mousex > 296 && mousex < 320){
2537 				        if(mousey >581 && mousey < 607){
2538 				                return A23;
2539 				                break;
2540 					}
2541 				}
2542 				if(mousex > 329 && mousex < 352){
2543 					if(mousey >581 && mousey < 607){
2544 						return ASTD;
2545 						break;
2546 					}
2547 				}
2548 				if(mousex > 364 && mousex < 384){
2549 				        if(mousey >581 && mousey < 607){
2550 				                return AFULL;
2551 				                break;
2552 					}
2553 				}
2554 				if(mousex > 397 && mousex < 416){
2555 					if(mousey >581 && mousey < 607){
2556 						return AFLK;
2557 						break;
2558 					}
2559 				}
2560 				if(mousex > 200 && mousex < 218){
2561 					if(mousey >581 && mousey < 607){
2562 						return B13;
2563 						break;
2564 					}
2565 				}
2566 				if(mousex > 166 && mousex < 185){
2567 				        if(mousey >581 && mousey < 607){
2568 				                return B23;
2569 				                break;
2570 					}
2571 				}
2572 				if(mousex > 134 && mousex < 152){
2573 					if(mousey >581 && mousey < 607){
2574 						return BSTD;
2575 						break;
2576 					}
2577 				}
2578 				if(mousex > 100 && mousex < 118){
2579 					if(mousey >581 && mousey < 607){
2580 						return BEMER;
2581 						break;
2582 					}
2583 				}
2584 				if(mousex > 717 && mousex < 757){
2585 					if(mousey >585 && mousey < 601){
2586 					  return EXTENDARRAY;
2587 						break;
2588 					}
2589 				}
2590 				if(mousex > 717 && mousex < 757){
2591 					if(mousey >612 && mousey < 628){
2592 					  return RETRACTARRAY;
2593 						break;
2594 					}
2595 				}
2596 			}
2597 
2598 			if(drawsonar){
2599 				if(mousex > 615 && mousex < 657){
2600 					if(mousey > 162 && mousey < 210){
2601 						return TOGGLETRUERELATIVE;
2602 						break;
2603 					}
2604 				}
2605 				if(mousex > 474 && mousex < 519){
2606 					if(mousey > 358 && mousey < 401){
2607 						return DESIGNATECONTACT;
2608 						break;
2609 					}
2610 				}
2611 				if(mousex > 615 && mousex < 657){
2612 					if(mousey > 215 && mousey < 261){
2613 						return TOGGLESPHERICALTOWED;
2614 						break;
2615 					}
2616 				}
2617 				if(mousex > 663 && mousex < 706){
2618 					if(mousey > 162 && mousey < 210){
2619 						return UPPERCRTBUTTON;
2620 						break;
2621 					}
2622 				}
2623 				if(mousex > 663 && mousex < 706){
2624 					if(mousey > 215 && mousey < 261){
2625 						return LOWERCRTBUTTON;
2626 						break;
2627 					}
2628 				}
2629                                 if (mousex > 472 && mousex < 520)
2630                                 {
2631                                     if (mousey > 590 && mousey < 638)
2632                                        return SEND_PING;
2633                                 }
2634                                 if(mousex > 520 && mousex < 567)
2635                                 {
2636                                     if (mousey > 590 && mousey < 638)
2637                                     {
2638                                        return CUTARRAY;
2639                                        break;
2640                                     }
2641                                 }
2642 				if(mousex >569  && mousex < 614){
2643 					if(mousey > 593 && mousey < 638){
2644 						return STOPWINCH;
2645 						break;
2646 					}
2647 				}
2648 				if(mousex > 617 && mousex < 660){
2649 					if(mousey > 593 && mousey < 638){
2650 						return EXTENDARRAY;
2651 						break;
2652 					}
2653 				}
2654 				if(mousex > 663 && mousex < 706){
2655 					if(mousey > 593 && mousey < 638){
2656 						return RETRACTARRAY;
2657 						break;
2658 					}
2659 				}
2660 				if(mousex > 476 && mousex < 517){
2661 					if(mousey > 406 && mousey < 447){
2662 						return ASSIGNTRACKER;
2663 						break;
2664 					}
2665 				}
2666 				if(mousex > 523 && mousex < 564){
2667 					if(mousey > 406 && mousey < 447){
2668 						return TRACKER1;
2669 						break;
2670 					}
2671 				}
2672 				if(mousex > 570 && mousex < 611){
2673 					if(mousey > 406 && mousey < 447){
2674 						return TRACKER2;
2675 						break;
2676 					}
2677 				}
2678 				if(mousex > 617 && mousex < 658){
2679 					if(mousey > 406 && mousey < 447){
2680 						return TRACKER3;
2681 						break;
2682 					}
2683 				}
2684 				if(mousex > 663 && mousex < 706){
2685 					if(mousey > 406 && mousey < 447){
2686 						return TRACKER4;
2687 						break;
2688 					}
2689 				}
2690 			}
2691 			break;
2692 		case SDL_QUIT:
2693 			return QUIT;
2694 			break;
2695 		case SDL_KEYDOWN:  //Process key presses
2696 			switch(event.key.keysym.sym){
2697 				case SDLK_PAGEUP:  // PgUp   Make Einstein proud.
2698 					return COMPRESSTIME;
2699 					break;
2700 				case SDLK_PAGEDOWN: // PgDown
2701 					return UNCOMPRESSTIME;
2702 					break;
2703 				case SDLK_KP_PLUS:
2704 				case SDLK_PLUS:  // Speed Up
2705 					return INCREASESPEED;
2706 					break;
2707 				case SDLK_KP_MINUS:
2708 				case SDLK_MINUS:  // Slow Down
2709 					return DECREASESPEED;
2710 					break;
2711 				// case SDLK_n: //  Navigation
2712                                 case SDLK_F2:
2713 					return NAVMAP;
2714 					break;
2715 				// case SDLK_s: //  Sonar
2716                                 case SDLK_F1:
2717 					return SONAR;
2718 					break;
2719 				// case SDLK_t: //  TMA
2720                                 case SDLK_F3:
2721 					return WEAPONS;
2722 				 	break;
2723 				case SDLK_ESCAPE: // Quit...
2724 					return QUIT;
2725 					break;
2726                                 case SDLK_TAB:  // switch target
2727                                         return SWITCHTARGET;
2728                                         break;
2729 				case SDLK_F10: //  Dump the screen
2730 					return DUMPSCREEN;
2731 					break;
2732                                 case SDLK_F4:
2733                                         return SHIPCONTROL;
2734                                         break;
2735                                 case SDLK_F5:
2736                                         return ESM;
2737                                         break;
2738                                 case SDLK_F6:
2739                                         return RADAR;
2740                                         break;
2741 				case SDLK_KP4: // Turn Left
2742 					return TURNPORT;
2743 					break;
2744 				case SDLK_KP6: // Turn Right
2745 					return TURNSTARBOARD;
2746 					break;
2747 				case SDLK_KP2: // Dive
2748 					return INCREASEDEPTH;
2749 					break;
2750 				case SDLK_KP8: //Surface
2751 					return DECREASEDEPTH;
2752 					break;
2753 				case SDLK_INSERT:
2754 					return INCREASEMAPSCALE;
2755 					break;
2756 				case SDLK_DELETE:
2757 					return DECREASEMAPSCALE;
2758 					break;
2759 				case SDLK_UP :
2760 					return SCROLLMAPUP;
2761 					break;
2762  				case SDLK_DOWN:
2763 					return SCROLLMAPDOWN;
2764 					break;
2765 				case SDLK_LEFT:
2766 					return SCROLLMAPLEFT;
2767 					break;
2768 				case SDLK_RIGHT:
2769 					return SCROLLMAPRIGHT;
2770 					break;
2771 				case SDLK_c:
2772 					return CENTERDISPLAY;
2773 					break;
2774 				case SDLK_e:
2775 					return EXTENDARRAY;
2776 					break;
2777 				case SDLK_r:
2778 					return RETRACTARRAY;
2779 					break;
2780 				case SDLK_w:
2781 					return STOPWINCH;
2782 					break;
2783 				// case 19: // Pause The Game
2784 				case SDLK_p: //  Pause The Game
2785 					return PAUSEGAME;
2786 					break;
2787                                 case SDLK_t:
2788                                          tube_action = LOAD_TORPEDO;
2789                                          tube_to_use = -1;
2790                                         return WHICHTUBE;
2791                                 case SDLK_n:
2792                                          tube_action = LOAD_NOISEMAKER;
2793                                          tube_to_use = -1;
2794                                          return WHICHTUBE;
2795                                 case SDLK_u:
2796                                          tube_action = UNLOAD_TUBE;
2797                                          tube_to_use = -1;
2798                                          return WHICHTUBE;
2799                                 case SDLK_f:
2800                                          tube_action = FIRE_TUBE;
2801                                          tube_to_use = -1;
2802                                          return WHICHTUBE;
2803                                 case SDLK_1:
2804                                          tube_to_use = 0;
2805                                          return USE_TUBE;
2806                                 case SDLK_2:
2807                                          tube_to_use = 1;
2808                                          return USE_TUBE;
2809                                 case SDLK_3:
2810                                          tube_to_use = 2;
2811                                          return USE_TUBE;
2812                                 case SDLK_4:
2813                                          tube_to_use = 3;
2814                                          return USE_TUBE;
2815                                 case SDLK_5:
2816                                          tube_to_use = 4;
2817                                          return USE_TUBE;
2818                                 case SDLK_6:
2819                                          tube_to_use = 5;
2820                                          return USE_TUBE;
2821                                 case SDLK_g:
2822                                         return SEND_PING;
2823                                 case SDLK_q:
2824                                         return UP_THERMAL;
2825                                 case SDLK_a:
2826                                         return HOLD_DEPTH;
2827                                 case SDLK_z:
2828                                         return DOWN_THERMAL;
2829                                 case SDLK_s:
2830                                         return GO_SURFACE;
2831                                 case SDLK_x:
2832                                         return GO_PERISCOPE_DEPTH;
2833 				default:
2834 					return 0;
2835 					break;
2836 				}
2837 		default:
2838 			return 0;
2839 			break;
2840 	}
2841 	return 0;
2842 }
2843 
main(int argc,char ** argv)2844 int main(int argc, char **argv){
2845 	static char text[120];
2846         int status;
2847 	int hours=0;
2848 	int minutes=0;
2849 	int seconds=0;
2850 	int option_choice;//a place to put command line switches
2851 	int screendumpcount = 0;
2852 	int mousex = 0, mousey = 0; //where is the mouse?
2853 	bool quit = false;  //Quit flag Duh!
2854 	int station; //flag to decide which work station to display
2855 	bool full_screen = false;
2856 	char *textline = "";
2857 	char file1[] = "images/font.png";
2858 	char file2[] = "data/font.dat";
2859 	char file3[] = "images/largefont.png";
2860 	char file4[] = "data/largefont.dat";
2861         int mission_number = 0;
2862         int enable_sound = FALSE;
2863 	SDL_Event event; //a typedef to hold events
2864 	drawsonar = 0; // draw the sonar flag
2865 	drawmap = 1; // draw the map flag
2866 	drawradar = 0;
2867 	drawesm = 0;
2868 	drawcontrol = 0;
2869 	northcenter = true; //make the sonar display N. centered
2870 	Uint32 timer1; // timer2; // our event timers....
2871 	SDL_TimerID timer_id, timer_id2;
2872         torpedoes = NULL;
2873         helicopters = NULL;
2874 	tmamutex = SDL_CreateMutex();
2875 	srand(time(NULL)); //Seed the random generator
2876 
2877 	//Process commandline options.
2878         /*
2879 	sprintf(text,"m:vwfkhs");
2880 	while ((option_choice = getopt(argc, argv, text)) != -1){
2881         */
2882         status = 1;
2883         while (status < argc)
2884         {
2885              if (argv[status][0] == '-')
2886                 option_choice = argv[status][1];
2887              else
2888                 option_choice = '\0';
2889 		switch (option_choice)
2890                 {
2891                         case 'm':
2892                                // mission_number = atoi(optarg);
2893                                mission_number = atoi(argv[status + 1]);
2894                                status++;
2895                                break;
2896 			case 'w': //they passed the '-w' flag.
2897 				full_screen = false;
2898 				break;
2899                         case 'f': // full screen
2900                                 full_screen = true;
2901                                 break;
2902 /*
2903 			case 'k': //This option is just for me cause when using kdevelop
2904 							//I don't start in the right directory.
2905 				chdir("./subsim");
2906 				break;
2907 */
2908                         case 'v':
2909                                 cout << "OpenSSN version " << VERSION << endl;
2910                                 return 0;
2911 			case 'h':
2912 				cout << "Usage:" << endl
2913                                 << "-m <mission> select specific mission." << endl
2914                                 << "-f For full screen mode." << endl
2915                                 << "-s Enable sound effects." << endl
2916 				<< "-w For Windowed Mode." << endl
2917                                 << "-v For version." << endl
2918 				<< "-h For this message." << endl;
2919 				return 0;
2920 				break;
2921                         case 's':
2922                                 enable_sound = TRUE;
2923                                 break;
2924 			default:
2925 				cout << "Unknown command-line argument" << endl
2926 				<< "Please use -h for a list of commands." << endl;
2927 				return 1;
2928 		}   // end of switch
2929                status++;
2930 	}    // end of while
2931 	SetupScreen(full_screen);
2932         Init_Audio(enable_sound);
2933 	// CreateShips(mission_number);
2934 	Tma.InitGraphics();
2935 	SonarStation.InitGraphics();
2936 //	msg Message;
2937 	Message.InitGraphics();
2938 	Clock.InitTime(12,15,0);
2939 	SonarStation.LoadWidgets();
2940 	SDL_EnableKeyRepeat(150,100);
2941 	LoadWidgets();
2942 	LoadScreen(0); //Display intro screen
2943 	DFont fnt(file1, file2);
2944 	static DFont fnt2(file3,file4);
2945         my_map = new MAP();
2946         #ifdef DEBUGMAP
2947         my_map->Test_Map();
2948         #endif
2949 	SDL_UpdateRect(screen, 0, 0, 0, 0);
2950 	timer1 = SDL_GetTicks();// initialize the timer
2951         SDL_Delay(1000);   // show splash screen for one second
2952 	quit = false; //reset loop exit flag
2953 	//LoadWidgets(); //load up the buttons
2954         LoadScreen(9);
2955         // main menu stuff goes here
2956         status = Main_Menu(&mission_number, screen);
2957         if (status == ACTION_QUIT)
2958           quit = true;
2959 
2960         CreateShips(mission_number, my_map);
2961 	SDL_Rect rectangle;
2962 	rectangle.x = 0;
2963 	rectangle.y = 0;
2964 	rectangle.w = 1024; // This block of code clears the screen
2965 	rectangle.h = 768;
2966 	SDL_FillRect(screen, &rectangle, black);
2967 	timecompression = 1;
2968 	station = 2; //default station
2969 	ShowStation(station);
2970 	// textline="OpenSSN VERSION 0.5";
2971         sprintf(text, "OpenSSN version %2.1f", VERSION);
2972 	Message.post_message(text);
2973 	textline="http://openssn.sourceforge.net";
2974 	Message.post_message(textline);
2975 	Message.display_message();
2976 	sprintf(text, "[%i] ", timecompression);
2977 	fnt.PutString(screen, 933, 718, text);
2978         my_mission_status = MISSION_STARTED;
2979 	timer_id = SDL_AddTimer(1000, timerfunc, NULL);
2980 	timer_id2 = SDL_AddTimer(60000, TmaTimer, NULL);
2981 	timer1 = SDL_GetTicks();
2982         // timer2 = SDL_GetTicks();
2983 	const int frameperiod = 100;	//how fast we want the displays to update (in milliseconds)... this allows for a fixed frame rate
2984 	while (!quit)
2985         { 	//This is the main loop.....
2986 		if (timer1 + (frameperiod) < SDL_GetTicks()){
2987 			timer1 = SDL_GetTicks();
2988 			RadarStation.Sweep(frameperiod*timecompression);
2989 			UpdateDisplay();
2990 
2991 			SDL_Rect rectangle;
2992 			rectangle.x=16;
2993 			rectangle.y=14;   //define a rectangle on the screen and make it black
2994 			rectangle.h=72;
2995 			rectangle.w=126;
2996 			SDL_FillRect(screen, &rectangle, black);
2997                         sprintf(text, "Now - Wanted");
2998                         fnt.PutString(screen, 30, 20, text);
2999 			sprintf(text, "S: [%3i]  -   [%3i]", (int)Subs->Speed, Subs->DesiredSpeed);
3000 			fnt.PutString(screen, 30, 31, text);
3001 			sprintf(text, "H: [%3i]  -   [%3i]", (int)Subs->Heading, Subs->DesiredHeading);
3002 			fnt.PutString(screen, 30, 42, text);
3003 			sprintf(text, "D: [%4i]  -  [%4i]", (int)Subs->Depth, Subs->DesiredDepth);
3004 			fnt.PutString(screen, 30, 53, text);
3005 			// sprintf(text, "ARRAY [%4i]", TB16.GetLength());
3006 			// fnt.PutString(screen, 40, 53, text);
3007 			Clock.GetTime(hours,minutes,seconds);
3008 			sprintf(text, "%.2i:%.2i:%.2i", hours, minutes, seconds);
3009 			fnt.PutString(screen, 40, 64, text);
3010 			SDL_UpdateRects(screen, 1, &rectangle);
3011 			}
3012 
3013 		while (SDL_PollEvent(&event)){
3014 		//If there are events waiting take care of them
3015 			switch (HandleInput(event, mousex, mousey)){
3016 				case SONAR:
3017 						ShowStation(1);
3018 						UpdateDisplay();
3019                                                 Message.post_message("Sonar station");
3020 						Message.display_message();
3021 						sprintf(text, "[%i] ", timecompression);
3022 						fnt.PutString(screen, 933, 718, text);
3023 					break;
3024 				case NAVMAP:
3025 					ShowStation(2);
3026 					UpdateDisplay();
3027                                         Message.post_message("Naviation display");
3028 					Message.display_message();
3029 					sprintf(text, "[%i] ", timecompression);
3030 					fnt.PutString(screen, 933, 718, text);
3031 					break;
3032 				case WEAPONS:
3033                                         update_weapons_screen = TRUE;
3034 					ShowStation(3);
3035 					UpdateDisplay();
3036                                         Message.post_message("Weapons console");
3037 					Message.display_message();
3038 					sprintf(text, "[%i] ", timecompression);
3039 					fnt.PutString(screen, 933, 718, text);
3040 					break;
3041                                 case WHICHTUBE:
3042                                         update_weapons_screen = TRUE;
3043                                         UpdateDisplay();
3044                                         Message.post_message("Which tube (1-6)?");
3045                                         Message.display_message();
3046                                         break;
3047 				case SHIPCONTROL:
3048 					ShowStation(4);
3049 					UpdateDisplay();
3050                                         Message.post_message("Helm control");
3051 					Message.display_message();
3052 					sprintf(text, "[%i] ", timecompression);
3053 					fnt.PutString(screen, 933, 718, text);
3054 					break;
3055 				case ESM:
3056 					ShowStation(6);
3057 					UpdateDisplay();
3058                                         Message.post_message("ESM station");
3059 					Message.display_message();
3060 					sprintf(text, "[%i] ", timecompression);
3061 					fnt.PutString(screen, 933, 718, text);
3062 					break;
3063 				case RADAR:
3064 					ShowStation(5);
3065 					UpdateDisplay();
3066                                         Message.post_message("Radar console");
3067 					Message.display_message();
3068 					sprintf(text, "[%i] ", timecompression);
3069 					fnt.PutString(screen, 933, 718, text);
3070 					break;
3071                                 case SWITCHTARGET:
3072 	                                current_target = Subs->Next_Target();
3073                                         if (drawmap)
3074                                         {
3075                                           DrawMap();
3076                                           // PlaceShips(mapscale, 0, -10, current_target);
3077                                         }
3078                                         SDL_Delay(100);
3079                                         break;
3080 				case QUIT:
3081                                         printf("Got quit signal.\n");
3082 					ResetWidgetFlags();
3083 					quitwidget=1;
3084 					DisplayWidgets();
3085 					SDL_Delay(200);
3086 					quitwidget=0;
3087 					DisplayWidgets();
3088 					SDL_Delay(500);
3089 					quit = true;
3090 					break;
3091 				case COMPRESSTIME:  //  Make Einstein proud.
3092 					destination_rectangle.x = 880; //upper left corner to
3093 					destination_rectangle.y = 710; //place the button.
3094 					destination_rectangle.h = plusbuttondown->h; //height &
3095 					destination_rectangle.w = plusbuttondown->w;//width of button.
3096 					SDL_BlitSurface(plusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3097 					SDL_UpdateRects(screen, 1, &destination_rectangle); //Show button on the screen...
3098 					timecompression++;
3099 					if(timecompression > 8){
3100 						timecompression = 8;
3101 					}else{
3102 						if (!pause_game){
3103 							SDL_RemoveTimer(timer_id);
3104 							SDL_RemoveTimer(timer_id2);
3105 							timer_id = SDL_AddTimer(1000/timecompression, timerfunc, NULL);
3106 							timer_id2 = SDL_AddTimer(60000/timecompression, TmaTimer, NULL);
3107 						}
3108 						sprintf(text, "[%i] ", timecompression);
3109 						fnt.PutString(screen, 933, 718, text);
3110 					}
3111 					SDL_Delay(150);
3112 					DisplayWidgets();
3113 					break;
3114 				case UNCOMPRESSTIME: // Take A Downer
3115 					destination_rectangle.x = 970; //upper left corner to
3116 					destination_rectangle.y = 710; //place the button.
3117 					destination_rectangle.h = minusbuttondown->h; //height &
3118 					destination_rectangle.w = minusbuttondown->w;//width of button.
3119 					SDL_BlitSurface(minusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3120 					SDL_UpdateRects(screen, 1, &destination_rectangle); //Show button on the screen...
3121 					timecompression--;
3122 					if(timecompression < 1){
3123 						timecompression = 1;
3124 					}else{
3125 						if (!pause_game){
3126 							SDL_RemoveTimer(timer_id);
3127 							SDL_RemoveTimer(timer_id2);
3128 							timer_id = SDL_AddTimer(1000/timecompression, timerfunc, NULL);
3129 							timer_id2 = SDL_AddTimer(60000/timecompression, TmaTimer, NULL);
3130 						}
3131 						sprintf(text, "[%i] ", timecompression);
3132 						fnt.PutString(screen, 933, 718, text);
3133 						}
3134 						SDL_Delay(150);
3135 						DisplayWidgets();
3136 						break;
3137 				case INCREASESPEED:
3138 					Subs->DesiredSpeed++;
3139 					break;
3140 				case DECREASESPEED:
3141 					Subs->DesiredSpeed--;
3142 					break;
3143 				case DUMPSCREEN:
3144 					screendumpcount++;
3145 					sprintf(text, "screendump%i.bmp", screendumpcount );
3146 					SDL_SaveBMP(screen,text); //screen dumps
3147 					cerr << "Screen Dump" << endl;
3148 					break;
3149 				case TURNPORT:
3150 					Subs->DesiredHeading--;
3151 					if(Subs->DesiredHeading < 0){
3152 						Subs->DesiredHeading += 360;
3153 					}
3154 					break;
3155 				case TURNSTARBOARD:
3156 					Subs->DesiredHeading++;
3157 					if(Subs->DesiredHeading > 359){
3158 						Subs->DesiredHeading -= 360;
3159 					}
3160 					break;
3161 				case INCREASEDEPTH:
3162 					Subs->DesiredDepth++;
3163                                         if (Subs->DesiredDepth > Subs->MaxDepth)
3164                                            Subs->DesiredDepth = Subs->MaxDepth;
3165 					break;
3166 				case DECREASEDEPTH:
3167 					Subs->DesiredDepth--;
3168 					if(Subs->DesiredDepth < 0){
3169 						Subs->DesiredDepth = 0;
3170 					}
3171 					break;
3172 				case INCREASEMAPSCALE:
3173 					if (drawmap){
3174 						mapscale++;
3175 						if(mapscale>MAX_MAP_SCALE) mapscale=MAX_MAP_SCALE;
3176 					 	destination_rectangle.x = 175; //upper left corner to
3177 						destination_rectangle.y = 359; //place the button.
3178 						destination_rectangle.h = plusbuttondown->h; //height &
3179 						destination_rectangle.w = plusbuttondown->w;//width of button.
3180 						SDL_BlitSurface(plusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3181 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
3182 						DrawMap();
3183 						//UpdateDisplay();
3184 						SDL_Delay(100);
3185 						DisplayNavigationWidgets();
3186 					}
3187 					if(drawtma){
3188 					 	destination_rectangle.x = 175; //upper left corner to
3189 						destination_rectangle.y = 359; //place the button.
3190 						destination_rectangle.h = plusbuttondown->h; //height &
3191 						destination_rectangle.w = plusbuttondown->w;//width of button.
3192 						SDL_BlitSurface(plusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3193 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
3194 						Tma.IncreasePlotScale();
3195 						DisplayTMA();
3196 						SDL_Delay(100);
3197 						DisplayTMAWidgets();
3198 					}
3199 					break;
3200 				case DECREASEMAPSCALE:
3201 					if(drawmap){
3202 						mapscale--;
3203 						if(mapscale<1) mapscale = 1;
3204 					 	destination_rectangle.x = 275; //upper left corner to
3205 						destination_rectangle.y = 359; //place the button.
3206 						destination_rectangle.h = minusbuttondown->h; //height &
3207 						destination_rectangle.w = minusbuttondown->w;//width of button.
3208 						SDL_BlitSurface(minusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3209 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3210 						DrawMap();
3211 						//UpdateDisplay();
3212 						SDL_Delay(100);
3213 						DisplayNavigationWidgets();
3214 					}
3215 					if(drawtma){
3216 						Tma.DecreasePlotScale();
3217 					 	destination_rectangle.x = 275; //upper left corner to
3218 						destination_rectangle.y = 359; //place the button.
3219 						destination_rectangle.h = minusbuttondown->h; //height &
3220 						destination_rectangle.w = minusbuttondown->w;//width of button.
3221 						SDL_BlitSurface(minusbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3222 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3223 						DisplayTMA();
3224 						SDL_Delay(100);
3225 						DisplayTMAWidgets();
3226 					}
3227 					break;
3228 				case SCROLLMAPUP:
3229 					if(drawmap){
3230 					 	destination_rectangle.x = 225; //upper left corner to
3231 						destination_rectangle.y = 219; //place the button.
3232 						destination_rectangle.h = upbuttondown->h; //height &
3233 						destination_rectangle.w = upbuttondown->w;//width of button.
3234 						SDL_BlitSurface(upbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3235 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3236 						PlaceShips(mapscale, 0, -10, current_target);
3237 						DrawMap();
3238 						SDL_Delay(100);
3239 						DisplayNavigationWidgets();
3240 					}
3241 					if(drawtma){
3242 					 	destination_rectangle.x = 225; //upper left corner to
3243 						destination_rectangle.y = 219; //place the button.
3244 						destination_rectangle.h = upbuttondown->h; //height &
3245 						destination_rectangle.w = upbuttondown->w;//width of button.
3246 						SDL_BlitSurface(upbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3247 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3248 						PlaceShips(mapscale, 0, -10, current_target);
3249 						DisplayTMA(0,-10);
3250 						SDL_Delay(100);
3251 						DisplayTMAWidgets();
3252 					}
3253 					break;
3254 				case SCROLLMAPDOWN:
3255 					if(drawmap){
3256 					 	destination_rectangle.x = 225; //upper left corner to
3257 						destination_rectangle.y = 319; //place the button.
3258 						destination_rectangle.h = downbuttondown->h; //height &
3259 						destination_rectangle.w = downbuttondown->w;//width of button.
3260 						SDL_BlitSurface(downbuttondown, NULL, screen, &destination_rectangle); // Do the Blit
3261 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen..
3262 						PlaceShips(mapscale, 0, 10, current_target);
3263 						DrawMap();
3264 						SDL_Delay(100);
3265 						DisplayNavigationWidgets();
3266 					}
3267 					if(drawtma){
3268 					 	destination_rectangle.x = 225; //upper left corner to
3269 						destination_rectangle.y = 319; //place the button.
3270 						destination_rectangle.h = downbuttondown->h; //height &
3271 						destination_rectangle.w = downbuttondown->w;//width of button.
3272 						SDL_BlitSurface(downbuttondown, NULL, screen, &destination_rectangle); // Do the Blit
3273 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen..
3274 						PlaceShips(mapscale, 0, 10, current_target);
3275 						DisplayTMA(0,10);
3276 						SDL_Delay(100);
3277 						DisplayTMAWidgets();
3278 					}
3279 					break;
3280 				case SCROLLMAPLEFT:
3281 					if(drawmap){
3282 				 		destination_rectangle.x = 175; //upper left corner to
3283 						destination_rectangle.y = 269; //place the button.
3284 						destination_rectangle.h = leftbuttondown->h; //height &
3285 						destination_rectangle.w = leftbuttondown->w;//width of button.
3286 						SDL_BlitSurface(leftbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3287 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
3288 						 PlaceShips(mapscale, -10, 0, current_target);
3289 						DrawMap();
3290 						SDL_Delay(100);
3291 						DisplayNavigationWidgets();
3292 					}
3293 					if(drawtma){
3294 				 		destination_rectangle.x = 175; //upper left corner to
3295 						destination_rectangle.y = 269; //place the button.
3296 						destination_rectangle.h = leftbuttondown->h; //height &
3297 						destination_rectangle.w = leftbuttondown->w;//width of button.
3298 						SDL_BlitSurface(leftbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3299 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen....
3300 						 PlaceShips(mapscale, -10, 0, current_target);
3301 						DisplayTMA(-10,0);
3302 						SDL_Delay(100);
3303 						DisplayTMAWidgets();
3304 					}
3305 					break;
3306 				case SCROLLMAPRIGHT:
3307 					if(drawmap){
3308 				 		destination_rectangle.x = 275; //upper left corner to
3309 						destination_rectangle.y = 269; //place the button.
3310 						destination_rectangle.h = rightbuttondown->h; //height &
3311 						destination_rectangle.w = rightbuttondown->w;//width of button.
3312 						SDL_BlitSurface(rightbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3313 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3314 						 PlaceShips(mapscale, 10, 0, current_target);
3315 						DrawMap();
3316 						SDL_Delay(100);
3317 						DisplayNavigationWidgets();
3318 					}
3319 					if(drawtma){
3320 				 		destination_rectangle.x = 275; //upper left corner to
3321 						destination_rectangle.y = 269; //place the button.
3322 						destination_rectangle.h = rightbuttondown->h; //height &
3323 						destination_rectangle.w = rightbuttondown->w;//width of button.
3324 						SDL_BlitSurface(rightbuttondown, NULL, screen, &destination_rectangle); // Do the Blit.
3325 						SDL_UpdateRects(screen, 1, &destination_rectangle); //Show the screen...
3326 						DisplayTMA(10,0);
3327 						SDL_Delay(100);
3328 						DisplayTMAWidgets();
3329 					}
3330 					break;
3331                                 case UP_THERMAL:
3332                                         if ( (player) && (my_map) )
3333                                         {
3334                                            status = my_map->Next_Up(player->Depth);
3335                                            if (status != player->Depth)
3336                                            {
3337                                                player->DesiredDepth = status - 25;
3338                                                Message.post_message("Going up one thermal.");
3339                                                Message.display_message();
3340                                            }
3341                                         }
3342                                         break;
3343                                 case DOWN_THERMAL:
3344                                         if ( (player) && (my_map) )
3345                                         {
3346                                             status = my_map->Next_Down(player->Depth);
3347                                             if (status != player->Depth)
3348                                             {
3349                                                player->DesiredDepth = status + 25;
3350                                                Message.post_message("Going down one thermal.");
3351                                                Message.display_message();
3352                                             }
3353                                         }
3354                                         break;
3355                                 case HOLD_DEPTH:
3356                                         if (player)
3357                                           player->DesiredDepth = player->Depth;
3358                                         Message.post_message("Holding depth, Captain.");
3359                                         Message.display_message();
3360                                         break;
3361                                  case GO_SURFACE:
3362                                         if (player)
3363                                            player->DesiredDepth = 0;
3364                                         Message.post_message("Surfacing, Captain!");
3365                                         Message.display_message();
3366                                         break;
3367                                  case GO_PERISCOPE_DEPTH:
3368                                         if (player)
3369                                            player->DesiredDepth = PERISCOPE_DEPTH;
3370                                         Message.post_message("Heading to periscope depth.");
3371                                         Message.display_message();
3372                                         break;
3373 
3374 				case TOGGLESPHERICALTOWED:
3375 					SonarStation.ToggleArrayChoice();
3376 					SonarStation.DisplaySonarWidgets();
3377 					break;
3378 				case TOGGLETRUERELATIVE:
3379 					SonarStation.ToggleTrueRel();
3380 					SonarStation.DisplaySonarWidgets();
3381 					break;
3382 				case UPPERCRTBUTTON:
3383 					SonarStation.UpperCRT_Button();
3384 					break;
3385 				case LOWERCRTBUTTON:
3386 					SonarStation.LowerCRT_Button();
3387 					break;
3388 				case CENTERDISPLAY:
3389 					if(drawmap){
3390 						if(mapcenter) {
3391 							mapcenter = 0;
3392 							DisplayNavigationWidgets();
3393 						}else{
3394 							mapcenter = 1;
3395 							DisplayNavigationWidgets();
3396 						}
3397 						UpdateDisplay();
3398 					}
3399 					if(drawsonar){
3400 						SonarStation.ToggleNorthCenter();
3401 						SonarStation.ClearSonarData();
3402 						UpdateDisplay();
3403 						Message.display_message();
3404 					}
3405 					if(drawtma){
3406 						Tma.ToggleGeoPlotCenter();
3407 						DisplayTMAWidgets();
3408 						UpdateDisplay();
3409 						Message.display_message();
3410 					}
3411 					break;
3412 				case EXTENDARRAY:
3413 					status = TB16.Extend();
3414                                         if (status)
3415                                         {
3416 					  SonarStation.DisplaySonarWidgets();
3417                                           Message.post_message("Extending sonar array.");
3418                                         }
3419                                         else
3420                                            Message.post_message("Unable to extend array.");
3421                                         Message.display_message();
3422 					break;
3423 				case RETRACTARRAY:
3424 					status = TB16.ReelIn();
3425                                         if (status)
3426                                         {
3427 					  SonarStation.DisplaySonarWidgets();
3428                                           Message.post_message("Retrieving sonar array.");
3429                                         }
3430                                         else
3431                                           Message.post_message("Unable to retrieve array.");
3432                                         Message.display_message();
3433 					break;
3434                                 case CUTARRAY:
3435                                         status = TB16.CutArray();
3436                                         SonarStation.DisplaySonarWidgets();
3437                                         if (status)
3438                                            Message.post_message("Cut towed array.");
3439                                         else
3440                                            Message.post_message("Cannot cut array.");
3441                                         Message.display_message();
3442                                         break;
3443 				case STOPWINCH:
3444 					SonarStation.StopWinch();
3445                                         Message.post_message("Stopping sonar array.");
3446                                         Message.display_message();
3447 					break;
3448 				case ASSIGNTRACKER:
3449 					SonarStation.ToggleAssignTracker();
3450 					SonarStation.DisplaySonarWidgets();
3451 					break;
3452 				case TRACKER1:
3453 					if(SonarStation.assigntracker){
3454 						SonarStation.ToggleAssignTracker();
3455 						Tma.AssignTracker(0,0);
3456 						SonarStation.DisplaySonarWidgets();
3457 					}
3458 					break;
3459 				case TRACKER2:
3460 					if(SonarStation.assigntracker){
3461 						SonarStation.ToggleAssignTracker();
3462 						Tma.AssignTracker(1,0);
3463 						SonarStation.DisplaySonarWidgets();
3464 					}
3465 					break;
3466 				case TRACKER3:
3467 					if(SonarStation.assigntracker){
3468 						SonarStation.ToggleAssignTracker();
3469 						Tma.AssignTracker(2,0);
3470 						SonarStation.DisplaySonarWidgets();
3471 					}
3472 					break;
3473 				case TRACKER4:
3474 					if(SonarStation.assigntracker){
3475 						SonarStation.ToggleAssignTracker();
3476 						Tma.AssignTracker(3,0);
3477 						SonarStation.DisplaySonarWidgets();
3478 					}
3479 					break;
3480 				case DESIGNATECONTACT:
3481 					// textline="CON, SONAR, NEW CONTACT BEARING 123. DESIGNATEING CONTACT S1.";
3482 					// Message.post_message(textline);
3483 					break;
3484 				case TOGGLER10:
3485 					RadarStation.ToggleRangeScale10();
3486 					RadarStation.DisplayWidgets();
3487 					break;
3488 				case TOGGLER20:
3489 					RadarStation.ToggleRangeScale20();
3490 					RadarStation.DisplayWidgets();
3491 					break;
3492 				case TOGGLER30:
3493 					RadarStation.ToggleRangeScale30();
3494 					RadarStation.DisplayWidgets();
3495 					break;
3496 				case TOGGLER40:
3497 					RadarStation.ToggleRangeScale40();
3498 					RadarStation.DisplayWidgets();
3499 					break;
3500 				case TOGGLER50:
3501 					RadarStation.ToggleRangeScale50();
3502 					RadarStation.DisplayWidgets();
3503 					break;
3504 				case TOGGLER60:
3505 					RadarStation.ToggleRangeScale60();
3506 					RadarStation.DisplayWidgets();
3507 					break;
3508 				case RING0:
3509 					RadarStation.ToggleRangeRing0();
3510 					RadarStation.DisplayWidgets();
3511 					break;
3512 				case RING5:
3513 					RadarStation.ToggleRangeRing5();
3514 					RadarStation.DisplayWidgets();
3515 					break;
3516 			        case RING10:
3517 					RadarStation.ToggleRangeRing10();
3518 					RadarStation.DisplayWidgets();
3519 					break;
3520 			        case RING15:
3521 					RadarStation.ToggleRangeRing15();
3522 					RadarStation.DisplayWidgets();
3523 					break;
3524 			        case RING20:
3525 					RadarStation.ToggleRangeRing20();
3526 					RadarStation.DisplayWidgets();
3527 					break;
3528 			     	case RING25:
3529 					RadarStation.ToggleRangeRing25();
3530 					RadarStation.DisplayWidgets();
3531 					break;
3532 				case RADARDOWN:
3533 					RadarStation.LowerMast();
3534 					RadarStation.DisplayWidgets();
3535 					RadarStation.ClearScreen();
3536                                         if (player)
3537                                             player->using_radar = FALSE;
3538 					break;
3539 				case RADARUP:
3540                                         if (Subs->Depth <= PERISCOPE_DEPTH)
3541                                         {
3542 					  RadarStation.RaiseMast();
3543 					  RadarStation.DisplayWidgets();
3544                                           if (player)
3545                                              player->using_radar = TRUE;
3546                                         }
3547 					break;
3548 				case ESMDOWN:
3549 					EsmStation.LowerMast();
3550 					EsmStation.DisplayWidgets();
3551 					EsmStation.ClearScreen();
3552 					break;
3553 				case ESMUP:
3554                                         if (Subs->Depth <= PERISCOPE_DEPTH)
3555                                         {
3556 					  EsmStation.RaiseMast();
3557 					  EsmStation.DisplayWidgets();
3558                                         }
3559 					break;
3560 			        case ASTOP:
3561 					ControlStation.ToggleASTOP();
3562 					ControlStation.DisplayWidgets();
3563 					break;
3564 			        case A13:
3565 					ControlStation.ToggleA13();
3566 					ControlStation.DisplayWidgets();
3567 					break;
3568 			        case A23:
3569 					ControlStation.ToggleA23();
3570 					ControlStation.DisplayWidgets();
3571 					break;
3572 			        case ASTD:
3573 					ControlStation.ToggleASTD();
3574 					ControlStation.DisplayWidgets();
3575 					break;
3576 				case AFULL:
3577 					ControlStation.ToggleAFULL();
3578 					ControlStation.DisplayWidgets();
3579 					break;
3580 			        case AFLK:
3581 					ControlStation.ToggleAFLK();
3582 					ControlStation.DisplayWidgets();
3583 					break;
3584 			        case B13:
3585 					ControlStation.ToggleB13();
3586 					ControlStation.DisplayWidgets();
3587 					break;
3588 				case B23:
3589 					ControlStation.ToggleB23();
3590 					ControlStation.DisplayWidgets();
3591 					break;
3592 			        case BSTD:
3593 					ControlStation.ToggleBSTD();
3594 					ControlStation.DisplayWidgets();
3595 					break;
3596 				case BEMER:
3597 					ControlStation.ToggleBEMER();
3598 					ControlStation.DisplayWidgets();
3599 					break;
3600                                 case SEND_PING:
3601                                         player->Send_Ping(Subs);
3602                                         Message.post_message("Sending active ping, sir.");
3603                                         Message.display_message();
3604                                         break;
3605                                 case USE_TUBE:
3606                                         // check to see if we already have too
3607                                         // many items out there
3608                                         status = player->Count_Torpedoes(torpedoes);
3609                                         status += player->Count_Noisemakers(torpedoes);
3610                                         if (status >= MAX_PLAYER_WEAPONS)
3611                                         {
3612                                             Message.post_message("Tracking computer full, Captain.");
3613                                             Message.display_message();
3614                                             break;
3615                                         }
3616                                         // load, fire or unload a tube
3617                                         status = Subs->Use_Tube(tube_action, tube_to_use);
3618                                         if (status == TUBE_ERROR_FIRE_NOISEMAKER)
3619                                         {
3620                                             Submarine *new_torpedo, *my_torp;
3621                                             char *ship_file, filename[] = "ships/class6.shp";
3622                                             ship_file = Find_Data_File(filename);
3623                                             new_torpedo = Subs->Fire_Tube(NULL, ship_file);
3624                                             if ( (ship_file) && (ship_file != filename) )
3625                                                 free(ship_file);
3626                                             if (new_torpedo)
3627                                             {
3628                                                 new_torpedo->Friend = player->Friend;
3629                                                 new_torpedo->owner = player;
3630                                                 torpedoes = Add_Ship(torpedoes, new_torpedo);
3631                                                 Message.post_message("Noise maker launched!");
3632                                                 Message.display_message();
3633                                                 my_torp = torpedoes;
3634                                                 while (my_torp)
3635                                                 {
3636                                                      if (my_torp->target == player)
3637                                                         my_torp->Is_Distracted_By_Noisemaker(new_torpedo);
3638                                                      my_torp = my_torp->next;
3639                                                 }
3640                                             }
3641                                         }
3642                                         else if ( (status == TUBE_ERROR_FIRE_SUCCESS) && (current_target) )
3643                                         {
3644                                            char *ship_file, filename[] = "ships/class5.shp";
3645                                            ship_file = Find_Data_File(filename);
3646                                            if (current_target)
3647                                            {
3648                                               Submarine *new_torpedo;
3649                                               new_torpedo = Subs->Fire_Tube(current_target, ship_file );
3650                                               if ( (ship_file) && (ship_file != filename) )
3651                                                 free(ship_file);
3652                                               if (new_torpedo)
3653                                               {
3654                                                   char *sound_file, *file_name = "sounds/torpedo-launch.ogg";
3655                                                   sound_file = Find_Data_File(file_name);
3656                                                   Play_Sound(sound_file);
3657                                                   if ( (sound_file) && (sound_file != file_name) )
3658                                                       free(sound_file);
3659                                                   new_torpedo->Friend = FRIEND;
3660                                                   new_torpedo->owner = Subs;
3661                                                   torpedoes = Add_Ship(torpedoes, new_torpedo);
3662                                                   Message.post_message("Torpedo launched!");
3663                                                   Message.display_message();
3664                                               }
3665                                            }
3666                                           }
3667                                           else if (status == TUBE_ERROR_FIRE_SUCCESS)
3668                                            {
3669                                                Message.post_message("Torpedo has no target.");
3670                                                Message.display_message();
3671                                                Subs->TorpedosOnBoard++;
3672                                            }
3673 
3674 
3675                                         tube_action = 0;
3676                                         tube_to_use = -1;
3677                                         update_weapons_screen = TRUE;
3678                                         UpdateDisplay();
3679                                         break;
3680 				case PAUSEGAME:
3681 					if (pause_game){ //UnPause
3682 						pause_game = !pause_game;
3683 						timer_id = SDL_AddTimer(1000/timecompression, timerfunc, NULL);
3684 						timer_id2 = SDL_AddTimer(60000/timecompression, TmaTimer, NULL);
3685 					}else{  //Pause
3686 						pause_game = !pause_game;
3687 						SDL_RemoveTimer(timer_id);
3688 						SDL_RemoveTimer(timer_id2);
3689 					}
3690 					break;
3691 				default:
3692 					break;
3693 				}
3694 			}
3695                 /*
3696                 if (timer2 < (SDL_GetTicks() - (1000/timecompression) ) )
3697                 {
3698                    #ifdef DEBUG
3699                    printf("Launching timer function.\n");
3700                    #endif
3701                    // timerfunc(0, NULL);
3702                    timer2 = SDL_GetTicks();
3703                 }
3704                 */
3705                 if (should_update_everything)
3706                 {
3707                      should_update_everything = FALSE;
3708                      Update_Everything();
3709                 }
3710                 if (my_mission_status == MISSION_SUCCESS)
3711                 {
3712                    printf("Mission completed successfully!\n");
3713                    LoadScreen(7);
3714                    SDL_Delay(5000);
3715                    quit = true;
3716                 }
3717                 else if (my_mission_status == MISSION_FAILED)
3718                 {
3719                    printf("Mission failed.\n");
3720                    LoadScreen(8);
3721                    SDL_Delay(5000);
3722                    quit = true;
3723                 }
3724 
3725                 SDL_Delay(GAME_DELAY);
3726 		}   // end of main loop
3727         #ifdef DEBUG
3728         printf("Unloading widgets.\n");
3729         #endif
3730 	UnLoadWidgets();
3731         // get rid of torpedoes
3732         #ifdef DEBUG
3733         printf("Destroying torpedoes\n");
3734         #endif
3735         while (torpedoes)
3736             torpedoes = Remove_Ship(torpedoes, torpedoes);
3737         #ifdef DEBUG
3738         printf("Destroying subs\n");
3739         #endif
3740         while (Subs)
3741             Subs = Remove_Ship(Subs, Subs);
3742         #ifdef DEBUG
3743         printf("Removing helicopters.\n");
3744         #endif
3745         while (helicopters)
3746           helicopters = Remove_Helicopter(helicopters, helicopters);
3747         #ifdef DEBUG
3748         printf("Killing SDL\n");
3749         #endif
3750         Clean_Up_Audio();
3751         if (my_map)
3752             delete my_map;
3753 	SDL_Quit();
3754         return 0;   // just to make the compiler happy
3755 }
3756 
3757