Subversion Repositories Kolibri OS

Rev

Rev 7142 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7185 siemargl 1
#include 
7142 siemargl 2
 
3
#ifdef MSDOS
4
#include 
5
#endif
6
 
7185 siemargl 7
#ifdef WINDOWS
8
#include 
9
#endif
10
 
7142 siemargl 11
#ifndef KOS32
12
#include 
13
#else
14
#include 
7185 siemargl 15
#include 
7142 siemargl 16
#endif
17
 
18
#define INCLUDED	// Define externs here
19
#include "sst.h"
20
 
21
/*int getch(void);
22
*/
23
 
24
static char line[128], *linep = line;
25
static int linecount;	/* for paging */
26
 
27
static void clearscreen(void);
28
 
29
/* Compared to original version, I've changed the "help" command to
30
   "call" and the "terminate" command to "quit" to better match
31
   user expectations. The DECUS version apparently made those changes
32
   as well as changing "freeze" to "save". However I like "freeze".
33
 
34
   When I got a later version of Super Star Trek that I was converting
35
   from, I added the emexit command.
36
 
37
   That later version also mentions srscan and lrscan working when
38
   docked (using the starbase's scanners), so I made some changes here
39
   to do this (and indicating that fact to the player), and then realized
40
   the base would have a subspace radio as well -- doing a Chart when docked
41
   updates the star chart, and all radio reports will be heard. The Dock
42
   command will also give a report if a base is under attack.
43
 
44
   Movecom no longer reports movement if sensors are damaged so you wouldn't
45
   otherwise know it.
46
 
47
   Also added:
48
 
49
   1. Better base positioning at startup
50
 
51
   2. deathray improvement (but keeping original failure alternatives)
52
 
53
   3. Tholian Web
54
 
55
   4. Enemies can ram the Enterprise. Regular Klingons and Romulans can
56
      move in Expert and Emeritus games. This code could use improvement.
57
 
58
   5. The deep space probe looks interesting! DECUS version
59
 
60
   6. Cloaking (with contributions from Erik Olofsen) and Capturing (BSD version).
61
 
62
   */
63
 
64
// I don't like the way this is done, relying on an index. But I don't
65
// want to invest the time to make this nice and table driven.
66
 
67
static char *commands[] = {
68
	"srscan",
69
	"lrscan",
70
	"phasers",
71
	"photons",
72
	"move",
73
	"shields",
74
	"dock",
75
	"damages",
76
	"chart",
77
	"impulse",
78
	"rest",
79
	"warp",
80
	"status",
81
	"sensors",
82
	"orbit",
83
	"transport",
84
	"mine",
85
	"crystals",
86
	"shuttle",
87
	"planets",
88
	"request",
89
	"report",
90
	"computer",
91
	"commands",
92
    "emexit",
93
    "probe",
94
    "cloak",
95
    "capture",
96
    "score",
97
	"abandon",
98
	"destruct",
99
	"freeze",
100
	"deathray",
101
	"debug",
102
	"call",
103
	"quit",
104
    "help"
105
 
106
};
107
 
108
#define NUMCOMMANDS (sizeof(commands)/sizeof(char *))
109
 
110
static void listCommands(int x) {
111
	prout("   SRSCAN    MOVE      PHASERS   CALL\n"
112
		  "   STATUS    IMPULSE   PHOTONS   ABANDON\n"
113
		  "   LRSCAN    WARP      SHIELDS   DESTRUCT\n"
114
		  "   CHART     REST      DOCK      QUIT\n"
115
		  "   DAMAGES   REPORT    SENSORS   ORBIT\n"
116
		  "   TRANSPORT MINE      CRYSTALS  SHUTTLE\n"
117
		  "   PLANETS   REQUEST   DEATHRAY  FREEZE\n"
118
          "   COMPUTER  EMEXIT    PROBE     COMMANDS");
119
    proutn("   ");
120
#ifdef SCORE
121
    proutn("SCORE     ");
122
#endif
123
#ifdef CLOAKING
124
    proutn("CLOAK     ");
125
#endif
126
#ifdef CAPTURE
127
    proutn("CAPTURE   ");
128
#endif
129
    if (x) proutn("HELP     ");
130
    prout("");
131
}
132
 
133
static void helpme(void) {
134
	int i, j;
135
	char cmdbuf[32];
136
	char linebuf[132];
137
	FILE *fp;
138
	/* Give help on commands */
139
	int key;
140
	key = scan();
141
	while (TRUE) {
142
		if (key == IHEOL) {
143
			proutn("Help on what command?");
144
			key = scan();
145
		}
146
		if (key == IHEOL) return;
147
		for (i = 0; i < NUMCOMMANDS; i++) {
148
			if (strcmp(commands[i], citem)==0) break;
149
		}
150
		if (i != NUMCOMMANDS) break;
151
		skip(1);
152
		prout("Valid commands:");
153
		listCommands(FALSE);
154
		key = IHEOL;
155
		chew();
156
		skip(1);
157
	}
158
	if (i == 23) {
159
		strcpy(cmdbuf, " ABBREV");
160
	}
161
	else {
162
		strcpy(cmdbuf, "  Mnemonic:  ");
163
		j = 0;
164
		while ((cmdbuf[j+13] = toupper(commands[i][j])) != 0) j++;
165
	}
166
	fp = fopen("sst.doc", "r");
167
	if (fp == NULL) {
168
		prout("Spock-  \"Captain, that information is missing from the");
169
		prout("   computer. You need to find SST.DOC and put it in the");
170
		prout("   current directory.\"");
171
		return;
172
	}
173
	i = strlen(cmdbuf);
174
	do {
175
		if (fgets(linebuf, 132, fp) == NULL) {
176
			prout("Spock- \"Captain, there is no information on that command.\"");
177
			fclose(fp);
178
			return;
179
		}
180
	} while (strncmp(linebuf, cmdbuf, i) != 0);
181
 
182
	skip(1);
183
	prout("Spock- \"Captain, I've found the following information:\"");
184
	skip(1);
185
 
186
	do {
187
		if (linebuf[0]!=12) { // ignore page break lines
188
			linebuf[strlen(linebuf)-1] = '\0'; // No \n at end
189
			prout(linebuf);
190
		}
191
		fgets(linebuf,132,fp);
192
	} while (strstr(linebuf, "******")==NULL);
193
	fclose(fp);
194
}
195
 
196
static void makemoves(void) {
197
	int i, hitme;
198
	char ch;
199
	while (TRUE) { /* command loop */
200
		hitme = FALSE;
201
		justin = 0;
202
		Time = 0.0;
203
		i = -1;
204
		while (TRUE)  { /* get a command */
205
			chew();
206
			skip(1);
207
			proutn("COMMAND> ");
208
			if (scan() == IHEOL) continue;
209
			for (i=0; i < 29; i++) // Abbreviations allowed for the first 29 commands, only.
210
				if (isit(commands[i]))
211
					break;
212
			if (i < 29) break;
213
			for (; i < NUMCOMMANDS; i++)
214
				if (strcmp(commands[i], citem) == 0) break;
215
			if (i < NUMCOMMANDS
216
#ifndef CLOAKING
217
			    && i != 26 // ignore the CLOAK command
218
#endif
219
#ifndef CAPTURE
220
			    && i != 27 // ignore the CAPTURE command
221
#endif
222
#ifndef SCORE
223
			    && i != 28 // ignore the SCORE command
224
#endif
225
#ifndef DEBUG
226
			    && i != 33 // ignore the DEBUG command
227
#endif
228
			   ) break;
229
 
230
			if (skill <= SFAIR)  {
231
				prout("UNRECOGNIZED COMMAND. LEGAL COMMANDS ARE:");
232
				listCommands(TRUE);
233
			}
234
			else prout("UNRECOGNIZED COMMAND.");
235
		}
236
		switch (i) { /* command switch */
237
			case 0:			// srscan
238
				srscan(1);
239
				break;
240
			case 1:			// lrscan
241
				lrscan();
242
				break;
243
			case 2:			// phasers
244
				phasers();
245
                if (ididit) {
246
#ifdef CLOAKING
247
                    if (irhere && d.date >= ALGERON && !isviolreported && iscloaked) {
248
                        prout("The Romulan ship discovers you are breaking the Treaty of Algeron!");
249
                        ncviol++;
250
                        isviolreported = TRUE;
251
                    }
252
#endif
253
                    hitme = TRUE;
254
                }
255
				break;
256
			case 3:			// photons
257
				photon();
258
                if (ididit) {
259
#ifdef CLOAKING
260
                    if (irhere && d.date >= ALGERON && !isviolreported && iscloaked) {
261
                        prout("The Romulan ship discovers you are breaking the Treaty of Algeron!");
262
                        ncviol++;
263
                        isviolreported = TRUE;
264
                    }
265
#endif
266
                    hitme = TRUE;
267
                }
268
				break;
269
			case 4:			// move
270
				warp(1);
271
				break;
272
			case 5:			// shields
273
				sheild(1);
274
				if (ididit) {
275
					attack(2);
276
					shldchg = 0;
277
				}
278
				break;
279
			case 6:			// dock
280
				dock();
281
				break;
282
			case 7:			// damages
283
				dreprt();
284
				break;
285
			case 8:			// chart
286
				chart(0);
287
				break;
288
			case 9:			// impulse
289
				impuls();
290
				break;
291
			case 10:		// rest
292
				waiting();
293
				if (ididit) hitme = TRUE;
294
				break;
295
			case 11:		// warp
296
				setwrp();
297
				break;
298
			case 12:		// status
299
				srscan(3);
300
				break;
301
			case 13:			// sensors
302
				sensor();
303
				break;
304
			case 14:			// orbit
305
				orbit();
306
				if (ididit) hitme = TRUE;
307
				break;
308
			case 15:			// transport "beam"
309
				beam();
310
				break;
311
			case 16:			// mine
312
				mine();
313
				if (ididit) hitme = TRUE;
314
				break;
315
			case 17:			// crystals
316
				usecrystals();
317
				break;
318
			case 18:			// shuttle
319
				shuttle();
320
				if (ididit) hitme = TRUE;
321
				break;
322
			case 19:			// Planet list
323
				preport();
324
				break;
325
			case 20:			// Status information
326
				srscan(2);
327
				break;
328
			case 21:			// Game Report
329
				report(0);
330
				break;
331
			case 22:			// use COMPUTER!
332
				eta();
333
				break;
334
			case 23:
335
				listCommands(TRUE);
336
				break;
337
			case 24:		// Emergency exit
338
				clearscreen();	// Hide screen
339
				freeze(TRUE);	// forced save
340
#ifdef KOS32
341
				con_exit(1);
342
#endif
343
				exit(1);		// And quick exit
344
				break;
345
			case 25:
346
				probe();		// Launch probe
347
				break;
348
#ifdef CLOAKING
349
			case 26:
350
				cloak();        // turn on/off cloaking
351
				if (iscloaking) {
352
					attack(2); // We will be seen while we cloak
353
					iscloaking = FALSE;
354
					iscloaked = TRUE;
355
				}
356
				break;
357
#endif
358
#ifdef CAPTURE
359
			case 27:
360
				capture();      // Attempt to get Klingon ship to surrender
361
				if (ididit) hitme = TRUE;
362
				break;
363
#endif
364
#ifdef SCORE
365
			case 28:
366
				score(1);    // get the score
367
				break;
368
#endif
369
			case 29:			// Abandon Ship
370
				abandn();
371
				break;
372
			case 30:			// Self Destruct
373
				dstrct();
374
				break;
375
			case 31:			// Save Game
376
				freeze(FALSE);
377
				if (skill > SGOOD)
378
					prout("WARNING--Frozen games produce no plaques!");
379
				break;
380
			case 32:			// Try a desparation measure
381
				deathray();
382
				if (ididit) hitme = TRUE;
383
				break;
384
#ifdef DEBUG
385
			case 33:			// What do we want for debug???
386
				debugme();
387
				break;
388
#endif
389
			case 34:		// Call for help
390
				help();
391
				break;
392
			case 35:
393
				alldone = 1;	// quit the game
394
#ifdef DEBUG
395
				if (idebug) score(0);
396
#endif
397
				break;
398
			case 36:
399
				helpme();	// get help
400
				break;
401
		}
402
		for (;;) {
403
			if (alldone) break;		// Game has ended
404
#ifdef DEBUG
405
			if (idebug) prout("2500");
406
#endif
407
			if (Time != 0.0) {
408
				events();
409
				if (alldone) break;		// Events did us in
410
			}
411
			if (d.galaxy[quadx][quady] == 1000) { // Galaxy went Nova!
412
				atover(0);
413
				continue;
414
			}
415
			if (nenhere == 0) movetho();
416
			if (hitme && justin==0) {
417
				attack(2);
418
				if (alldone) break;
419
				if (d.galaxy[quadx][quady] == 1000) {	// went NOVA!
420
					atover(0);
421
					hitme = TRUE;
422
					continue;
423
				}
424
			}
425
			break;
426
		}
427
		if (alldone) break;
428
	}
429
}
430
 
431
 
432
int main(int argc, char **argv) {
433
	int i;
434
	int hitme;
435
	char ch;
436
 
437
#ifdef KOS32
438
	if (con_init_console_dll()) return 1; // init fail
439
	con_set_title("-SUPER- STAR TREK");
440
	con_set_flags(CON_COLOR_GREEN);
441
#endif
7185 siemargl 442
#ifdef WINDOWS
443
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);  // Get handle to standard output
444
	SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN);
445
#endif
446
 
7142 siemargl 447
 
448
	prelim();
449
 
450
	if (argc > 1) { // look for -f option
451
		if (strcmp(argv[1], "-f")== 0) {
452
			coordfixed = 1;
453
			argc--;
454
			argv++;
455
		}
456
	}
457
 
458
 
459
	if (argc > 1) {
460
		fromcommandline = 1;
461
		line[0] = '\0';
462
		while (--argc > 0) {
463
			strcat(line, *(++argv));
464
			strcat(line, " ");
465
		}
466
	}
467
	else fromcommandline = 0;
468
 
469
 
470
	while (TRUE) { /* Play a game */
471
		setup();
472
		if (alldone) {
473
			score(0);
474
			alldone = 0;
475
		}
476
		else makemoves();
477
		skip(2);
478
		stars();
479
		skip(1);
480
 
481
		if (tourn && alldone) {
482
			printf("Do you want your score recorded?");
483
			if (ja()) {
484
				chew2();
485
				freeze(FALSE);
486
			}
487
		}
488
		printf("Do you want to play again?");
489
		if (!ja()) break;
490
	}
491
	skip(1);
492
	prout("May the Great Bird of the Galaxy roost upon your home planet.");
493
	return 0;
494
}
495
 
496
 
497
void cramen(int i) {
498
	/* return an enemy */
499
	char *s;
500
 
501
	switch (i) {
502
		case IHR: s = "Romulan"; break;
503
		case IHK: s = "Klingon"; break;
504
		case IHC: s = "Commander"; break;
505
		case IHS: s = "Super-commander"; break;
506
		case IHSTAR: s = "Star"; break;
507
		case IHP: s = "Planet"; break;
508
		case IHB: s = "Starbase"; break;
509
		case IHBLANK: s = "Black hole"; break;
510
		case IHT: s = "Tholean"; break;
511
		case IHWEB: s = "Tholean web"; break;
512
		default: s = "Unknown??"; break;
513
	}
514
	proutn(s);
515
}
516
 
517
void cramlc(int key, int x, int y) {
518
	if (key == 1) proutn(" Quadrant");
519
	else if (key == 2) proutn(" Sector");
520
	proutn(" ");
521
	crami(x, 1);
522
	proutn(" - ");
523
	crami(y, 1);
524
}
525
 
526
void crmena(int i, int enemy, int key, int x, int y) {
527
	if (i == 1) proutn("***");
528
	cramen(enemy);
529
	proutn(" at");
530
	cramlc(key, x, y);
531
}
532
 
533
void crmshp(void) {
534
	char *s;
535
	switch (ship) {
536
		case IHE: s = "Enterprise"; break;
537
		case IHF: s = "Faerie Queene"; break;
538
		default:  s = "Ship???"; break;
539
	}
540
	proutn(s);
541
}
542
 
543
void stars(void) {
544
	prouts("******************************************************");
545
	skip(1);
546
}
547
 
548
double expran(double avrage) {
549
	return -avrage*log(1e-7 + Rand());
550
}
551
 
552
double Rand(void) {
553
	return rand()/(1.0 + (double)RAND_MAX);
554
}
555
 
556
void iran8(int *i, int *j) {
557
	*i = Rand()*8.0 + 1.0;
558
	*j = Rand()*8.0 + 1.0;
559
}
560
 
561
void iran10(int *i, int *j) {
562
	*i = Rand()*10.0 + 1.0;
563
	*j = Rand()*10.0 + 1.0;
564
}
565
 
566
void chew(void) {
567
	linecount = 0;
568
	linep = line;
569
	*linep = 0;
570
}
571
 
572
void chew2(void) {
573
	/* return IHEOL next time */
574
	linecount = 0;
575
	linep = line+1;
576
	*linep = 0;
577
}
578
 
579
int scan(void) {
580
	int i;
581
	char *cp;
582
 
583
	linecount = 0;
584
 
585
	// Init result
586
	aaitem = 0.0;
587
	*citem = 0;
588
 
589
	// Read a line if nothing here
590
	if (*linep == 0) {
591
		if (linep != line) {
592
			chew();
593
			return IHEOL;
594
		}
595
#ifdef KOS32
596
		cp = gets(line);
7185 siemargl 597
		if (!cp) exit(0);
7142 siemargl 598
#else
599
		// We should really be using fgets
600
		fgets(line,sizeof(line),stdin);
601
#endif
602
		if (line[strlen(line)-1] == '\n')
603
			line[strlen(line)-1] = '\0';
604
		linep = line;
605
	}
606
	// Skip leading white space
607
	while (*linep == ' ') linep++;
608
	// Nothing left
609
	if (*linep == 0) {
610
		chew();
611
		return IHEOL;
612
	}
613
	if (isdigit(*linep) || *linep=='+' || *linep=='-' || *linep=='.') {
614
		// treat as a number
615
	    if (sscanf(linep, "%lf%n", &aaitem, &i) < 1) {
616
		linep = line; // Invalid numbers are ignored
617
		*linep = 0;
618
		return IHEOL;
619
	    }
620
	    else {
621
		// skip to end
622
		linep += i;
623
		return IHREAL;
624
	    }
625
	}
626
	// Treat as alpha
627
	cp = citem;
628
	while (*linep && *linep!=' ') {
629
		if ((cp - citem) < 9) *cp++ = tolower(*linep);
630
		linep++;
631
	}
632
	*cp = 0;
633
	return IHALPHA;
634
}
635
 
636
int ja(void) {
637
	chew();
638
	while (TRUE) {
639
		scan();
640
		chew();
641
		if (*citem == 'y') return TRUE;
642
		if (*citem == 'n') return FALSE;
643
		proutn("Please answer with \"Y\" or \"N\":");
644
	}
645
}
646
 
647
void cramf(double x, int w, int d) {
648
	char buf[64];
649
	sprintf(buf, "%*.*f", w, d, x);
650
	proutn(buf);
651
}
652
 
653
void crami(int i, int w) {
654
	char buf[16];
655
	sprintf(buf, "%*d", w, i);
656
	proutn(buf);
657
}
658
 
659
double square(double i) { return i*i; }
660
 
661
static void clearscreen(void) {
662
	/* Somehow we need to clear the screen */
663
	proutn("\033[2J\033[0;0H");	/* Hope for an ANSI display */
664
}
665
 
666
/* We will pull these out in case we want to do something special later */
667
 
668
void pause(int i) {
669
#ifdef CLOAKING
670
	if (iscloaked) return;
671
#endif
672
	putchar('\n');
673
	if (i==1) {
674
		if (skill > SFAIR)
675
			prout("[ANNOUNCEMENT ARRIVING...]");
676
		else
677
			prout("[IMPORTANT ANNOUNCEMENT ARRIVING -- HIT ENTER TO CONTINUE]");
678
		getchar();
679
	}
680
	else {
681
		if (skill > SFAIR)
682
			proutn("[CONTINUE?]");
683
		else
684
			proutn("[HIT ENTER TO CONTINUE]");
685
		getchar();
686
		proutn("\r                           \r");
687
	}
688
	if (i != 0) {
689
		clearscreen();
690
	}
691
    linecount = 0;
692
}
693
 
694
 
695
void skip(int i) {
696
	while (i-- > 0) {
697
		linecount++;
698
		if (linecount >= 23)
699
			pause(0);
700
		else
701
			putchar('\n');
702
	}
703
}
704
 
705
 
706
void proutn(char *s) {
707
#ifndef KOS32
708
	fputs(s, stdout);
709
#else
710
	con_write_asciiz(s);
711
#endif
712
}
713
 
714
void prout(char *s) {
715
	proutn(s);
716
	skip(1);
717
}
718
 
719
void prouts(char *s) {
720
#ifdef KOS32
721
#define clock_t long int
722
#define clock() get_tick_count()
723
#define CLOCKS_PER_SEC 100
724
#endif
725
 
726
	clock_t endTime;
727
	/* print slowly! */
728
	while (*s) {
729
		endTime = clock() + CLOCKS_PER_SEC*0.05;
730
		while (clock() < endTime) ;
731
		putchar(*s++);
732
#ifndef KOS32
733
		fflush(stdout);
734
#endif
735
	}
736
}
737
 
738
void huh(void) {
739
	chew();
740
	skip(1);
741
	prout("Beg your pardon, Captain?");
742
}
743
 
744
int isit(char *s) {
745
	/* New function -- compares s to scaned citem and returns true if it
746
	   matches to the length of s */
747
 
748
	return strncmp(s, citem, max(1, strlen(citem))) == 0;
749
 
750
}
751
 
752
#ifdef DEBUG
753
void debugme(void) {
754
	proutn("Reset levels? ");
755
	if (ja() != 0) {
756
		if (energy < inenrg) energy = inenrg;
757
		shield = inshld;
758
		torps = intorps;
759
		lsupres = inlsr;
760
	}
761
	proutn("Reset damage? ");
762
	if (ja() != 0) {
763
		int i;
764
		for (i=0; i <= ndevice; i++) if (damage[i] > 0.0) damage[i] = 0.0;
765
		stdamtim = 1e30;
766
	}
767
	proutn("Toggle idebug? ");
768
	if (ja() != 0) {
769
		idebug = !idebug;
770
		if (idebug) prout("Debug output ON");
771
		else prout("Debug output OFF");
772
	}
773
	proutn("Cause selective damage? ");
774
	if (ja() != 0) {
775
		int i, key;
776
		for (i=1; i <= ndevice; i++) {
777
			proutn("Kill ");
778
			proutn(device[i]);
779
			proutn("? ");
780
			chew();
781
			key = scan();
782
			if (key == IHALPHA &&  isit("y")) {
783
				damage[i] = 10.0;
784
				if (i == DRADIO) stdamtim = d.date;
785
			}
786
		}
787
	}
788
	proutn("Examine/change events? ");
789
	if (ja() != 0) {
790
		int i;
791
		for (i = 1; i < NEVENTS; i++) {
792
			int key;
793
			if (future[i] == 1e30) continue;
794
			switch (i) {
795
				case FSNOVA:  proutn("Supernova       "); break;
796
				case FTBEAM:  proutn("T Beam          "); break;
797
				case FSNAP:   proutn("Snapshot        "); break;
798
				case FBATTAK: proutn("Base Attack     "); break;
799
				case FCDBAS:  proutn("Base Destroy    "); break;
800
				case FSCMOVE: proutn("SC Move         "); break;
801
				case FSCDBAS: proutn("SC Base Destroy "); break;
802
			}
803
			cramf(future[i]-d.date, 8, 2);
804
			chew();
805
			proutn("  ?");
806
			key = scan();
807
			if (key == IHREAL) {
808
				future[i] = d.date + aaitem;
809
			}
810
		}
811
		chew();
812
	}
813
	proutn("Make universe visible? ");
814
	if (ja() != 0) {
815
		int i, j;
816
		for (i = 1; i < 9; i++)
817
		{
818
			for (j = 1; j < 9; j++)
819
			{
820
				starch[i][j] = 1;
821
			}
822
		}
823
	}
824
}
825
 
826
 
827
#endif