[Back to MISC SWAG index] [Back to Main SWAG index] [Original]

    {
    ========================================================

           EARTH INVADERS (Original LCD game by CGL 1982..)
           (I feel a copyright wangle coming on - NOT!)

    --------------------------------------------------------

    PC CONVERSION EXCLUSIVELY FOR SWAG, BY SCOTT TUNSTALL 1996
       (But why? ;) )

    Reqs: Turbo Pascal 5.5 +
          CGA
          Good technique in chatting up women

    ==========

    DISCLAIMER

    ----------

    I (Scott Tunstall) am not responsible if this program causes any
    damage to ANY hardware or software part of the computer system it
    runs on or detriment to mental health caused (finding any bugs I
    may have missed) OK?.

    You can alter/delete or even ADD (if you're sad enough) new bits
    to the program just as long as I am credited with the ORIGINAL
    version. You are not permitted to distribute the original or
    changed code for monetary gain however.

    ========

    FORENOTE

    --------

    I was playing a hand held LCD game one saturday and it was actually
    simple to play, yet quite addictive. Unusual for a hand held.

    Anyway, being the sad idiot that I am, I decided to convert it to
    Pascal, and give y' all a taste of the game. Hope you enjoy playing
    it, I certainly almost did ! (in between debugging)

    ========

    THE GAME

    --------

    Aliens appear on the screen, you must dig holes for them to fall in.
    If an alien falls in you must bury it in the hole, but beware! If
    an alien touches an alien in a hole it is helped out and will jump
    at the human!!!

    Maybe, I will write a two player version of this game. After the Bsc,
    perhaps?.

    Keys are (until I write a define key routine)

    CTRL = Dig hole
    ALT  = Fill hole in (to kill an alien you do this)

    CURSOR UP    = Move up
    CURSOR DOWN  = Move down
    CURSOR LEFT  = Move left
    CURSOR RIGHT = Move right

    Err... your guy is represented by a 'x' and the aliens are all 's (until
    I actually draw up some GFX! (Knowing me - NEVER!).

    Hell, what do you want from me, SVGA? ;^)

    =============

    FOR YOU TO DO

    -------------

    Add a title screen
    Better sound (even samples)
    Check if all aliens are dead
    2/3/4 player mode
    A lager drinking section.... (please! I've always wanted to see a game
                                  with this in it!)

    =====

    NOTES

    -----

    NewKbdInt (The Multiple key reader) is appended to the bottom of
    this source so it can be compiled. I didn't write it - Lou Duchez
    did. Credits to him....

    }

    uses crt, nwkbdint;     { Present in the SWAG }

    {

    All objects are mapped directly to the map,
    no external data types are used to contain Aliens X,Y coordinates

    0 = Empty
    1 = Wall
    2 = Human
    3 = Quarter Dug Hole 1
    4 = Half Dug Hole 2
    5 = Three Quarter Dug Hole 3
    6 = Fully Dug Hole

    20..40 = Alien (In various stages of falling.. 40 = Not inhole)
    }

    const Empty               = 0;
          Wall                = 1;
          Human               = 2;
          QuarterDugHole      = 3;
          HalfDugHole         = 4;
          ThreeQuarterDugHole = 5;
          FullyDugHole        = 6;

          AlienFilledIn         = 19;
          AlienCompletelyBuried = 30;
          AlienBeginsClimbOut   = 36;
          AlienAlmostBuried     = 40;
          AlienHalfBuried       = 50;
          NormalAlien           = 70;
          AlienTripped          = NormalAlien-5;

          Amateur             = 1;
          Pro                 = 2;
          Kamikaze            = 3;  { Not implemented, Pro is hard enough! }

          UpKey               = 72;
          DownKey             = 80;
          LeftKey             = 75;
          RightKey            = 77;
          DigKey              = 29;
          FillKey             = 56;

    var map         : array[1..7,1..5] of byte;    { Playfield }
        killedplayer  : boolean;
        SkillLevel  : byte;
        GameLevel   : byte;
        GameSpeed   : byte;
        AlienPause  : byte;

        HumanX, HumanY : byte;
        Currx,Curry : byte;

    type AlienInfo      = record
         AlienState     : byte;
         AlienX, AlienY : byte;
         end;

    {
    The following values are written to the map, the values contained
    may be:

    0 = Empty
    1 = Wall
    2 = Human
    3 = Quarter Dug Hole 1
    4 = Half Dug Hole 2
    5 = Three Quarter Dug Hole 3
    6 = Fully Dug Hole

    20 + = Reserved for aliens, see constants above

    Therefore, if map[1,1] was 3 then that means a Quarter Dug hole
    is at the top left of the map.

    }

    procedure initmap;
    var x:byte;
        y:byte;

    begin
         {
         Erase all of map. If you're sad enough, like me, then you
         could design small maps, or even extend 'em to fill the
         entire screen.
         }

         for y:=1 to 5 do
             for x:=1 to 7 do
             map[x,y]:=empty;

         {
         Set Walls
         }

         for x:=1 to 3 do
             begin
             map[x *2,2]:=Wall;
             map[x *2,4]:=Wall;
         end;

         {
         Determine game speed
         }

         case SkillLevel of
         Amateur  : GameSpeed:=6;
         Pro      : GameSpeed:=2;    { Life expectancy - 3 seconds }
         Kamikaze : GameSpeed:=1;    { Life expectancy - NIL! }
         end;

         AlienPause:=GameSpeed;

         {
         Now place aliens
         }

         for x:=1 to 3 do
             map[x*2,1]:=NormalAlien;

         if gamelevel > 1 then
            begin
            map[2,3]:=NormalAlien;
            map[6,3]:=NormalAlien;
         end;

         if gamelevel > 2 then
            map[4,3]:=NormalAlien;

         {
         Place human
         }

         HumanX:=4;
         HumanY:=5;

         map[HumanX,HumanY]:=Human;

    end;

    { The following 2 procedures are NOT mine; they were written by
      Robert E. Swart and cut and pasted to this routine

      I modified these routines for my own use!
    }

    procedure Lines200;
        { Set 200 scanlines on VGA display }
        InLine(
          $B8/$01/$00/  {  mov   AX,$0001  }
          $CD/$10/      {  int   $10       }
          $B8/$00/$12/  {  mov   AX,$1200  }
          $B3/$30/      {  mov   BL,$30    }
          $CD/$10);     {  int   $10       }

        procedure Font8x16;
        { Set 8x16 VGA-font on VGA display }
        InLine(
          $B8/$01/$00/  {  mov   AX,$0001  }
          $CD/$10/      {  int   $10       }
          $B8/$14/$11/  {  mov   AX,$1114  }
          $B3/$00/      {  mov   BL,0      }
          $CD/$10);     {  int   $10       }

    procedure SetCurPos(newx, newy: byte);
    begin
         currx:=newx-1;             { Conv phys to log }
         curry:=newy-1;
    end;

    { Faster than using the write command for only one char }

    procedure text(TheChar: char; TheColour: byte);
    begin
         memw[$b800: (curry * 80) + (currx SHL 1)]:=word (ord(TheChar)+(TheColour SHL 8));
    end;

    {
    ====================================================================

    Draw the game screen.

    Note: All of the aliens actually exist on map, they are not simply
    sprites overlaid on the map during draw time, so in theory you could
    fill the entire map with aliens.... Have fun!

    --------------------------------------------------------------------
    }

    procedure DrawMap;
    var x, y : byte;

    begin
         for y:=1 to 5 do
             for x:=1 to 7 do
             begin
             SetCurPos(x,y);

             case map[x,y] of
             Empty               : text(' ', BLACK);
             Wall                : text('#', BLUE);
             Human               : text('x', RED);
    AlienCompletelyBuried..
    (AlienBeginsClimbOut-1)      : text(#1, random(7) OR 1);

    AlienBeginsClimbout..
    (NormalAlien-1)              : text(#1, GREEN);

             NormalAlien         : text(#2, GREEN);
             QuarterDugHole      : text('.',LIGHTGRAY);

             HalfDugHole,
             ThreeQuarterDugHole : text('o', LIGHTGRAY);
             FullyDugHole        : text('O',LIGHTGRAY);
             end;
         end;
    end;

    {
    ==============================================================

    Free an alien that may be trapped at maybex, maybey on the map

    --------------------------------------------------------------
    }

    Procedure ReleaseAlien(maybex, maybey: byte);
    var TheObject: byte;

    begin
         if (maybex > 0) and (maybex < 8) and (maybey > 0) and (maybey < 6) then
            begin
            theObject:=map[maybex, maybey];
            if (theObject> AlienFilledIn) And
               (theobject < NormalAlien) Then
               map[maybex, maybey]:=NormalAlien;
            end;
    end;

    procedure MoveAliens;
    var AlienArray        : Array[1..10] of AlienInfo;
        x, y, TheObject   : byte;
        index             : byte;
        noblank           : boolean;
        NewDir,
        NewXp,
        NewYp,
        ObjectHit         : byte;

    begin
         dec(AlienPause);
         if AlienPause = 0 Then

         { Find all aliens on the map, and remember where they
           are so they can be moved later.
         }

             Begin
             AlienPause:=GameSpeed;

             index:=1;
             For y:=1 to 5 do
                 For x:=1 to 7 do
                     begin
                     TheObject:=map[x,y];
                     If (TheObject >=AlienCompletelyBuried) And
                        (TheObject <=NormalAlien) Then
                        With AlienArray[index] do
                        Begin
                        AlienState :=TheObject;
                        AlienX     :=x;
                        AlienY     :=y;
                        Inc(index);
                        End;

                 end;

             { Now that an array of aliens has been built up,
               move em out! Also note x is being re-used. }

             for x:=(index-1) downto 1 do
             With AlienArray[x] do
                 begin
                 if AlienState = NormalAlien Then
                    Begin

                    { An alien can free it's trapped brother }

                    releasealien(AlienX-1,AlienY);
                    releasealien(AlienX+1,AlienY);
                    releasealien(AlienX,AlienY-1);
                    releasealien(AlienX,AlienY+1);

                    {
                    =============================

                    Move alien in a direction

                    -----------------------------
                    }

                    NewDir :=random(5)+1;
                    NewXp  :=AlienX;
                    NewYp  :=AlienY;

                    case NewDir of
                    1: if newxp <> 1 then dec(newxp);
                    2: if newxp <> 7 then inc(newxp);
                    3: if newyp <> 1 then dec(newyp);
                    4: if newyp <> 5 then inc(newyp);
                    5..6: if newyp < humany then         { A wee bit of AI :) }
                          inc(newyp)
                       else
                           if newyp > humany then
                              dec(newyp);

                    end;

                    {
                    }

                    noblank:=false;
                    objecthit:=map[newxp,newyp];

                    case objecthit of
                    empty               : map[newxp, newyp]:=NormalAlien;
                    human               : killedplayer:=true;
                    QuarterDugHole      : map[newxp, newyp]:=AlienTripped;
                    HalfDugHole         : map[newxp, newyp]:=AlienHalfBuried;
                    ThreeQuarterDugHole : map[newxp, newyp]:=AlienAlmostBuried;
                    FullyDugHole        : map[newxp, newyp]:=AlienCompletelyBuried;
                    else
                        noblank:=true;
                    end;

                    {
                    Noblank, when set FALSE means the alien has moved
                    and the area where the alien was on the map shall be
                    set empty.
                    }

                    if not noblank then
                       map[AlienX, AlienY]:=Empty;

                    { I used this for debugging. I thought it was cos
                      the SWAG keyboard handler was dodgy, but it wasn't
                      - my code was !!! }

                    { gotoxy(1,24); write (chr (random(128)+32)); }

                    end
                 else
                     If AlienState < NormalAlien Then
                        Begin
                        TheObject:=Map[AlienX, AlienY];
                        Inc(TheObject,1);
                        If TheObject > NormalAlien Then
                           TheObject:=NormalAlien;

                        Map[AlienX,AlienY]:=TheObject;
                        End;
                 end;
             end;

    end;

    {
    ======================

    Guess what this does ?

    ----------------------
    }

    Procedure DigHole(holex, holey: byte);
    var TheObject: byte;

    Begin

         TheObject:=Map[holex, holey];
         If TheObject = Empty Then
            Map[HoleX,Holey]:=QuarterDugHole
         Else
             If (TheObject >= QuarterDugHole)
             And (TheObject < FullyDugHole) Then
                 Begin
                 Sound(50);
                 Delay(100);
                 NoSound;
                 Inc(Map[HoleX,HoleY]);
                 End;
    End;

    {
    ==============================

    FILL IN A HOLE / BURY AN ALIEN

    ------------------------------
    }

    Procedure FillHole(holex, holey:byte);
    Var TheObject: byte;

    Begin

         TheObject:=Map[Holex, Holey];
         If (TheObject >= QuarterDugHole) And (TheObject <= FullyDugHole) Then
            Begin
            Sound(20);
            Delay(100);
            NoSound;
            Dec(Map[HoleX, HoleY]);
            If Map[HoleX, HoleY] < QuarterDugHole Then
               Map[HoleX, HoleY]:=Empty;
            End
         Else
             If (TheObject >=AlienFilledIn) And
             (TheObject <= AlienBeginsClimbOut) Then
                Begin
                Sound(90);
                Delay(40);
                NoSound;
                Dec(Map[HoleX,HoleY],1);
                If Map[HoleX,HoleY] <= AlienFilledIn Then
                   Map[HoleX,HoleY]:=Empty;
                End;
    End;

    {
    =======================================

    Try and move the human to a new square.

    If he walks into an alien though....

    ---------------------------------------
    }

    Procedure TryMove(newx, newy: byte);
    Var TheObject: byte;

    Begin
         TheObject:=Map[NewX, NewY];
         If TheObject = Empty Then
            Begin
            Map[HumanX, HumanY]:=Empty;
            Map[NewX, NewY]:=Human;
            HumanX:=newx;
            HumanY:=newy;
            End
         Else
             If TheObject = NormalAlien Then
                killedplayer:=true;
    End;

    {
    =====================

    MOVE THE HUMAN AROUND

    ---------------------
    }

    Procedure MovePlayers;

    var currpx, currpy     : byte;
        digging, burying : boolean;

    Begin
         currpx:=humanx;
         currpy:=humany;

         digging:=false;
         burying:=false;

         if (keydown[DigKey]) then
            digging:=true
         else
             if (keydown[FillKey]) then
                burying:=true;

         if keydown[UpKey] and (currpy <>1) then
            begin
            if digging or burying then
               begin
               if digging then
                  dighole(currpx, currpy-1)
               else
                   fillhole(currpx, currpy-1);
               end
            else
                trymove(currpx,currpy-1);
            end
         else
             if keydown[DownKey] and (currpy <>5) then
                begin
                if digging or burying then
                   begin
                   if digging then
                      dighole(currpx, currpy+1)
                   else
                       fillhole(currpx, currpy+1);
                   end
                else
                    trymove(currpx,currpy+1);
                end
             else
                 if keydown[LeftKey] and (currpx <>1) then
                    begin
                    if digging or burying then
                       begin
                       if digging then
                          dighole(currpx-1, currpy)
                       else
                           fillhole(currpx-1, currpy);
                       end
                    else
                        trymove(currpx-1,currpy);
                    end
                 else
                     if keydown[RightKey] and (currpx <>7) then
                        begin
                        if digging or burying then
                           begin
                           if digging then
                              dighole(currpx+1, currpy)
                           else
                               fillhole(currpx+1, currpy);
                           end
                        else
                            trymove(currpx+1,currpy);
                        end;
    end;

    begin
         randomize;
         skilllevel:=amateur;
         gamelevel:=1;

         initmap;                   { Set map up }

         Lines200;
         Font8x16;

         hookkeyboardint;

         repeat
               drawmap;

               movealiens;
               moveplayers;
               delay(125);

         until keydown[1] or killedplayer ;
         textmode(CO80);

         unhookkeyboardint;
    end.

    {
    If you actually play this game in it's unaltered state.. my commiserations!
    Contact address: CG93SAT@IBMRISC.DCT.AC.UK

    What I'd like to see more of in the SWAG are humour games... the Amiga
    has loads (cos it's a joke machine - just kidding, I own one too)

    Remember to write that lager drinking sim now ;)  !!!
    }

[Back to MISC SWAG index] [Back to Main SWAG index] [Original]