{ SPACE LORDS 7 - VGA PC VERSION. (C) 1995 Scott Tunstall & K. Sillett (BBC Maestro) 3 PLAYER ACTION !!! Apologies for the swearing in some of my posts Gayle. To make up for it, I've given ya a QUALITY video game. Seriously! It certainly looks smart... don't ask me where I got the graphics from tho' - some folk may complain! ;) BEFORE YOU RUN THIS PLEASE USE THE XX3402 DECODER ON PART 2 OF THE SPACE LORDS POST TO CREATE THE FILE IMAGES.ZIP. THEN UNZIP THE IMAGES FILE INTO WHERE YOUR SPACE LORDS GAME EXECUTABLE FILE (LORDS.EXE) WILL BE. THEN, RUN THE EXE AND HAVE FUN! :) New game requirements: ---------------------- 500K of base memory MCGA/VGA graphics adaptor supporting 320 x 200 x 256 mode 386 SX 25 processor (at worst) - will run VERY SLOWLY ON THIS MACHINE (Ok on a 486 DX-2) (Of course, if you are Dave "Stallion Man" Norrie you can use a 8Mb RAM Pentium f***ing 90 - lucky c***!! I'll put one over him and buy an IBMRISC 400Mhz baby! (No games for it tho' - I'll change that !) Most importantly a 101 key keyboard is essential. PLAYER # UP ROTATE LEFT ROTATE RIGHT FIRE ----------------------------------------------------------------- 1 '1' 'A' 'X' 'LEFT SHIFT' 2 'O' ';' '@' '>' 3 'Home' 'Keypad 9' 'Keypad -' 'Keypad 3' 4 JOYSTICK 1 (Not implemented) 5 JOYSTICK 2 (Not implemented) 6..100 require to be LapLinked (Aye right then) } {$DEFINE FULLDISPLAY} { <-- $UNDEF if using a slow 386 } {$DEFINE BUMPING} { <-- Player to player bumping } {$DEFINE BONUSES} { <-- Want Any bonuses on screen } {$DEFINE MESSAGES} { <-- This may be silly of you to $UNDEF. } {$a+,b-,s-,e+,n+,r-,v-,g+} Program SPACE_LORDS_7; { 7 editions already - GULP! } Uses Dos,NEWGRAPH, NwKBDInt, Crt; {NEWGRAPH is in JUNE 1996 EDITION OF THE SWAG } {AS IS NEWKBDINT - KEYBOARD HANDLER } Const TopBoundary = -8; { Top of window } BottomBoundary = 204; LeftBoundary = -4; RightBoundary = 323; MaxPlayers = 3; { Max no of players on screen at once } {$IFDEF BONUSES} MaxBonuses = 6; { Max no of bonuses on screen at once } {$ENDIF} MaxAliens = 10; { Getting busy on the screen ! } MaxStars = 20; { Number of parallax stars } MaxExplodeWidth = 200; { And how far the explosion circles go } ShipTurnAngle = 4; { Degrees that ships turn in } PointsForBumping = 500; { Guess what these are ? } PointsForShooting = 100; DeductionForShooting = 10; { BIT FLAGS - LEAVE ALONE } Dead = 0; { Playerstatus defines } ShootAble = 1; { This MUST stay at 1 - V. Important } Warping = 2; { This MUST stay at 2 ! } Exploding = 4; { This MUST stay at 4 ! } Spinning = 8; { This MUST stay at 8 ! } Frozen = 16; { Player Speed stuff } MaxPlayerSpeed = 4; { This is the MAXIMUM number of pixels that a player ship jumps in 1 pass. Pretty fast man } SlowestPlayerSpeed = 1; { The least number of pixel jumps } { Laser stuff - Alter MaxLasers if you like, leave the rest } MaxLasers = (MaxPlayers * 10)+10; { How many lasers allocated } MaxPlayerLasers = 10; { How many each player has } MaxLaserPower = 5; NumLaserTypes = 3; { The current # of laser types } LaserFree = 0; NormalLaser = 1; { Lasers stop at edge of screen } LaserWraps = 2; { Lasers can go off one side & reappear on the other } LaserRebound = 3; { Makes lasers bounce off wall } PlayerLaserSize = 4; AlienLaserSize = 4; { Bonus stuff - don't change the values of the constants otherwise some strange effects will occur, OK? If you want to add some more stuff you'll have to update BonusString too.. } {$IFDEF BONUSES} NumberOfBonuses = 13; { BONUS NAME POINTS FOR COLLECTING IT ---------- ------------------------ } SlowDownBonus = 1; SlowDownBonusPointsValue = 100; EnergyBonus = 2; EnergyBonusPointsValue = 200; FreezeBonus = 3; FreezeBonusPointsValue = 300; ReverseBonus = 4; ReverseBonusPointsValue = 400; DisableBonus = 5; DisableBonusPointsValue = 500; InvulnerabilityBonus = 6; InvulnerabilityBonusPointsValue = 600; AssFiringBonus = 7; AssFiringBonusPointsValue = 700; NormalBonus = 8; NormalBonusPointsValue = 50; ToodysBonus = 9; ToodysBonusPointsValue = 2000; LaserBonus = 10; LaserBonusPointsValue = 200; WarpBonus = 11; WarpBonusPointsValue = 1000; BounceLaserBonus = 12; BounceLaserBonusPointsValue = 200; UnknownBonus = 13; {$ENDIF} MaxInvulnerableTime = 200; {$IFDEF BONUSES} MaxFrozenTime = 100; MaxFireHaltTime = 100; MaxKeyReverseTime = 200; MaxSlowedDownTime = 100; MaxBanzaiTime = 100; MaxDisableTime = 100; {$ENDIF} EnergyIncrement = 5; SlowDownIncrement = 10; NormalMessageTime = 80; PacDelayConst = 4; { And now to define ALL aspects of a player's ship } Type PlayerStruct = Record PlayerStatus: byte; { 0 = Dead, 1 = ShootAble, 2= Exploding, 4 = Spinning, 8 = Frozen } FrozenTime: word; ExplodeWidth:byte; PlayerColour: byte; PlayerAngle: integer; SpinAngle: integer; SpinSpeed: byte; SpinCount: byte; PlayerX: integer; PlayerY: integer; PlayerWraps : boolean; PlayerMessage: String[38]; MessageTime: byte; BanzaiTime: word; { Speed stuff } PlayerSpeed: byte; { Exceed 3 and ship movement is quite jerky. } NormalPlayerSpeed: byte; SlowedDownTime: word; PlayerWait: byte; WaitCount: byte; MaxWaitCount: byte; Thrusting: boolean; PlayerEnergy: integer; MaxPlayerEnergy: integer; RechargeTime: byte; RechargeLatch: byte; RechargeDeduction: byte; KeyReverseTime: byte; AutoFire: boolean; DisableTime: byte; AssFiring : boolean; FireKeyReleased: boolean; FireDelay:byte; FireLatch:byte; LaserDeduction: byte; CurrentLaserType: byte; CurrentLaserPower: byte; CurrentLaserSpeed: byte; CurrentMaxLaserTravel: byte; LaserHurts: boolean; EnemyLaserHurts: boolean; Invulnerable: boolean; InvulnerableTime: word; PlayerScore: LongInt; End; Type Laser = Record LaserType: byte; FiredBy: byte; LaserAngle: integer; LaserX: integer; LaserY: integer; LaserColour: byte; LaserSize: byte; LaserSpeed: byte; LaserTravel: byte; MaxLaserTravel: byte; LaserPower: byte; End; {$IFDEF BONUSES} { Yeah! Some Pick - Ups for the players! } Type Bonus = Record BonusType: byte; BonusX: integer; { Position on screen } BonusY: integer; BonusXIncrement: integer; BonusYIncrement: integer; End; Type BonusArray = Array[1..MaxBonuses] of Bonus; {$ENDIF} Type PlayerArray = Array[1..MaxPlayers] of PlayerStruct; Type LaserArray = Array[1..MaxLasers] of Laser; Var PlayerRec: PlayerArray; LaserRec: LaserArray; TempLaser: Laser; {$IFDEF BONUSES} BonusRec: BonusArray; {$ENDIF} OldKbdInt: procedure; PlanetSeg,PlanetOfs: word; titleBitmapSeg,titleBitmapOfs: word; EmporerSeg,EmporerOfs: word; ScratchSeg,ScratchOfs: word; FontSegment, FontOffset: word; FontHeight: byte; PacPointer: Array[0..7] of Pointer; AlienPointer: Pointer; AlienShapeSize: word; DestroyerPalette: PaletteType; titleBitmapPalette: PaletteType; EmporerPalette: PaletteType; TempKey: char; ColourTable: array[1..MaxPlayers] of byte; QCos, QSin : array[0..359] of real; PlayersOn: byte; PlayersAlive: byte; { How many players are left on the screen - initially, PlayersAlive equals PlayersOn but as people are killed it decrements } LasersFired: byte; LastLaserIndex: byte; AlienCount: byte; {$IFDEF BONUSES} BonusesOnScreen: byte; BonusString: string[NumberOfBonuses]; {$ENDIF} Message: String[40]; Procedure Warp(PlayerNo:byte); Forward; Procedure LoadGraphics; Var Count: byte; Begin TextMode(CO80); TextBackGround(Black); ClrScr; TextBackGround(Red); For Count:=0 to 79 do Write(Chr(32)); TextColor(White); Gotoxy(1,1); Writeln('SPACE LORDS 7.1.2.3.5.2.9.« (C) 1994,5 Scott Tunstall. Lauder College Version'); Writeln; Writeln; TextBackGround(Black); TextColor(LightGray); Writeln('Beginning LORDS_INIT Refresh daemon.. OK.'); Writeln; For Count:=0 to 79 do write('='); Writeln('THIS VERSION IS PUBLIC DOMAIN AND MAY BE SWAPPED AND COPIED FREELY'); Writeln('YOU MAY NOT DISASSEMBLE, REPLICATE OR ALTER THE PROGRAM CODE IN ANY'); Writeln('WAY UNLESS YOU CONTACT THE AUTHOR.'); For Count:=0 to 79 do write('='); Writeln('Please wait.. Loading in PCX files from hard disk..'); Writeln; Bitmap(PlanetSeg, PlanetOfs); Bitmap(titleBitmapSeg, titleBitmapOfs); Bitmap(EmporerSeg, EmporerOfs); Bitmap(ScratchSeg, ScratchOfs); Write('DESTROYR.PCX .. '); SetSourceBitmapAddr(PlanetSeg, PlanetOfs); LoadPCX('DESTROYR.PCX',DestroyerPalette); Writeln('loaded.'); Write('BACK.PCX .. '); SetSourceBitmapAddr(titleBitmapSeg, titleBitmapOfs); LoadPCX('BACK.PCX',titleBitmapPalette); Writeln('loaded.'); Write('EMPORER.PCX .. '); SetSourceBitmapAddr(EmporerSeg, EmporerOfs); LoadPCX('EMPORER.PCX',EmporerPalette); Writeln('loaded.'); End; { Sorry I had to get rid of the Pascal but I was pissed off with it's slothfulness ! } Procedure BitMapCopy(TheSegment, TheOffset:word); Begin Asm MOV AX,DS MOV ES,ScratchSeg MOV DI,ScratchOfs MOV SI,TheOffset MOV DS,TheSegment MOV CX,16000 REPZ DB $66 MOVSW MOV DS,AX End; SetSourceBitmapAddr(ScratchSeg,ScratchOfs); SetDestinationBitmapAddr($a000,0); End; {======================================================== This routine could possibly be slowing the system down quite a lot as it calls the video interrupt which as most codies know is as slow as a snail on mogadon. Hmm. I will update this in 1998 when I've got me postgraduate but right now you'll have to make do with this s**t OK? } Procedure SelectFont(FontNo: byte); Var TempWidth: byte; Begin UseFont(FontNo); GetCurrentFontAddr(FontSegment,FontOffset); GetCurrentFontSize(TempWidth,FontHeight); End; {==================== Display coloured text } Procedure TextXY(x,y:integer;txt:string); Begin SetColour(254); OutTextXY(x+1,y+1,txt); SetColour(255); OutTextXY(x,y,txt); End; {=============================================================== This Bresenham circle routine isn't mine. I nicked it from the SWAG (the rest of the stuff is 100% mine though) and to be quite honest I couldn't be bothered converting it to assembler, so if any gurus out there (like me!) want to then they can convert. *** You'd be sad tho' !! *** } Procedure Circle(X, Y : integer; Radius:byte); Var Xs, Ys : Integer; Da, Db, S : Integer; TX, TR : word; begin if (Radius = 0) then Exit; if (Radius = 1) then begin PutPixel(X, Y, GetColour); Exit; end; Xs := 0; Ys := Radius; Repeat TX:=Sqr(Xs+1); TR:=Sqr(Radius); Da := TX + Sqr(Ys) - TR; Db := TX + Sqr(Ys - 1) - TR; S := Da + Db; Inc(Xs); if (S > 0) then Dec(Ys); PutPixel(X+Xs-1, Y-Ys+1, GetColour); PutPixel(X-Xs+1, Y-Ys+1, GetColour); PutPixel(X+Ys-1, Y-Xs+1, GetColour); PutPixel(X-Ys+1, Y-Xs+1, GetColour); PutPixel(X+Xs-1, Y+Ys-1, GetColour); PutPixel(X-Xs+1, Y+Ys-1, GetColour); PutPixel(X+Ys-1, Y+Xs-1, GetColour); PutPixel(X-Ys+1, Y+Xs-1, GetColour); Until (Xs >= Ys); end; Procedure InitPlayers; Var count: byte; Begin For count:= 1 to MaxPlayers do With PlayerRec[count] do Begin Warp(Count); PlayerMessage:='Player '+chr(48+Count)+' ready !'; MessageTime:=NormalMessageTime; ExplodeWidth:=0; PlayerColour:=ColourTable[Count]; PlayerWraps:=True; PlayerSpeed:=4; NormalPlayerSpeed:=PlayerSpeed; SlowedDownTime:=0; PlayerWait:=1; WaitCount:=15; MaxWaitCount:=WaitCount; Thrusting:=False; InvulnerableTime:=MaxInvulnerableTime; { So if you warp into Paccy you can still get away } BanzaiTime:=0; PlayerEnergy:=20; MaxPlayerEnergy:=PlayerEnergy; RechargeTime:=40; RechargeLatch:=RechargeTime; RechargeDeduction:=10; KeyReverseTime:=0; AssFiring:=False; DisableTime:=0; AutoFire:=True; FireKeyReleased:=true; FireDelay:=3; FireLatch:=FireDelay; CurrentLaserType:=NormalLaser; CurrentLaserPower:=1; CurrentLaserSpeed:=8; CurrentMaxLaserTravel:=80; LaserDeduction:=1; LaserHurts:=False; EnemyLaserHurts:=True; PlayerScore:=0; End; End; { Flush laser array } Procedure InitLasers; Var Count: byte; Begin LasersFired:=0; LastLaserIndex:=1; For Count:=1 to MaxLasers do With LaserRec[Count] do LaserType:=LaserFree; End; {$IFDEF BONUSES} Procedure InitBonuses; Var Count: byte; Begin BonusesOnScreen:=0; BonusString:='SEFRDIANTLWB?'; { Not explaining what this is for } For Count:= 1 to MaxBonuses do With BonusRec[Count] do Begin BonusType:=0; End; End; {$ENDIF} Procedure SetUpPlayers; var Count: word; keyhit: char; PromptLatch: byte; PromptTime: byte; TextRefreshCount: byte; Begin For Count:=0 to 359 do Begin QCos[Count]:=Cos(Count * (PI/180)); QSin[Count]:=Sin(Count * (PI/180)); end; { Assign player colours } For Count:=1 to MaxPlayers do ColourTable[Count]:=256-Count; Randomize; PlayersOn:=MaxPlayers; PlayersAlive:=PlayersOn; InitPlayers; InitLasers; {$IFDEF BONUSES} InitBonuses; {$ENDIF} { Now draw the title screen } PromptLatch:=50; PromptTime:=PromptLatch; TextRefreshCount:=0; SetPalette(254, 63,0,0); SetPalette(255, 63,63,0); Repeat BitMapCopy(titleBitmapSeg,titleBitmapOfs); SelectFont(6); TextXY(92,8,'SPACE LORDS 7«'); SelectFont(1); TextXY(32,70, 'PROGRAMMING BY : Scott Tunstall'); if (TextRefreshCount < 4) Then Begin TextXY(32,96, 'VECTOR GFX BY : Scott Tunstall'); TextXY(32,112, 'PAC MAN BY : Namco (tm)'); TextXY(32,128, 'DIRTY WOMEN AT : MarketGait'); end else Begin SelectFont(Font8x16); TextXY(48,96, 'SO RONNY NOW DO YOU BELIEVE'); TextXY(48,114, 'THAT I WROTE THIS PROGRAM ?'); SelectFont(Int43Font); End; Delay(1); Dec(PromptTime); If PromptTime=0 Then Begin PromptTime:=50; Inc(TextRefreshCount); Asm AND BYTE PTR TextRefreshCount, $7 End; End; If (PromptTime > 25) Then Begin TextXY(32,162,'PRESS SPACE TO BEGIN THE GAME !'); End; SelectFont(Font8x16); TextXY(32,180,'Program (C) 1995 Scott Tunstall.'); CopySourceBitmap ; if keypressed then keyhit:=readkey; Until keyhit = ' '; End; Procedure DrawPlayerStuff; var PlayerCount: byte; OriginX: integer; OriginY: integer; Angle: integer; LineCount: byte; CircCount: byte; TempString: string[6]; Begin UseFont(1); For PlayerCount:=1 to PlayersOn do With PlayerRec[PlayerCount] do Begin Str(PlayerScore,TempString); SetColour(PlayerColour); OutTextXY(0,192- PlayerCount SHL 3,TempString); If MessageTime <>0 Then Begin Dec(MessageTime); {$IFDEF FULLDISPLAY} TextXY(56,192-PlayerCount SHL 3,PlayerMessage); SetColour(PlayerColour); {$ELSE} OutTextXY(56,192-PlayerCount SHL 3,PlayerMessage); {$ENDIF} End; { Time to draw the ship. I am quite pleased that this routine is fairly fast. } If (PlayerStatus And ShootAble)=ShootAble Then Begin If (InvulnerableTime >10) Or (InvulnerableTime MOD 2 = 1) Then Circle(PlayerX,PlayerY,12); If (BanzaiTime = 0) Or ((BanzaiTime MOD 8 )>3 ) Then Begin Angle:=PlayerAngle; { Nose of ship is 8 pixels away from the start area at degree } OriginX:=PlayerX+ Round(QCos[Angle] * 8); OriginY:=PlayerY+ Round(QSin[Angle] * 8); MoveTo(OriginX,OriginY); Asm MOV AX,Angle ADD AX,135 CMP AX,360 JB @ThisAngleIsOK1 SUB AX,360 @ThisAngleIsOK1: MOV Angle,AX End; LineTo(PlayerX+ Round(QCos[Angle] * 8), PlayerY+ Round(QSin[Angle] * 8)); ; Asm MOV AX,Angle ADD AX,45 CMP AX,360 JB @ThisAngleIsOK2 SUB AX,360 @ThisAngleIsOK2: MOV Angle,AX End; LineTo(PlayerX+Round(QCos[Angle] * 2), PlayerY+Round(QSin[Angle] * 2)); Asm MOV AX,Angle ADD AX,45 CMP AX,360 JB @ThisAngleIsOK3 SUB AX,360 @ThisAngleIsOK3: MOV Angle,AX End; LineTo(PlayerX+Round(QCos[Angle] * 8), PlayerY+Round(QSin[Angle] * 8)); LineTo(OriginX,OriginY); {$IFDEF FULLDISPLAY} If Thrusting And (Random(2)=1) Then Begin SetColour(Random(255)); Angle:=PlayerAngle; Asm MOV AX,Angle { I've tried the other way ! } ADD AX,150 CMP AX,360 JB @ThisAngleIsOK4 SUB AX,360 @ThisAngleIsOK4: MOV Angle,AX End; MoveTo(PlayerX+Round(QCos[Angle]*5), PlayerY+Round(QSin[Angle]*5)); Asm MOV AX,Angle ADD AX,30 CMP AX,360 JB @ThisAngleIsOK5 SUB AX,360 @ThisAngleIsOK5: MOV Angle,AX End; LineTo(PlayerX+Round(QCos[Angle]*8), PlayerY+Round(QSin[Angle]*8)); {Inc(Angle,30); If Angle > 360 Then Dec(Angle,360);} Asm MOV AX,Angle ADD AX,30 CMP AX,360 JB @ThisAngleIsOK6 SUB AX,360 @ThisAngleIsOK6: MOV Angle,AX End; LineTo(PlayerX+Round(QCos[Angle]*5),PlayerY+Round(QSin[Angle]*5)); End; {$ENDIF} SetColour(PlayerColour); OriginX:=PlayerX-12; OriginY:=PlayerY+12; Line(OriginX,OriginY,OriginX + PlayerEnergy,OriginY); End; End Else If (PlayerStatus = Exploding) Or (PlayerStatus = Warping) Then Begin For circcount:=0 to 40 do PutPixel(PlayerX+Round(QCos[circcount SHL 3]*ExplodeWidth), PlayerY+Round(QSin[circcount SHL 3]*ExplodeWidth),PlayerColour); End; End; End; { Put the lasers on the screen. } Procedure DrawLasers; var LaserCount: byte; Begin If LasersFired <>0 Then For LaserCount:=1 to MaxLasers do If LaserRec[LaserCount].LaserType <> LaserFree Then With LaserRec[LaserCount] do Begin SetColour(LaserColour); MoveTo(LaserX,LaserY); LineRel(Round(QCos[LaserAngle]*LaserSize), Round(QSin[LaserAngle]*LaserSize)); End; End; {$IFDEF BONUSES} Procedure DrawBonuses; var BonusCount: byte; Begin SetColour(255); If BonusesOnScreen <>0 Then For BonusCount:=1 to MaxBonuses do With BonusRec[BonusCount] do If BonusType <>0 Then Begin Circle(BonusX+4,BonusY+4,12); {$IFDEF FULLDISPLAY} UseFont(Font8x14); TextXY(BonusX,BonusY,BonusString[BonusType]); {$ELSE} OutTextXY(BonusX,BonusY,BonusString[BonusType]); {$ENDIF} End; End; {$ENDIF} Procedure CheckBounds(Var XPos,YPos:integer; ObjectWraps: boolean; Var DidWrap:boolean); Assembler; Asm CMP ObjectWraps,1 JNE @ObjectDoesNotWrap MOV SI,RightBoundary MOV DI,LeftBoundary MOV CX,BottomBoundary MOV DX,TopBoundary JMP @LetsDoThisshit @ObjectDoesNotWrap: MOV SI,LeftBoundary MOV DI,RightBoundary MOV CX,TopBoundary MOV DX,BottomBoundary @LetsDoThisshit: XOR AL,AL LES BX,XPos MOV BX,[ES:BX] CMP BX,LeftBoundary JG @XPosMoreThanLeft LES DI,XPos MOV [ES:DI],SI INC AL JMP @NowTestVertical @XPosMoreThanLeft: CMP BX,RightBoundary JL @NowTestVertical LES SI,Xpos MOV [ES:SI],DI INC AL @NowTestVertical: LES BX,Ypos MOV BX,[ES:BX] CMP BX,TopBoundary JG @YPosMoreThanTop LES DI,Ypos MOV [ES:DI],CX MOV AL,1 JMP @Finito @YPosMoreThanTop: CMP BX,BottomBoundary JL @Finito LES DI,YPos MOV [ES:DI],DX MOV AL,1 @Finito: LES DI,DidWrap MOV [ES:DI],AL End; Procedure AddLaser(LaserToAdd: Laser); Var VacantLaserNumber: byte; LaserCount: byte; Begin If LaserRec[LastLaserIndex].LaserType = LaserFree Then VacantLaserNumber:=LastLaserIndex Else Begin VacantLaserNumber:=$FF; For LaserCount:=1 to MaxLasers do Begin If LaserRec[LaserCount].LaserType = LaserFree Then Begin VacantLaserNumber:=LaserCount; LaserCount:=MaxLasers; End; End; End; If VacantLaserNumber <> $FF Then Begin Inc(LasersFired); LaserRec[VacantLaserNumber]:=LaserToAdd; End; End; Procedure DoFireRoutine(ShipNo:byte); Var TAngle: word; Begin If LasersFired <> MaxLasers Then With PlayerRec[ShipNo] do Begin TempLaser.LaserType:=CurrentLaserType; TempLaser.FiredBy:=ShipNo; If AssFiring Then Begin TempLaser.LaserX:=PlayerX-Round(QCos[PlayerAngle] * 6); TempLaser.LaserY:=PlayerY-Round(QSin[PlayerAngle] * 6); TAngle:=PlayerAngle+180; Asm MOV AX,TAngle CMP AX,360 JB @NoReset SUB AX,360 @NoReset: MOV Tangle,AX End; TempLaser.LaserAngle:= TAngle; End Else Begin Templaser.LaserX:=PlayerX+Round(QCos[PlayerAngle] * 6); Templaser.LaserY:=PlayerY+Round(QSin[PlayerAngle] * 6); Templaser.LaserAngle:= PlayerAngle; End; { Make sure you know who fired the laser } TempLaser.LaserColour:=PlayerColour; TempLaser.LaserPower:=CurrentLaserPower; TempLaser.LaserSize:= PlayerLaserSize; TempLaser.LaserSpeed:=CurrentLaserSpeed; TempLaser.MaxLaserTravel:=CurrentMaxLaserTravel; AddLaser(TempLaser); Dec(PlayerScore,DeductionForShooting); If PlayerScore < 0 Then PlayerScore:=0; End; End; Procedure AlterShip(ShipNo:byte;UpKey,DownKey,LeftKey,RightKey,FireKey:boolean); Var DiscardedVar: boolean; TempKey: boolean; Begin With PlayerRec[ShipNo] do Begin If UpKey Then Begin Thrusting:=True; If WaitCount > 1 Then Dec(WaitCount); End Else Begin Thrusting:=False; If WaitCount < MaxWaitCount Then Inc(WaitCount) Else Begin Dec(RechargeTime); If (RechargeTime = 0) And (PlayerEnergy < MaxPlayerEnergy) And (PlayerScore >= RechargeDeduction) Then Begin RechargeTime:=RechargeLatch; Inc(PlayerEnergy); Dec(PlayerScore, RechargeDeduction); End; End; End; If KeyReverseTime <>0 Then Begin TempKey:=LeftKey; LeftKey:=RightKey; RightKey:=TempKey; End; If LeftKey Then Begin Dec(PlayerAngle,ShipTurnAngle); If PlayerAngle <1 Then Inc(PlayerAngle,360); End; If RightKey Then Begin Inc(PlayerAngle,ShipTurnAngle); If PlayerAngle > 359 Then Dec(PlayerAngle,360); End; { Has the player held down the fire button. } If FireKey Then Begin If (DisableTime=0) Then Begin If AutoFire Then Begin If FireDelay = 0 Then Begin FireDelay:=FireLatch; DoFireRoutine(ShipNo); End Else Dec(FireDelay); End Else If FireKeyReleased Then Begin FireKeyReleased:=False; DoFireRoutine(ShipNo); End; End; End Else FireKeyReleased:=True; If WaitCount <> MaxWaitCount Then Begin Inc(PlayerWait); If PlayerWait >= WaitCount Then Begin PlayerWait:=0; Inc(PlayerX, Round(Qcos[PlayerAngle]*PlayerSpeed)); Inc(PlayerY, Round(QSin[PlayerAngle]*PlayerSpeed)); CheckBounds(PlayerX,PlayerY,PlayerWraps,DiscardedVar); End; End; End; End; Procedure UpDatePlayersSpin(PlayerNo:byte); Var DiscardedVar: boolean; Begin With PlayerRec[PlayerNo] do Begin Inc(PlayerAngle,ShipTurnAngle SHL 3); If PlayerAngle > 359 Then Dec(PlayerAngle,360); Inc(PlayerX, Round(Qcos[SpinAngle]*SpinSpeed)); Inc(PlayerY, Round(QSin[SpinAngle]*SpinSpeed)); CheckBounds(PlayerX,PlayerY,PlayerWraps,DiscardedVar); End; End; {$IFNDEF BONUSES} Procedure UpDateBonusTimer(PlayerNo:byte); Begin { Shields } With PlayerRec[PlayerNo] do If InvulnerableTime <>0 Then Begin Dec(InvulnerableTime); If InvulnerableTime = 0 Then Begin PlayerMessage:='SHIELDS DOWN!'; MessageTime:=NormalMessageTIme; EnemyLaserHurts:=True; End; End; End; {$ELSE} Procedure UpdateBonusTimers(PlayerNo:byte); Begin With PlayerRec[PlayerNo] do Begin { Firing } If DisableTime <>0 Then Begin Dec(DisableTime); If DisableTime = 0 Then Begin PlayerMessage:='I CAN SHOOT AGAIN!'; MessageTime:=NormalMessageTime; End; End; { Slothfullness } If SlowedDownTime <>0 Then Begin Dec(SlowedDownTime); If SlowedDownTime = 0 Then PlayerSpeed:=NormalPlayerSpeed; End; { Key reversing, i.e. press key for left and you go right } If KeyReverseTime <>0 Then Dec(KeyReverseTime); { Shields } If InvulnerableTime <>0 Then Begin Dec(InvulnerableTime); If InvulnerableTime = 0 Then Begin PlayerMessage:='SHIELDS DOWN!'; MessageTime:=NormalMessageTIme; EnemyLaserHurts:=True; End; End; { Toody's special bonus } If BanzaiTime <> 0 Then Begin Dec(BanzaiTime); If BanzaiTime = 0 Then Begin PlayerMessage:='TOODY''S POWER GONE!'; MessageTime:=NormalMessageTime; End; End; End; End; {$ENDIF} { You have to check the player's status byte to determine whether or not he's spinning, frozen, etc. } Procedure CheckPlayerStatusByte(PlayerNo:byte); Begin With PlayerRec[PlayerNo] Do Begin { Now service the PlayerStatus bits } If (PlayerStatus And Frozen)=Frozen Then Begin If FrozenTime > 0 Then Dec(FrozenTime) Else PlayerStatus:=PlayerStatus And (255-Frozen); End; If (PlayerStatus And Spinning)=Spinning Then Begin Dec(SpinCount); If SpinCount <>0 Then UpdatePlayersSpin(PlayerNo) Else Begin PlayerStatus:= ShootAble; WaitCount:=MaxWaitCount; End; End Else If PlayerStatus = Exploding Then Begin Inc(ExplodeWidth,5); If ExplodeWidth >= MaxExplodeWidth Then Begin PlayerStatus:= Dead; Dec(PlayersAlive); End; End Else If PlayerStatus = Warping Then Begin Dec(ExplodeWidth,5); If ExplodeWidth <=5 Then PlayerStatus:=ShootAble; End; End; End; { Update the player's ships. PlayerStatus is a combination of BIT FLAGS which indicate to the program the current player status. Doh! If bit 0 of PlayerStatus is set then the player is still ShootAble. (i.e. Alive) If bit 1 of PlayerStatus is set then the player is Warping. If bit 2 of PlayerStatus is set then the player is Exploding. If bit 3 of PlayerStatus is set then the Player is Spinning. If bit 4 of PlayerStatus is set the player is Frozen. Bits 5 - 7 are undefined and should stay that way for now. } Procedure MoveShips; Var PlayerCount: byte; Begin For PlayerCount:=1 to PlayersOn do With PlayerRec[PlayerCount] do If (PlayerStatus = ShootAble) Then Begin Case PlayerCount Of 1: AlterShip(1,keydown[2],keydown[15],keydown[30],keydown[45],keydown[42]); 2: AlterShip(2,keydown[24],keydown[38],keydown[39],keydown[40],keydown[52]); 3: AlterShip(3,keydown[71],keydown[76],keydown[73],keydown[74],keydown[81]); End; {$IFNDEF BONUSES} UpdateBonusTimer(PlayerCount); {$ELSE} UpdateBonusTimers(PlayerCount); {$ENDIF} End Else CheckPlayerStatusByte(PlayerCount); End; { O.K. You've got to update the lasers (and special weapons later on, perhaps) } Procedure MoveLasers; var playercount: byte; LaserCount: byte; ItWrapped: boolean; Begin If LasersFired <>0 Then Begin For LaserCount:=1 to MaxLasers do With LaserRec[LaserCount] do Begin If LaserType<>LaserFree Then Begin Inc(LaserTravel); If LaserTravel < MaxLaserTravel Then Begin Inc(LaserX, Round(Qcos[LaserAngle]*LaserSpeed)); Inc(LaserY, Round(QSin[LaserAngle]*LaserSpeed)); CheckBounds(LaserX,LaserY, LaserType = LaserWraps,ItWrapped); If ItWrapped Then Begin Case LaserType of NormalLaser: Begin LaserType:=LaserFree; LastLaserIndex:=LaserCount; Dec(LasersFired); End; LaserRebound: LaserAngle:=Random(359); End; End; End Else Begin LaserType:=LaserFree; Dec(LasersFired); LastLaserIndex:=LaserCount; End; End; End; End; End; {$IFDEF BONUSES} { The Bonuses are not player controlled (of course) so therefore the MoveBonuses routine should initiate some bonuses as well as move them. How will the CPU know when to initiate bonuses? Well as you know, it can't so It'll have to be a purely random thingie. } Procedure MoveBonuses; Var BonusCount: byte; SearchCount: byte; BonusDidWrap: boolean; Begin If BonusesOnScreen <>0 Then For BonusCount:=1 to MaxBonuses do With BonusRec[BonusCount] do If BonusType <>0 Then Begin Inc(BonusX,BonusXIncrement); Inc(BonusY,BonusYIncrement); CheckBounds(BonusX,BonusY,true,BonusDidWrap); End; { Of course, some bonuses just have to be initialised as well ! } If (BonusesOnScreen <= MaxBonuses) And (Random(80)=40) Then Begin SearchCount:=1; Repeat With BonusRec[SearchCount] do If BonusType = 0 Then Begin Inc(BonusesOnScreen); BonusType:=1+(Random(NumberOfBonuses)); BonusX:=Random(319); Case Random(3) of 0..1: BonusY:=-1; 2..3: BonusY:=200; End; Case Random(3) of 0..1: BonusXIncrement:=-1; 2..3: BonusXIncrement:=1; End; Case Random(3) of 0..1: BonusYIncrement:=-1; 2..3: BonusYIncrement:=1; End; SearchCount:=MaxBonuses; End; Inc(SearchCount); Until SearchCount > MaxBonuses; End; End; {$ENDIF} Function Collision(X1,Y1,X2,Y2:integer;DistX,DistY:word): boolean; {Assembler;} Begin Collision:=(Abs(X2-X1) < DistX) And (Abs(Y2-Y1) < DistY) End; {=================================================================== Guess what this routine does ? } Procedure UpdatePlayerScore(PlayerNo: byte; HowManyPoints: integer); Begin With PlayerRec[PlayerNo] do Begin Inc(PlayerScore,HowManyPoints); If PlayerScore > $7FFFFFFF Then PlayerScore := $7FFFFFFF; End; End; {===================================================== I'm gonna have to optimize this one day.. For now tho' I'll leave it as it is so that the B.Sc chaps can suss what's happening.. } Procedure DoPlayerToLaser; Var PlayerCount: byte; LaserCount: byte; Object1X: integer; Object2X: integer; Object1Y: integer; Object2Y: integer; TempLaserPower: byte; PersonWhoShot: byte; Begin If LasersFired <>0 Then For PlayerCount:=1 to PlayersOn do With PlayerRec[PlayerCount] do If ((PlayerStatus AND Shootable)<>0) Then Begin Object2X:=PlayerX; Object2Y:=PlayerY; For LaserCount:=1 to MaxLasers do If (LaserRec[LaserCount].LaserType <> LaserFree) Then Begin With LaserRec[LaserCount] do Begin Object1X:=LaserX; Object1Y:=LaserY; End; If Collision( Object1X,Object1Y, Object2X,Object2Y,8,8) Then Begin PersonWhoShot:=LaserRec[LaserCount].FiredBy; With PlayerRec[PersonWhoShot] do Begin Inc(PlayerScore,PointsForShooting); If Playerscore > $7FFFFF Then PlayerScore:= $7fffff; End; { Player has been hit so make the missile whack into the ships side and disappear } With PlayerRec[PlayerCount] do If (InvulnerableTime <>0) Then LaserRec[LaserCount].LaserAngle:=Random(359) Else Begin Dec(LasersFired); LaserRec[LaserCount].LaserType:=LaserFree; TempLaserPower:=LaserRec[LaserCount].LaserPower; If LaserRec[LaserCount].Firedby <> PlayerCount Then Begin Dec(PlayerEnergy,TempLaserPower); If PlayerEnergy <= 0 Then Begin PlayerStatus:=Exploding; ExplodeWidth:=0; End; End; End; End; End; End; End; {========================================================== Guess what this does ? } Procedure SpinPlayer( PlayerBumped, PlayerWhoBumped: byte); Var SpeedVar: byte; Ratio: byte; begin With PlayerRec[PlayerBumped] do Begin PlayerStatus:=PlayerStatus OR Spinning; SpeedVar := PlayerRec[PlayerWhoBumped].WaitCount; Ratio := PlayerRec[PlayerWhoBumped].MaxWaitCount - SpeedVar; WaitCount:=SpeedVar; SpinAngle:=PlayerRec[PlayerWhoBumped].PlayerAngle; SpinSpeed:= (Ratio SHR 2)+4; SpinCount:= (Ratio SHL 1)+4; UpDatePlayersSpin(PlayerBumped); End End; { Check if two players did bump } {$IFDEF BUMPING } Procedure CheckBump(PlayerCount1, PlayerCount2 : byte); var PlayerSpeed1: byte; PlayerSpeed2: byte; Begin If (PlayerRec[PlayerCount1].PlayerStatus = Exploding) Or (PlayerRec[PlayerCount2].PlayerStatus = Exploding) Then Exit; If (PlayerRec[PlayerCount1].BanzaiTime <>0) And (PlayerRec[PlayerCount2].InvulnerableTime = 0) Then With PlayerRec[PlayerCount2] do Begin PlayerStatus:=Exploding; ExplodeWidth:=0; Message:='AARGH etc. etc. !!'; MessageTime:=NormalMessageTime; End Else Begin PlayerSpeed1:= PlayerRec[PlayerCount1].WaitCount; PlayerSpeed2:= PlayerRec[PlayerCount2].WaitCount; If (PlayerSpeed2 <= PlayerSpeed1) Then SpinPlayer(PlayerCount1,PlayerCount2) Else UpdatePlayerScore(PlayerCount1,PointsForBumping); End; End; {$ENDIF} {$IFDEF BUMPING} Procedure DoPlayerToPlayer; Var PlayerCount1: byte; PlayerCount2: byte; Object1X: integer; Object2X: integer; Object1Y: integer; Object2Y: integer; Begin For PlayerCount1:=1 to PlayersOn do If (PlayerRec[PlayerCount1].PlayerStatus AND Shootable = ShootAble) Then Begin With PlayerRec[PlayerCount1] do Begin Object1X:=PlayerX; Object1Y:=PlayerY; End; { Check if the two ships have bumped into each other. Not too keen on what I wrote for this part but it works. As I said when me B.Sc is finished this part will be upgraded. } For PlayerCount2:=1 to PlayersOn do If (PlayerRec[PlayerCount2].PlayerStatus And Shootable = Shootable) And (PlayerCount1 <> PlayerCount2) Then Begin { Check if a collision has occurred. } With PlayerRec[PlayerCount2] do Begin Object2X:=PlayerX; Object2Y:=PlayerY; End; { Bumping? } If Collision(Object1X,Object1Y,Object2X,Object2Y,12,12) Then Begin CheckBump(PlayerCount1, PlayerCount2); CheckBump(PlayerCount2, PlayerCount1); End; End; End; End; {$ENDIF} Procedure Warp(PlayerNo:byte); Begin With PlayerRec[PlayerNo] do Begin PlayerStatus:=Warping; ExplodeWidth:=MaxExplodeWidth; PlayerAngle:= Random(359); PlayerX:=Random(319); PlayerY:=Random(199); End; End; {$IFDEF BONUSES} Procedure DoPlayerToBonuses; Var PlayerCount: byte; BonusCount: byte; OtherCount: byte; Object1X: integer; Object2X: integer; Object1Y: integer; Object2Y: integer; Begin For PlayerCount:=1 to PlayersOn do If (PlayerRec[PlayerCount].PlayerStatus And Shootable) = Shootable Then Begin With PlayerRec[PlayerCount] do Begin Object1X:=PlayerX; Object1Y:=PlayerY; End; For BonusCount:=1 to MaxBonuses do If (BonusRec[BonusCount].BonusType <>0 ) Then Begin With BonusRec[BonusCount] do Begin Object2X:=BonusX; Object2Y:=BonusY; End; If collision( Object1X,Object1Y, Object2X,Object2Y,12,12) Then With BonusRec[BonusCount] do Begin If BonusType = UnknownBonus Then BonusType:= Random(NumberOfBonuses-2)+1; Case BonusType Of SlowDownBonus: begin With PlayerRec[PlayerCount] do Begin Inc(PlayerScore,SlowDownBonusPointsValue); {$IFDEF MESSAGES} PlayerMessage:='PICKED UP A SLOWDOWN BONUS !'; MessageTime:=NormalMessageTime; {$ENDIF} End; For OtherCount:=1 to PlayersOn do If OtherCount <> PlayerCount Then With PlayerRec[OtherCount] do Begin If PlayerSpeed <>SlowestPlayerSpeed Then Dec(PlayerSpeed); Inc(SlowedDownTime,MaxSlowedDownTime); End; End; EnergyBonus: With PlayerRec[PlayerCount] do Begin Inc(PlayerScore,EnergyBonusPointsValue); Inc(PlayerEnergy,EnergyIncrement); If PlayerEnergy >MaxPlayerEnergy Then Begin PlayerEnergy:=MaxPlayerEnergy; {$IFDEF MESSAGES} PlayerMessage:='I DIDN''T NEED THE ENERGY !'; MessageTime:=NormalMessageTime; {$ENDIF} {$IFDEF MESSAGES} End Else If PlayerEnergy <= EnergyIncrement Then Begin PlayerMessage:='ENERGY JUST IN TIME, TOO !'; MessageTime:=NormalMessageTime; End Else Begin PlayerMessage:='PICKED UP AN ENERGY BONUS !'; messageTime:=NormalMessageTime; End; {$ENDIF} End; FreezeBonus: Begin With PlayerRec[PlayerCount] do Begin Inc(PlayerScore,FreezeBonusPointsValue); {$IFDEF MESSAGES} PlayerMessage:='PICKED UP A FREEZE BONUS !'; MessageTime:=NormalMessageTime; {$ENDIF} End; For OtherCount:=1 to PlayersOn do If OtherCount <> PlayerCount Then With PlayerRec[OtherCount] do Begin PlayerStatus:=PlayerStatus OR Frozen; Inc(FrozenTime,MaxFrozenTime); WaitCount:=MaxWaitCount; End; End; ReverseBonus: Begin With PlayerRec[PlayerCount] do Begin Inc(PlayerScore,ReverseBonusPointsValue); {$IFDEF MESSAGES} PlayerMessage:='PICKED UP A REVERSE BONUS !'; MessageTime:=NormalMessageTime; {$ENDIF} End; For OtherCount:=1 to PlayersOn do If OtherCount <> PlayerCount Then With PlayerRec[OtherCount] do Begin Inc(KeyReverseTime,MaxKeyReverseTime); PlayerMessage:='OH NO! KEYS ARE REVERSED !'; MessageTime:=NormalMessageTime; End; End; DisableBonus: Begin With PlayerRec[PlayerCount] do Begin Inc(PlayerScore,DisableBonusPointsValue); {$IFDEF MESSAGES} PlayerMessage:='PICKED UP A DISABLE BONUS !'; MessageTime:=NormalMessageTime; {$ENDIF} End; For OtherCount:=1 to PlayersOn do If OtherCount <> PlayerCount Then Inc(PlayerRec[OtherCount].DisableTime,MaxDisableTime); End; InvulnerabilityBonus: Begin With PlayerRec[PlayerCount] do Begin EnemyLaserHurts:=False; InvulnerableTime:=MaxInvulnerableTime; Inc(PlayerScore,InvulnerabilityBonusPointsValue); {$IFDEF MESSAGES} PlayerMessage:='YEAH! I AM INVULNERABLE !'; MessageTime:=NormalMessageTime; {$ENDIF} End; End; AssFiringBonus: Begin With PlayerRec[PlayerCount] do Begin Inc(PlayerScore,AssFiringBonusPointsValue); {$IFDEF MESSAGES} PlayerMessage:='PICKED UP AN Ass FIRING BONUS !'; MessageTime:=NormalMessageTime; {$ENDIF} End; For OtherCount:=1 to PlayersOn do If OtherCount <> PlayerCount Then With PlayerRec[OtherCount] do Begin AssFiring:=True; End; End; NormalBonus: Begin With PlayerRec[Playercount] do Begin DisableTime:=1; KeyReverseTime:=1; SlowedDownTime:=1; PlayerSpeed:=NormalPlayerSpeed; CurrentLaserType:=NormalLaser; AssFiring:=False; Inc(PlayerScore,NormalBonusPointsValue); {$IFDEF MESSAGES} PlayerMessage:='PICKED UP A NORMALITY BONUS.'; MessageTime:=NormalMessageTime; {$ENDIF} End; End; ToodysBonus: Begin With PlayerRec[PlayerCount] do begin Inc(BanzaiTime,MaxBanzaiTime); Inc(PlayerScore,ToodysBonusPointsValue); {$IFDEF MESSAGES} PlayerMessage:='BANZAI THE OTHER PLAYERS !'; MessageTime:=MaxBanzaiTime; {$ENDIF} End; For OtherCount:=1 to PlayersOn do If OtherCount <> PlayerCount Then With PlayerRec[OtherCount] do Begin {$IFDEF MESSAGES} PlayerMessage:='DO NOT BUMP PLAYER '+chr(48 + PlayerCount)+' !'; MessageTime:=MaxBanzaiTime; {$ENDIF} End End; LaserBonus: Begin With PlayerRec[PlayerCount] do If CurrentLaserPower < MaxLaserPower Then Begin Inc(CurrentlaserPower); Inc(PlayerScore,LaserBonusPointsValue); {$IFDEF MESSAGES} PlayerMessage:='LASERS ENHANCED !'; MessageTime:=NormalMessageTime; {$ENDIF} End Else Begin PlayerMessage:='WRAP AROUND LASERS !'; CurrentLaserType:=LaserWraps; MessageTime:=NormalMessageTime; End; End; WarpBonus: With PlayerRec[PlayerCount] do Begin Warp(PlayerCount); Inc(PlayerScore,WarpBonusPointsValue); {$IFDEF MESSAGES} PlayerMessage:='WARPING !'; MessageTime:=NormalMessageTime; {$ENDIF} End; BounceLaserBonus: With PlayerRec[PlayerCount] do Begin CurrentLaserType:= LaserRebound; {$IFDEF MESSAGES} PlayerMessage:='OOH! BOUNCY LASERS!'; MessageTime:=NormalMessageTime; {$ENDIF} End; End; { Indicate bonus has been taken } BonusRec[BonusCount].BonusType:=0; Dec(BonusesOnScreen); End; End; End; End; {$ENDIF} Procedure DoCollisions; Begin DoPlayerToLaser; {$IFDEF BUMPING} DoPlayerToPlayer; {$ENDIF} {$IFDEF BONUSES} DoPlayerToBonuses; {$ENDIF} End; Begin LoadGraphics; If (PlanetSeg <>0) And (titleBitmapSeg<>0) And (EmporerSeg<>0) And (ScratchSeg<>0) Then Begin Repeat InitVGAMode; SetAllPalette(titleBitmapPalette); SetUpPlayers; SetAllPalette(DestroyerPalette); SetPalette(253,63,63,63); SetPalette(254,63,0,0); SetPalette(255,63,63,0); HookKeyboardInt; SelectFont(1); Repeat BitmapCopy(PlanetSeg,PlanetOfs); DrawPlayerStuff; DrawLasers; {$IFDEF BONUSES} DrawBonuses; {$ENDIF} Vwait(1); CopySourceBitmap ; MoveShips; MoveLasers; {$IFDEF BONUSES} MoveBonuses; {$ENDIF} DoCollisions; delay(1); Until (keydown[1]) or (PlayersAlive <= 1); { back to normal crap DOS key reading } UnHookKeyboardInt; If PlayersAlive <= 1 Then Begin Memw[$0040:$1a]:=Memw[$0040:$1c]; SetAllPalette(EmporerPalette); BitMapCopy(EmporerSeg,EmporerOfs); SelectFont(6); SetColour(255); { El snido messago (Adjust to suit your peer group) } Case Random(20) of 0: Message:='Even Paul Langa has scored more !'; 1: Message:='Stop drinking and you''ll shoot better !'; 2: Message:='Next time, press the fire button !'; 3: Message:='Are you sure that you weren''t cheating ?'; 4: Message:='Come in and meet my daughter, son!'; 5: Message:='Next time SHOOT the other players !!'; 6: Message:='Would you like to see my puppies ?'; 7: Message:='Ian Makin has eyebrows just like these !'; 9: Message:=''; 10: Message:='What a waste of good hard disk space !'; 11: Message:='Does your maw know you''re here ?'; 12: Message:='I bet you''re one of Tunstall''s mates !'; 13: Message:='Your performance was pure f***ing crap !'; 14: Message:='Come up and see my etchings, young man !'; 15: Message:='You sure did kick some ass out there !'; 16: Message:='I bet you drink Carling Black Label !'; 17: Message:='Err... I love you.'; 18: Message:='I never liked Dune that much anyway !'; 19: Message:='Your mum looks like Yoda from Star Wars !'; 20: Message:='I''m buying the rounds tonight son !'; End; OutTextXY( ((40 - Length(Message))DIV 2) *8,160,Message); CopySourceBitmap ; Delay(2000); Memw[$0040:$1a]:=Memw[$0040:$1c]; TempKey:=ReadKey; End; Until Keydown[1]; { Until key is definitely ESC } { Right, deallocate the memory required for the game & virtual screens. } FreeBitmap(PlanetSeg,PlanetOfs); FreeBitmap(titleBitmapSeg,TitleBitmapOfs); FreeBitmap(EmporerSeg, EmporerOfs); FreeBitmap(ScratchSeg,ScratchOfs); End Else Begin Writeln; Writeln('Memory allocation error! 400K bytes free on heap needed.'); End; End. { I love you all !!! ;) }