-
Notifications
You must be signed in to change notification settings - Fork 5
/
startrek-tos.lua
1739 lines (1429 loc) · 53.9 KB
/
startrek-tos.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
--[[
*** **** STAR TREK ****
*** SIMULATION OF A MISSION OF THE STARSHIP ENTERPRISE,
*** AS SEEN ON THE STAR TREK TV SHOW.
***
*** ORIGINAL PROGRAM BY MIKE MAYFIELD, MODIFIED VERSION
*** PUBLISHED IN DEC'S "101 BASIC GAMES", BY DAVE AHL.
*** MODIFICATIONS TO THE LATTER (PLUS DEBUGGING) BY BOB
*** LEEDOM - APRIL & DECEMBER 1974,
***
*************************************************************
*** LUA Conversion by Emanuele Bolognesi - v1.0 Oct 2020
***
***
*** My blog: http://emabolo.com/
*** Github: https://github.com/emabolo
***
*************************************************************
--]]
-- this version uses a global map 64x64 to store all the objects
-- present in the game. This the position and attributes of ships,
-- starbases and stars don't reset every time you exit the sector
-- the following functions are useful to manage the global map
-- and the difference between local and global coordinates
function localToGlobalCoord(sx,sy,x,y)
-- only integer numbers should arrive here
local gx = (sx-1) * 8 +x
local gy = (sy-1) * 8 +y
return gx,gy
end
function roundTo(val,precision)
precision = 10^precision
val = math.floor(val*precision)
return val/precision
end
function sectorFromGlobalCx(gx,gy)
if gx<0.5 or gx>64.5 or gy<0.5 or gy>64.5 then return 0,0 end -- invalid coordinates
local sx = math.floor((gx-0.5)/8+1)
local sy = math.floor((gy-0.5)/8+1)
return sx,sy
end
function sectorNumberFromGlobalCx(gx,gy)
local sx,sy = sectorFromGlobalCx(gx,gy)
if sx == 0 or sy == 0 then return 0 end
return (sx-1)*8+sy
end
function globalToLocalCoord(gx,gy)
local sx,sy = sectorFromGlobalCx(gx,gy)
local lx = math.floor(gx+0.5) % 8
local ly = math.floor(gy+0.5) % 8
if lx == 0 then lx = 8 end
if ly == 0 then ly = 8 end
return lx,ly,sx,sy
end
function MapCell(gx,gy)
local x = math.floor(gx+0.5)
local y = math.floor(gy+0.5)
return GlobalMap[x][y]
end
function UpdateMapCell(gx,gy,element)
local x = math.floor(gx+0.5)
local y = math.floor(gy+0.5)
GlobalMap[x][y] = element
end
function foundStarbaseInCell(x,y)
if MapCell(x,y)>9 and MapCell(x,y)<100 then return true
else return false end
end
function foundKlingonInCell(x,y)
if MapCell(x,y)>99 and MapCell(x,y)<1000 then return true
else return false end
end
function foundStarInCell(x,y)
if MapCell(x,y)>999 then return true
else return false end
end
function foundEnterpriseInCell(x,y)
if MapCell(x,y) == 1 then return true
else return false end
end
function mapCellIsNotEmpty(x,y)
if MapCell(x,y) > 0 then return true
else return false end
end
function mapCellIsEmpty(x,y)
if MapCell(x,y) == 0 then return true
else return false end
end
-- place the object in a random free location of the sector specified
function PlaceElementInSector(sectorx,sectory,element)
local x,y
repeat
local rx = math.random(1,8)
local ry = math.random(1,8)
x,y = localToGlobalCoord(sectorx,sectory,rx,ry)
until GlobalMap[x][y] == 0
GlobalMap[x][y] = element
return x,y
end
-- trasform the value into an element on the screen
function PrintElementOfMap(x,y)
local elem = ' '
if foundEnterpriseInCell(x,y) then elem = '<e>'
elseif foundStarbaseInCell(x,y) then elem = '>!<'
elseif foundKlingonInCell(x,y) then elem = '+K+'
elseif foundStarInCell(x,y) then elem=' * '
end
return elem
end
-- print full map and save it to file for debug
function PrintFullMap()
mapfile = io.open("startrek.map", "w")
print(' '..string.rep(' -',72))
for i=1,64 do
io.write('|')
for j=1,64 do
mapfile:write(GlobalMap[i][j]..',')
local elem = PrintElementOfMap(i,j)
io.write(' '..elem:sub(2,2))
if j % 8 == 0 then io.write(' |') end
end
print()
mapfile:write("\n")
if i % 8 == 0 then print(' '..string.rep(' -',72)) end
end
EnergyLevel = 3000
for i=1,8 do
if DamageLevel[i]<0 then DamageLevel[i]=0 end
end
mapfile:close()
return true
end
-- Perform a scan of current sector and pupulates B3,K3,S3
function CurrentSectorScan(sx,sy)
local k3,b3,s3 = 0,0,0
for i=(sx-1)*8+1,sx*8 do
for j=(sy-1)*8+1,sy*8 do
local elem = GlobalMap[i][j]
if foundStarbaseInCell(i,j) then
b3=b3+1
B4,B5,sxx,syy = globalToLocalCoord(i,j)
CurrentStarbase = elem-10
elseif foundKlingonInCell(i,j) then
k3=k3+1
table.insert(EnemyShips,elem-100) -- add the ship data to the current sector enemies array
elseif foundStarInCell(i,j) then
s3=s3+1
end
end
end
return k3,b3,s3
end
-- returns the string KBS (Klingons+Stabases+Stars) for selected sector
function SectorRecord(sx,sy)
local k3,b3,s3 = 0,0,0
for i=(sx-1)*8+1,sx*8 do
for j=(sy-1)*8+1,sy*8 do
local elem = GlobalMap[i][j]
if foundStarbaseInCell(i,j) then
b3=b3+1
elseif foundKlingonInCell(i,j) then
k3=k3+1
elseif foundStarInCell(i,j) then
s3=s3+1
end
end
end
return k3*100+b3*10+s3
end
-- generates the screen of the current sector
function GenerateSectorScreen(sx,sy)
local screen = ''
for i=1,8 do
for j=1,8 do
local x,y = localToGlobalCoord(sx,sy,i,j)
elem = PrintElementOfMap(x,y)
screen = screen .. elem
end
end
return screen
end
-- Other Utilities =============================================
function FNR(r)
return math.random(1,8) -- replaced with this simple rand, parameter r is useless
end
function smallDelay(sec)
sec = sec or 0.15
if DisableTeleprint then return 0 end
local t0 = os.clock()
while os.clock() - t0 <= sec do end
end
function telePrint(str,delay)
str = str or ''
delay = delay or 0.10
print(str)
smallDelay(delay)
end
function die (msg) -- for debug
msg = msg or 'I died well'
io.stderr:write(msg,'\n')
os.exit(1)
end
function formatWithSpaces(str,maxlength,centered)
-- if not centered it's aligned to the right
centered = centered or false
local final = ""
if centered then
spaces = string.rep(" ",math.floor((maxlength-string.len(str))/2) )
final = spaces .. str .. spaces
if string.len(final) < maxlength then final = final..' ' end
else
spaces = string.rep(" ",maxlength-string.len(str))
final = str .. spaces
end
return final
end
-- Instructions =============================================
function printInstructions()
text = [[
*************************************
* *
* *
* * * SUPER STAR TREK * * *
* *
* *
*************************************
INSTRUCTIONS FOR 'SUPER STAR TREK'
1. WHEN YOU SEE \COMMAND ?\ PRINTED, ENTER ONE OF THE LEGAL
COMMANDS (NAV,SRS,LRS,PHA,TOR,SHE,DAM,COM, OR XXX).
2. IF YOU SHOULD TYPE IN AN ILLEGAL COMMAND, YOU'LL GET A SHORT
LIST OF THE LEGAL COMMANDS PRINTED OUT.
3. SOME COMMANDS REQUIRE YOU TO ENTER DATA (FOR EXAMPLE, THE
'NAV' COMMAND COMES BACK WITH 'COURSE (1-9) ?'.) IF YOU
TYPE IN ILLEGAL DATA (LIKE NEGATIVE NUMBERS), THAN COMMAND
WILL BE ABORTED
THE GALAXY IS DIVIDED INTO AN 8 X 8 QUADRANT GRID,
AND EACH QUADRANT IS FURTHER DIVIDED INTO AN 8 X 8 SECTOR GRID.
YOU WILL BE ASSIGNED A STARTING POINT SOMEWHERE IN THE
GALAXY TO BEGIN A TOUR OF DUTY AS COMANDER OF THE STARSHIP
\ENTERPRISE\; YOUR MISSION: TO SEEK AND DESTROY THE FLEET OF
KLINGON WARWHIPS WHICH ARE MENACING THE UNITED FEDERATION OF
PLANETS.
YOU HAVE THE FOLLOWING COMMANDS AVAILABLE TO YOU AS CAPTAIN
OF THE STARSHIP ENTERPRISE:
\NAV\ COMMAND = WARP ENGINE CONTROL --
COURSE IS IN A CIRCULAR NUMERICAL 4 3 2
VECTOR ARRANGEMENT AS SHOWN . . .
INTEGER AND REAL VALUES MAY BE ...
USED. (THUS COURSE 1.5 IS HALF- 5 ---*--- 1
WAY BETWEEN 1 AND 2 ...
. . .
VALUES MAY APPROACH 9.0, WHICH 6 7 8
ITSELF IS EQUIVALENT TO 1.0
COURSE
ONE WARP FACTOR IS THE SIZE OF
ONE QUADTANT. THEREFORE, TO GET
FROM QUADRANT 6,5 TO 5,5, YOU WOULD
USE COURSE 3, WARP FACTOR 1.
\SRS\ COMMAND = SHORT RANGE SENSOR SCAN
SHOWS YOU A SCAN OF YOUR PRESENT QUADRANT.
SYMBOLOGY ON YOUR SENSOR SCREEN IS AS FOLLOWS:
<*> = YOUR STARSHIP'S POSITION
+K+ = KLINGON BATTLE CRUISER
>!< = FEDERATION STARBASE (REFUEL/REPAIR/RE-ARM HERE!)
* = STAR
A CONDENSED 'STATUS REPORT' WILL ALSO BE PRESENTED.
\LRS\ COMMAND = LONG RANGE SENSOR SCAN
SHOWS CONDITIONS IN SPACE FOR ONE QUADRANT ON EACH SIDE
OF THE ENTERPRISE (WHICH IS IN THE MIDDLE OF THE SCAN)
THE SCAN IS CODED IN THE FORM \###\, WHERE TH UNITS DIGIT
IS THE NUMBER OF STARS, THE TENS DIGIT IS THE NUMBER OF
STARBASES, AND THE HUNDRESDS DIGIT IS THE NUMBER OF
KLINGONS.
EXAMPLE - 207 = 2 KLINGONS, NO STARBASES, & 7 STARS.
\PHA\ COMMAND = PHASER CONTROL.
ALLOWS YOU TO DESTROY THE KLINGON BATTLE CRUISERS BY
ZAPPING THEM WITH SUITABLY LARGE UNITS OF ENERGY TO
DEPLETE THEIR SHIELD POWER. (REMBER, KLINGONS HAVE
PHASERS TOO!)
\TOR\ COMMAND = PHOTON TORPEDO CONTROL
TORPEDO COURSE IS THE SAME AS USED IN WARP ENGINE CONTROL
IF YOU HIT THE KLINGON VESSEL, HE IS DESTROYED AND
CANNOT FIRE BACK AT YOU. IF YOU MISS, YOU ARE SUBJECT TO
HIS PHASER FIRE. IN EITHER CASE, YOU ARE ALSO SUBJECT TO
THE PHASER FIRE OF ALL OTHER KLINGONS IN THE QUADRANT.
THE LIBRARY-COMPUTER (\COM\ COMMAND) HAS AN OPTION TO
COMPUTE TORPEDO TRAJECTORY FOR YOU (OPTION 2)
\SHE\ COMMAND = SHIELD CONTROL
DEFINES THE NUMBER OF ENERGY UNITS TO BE ASSIGNED TO THE
SHIELDS. ENERGY IS TAKEN FROM TOTAL SHIP'S ENERGY. NOTE
THAN THE STATUS DISPLAY TOTAL ENERGY INCLUDES SHIELD ENERGY
\DAM\ COMMAND = DAMAGE CONTROL REPORT
GIVES THE STATE OF REPAIR OF ALL DEVICES. WHERE A NEGATIVE
'STATE OF REPAIR' SHOWS THAT THE DEVICE IS TEMPORARILY
DAMAGED.
\COM\ COMMAND = LIBRARY-COMPUTER
THE LIBRARY-COMPUTER CONTAINS SIX OPTIONS:
OPTION 0 = CUMULATIVE GALACTIC RECORD ** SHORTCUT: \MAP\
THIS OPTION SHOWES COMPUTER MEMORY OF THE RESULTS OF ALL
PREVIOUS SHORT AND LONG RANGE SENSOR SCANS
OPTION 1 = STATUS REPORT ** SHORTCUT: \STA\
THIS OPTION SHOWS THE NUMBER OF KLINGONS, STARDATES,
AND STARBASES REMAINING IN THE GAME.
OPTION 2 = PHOTON TORPEDO DATA ** SHORTCUT: \POS\
WHICH GIVES DIRECTIONS AND DISTANCE FROM THE ENTERPRISE
TO ALL KLINGONS IN YOUR QUADRANT
OPTION 3 = STARBASE NAV DATA
THIS OPTION GIVES DIRECTION AND DISTANCE TO ANY
STARBASE WITHIN YOUR QUADRANT
OPTION 4 = DIRECTION/DISTANCE CALCULATOR
THIS OPTION ALLOWS YOU TO ENTER COORDINATES FOR
DIRECTION/DISTANCE CALCULATIONS
OPTION 5 = GALACTIC /REGION NAME/ MAP
THIS OPTION PRINTS THE NAMES OF THE SIXTEEN MAJOR
GALACTIC REGIONS REFERRED TO IN THE GAME.
]]
print (text)
print ("-- HIT RETURN TO CONTINUE ")
io.read()
end
function askForInstructions()
io.write("DO YOU NEED INSTRUCTIONS (Y/N) ? ")
yesno = string.upper(io.read())
if yesno == 'Y' or yesno == 'YES' then
printInstructions()
end
end
function PressEnterToContinue()
print ("<Hit Return to continue>")
io.read()
end
-- Names Utilities ===========================================================
function StarTrekSectorNames()
local names = {'Algira','Almatha','Antares','Archanis','Argelius','Argosian','Argus','Bajor',
'Beloti','Bolian','Cabral','Cygnus','Dalmine','Delta Vega','Dorvan','Epsilon IX',
'Ficus','Galloway','Gamma 7','Gamma Hydra','Gamma Trianguli','Gand','Gariman','Genesis',
'Glessene','Glintara','Grewler','Hekaras','Hyralan','Igo','Ipai','Jaradan',
"K'Rebeca",'Kalandra','Kaleb','Kandari','Kavis Alpha',
'Kepla','Lagana',"Lan'Tuana",'Lantaru','Marrab','Maxia','Mekorda','Mempa',
'Moab','Mutara','Omega','Oneamisu','Onias','Orion','Podaris','Qiris',
'Rakhari','Rhomboid Dronegar','Rukani','Rutharian','Selcundi Drema','Shepard','Sigma Antares',
'Silarian','Takara','Tandar','Tholian','Typhon','Vaskan','Vay','Vega-Omicron','Woden','Zaphod','Zed Lapis'}
for i = #names, 2, -1 do
local j = math.random(i)
names[i], names[j] = names[j], names[i]
end
end
function GetQuadrantName(Z4,Z5,RegionNameOnly)
RegionNameOnly = RegionNameOnly or false
-- Real sector names are number in TOS
local starnames = {}
if Z5<=4 then
starnames ={'ANTARES','RIGEL','PROCYON','VEGA','CANOPUS','ALTAIR','SAGITTARIUS','POLLUX'}
else
starnames ={'SIRIUS','DENEB','CAPELLA','BETELGEUSE','ALDEBARAN','REGULUS','ARCTURUS','SPICA'}
end
QuadrantName = starnames[Z4] -- array in LUA start from 1
if (not(RegionNameOnly)) then
if Z5 ==1 or Z5 ==5 then
QuadrantName = QuadrantName .. " I"
elseif Z5 == 2 or Z5 == 6 then
QuadrantName = QuadrantName .. " II"
elseif Z5 == 3 or Z5 == 7 then
QuadrantName = QuadrantName .. " III"
elseif Z5 == 4 or Z5 == 8 then
QuadrantName = QuadrantName .. " IV"
end
end
return QuadrantName
end
-- Ship Status Management ================================
function CheckShipStatus()
if ShipDocked then
return 'DOCKED'
elseif K3>0 then
return "*RED*"
elseif EnergyLevel < (MaxEnergyLevel/10) then
return "YELLOW"
else
return "GREEN"
end
end
function checkIfDocked()
-- checking all the sectors around the Enterprise to see if it's docked
ShipDocked=false
local enterpriseSector = sectorNumberFromGlobalCx(EntX,EntY)
for i=EntX-1,EntX+1 do
for j=EntY-1,EntY+1 do
local checkingSector = sectorNumberFromGlobalCx(i,j) -- 0 if outside borders
if enterpriseSector == checkingSector and foundStarbaseInCell(i,j) then
ShipDocked=true
ShipCondition="DOCKED"
EnergyLevel=MaxEnergyLevel
PhotonTorpedoes=MaxTorpedoes
if K3 > 0 then
telePrint("SULU: Sir, we are approaching "..AllStarbases[CurrentStarbase].name..". We are still under attack.")
else
telePrint("\nUHURA: "..AllStarbases[CurrentStarbase].name.." clears us for normal approach, sir.")
telePrint("KIRK: Normal approach procedures, Mister Sulu.")
telePrint("SULU: Approaching Stabase, sir. Shields dropped.")
end
print()
ShieldLevel=0
break
end
end
end
ShipCondition = CheckShipStatus()
return ShipDocked
end
-- Math functions to calculate distance and direction ==================
-- The original code was not using trigonometry
function getAngle(x,y,mCentreX,mCentreY)
local dx = x - mCentreX
local dy = -(y - mCentreY)
local inRads = math.atan2(dy, dx)
if inRads < 0 then
inRads = math.abs(inRads)
else
inRads = 2 * math.pi - inRads
end
inRads = inRads - (math.pi/2)
if inRads<0 then inRads=(math.pi*2+inRads) end -- rotate
return (4*inRads)/math.pi +1 -- convert in course
end
function CalcDistanceOfShip(x1,y1,x2,y2)
local DX = x1-x2
local DY = y1-y2
return math.sqrt(DX^2 + DY^2)
end
function PrintDistanceAndDirection(x1,y1,x2,y2)
local Direction = getAngle(x1,y1,x2,y2)
telePrint(" Direction = "..roundTo(Direction,2))
local Distance = CalcDistanceOfShip(x1,y1,x2,y2)
telePrint(" Distance = ".. roundTo(Distance,2))
return Distance
end
-- Main Commands of the Game =======================================
function ShortRangeSensorScan()
-- SHORT RANGE SENSOR SCAN & STARTUP SUBROUTINE
-- line 6720 was here
if DamageLevel[2]<0 then
telePrint("\n** SPOCK: Sensors are inoperative. Without them, we are blind. **\n")
return
end
QuadString = GenerateSectorScreen(Q1,Q2)
telePrint(" --- --- --- --- --- --- --- --- ")
for i=1,8 do
local line = i-1
io.write('| ')
for j=line*24+1,line*24+22,3 do
io.write(string.sub(QuadString,j,j+2)..' ')
end
io.write('|')
if i == 1 then telePrint(" STARDATE "..roundTo(Stardate,1)) end
if i == 2 then telePrint(" CONDITION "..ShipCondition) end
if i == 3 then telePrint(" SECTOR "..Q1.." , "..Q2) end
if i == 4 then telePrint(" COORDINATES "..S1.." , "..S2) end
if i == 5 then telePrint(" PHOTON TORPEDOES "..math.floor(PhotonTorpedoes)) end
if i == 6 then telePrint(" TOTAL ENERGY "..math.floor(EnergyLevel+ShieldLevel)) end
if i == 7 then telePrint(" SHIELDS "..math.floor(ShieldLevel)) end
if i == 8 then telePrint(" KLINGONS REMAINING "..math.floor(TotalKlingonShips)) end
end
telePrint(" --- --- --- --- --- --- --- --- ")
return true
end
function LongRangeSensorScan()
--# it was line 4000
telePrint("KIRK: Long range sensor scan, Mister Sulu.")
local N = {}
if DamageLevel[3]<0 then
telePrint("\n** SPOCK: Captain, some equipment is out of order. Long range sensors are inoperative. **\n")
return
end
telePrint("SULU: Sectors surrounding "..Q1..','..Q2.." charted and examined:")
-- Sectors one through twenty five charted and examined
Header="-------------------"
telePrint(Header)
for i=Q1-1,Q1+1 do
io.write(": ")
for j=Q2-1,Q2+1 do
if i>0 and i<9 and j>0 and j<9 then
if ExploredSpace[i][j] == 0 then
ExploredSpace[i][j]=SectorRecord(i,j)
end
local str = tostring(ExploredSpace[i][j]+1000)
io.write(string.sub(str,2,4))
else
io.write("***")
end
io.write(' : ')
end
telePrint()
telePrint(Header)
end
return true
end
function ShieldControl()
telePrint("KIRK: Deflectors control.")
-- 5520 REM SHIELD CONTROL - 5530
if DamageLevel[7]<0 then
telePrint("SULU: Sir, I have readings that deflectors are inoperative. The controls are frozen.") -- S03E11 Wink Of An Eye
return false
end
telePrint("CHEKOV: Sir, total power at "..(EnergyLevel+ShieldLevel).." units.")
io.write("CHEKOV: How many shall I use? ")
local Units = tonumber(io.read())
if Units == nil then
telePrint("CHEKOV: Sorry, Captain. I can't understand it.")
elseif Units<0 or ShieldLevel == Units then
telePrint("<SHIELDS UNCHANGED>")
elseif Units > EnergyLevel+ShieldLevel then
telePrint("SCOTT: Ach! You're joking. We can't do it.")
-- SCOTT: Giving them all we got.
--SCOTT: Captain, if we try, we'll overload our own engines
telePrint("<SHIELDS UNCHANGED>")
else
EnergyLevel=EnergyLevel+ShieldLevel-Units
ShieldLevel=Units
if Units == 0 then
telePrint("CHEKOV: Deflector shields down, sir.")
else
telePrint("CHEKOV: Deflectors up, sir. Shields at "..ShieldLevel.." units.")
end
end
return ShieldLevel
end
function DamageControl()
-- 5680 REM DAMAGE CONTROL - 5690
telePrint("KIRK: Damage Control, report.")
-- SCOTT: We need some repairs, sir, but the ship is intact.
local TimeToRepair=0
for I=1,8 do
if DamageLevel[I]<0 then
TimeToRepair=TimeToRepair+.1 -- 1/10 day for each damaged system - regardless of the Damage level
end
end
if TimeToRepair==0 then
telePrint("SPOCK: All systems report normal, Captain. No ascertainable damage.")
return false
end
telePrint("UHURA: Damage report coming in, Captain. Situation under control. Minor damage, stations three, seven, and nineteen.")
telePrint("MCCOY: Sickbay reports five minor injuries, all being treated.")
if DamageLevel[6]<0 then
telePrint("SPOCK: Detailed Damage control report not available, Captain")
else
telePrint("\nDEVICE STATE OF REPAIR")
for index=1,8 do
local tabs = 27
if DamageLevel[index]<0 then tabs=26 end -- for formatting
telePrint(formatWithSpaces(DeviceNames[index],tabs) .. roundTo(DamageLevel[index],2) )
end
end
if ShipDocked then
TimeToRepair=roundTo(TimeToRepair+math.random()*0.5,2) -- add a random factor and round to 2 decimals
if TimeToRepair >0.9 then TimeToRepair=0.9 end -- time to repair cannot be more than 1 day
telePrint("\nSCOTT: Sir, the damage control party just beamed to the Enterprise.")
telePrint("SCOTT: Estimate time to repair: "..TimeToRepair.." stardates.")
io.write("SCOTT: Permission to proceed with repairs, sir (Y/N) ? ")
local YesNo = io.read()
if YesNo == "Y" then
telePrint("KIRK: Permission granted.")
for i=1,8 do
if DamageLevel[i]<0 then DamageLevel[i]=0 end
end
Stardate=Stardate+TimeToRepair+0.1; -- never trust engineers!
telePrint("SPOCK: All systems operational, Captain.")
else
telePrint("KIRK: Request denied.")
--telePrint("SCOTT: Several systems out, sir. Operating on emergency backup.")
end
end
return true
end
function Communication()
telePrint("KIRK: This is Captain James T. Kirk, commanding the USS Enterprise. Please identify yourself.")
end
function PrintComputerRecord(GalaxyMapOn)
telePrint(" 1 2 3 4 5 6 7 8")
telePrint(" ----- ----- ----- ----- ----- ----- ----- -----")
for i=1,8 do
io.write(i..' ')
if GalaxyMapOn then
QuadrantName = GetQuadrantName(i,1,true)
io.write(' '..formatWithSpaces(QuadrantName,23,true)) -- centered string
QuadrantName = GetQuadrantName(i,5,true)
io.write(' '..formatWithSpaces(QuadrantName,23,true))
else
for j=1,8 do
io.write(" ")
if ExploredSpace[i][j]==0 then
io.write("***")
else
local str = tostring(ExploredSpace[i][j]+1000)
io.write(str:sub(2,4))
end
end
end
print("")
telePrint(" ----- ----- ----- ----- ----- ----- ----- -----")
end
print("")
return false
end
function GalaxyMap()
--#7390 REM SETUP TO CHANGE CUM GAL RECORD TO GALAXY MAP
telePrint(" THE GALAXY") -- # GOTO7550
PrintComputerRecord(true)
return true
end
function ComulativeGalacticRecord()
if DamageLevel[8]<0 then
telePrint("SPOCK: Library computer is inoperative, sir.")
return false
end
telePrint(" COMPUTER RECORD OF GALAXY FOR SECTOR "..Q1..','..Q2.."\n")
PrintComputerRecord(false)
return true
end
function StatusReport()
telePrint("KIRK: Mister Spock. Status.")
if TotalKlingonShips>1 then
telePrint("SPOCK: Captain, there are "..TotalKlingonShips.." Klingon ships left.")
else
telePrint("SPOCK: Captain, there is only one Klingon ship left.")
end
telePrint("Our mission must be completed in "..roundTo(T0+MaxNumOfDays-Stardate,1).." stardates.")
if B3>0 then
telePrint("UHURA: Captain, "..AllStarbases[CurrentStarbase].name.." is within range.")
elseif TotalStarbases == 1 then
telePrint("SPOCK: Captain, there is only one starbase left. We must protect it.")
elseif TotalStarbases>1 then
telePrint("SPOCK: Captain, "..TotalStarbases.." Federation starbases can assist us.")
else
telePrint("SPOCK: There are no starbases left. ")
end
telePrint("CHEKOV: Shields level is "..ShieldLevel..", with "..EnergyLevel.." units of energy left." )
if K3>0 then
if B3>0 then
telePrint("UHURA: I'm picking up a subspace distress call. It's from "..AllStarbases[CurrentStarbase].name..".")
else
telePrint("SULU: Captain, we are under attack!")
end
end
--DamageControl()
return true
end
function PhotonTorpedoData()
if DamageLevel[8]<0 then
telePrint("SPOCK: Computer is inoperative, sir.")
return false
end
local shiporships = 'ships'
if K3 == 1 then shiporships = 'ship' end
telePrint("KIRK: What is the position of the Klingon "..shiporships.."?")
if K3<=0 then
telePrint("SULU: No signs of hostile activities in this area.")
return true
end
--SPOCK: Impossible to calculate. We lack data to analyse. Our instruments appear to be functioning
--normally, but what they tell us makes no sense. Our records are clear up to the point at which we left our galaxy.
telePrint("SPOCK: Captain, I have the calculations.")
telePrint("From Enterprise to Klingon "..shiporships..":")
for i,k in ipairs(EnemyShips) do
if AllKlingons[k].energy > 0 then
PrintDistanceAndDirection(AllKlingons[k].x,AllKlingons[k].y,EntX,EntY)
end
end
return true
end
function DistanceCalculator()
telePrint("KIRK: Computer, compute course and distance.")
--telePrint("COMPUTER: Current Sector "..Q1..","..Q2..". Coordinates: "..S1..","..S2)
io.write("COMPUTER: Starting co-ordinates (row,col)? ")
local Coord = io.read()
local inp1, inp2 = Coord:match("(%d+),(%d+)")
local y1, x1 = tonumber(inp1), tonumber(inp2)
io.write("COMPUTER: Final co-ordinates (row,col)? ")
Coord = io.read()
inp1, inp2 = Coord:match("(%d+),(%d+)")
local y2, x2 = tonumber(inp1), tonumber(inp2)
if y1 == nil or x1 == nil or x2 == nil or y2 == nil then
telePrint("COMPUTER: Unable to comply.")
return false
end
PrintDistanceAndDirection(y2,x2,y1,x1)
return true
end
function StarbaseNavData()
telePrint("KIRK: Lay in a course for the starbase, Mister Sulu.")
if B3 > 0 then
telePrint("SULU: Aye, aye, sir.")
PrintDistanceAndDirection(B4,B5,S1,S2)
else
telePrint("SULU: Captain, no signs of starbases in this area.")
end
return true
end
function LibraryComputer()
if DamageLevel[8]<0 then
telePrint("SPOCK: Library computer is inoperative, sir.")
return false
end
local ComputerDone = false
while not ComputerDone do
io.write("COMPUTER: Library computer ready. Command? ")
local Command = tonumber(io.read())
print("")
if Command == 0 then
ComputerDone = ComulativeGalacticRecord() -- #7540
elseif Command == 1 then
ComputerDone = StatusReport() -- #7900
elseif Command == 2 then
ComputerDone = PhotonTorpedoData() -- #8070
elseif Command == 3 then
ComputerDone = StarbaseNavData() -- #8500
elseif Command == 4 then
ComputerDone = DistanceCalculator() -- #8150
elseif Command == 5 then
ComputerDone = GalaxyMap() -- #7400
else
print("FUNCTIONS AVAILABLE FROM LIBRARY-COMPUTER:")
print(" 0 = CUMULATIVE GALACTIC RECORD")
print(" 1 = STATUS REPORT")
print(" 2 = PHOTON TORPEDO DATA")
print(" 3 = STARBASE NAV DATA")
print(" 4 = DIRECTION/DISTANCE CALCULATOR")
print(" 5 = GALAXY 'REGION NAME' MAP\n")
end
end
return false
end
-- End of Game functions ===============================================
function EnterpriseDestroyed()
telePrint("\n** The Enterprise has been destroyed. The Federation is lost. **")
smallDelay(2)
return
end
function KlingonsDefeated()
telePrint("\nSPOCK: Congratulations, Captain! The last Klingon warship has been defeated.")
telePrint("UHURA: Captain, Starfleet Control is calling the Enterprise.")
telePrint("KIRK: Open a channel, Uhura.",2)
telePrint("UHURA: Frequency open, sir.",2)
telePrint("KIRK: Starfleet Control, this is the Enterprise. Captain Kirk speaking.",2)
telePrint("FEDERATION: Thank you, Captain! You saved the Federation!",2)
telePrint("FEDERATION: You and your crew will receive a Medal of Honour. Come back here to celebrate!")
PressEnterToContinue()
telePrint("\nSPOCK: Captain, our efficiency rating is " .. math.floor(1000*(InitialKlingonShips/(Stardate-T0))^2))
telePrint("We can do better next time.")
return
end
function TimeExpired()
telePrint("\nSPOCK: It's too late, Captain. We failed our mission",2)
--telePrint("Captain's Log, stardate "..roundTo(Stardate,1)..". Entry made by Second Officer Spock.")
telePrint("It is stardate "..roundTo(Stardate,1).." and there are "..TotalKlingonShips.." Klingons ships left.",2)
telePrint("The Federation has been conquered.")
end
-- Combat functions ===============================================
--# this was line-6000
function KlingonsAttack()
if K3<=0 then
return false
end
-- "KLINGON [on viewscreen]: Enterprise, prepare to be boarded or destroyed."
if ShipDocked then
telePrint("SPOCK: Klingons are firing, but the Enterprise is protected by the Starbase shields.")
return false
end
print()
telePrint("<Klingons turn>")
for i,k in ipairs(EnemyShips) do
local KlingonEnergy = AllKlingons[k].energy
local KlingonName = AllKlingons[k].name
if KlingonEnergy> 0 then
print()
local kx,ky,ksx,ksy = globalToLocalCoord(AllKlingons[k].x,AllKlingons[k].y)
telePrint("SULU: Klingon ship at " ..kx..","..ky.." is firing, sir.")
local Distance = CalcDistanceOfShip(AllKlingons[k].x,AllKlingons[k].y,EntX,EntY)
local Hits = math.floor((KlingonEnergy/Distance)*(2+math.random()))+1
local SysDamaged = 0
ShieldLevel = ShieldLevel-Hits
-- this is a strange choice. Energy of the klingon decrease when they fire
-- but it does not depend on the power used by the phasers
-- also it decreases a lot, because it can become 1/3 or 1/4 of the previous energy
-- would be better to use an algorithm similar to the one used for the Enterprise
AllKlingons[k].energy = KlingonEnergy/(3+math.random())
if ShieldLevel<0 then
telePrint("** SPOCK: Phaser penetrated the shields, Captain. All decks report damage. **")
EnterpriseDestroyed()
GameOver = true
return true
end
telePrint("SPOCK: Phaser hit on port deflector four, Captain. "..Hits.." units of power lost.")
if Hits>19 and (ShieldLevel==0 or (math.random()<.6 and (Hits/ShieldLevel) > 0.02)) then
SysDamaged=FNR(1)
DamageLevel[SysDamaged]= DamageLevel[SysDamaged] - (Hits/ShieldLevel) - (0.5 * math.random())
telePrint("SCOTT: Sir, "..DeviceNames[SysDamaged].." was damaged by the hit.")
end
if ShieldLevel>(ShieldLevel+Hits)/2 and SysDamaged == 0 then
telePrint("SCOTT: Shields still holding, sir.")
elseif ShieldLevel<20 then
telePrint("SPOCK: Captain, shields are down. We cannot survive another hit.")
else
telePrint("SPOCK: Shields are down to "..ShieldLevel.." units.")
end
end
end
return false
end
--#4690 REM PHOTON TORPEDO CODE BEGINS HERE
function FirePhotonTorpedoes()
telePrint("KIRK: Chekov, arm photon torpedoes.")
if PhotonTorpedoes<=0 then
telePrint("CHEKOV: Captain, we already fired all of them.")
return false
end
if DamageLevel[5]<0 then
telePrint("SPOCK: Captain, photon torpedoes are inoperative.")
return false
end
io.write("CHEKOV: Photon torpedoes ready. Course (1-9)? ")
local Course = tonumber(io.read())
if Course == nil then return false end
if Course == 9 then Course = 1 end
if Course<0.1 or Course>9 then
telePrint("CHEKOV: I don't understand, sir.")
return false
end
EnergyLevel=EnergyLevel-2
PhotonTorpedoes=PhotonTorpedoes-1
local CourseInRadiant = (math.pi/4)*(Course-1)
StepX = math.sin(CourseInRadiant)*(-1)
StepY = math.cos(CourseInRadiant)
local X,Y = EntX,EntY -- torpedoes starting coordinates = Enterprise coordinates
local TorStartingSector = sectorNumberFromGlobalCx(EntX,EntY)
telePrint("TORPEDO TRACK:")
--# this is line 4920
local KlingonDestroyed = 0
while (1) do
X=X+StepX
Y=Y+StepY
local X3,Y3,ssx,ssy = globalToLocalCoord(X,Y)