{$C-}
PROGRAM SpaceInv;

{
                      VERSION 5.1 -- By Timothy Campbell

}


TYPE
  Line       = STRING[80];
  Sprite     = STRING[7];
  SpriteType = (Base,Missle,Ufo1,Bomb1,Ufo2,Bomb2,Ufo3,Bomb3,Ufo4,Bomb4,
                Ufo5,Bomb5,Ufo6,Bomb6);
  Switch     = (Off,On);


CONST
  Blanks    = '       ';
  DelayAdj  = 3;
  DelayInit = 70;
  NumSyms   = 13;
  Shields   = ' '#176#177#178#219;
  Sprites   : ARRAY [0..NumSyms] OF Sprite =
            ( #213#209#202#209#184,
              #024,
              #017#016#174#153#175#017#016,
              #079,
              #060#243#234#242#062,
              #147,
              #174#017#016#175,
              #015,
              #017#001#016,
              #157,
              #199#002#182,
              #031,
              #233,
              'v'                      );
  Explode   : ARRAY [0..5] OF Sprite =
            ( #219#219#219#219#219#219#219,
              #178#178#178#178#178#178#178,
              #177#177#177#177#177#177#177,
              #176#176#176#176#176#176#176,
              '- - - - -',
              '       '               );

VAR
  Active    : ARRAY[0..NumSyms] OF BOOLEAN;
  ActiveCnt : BYTE;
  Beat      : INTEGER;
  BombType  : SpriteType;
  DelayTime : INTEGER;
  Explosion : BYTE;
  InChar    : CHAR;
  MisX      : BYTE;
  MisY      : BYTE;
  Move      : ARRAY[0..NumSyms] OF INTEGER;
  MoveUfo6  : BYTE;
  Noise     : BOOLEAN;
  NowX      : BYTE;
  NowY      : BYTE;
  ShieldLev : BYTE;
  RandomMod : BYTE;
  Score     : INTEGER;
  ShieldCnt : INTEGER;
  SpriteLen : BYTE;
  SprX      : BYTE;
  SprY      : BYTE;
  Thingy    : INTEGER;
  Tick      : BYTE;
  UfoTick   : BYTE;
  UfoType   : SpriteType;
  WX,WY     : BYTE;
  XPosn     : ARRAY[0..NumSyms] OF BYTE;
  YPosn     : ARRAY[0..NumSyms] OF BYTE;

FUNCTION Divis(Dv1,Dv2 : INTEGER) : BOOLEAN;
BEGIN
  IF (Dv1 DIV Dv2) * Dv2 = Dv1
  THEN Divis := TRUE
  ELSE Divis := FALSE;
END;

PROCEDURE Ce(CIn : Line);
BEGIN
  GOTOXY(((80 - LENGTH(Cin)) DIV 2),WHEREY);
  WRITELN(CIn);
END;

FUNCTION Sz(SIn : Line) : Line;
BEGIN
  Sz := Copy((SIn + Blanks),1,7);
END;

PROCEDURE DawdleJet;
VAR
  BanLoop : BYTE;
  Mult    : INTEGER;
BEGIN
  Mult   := 1;
  Thingy := 100;
  REPEAT
    Thingy := Thingy + Mult;
    IF Thingy > 4000 THEN Mult := -1;
    IF Thingy <  100 THEN Mult := 1;
    FOR BanLoop := 1 TO 5 DO
    BEGIN
      SOUND(Thingy);
      DELAY(1);
      SOUND(4200-Thingy);
      DELAY(1+RANDOM(8));
    END;
  UNTIL KEYPRESSED;
  READ(KBD,InChar);
  NOSOUND;
END;

PROCEDURE DawdleNoise;
BEGIN
  REPEAT
    SOUND(200+RANDOM(3000));
    DELAY(1+RANDOM(8));
    NOSOUND;
    DELAY(1+RANDOM(50));
  UNTIL KEYPRESSED;
  READ(KBD,InChar);
  NOSOUND;
END;

PROCEDURE Banner;
BEGIN
  CLRSCR;
  Ce('ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿');
  Ce('³  Pinnacle  Software''s  Space  Investors  Video  Game  ³     SPACEINV     ³');
  Ce('ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´');
  Ce('³  C O P Y R I G H T  (C)  1986   BY   P I N N A C L E    S O F T W A R E  ³');
  Ce('ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´');
  Ce('³ This program may be  freely distributed  so long as it is distributed in ³');
  Ce('³ its complete and unaltered form,  including this notice.                 ³');
  Ce('ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´');
  Ce('ÃÄÄÄÄÄÄÄÄÄÄÄÄ     ËÍÍ» ÍËÍ ËÍ» É ËÍ» É ÉÍÍ» ÉÍÍ» Ë    ËÍÍ»     ÄÄÄÄÄÄÄÄÄÄÄÄ´');
  Ce('ÃÄÄÄÄÄÄÄÄÄÄÄÄ     ÌÍÍ¼  º  º º º º º º ÌÍÍ¹ º    º    ÌÍ       ÄÄÄÄÄÄÄÄÄÄÄÄ´');
  Ce('ÃÄÄÄÄÄÄÄÄÄÄÄÄ     Ê    ÍÊÍ ¼ ÈÍ¼ ¼ ÈÍ¼ Ê  Ê ÈÍÍ¼ ÊÍÍ¼ ÊÍÍ¼     ÄÄÄÄÄÄÄÄÄÄÄÄ´');
  Ce('ÃÄÄÄÄÄÄÄÄÄÄÄÄ     ÉÍÍ» ÉÍÍ» ËÍÍ» ÉÍËÍ» »   É ÉÍ» ËÍÍ» ËÍÍ»     ÄÄÄÄÄÄÄÄÄÄÄÄ´');
  Ce('ÃÄÄÄÄÄÄÄÄÄÄÄÄ     ÈÍÍ» º  º ÌÍ     º   º º º ÌÍ¹ ÌÍË¼ ÌÍ       ÄÄÄÄÄÄÄÄÄÄÄÄ´');
  Ce('ÃÄÄÄÄÄÄÄÄÄÄÄÄ     ÈÍÍ¼ ÈÍÍ¼ Ê      Ê   ÈÍÊÍ¼ Ê Ê Ê È¼ ÊÍÍ¼     ÄÄÄÄÄÄÄÄÄÄÄÄ´');
  Ce('ÃÄÄÄÄÄÄÄÄÄÄÄÄ     Post Office Box 163 Cartierville Station     ÄÄÄÄÄÄÄÄÄÄÄÄ´');
  Ce('ÃÄÄÄÄÄÄÄÄÄÄÄÄ     Cartierville,  Quebec,  Canada,  H4K 2J5     ÄÄÄÄÄÄÄÄÄÄÄÄ´');
  Ce('ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ');
  WRITELN;
  Ce('Want to run a new kind of BBS?   Send us $35 and we''ll send you your copy of');
  Ce('one of Montreal''s  top BBS''s:  the Pyroto Mountain  BBS/Game system.  You''ll');
  Ce('need a 128K IBM-PC with two diskette drives and a "smart" modem.            ');
  WRITELN;
  Ce('PRESS A KEY TO CONTINUE');
  DawdleJet;
  CLRSCR;
  Ce('PINNACLE SOFTWARE PRESENTS');
  Ce('ÚÄ-Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä-Ä¿');
  Ce(')   S P A C E   I N V E S T O R S   (');
  Ce('ÀÄ-Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä=Ä-ÄÙ');
  WRITELN;
  Ce('Watch out for ...');
  WRITELN;
  Ce('THE MOTHER SHIP   ' + Sz(Sprites[ORD(Ufo1)]));
  Ce('THE BATTLE POD    ' + Sz(' '+Sprites[ORD(Ufo2)]));
  Ce('THE DRIFTER       ' + Sz(' '+Sprites[ORD(Ufo3)]));
  Ce('THE HARASSER      ' + Sz('  '+Sprites[ORD(Ufo4)]));
  Ce('THE DARE-DEVIL    ' + Sz('  '+Sprites[ORD(Ufo5)]));
  Ce('THE OBSERVER      ' + Sz('   '+Sprites[ORD(Ufo6)]));
  WRITELN;
  Ce('    The keys are used as follows...                 ');
  Ce('    F and J ..... move base left and right          ');
  Ce('    E and I ..... either key will stop base movement');
  Ce('    Spacebar .... fires a missle                    ');
  Ce('    - (minus) ... toggles sound on and off          ');
  Ce('    P ........... pauses the game                   ');
  Ce('    ESC ......... exits the game (you coward!)      ');
  WRITELN;
  Ce('*** PRESS A KEY TO START ***');
  DawdleNoise;
END;

PROCEDURE ShowScore;
BEGIN
  GOTOXY(1,25);
  WRITE('SCORE: ',Score,'   SHIELD LEVEL: ',
  Copy(Shields,1,ShieldLev),'  ');
END;

PROCEDURE Cursor(CCtl : Switch);
TYPE
  regpack =
  RECORD
    ax,bx,cx,dx,bp,di,si,ds,es,flags: INTEGER;
  END;
VAR
  recpack : regpack;
BEGIN
  WITH recpack DO
  BEGIN
    ax := $0100;
    IF CCtl = On
    THEN cx := $0CCD
    ELSE cx := $FFFF;
  END;
  INTR($10,recpack);
END;

PROCEDURE BEEP(Tone : INTEGER);
BEGIN
  IF Noise THEN SOUND(Tone);
END;

PROCEDURE SetPosn(IntST : SpriteType; IntX, IntY : BYTE);
BEGIN
  IF ((IntX = 0) AND (IntY = 0)) AND (Active[ORD(IntST)] = TRUE) THEN
  BEGIN
    Active[ORD(IntST)] := FALSE;
    ActiveCnt     := ActiveCnt - 1;
  END;
  IF ((IntX > 0) AND (IntY > 0)) THEN
  BEGIN
    IF Active[ORD(IntST)] = FALSE THEN
    BEGIN
      Active[ORD(IntST)] := TRUE;
      IF (RANDOM(100) < 33) AND (IntST IN [Ufo1,Ufo2,Ufo3,Ufo4,Ufo5,Ufo6]) THEN
      BEGIN
        Move[ORD(IntST)]   := -1;
        IntX := 80 - LENGTH(Sprites[ORD(IntST)]) - 1;
      END
      ELSE Move[ORD(IntST)]   := 1;
      ActiveCnt          := ActiveCnt + 1;
    END;
    XPosn[ORD(IntST)]  := IntX;
    YPosn[ORD(IntST)]  := IntY;
  END;
END;

PROCEDURE FindXY(FndST : SpriteType);
BEGIN
  NowX := XPosn[ORD(FndST)];
  NowY := YPosn[ORD(FndST)];
END;

{======= MOVEMENT =======}

PROCEDURE MoveX(SprTyp : SpriteType);
VAR
  OutSprite : STRING[9];
  XGo       : BYTE;
  YGo       : BYTE;
BEGIN
  OutSprite := Sprites[ORD(SprTyp)];
  SpriteLen := Length(OutSprite);
  FindXY(SprTyp);
  IF SprTyp <> Base THEN
  BEGIN
    IF (RANDOM(1000) < SpriteLen * 5)
    OR ((SprTyp = Ufo6) AND (RANDOM(100) < 5)) THEN
    BEGIN
      IF NowX < XPosn[ORD(Base)] THEN Move[ORD(SprTyp)] := 1;
      IF NowX > XPosn[ORD(Base)] THEN Move[ORD(SprTyp)] := -1;
    END;
  END;
  XGo := NowX + Move[ORD(SprTyp)];
  IF XGo < 1 THEN XGo := 1;
  IF XGo + SpriteLen > 80 THEN XGo := 80 - SpriteLen;
  SetPosn(SprTyp,XGo,NowY);
  IF SprTyp <> Base THEN
  BEGIN
    IF RANDOM(120) < ORD(SprTyp) THEN
    BEGIN
      OutSprite := COPY(Blanks,1,SpriteLen);
      IF RANDOM(100) < 33
      THEN YGo := NowY - 1
      ELSE YGo := NowY + 1;
      IF YGo < 1  THEN YGo := 1;
      IF YGo > 18 THEN YGo := 17;
      GOTOXY(NowX,YGo);
      WRITE(Sprites[ORD(SprTyp)]);
      FOR Thingy := 40 DOWNTO 5 DO BEEP(Thingy * 100);
      SetPosn(SprTyp,NowX,YGo);
    END;
  END;
  IF (XGo > 1) AND (Move[ORD(SprTyp)] > 0) THEN
  BEGIN
    XGo := XGo - 1;
    OutSprite := ' ' + OutSprite;
  END;
  IF (XGo < 80) AND (Move[ORD(SprTyp)] < 0) THEN OutSprite := OutSprite + ' ';
  GOTOXY(XGo,NowY);
  WRITE(OutSprite);
END;

PROCEDURE CheckBoom(BWep, Wnme : SpriteType; MisX, MisY : BYTE);
  BEGIN
    FindXY(Wnme);
    SpriteLen := LENGTH(Sprites[ORD(Wnme)]);
    IF (MisX IN [NowX .. (NowX + SpriteLen-1)]) AND (MisY = NowY)
    AND Active[ORD(Wnme)]
    THEN
    BEGIN
      FOR Explosion := 0 TO 5 DO
      BEGIN
        FOR Thingy := 1 TO (SpriteLen * 10) DO
        BEGIN
          DELAY(1);
          BEEP(500+RANDOM(4000 - Thingy * 50));
        END;
        GOTOXY(NowX,NowY);
        WRITE(Copy(Explode[Explosion],1,SpriteLen));
      END;
      IF BWep = Missle THEN
      BEGIN
        Score := Score + (14 - ORD(Wnme)) * 10;
        SetPosn(Wnme,0,0);
        SetPosn(Missle,0,0);
      END
      ELSE
      BEGIN
        IF Divis(Beat,3)
        THEN Move[ORD(PRED(BWep))] := Move[ORD(PRED(Bwep))] * -1;
        Score := Score - 100;
        IF Score < 0 THEN Score := 0;
        SetPosn(BWep,0,0);
        ShieldLev   := ShieldLev - 1;
      END;
      ShowScore;
    END;   { Weapon hit enemy }
  END;     { CheckBoom }


PROCEDURE MoveWeapon(WType : SpriteType);
  BEGIN
    IF Active[ORD(WType)] THEN
    BEGIN
      FindXY(WType);
      GOTOXY(NowX,NowY);
      WRITE(' ');
      IF (PRED(WType) IN [Ufo1,Ufo2]) THEN
      BEGIN
        {-- Smart Bomb --}
        IF Divis(Beat,ORD(WType)*3)
        AND Active[ORD(PRED(WType))]
        THEN
        BEGIN
          FOR Thingy := 1 TO (Score DIV 1000) DO
          BEGIN
            IF XPosn[ORD(Base)] > NowX THEN NowX := NowX + 1;
            IF XPosn[ORD(Base)] < NowX THEN NowX := NowX - 1;
          END;
        END;
      END;
      IF WType = Missle
      THEN NowY := NowY - 1
      ELSE NowY := NowY + 1;
      IF NOT (NowY IN [1..24])
      THEN SetPosn(WType,0,0)
      ELSE
      BEGIN
        BEEP(500+(ORD(WType)*RANDOM(200))+(25-NowY)*100);
        GOTOXY(NowX,NowY);
        WRITE(Sprites[ORD(WType)]);
        SetPosn(WType,NowX,NowY);
        WX := NowX;
        WY := NowY;
        IF WType = Missle
        THEN
        BEGIN
          CheckBoom(WType,Ufo1,WX,WY);
          CheckBoom(WType,Ufo2,WX,WY);
          CheckBoom(WType,Ufo3,WX,WY);
          CheckBoom(WType,Ufo4,WX,WY);
          CheckBoom(WType,Ufo5,WX,WY);
          CheckBoom(WType,Ufo6,WX,WY);
        END
        ELSE CheckBoom(WType,Base,WX,WY);
      END;     { Weapon on screen }
    END;       { Specified weapon active }
  END;


PROCEDURE MoveUfo(UfoST : SpriteType);
  BEGIN
    {--- Ufo Movement ---}
    IF Active[ORD(UfoST)] THEN
    BEGIN
      IF (Tick IN [1..7]) THEN Move[ORD(UfoST)] := Move[ORD(UfoST)] * -1;
      UfoTick := UfoTick + RANDOM(3);
      IF UfoTick > 99 THEN UfoTick := 0;
      IF Divis(UfoTick,(ORD(UfoST) DIV 2)) THEN
      BEGIN
        MoveX(UfoST);
        BEEP(ORD(UfoST) * 300);
        DELAY(1);
        SprX := NowX;
        FindXY(Base);
        {--- Drop a bomb? ---}
        IF (NOT Active[ORD(UfoST)+1])        { Not if one already dropping }
        AND
        (((Beat < LENGTH(Sprites[ORD(UfoST)])*10) AND
        (SprX IN [NowX-1,NowX,NowX+1]))      { Bigger Ufo's use good shots }
        OR
        (Beat < (Score DIV 20)))             { 100% chance at score 2000 }
        AND (NOT ((UfoST = Ufo6) AND (RANDOM(1000) < 995)))  { Rare bomber }
        THEN
        BEGIN
          BEEP(1200);
          FindXY(UfoST);
          SetPosn(SUCC(UfoST),
          (NowX+(LENGTH(Sprites[ORD(UfoST)]) DIV 2)),
          NowY+1);
        END;
        SpriteLen := LENGTH(Sprites[ORD(UfoST)]);
        FindXY(UfoST);
        IF (NowX = 1) OR ((NowX + SpriteLen) > 79) THEN
        BEGIN
          SetPosn(UfoST,0,0);
          BEEP(3500);
          GOTOXY(NowX,NowY);
          WRITE(Copy(Blanks,1,SpriteLen));
        END;
      END;   { Ufo Movement }
    END;     { Ufo Introduction }
  END;       { MoveUfo }

{======= INITIALIZATION =======}


PROCEDURE StartUp;
  VAR
    Loop1    : BYTE;

  BEGIN
    Banner;
    CLRSCR;
    ActiveCnt := 0;
    Beat      := 0;
    InChar    := '?';
    Noise     := TRUE;
    RandomMod := 0;
    Score     := 0;
    ShieldCnt := 0;
    ShieldLev := 5;
    UfoTick   := 0;
    FOR Loop1 := 0 TO NumSyms DO
    BEGIN
      Active[Loop1] := FALSE;
      Move[Loop1]   := 0;
      XPosn[Loop1]  := 0;
      YPosn[Loop1]  := 0;
    END;
    SetPosn(Base,39,24);
  END;


{======= MAINLINE =======}


BEGIN
  StartUp;
  Cursor(Off);
  ShowScore;
  REPEAT
    IF (Score DIV 1000 > ShieldCnt) AND (ShieldLev < 5)
    THEN
    BEGIN
      ShieldLev := ShieldLev + 1;
      ShieldCnt := ShieldCnt + 1;
      ShowScore;
    END;
    {--- Beats and Ticks ---}
    Tick := RANDOM(50) + RandomMod;
    IF InChar = 'F' THEN RandomMod := RandomMod + 1;
    IF RandomMod > 50 THEN RandomMod := 0;
    Beat := Beat + 1;
    IF Beat > 100 THEN Beat := 0;
    {--- Commands ---}
    IF KEYPRESSED THEN
    BEGIN
      BEEP(500);
      READ(KBD,InChar);
      InChar := UPCASE(InChar);
      CASE InChar OF
      '-' : BEGIN
              Noise := NOT Noise;
              NOSOUND;
            END;
      'F' : Move[ORD(Base)] := -1;
      'J' : Move[ORD(Base)] := 1;
      'I' : Move[ORD(Base)] := 0;
      'E' : Move[ORD(Base)] := 0;
      ' ' : BEGIN
              Score := Score - 1;
              IF Score < 0 THEN Score := 0;
              IF Active[ORD(Missle)] THEN
              BEGIN
                FindXY(Missle);
                GOTOXY(NowX,NowY);
                WRITE(' ');
              END;
              BEEP(2200);
              FindXY(Base);
              SetPosn(Missle,NowX+3,23);
            END;  { SPACE CASE }
      'P' : BEGIN
              NOSOUND;
              GOTOXY(70,1);
              WRITE('*PAUSED*');
              REPEAT UNTIL KEYPRESSED;
              READ(KBD,InChar);
              InChar := '?';
              GOTOXY(70,1);
              WRITE('        ');
            END;
      END;        { CASE }
  END;
  {--- Timing Delay ---}
  DelayTime := DelayInit - ActiveCnt * DelayAdj;
  DelayTime := DelayTime - (Score DIV 250);
  IF DelayTime < 0 THEN DelayTime := 0;
  IF Divis(Beat,10) THEN BEEP(150);
  DELAY(DelayTime);
  {--- Base Movement ---}
  MoveX(Base);
  IF (Divis(Beat,2)) AND (Move[ORD(Base)] <> 0)
  THEN BEEP(1000+NowX*10)
  ELSE NOSOUND;
  {--- Weapon Movement ---}
  MoveWeapon(Missle);
  IF ShieldLev > 0 THEN
  BEGIN
    {--- Bring in a new UFO? ---}
    UfoType := Ufo1;
    IF Beat > 10 THEN UfoType := Ufo2;
    IF Beat > 25 THEN UfoType := Ufo3;
    IF Beat > 50 THEN UfoType := Ufo4;
    IF Beat > 75 THEN UfoType := Ufo5;
    IF Beat > 90 THEN UfoType := Ufo6;
    IF ((RANDOM(1000) <= (Score DIV 100) + 15)
    OR (ActiveCnt <= 2))
    AND (Active[ORD(UfoType)] = FALSE)
    THEN SetPosn(UfoType,1,ORD(UfoType) + RANDOM(5));
    MoveWeapon(Bomb1);
    MoveUfo(Ufo1);
    MoveWeapon(Bomb2);
    MoveUfo(Ufo2);
    MoveWeapon(Bomb3);
    MoveUfo(Ufo3);
    MoveWeapon(Bomb4);
    MoveUfo(Ufo4);
    MoveWeapon(Bomb5);
    MoveUfo(Ufo5);
    MoveWeapon(Bomb6);
    FOR MoveUfo6 := 1 to 5 DO
    BEGIN
      MoveUfo(Ufo6);
    END;
  END;              { ShieldLev > 0 }
  IF ShieldLev <= 0 THEN
  BEGIN
    CLRSCR;
    WRITELN;
    WRITELN('             G A M E   O V E R  --  Score: ',Score);
    WRITELN;
    IF Noise THEN
    BEGIN
      FOR Thingy := 4 DOWNTO 1 DO
      BEGIN
        SOUND(500+Thingy * 1000);
        DELAY(500+RANDOM(5-Thingy)*80);
      END;
    END;
  END;
  UNTIL (InChar = #27) OR (ShieldLev = 0);
  NOSOUND;
  Cursor(On);
END.
