{E+,s-,n-,R-,Q-}
{$M 16384,0,655360}

Program Space_Invaders;

Uses PSE, Crt, Dos;

Var
    { variables para los sprites }
    h: char;
    ini, disparo1, exp1, exp2, exp3, exp_m1, exp_m2, exp_m3, exp_m4, c1, c2,
    nave1, nave2, title, hentai, safari, fondo, mhm, bona, tecla, sd,
    continue,scores : byte;
    n      : array [0..9] of byte;
    malo1  : array [1..7] of byte;
    malo2  : array [1..7] of byte;
    malo3  : array [1..7] of byte;
    malo4  : array [1..7] of byte;
    barrera: array [1..5] of byte;
    { variables de posicion      }
    a, x, y, z, i, j, k, l, p, s, t: integer;
    posicionx: integer;
    posiciony: integer;
    lim_i, lim_d: integer;
    puntos: integer;
    puntos2:real;
    muertos:integer;
    pix_puntos: integer;
    pix_muertos:integer;
    nivel: integer;
    total_muertos: integer;
    { variables para paleta      }
    pal: palette_buffer;
    { variables de comprobacion  }
    cont: boolean;
    ganar: boolean;
    golpe: boolean;
    salir: boolean;
    limites: boolean;
    disparo: boolean;
    dis_mal: boolean;
    ex_nave: boolean;
    regresar: boolean;
    explosion: boolean;
    minas:array [1..5] of boolean;
    malo: array [1..7,0..3] of boolean;

{----------------------=[Rutina para iniciar graficos]=----------------------}
Procedure iniciar;
          begin
          Init_PSE;                        { Iniciamos libreria grafica   }
          SetMCGA;                         { entramos al modo 13h         }
          Enable_background;
          Load_palette(pal, 'best.pal');   { Abrimos la paleta de colores }
          Set_palette(pal);
          end;
{----------------------------------------------------------------------------}

{----------------------=[Rutinas para la introduccion]=----------------------}
Procedure Fade;
    begin
         For i:= 150 downto 0 do    { Cambiamos la paleta a blanco  }
             begin                  {   y luego a negro             }
             fadeto(i,i,i);
             update_screen;
             end;
    end;

Procedure Intro;                    { Rutina de la introduccion     }
    begin
         iniciar;
         ini    := add_sprite ('01.pix',      1, 1,    0, False);
         mhm    := add_sprite ('mhm.pix',     1, 1,    0, False);
         title  := add_sprite ('title.pix',   1, 1,    1, False);
         fondo  := add_sprite ('fondo.pix',   1, 150,  0, True);
         hentai := add_sprite ('hentai.pix',  1, 1,    0, False);
         safari := add_sprite ('safari.pix',  1, 150,  0, True);
         bona   := add_sprite ('logobona.pix',1, 1,    0, False);
         tecla  := add_sprite ('tecla.pix',   100, 130,0, true);
                                     { Sprites utilizados           }
         hide_sprite (title);        { Escondemos las pantallas     }
         hide_sprite (hentai);       {   hasta necesitarlas         }
         hide_sprite (mhm);
         hide_sprite (safari);
         hide_sprite (fondo);
         hide_sprite (ini);
         hide_sprite (tecla);

         update_screen;             { Actualizamos pantalla         }
         delay(1500);
         fade;
         hide_sprite(bona);         { Escondemos el logo Bonaterra  }
         update_screen;
         show_sprite(ini);          { Entra el primer sprite        }
         set_palette(pal);          { Re-incorporamos paleta        }
         update_screen;
         delay(3000);
         hide_sprite(ini);          { Escondemos el primer sprite   }
         show_sprite(hentai);       { Entra el segundo sprite       }
         set_palette(pal);          { Re-incorporamos paleta        }
         update_screen;
         delay(2500);
         hide_sprite(hentai);       { Escondemos el 2do sprite      }
         update_screen;
         show_sprite(mhm);          { Entra el tercer sprite        }
         set_palette(pal);          { Re-incorporamos paleta        }
         update_screen;
         delay(3000);
         hide_sprite(mhm);          { Escondemos el 3er sprite      }
         update_screen;
         show_sprite(fondo);        { Metemos el cuarto sprite      }
         set_palette(pal);          { Re-incorporamos paleta        }
         For i:= 250 downto 20 do
             begin
             Move_sprite (fondo, 1, i);
             delay (30);
             Update_screen;
             end;
         fade;
         hide_sprite(fondo);        { Escondemos el 4rto sprite     }
         update_screen;
         show_sprite(title);        { Metemos el sprite de titulo   }
         Set_palette(pal);          { Re-incorporamos paleta        }
         update_screen;
         delay(1000);
         show_sprite(safari);
         For i:= 0 to 400 do
             begin
             move_sprite (safari, i, 150);
             update_screen;
             end;

         Remove_Sprite (ini);         { Quitamos los sprites que    }
         Remove_Sprite (hentai);      {   no vamos a usar mas       }
         Remove_Sprite (mhm);
         Remove_Sprite (safari);
         Remove_Sprite (bona);
         Repeat
               show_sprite (tecla);
               delay (200);
               update_screen;
               hide_sprite (tecla);
               delay (500);
               update_screen;
               until keypressed;
         h:= readkey;
         Shutdown_PSE;                { Cerramo graficos para liberar}
                                      {   memoria                    }
    end;
{----------------------------------------------------------------------------}

Procedure Opciones;                   { Rutina de las opciones      }
    begin
    end;

{----------------------=[Rutina para los creditos]=--------------------------}

Procedure Creditos;
    begin
         iniciar;
         c1      := add_sprite ('credi1.pix',     1,  1,    0, False);
         c2      := add_sprite ('credi2.pix',     1,  1,    0, False);
         sd      := add_sprite ('sd.pix',         1,  1,    0, False);
         nave2   := add_sprite ('n2.pix',         1,  1,    0, False);
         malo1[1]:= add_sprite ('m1.pix',       230, 30,    1, true);
         malo2[1]:= add_sprite ('m2.pix',       230, 30,    1, true);
         malo3[1]:= add_sprite ('m3.pix',       230, 30,    1, true);
         malo4[1]:= add_sprite ('m4.pix',       230, 30,    1, true);
         exp_m1:= add_sprite ('em1.pix', 1, 1, 0, true);
         exp_m2:= add_sprite ('em2.pix', 1, 1, 0, true);
         exp_m3:= add_sprite ('em3.pix', 1, 1, 0, true);
         exp_m4:= add_sprite ('em4.pix', 1, 1, 0, true);

         hide_sprite (exp_m1);
         hide_sprite (exp_m2);
         hide_sprite (exp_m3);
         hide_sprite (exp_m4);
         hide_sprite(c2);
         hide_sprite(nave2);
         hide_sprite(sd);

         For i:= 200 downto 1 do
             begin
             Move_sprite (c1, 1, i);
             move_sprite (malo4[1], i+180, i+80);
             move_sprite (malo3[1], i+220,  i+80);
             move_sprite (malo2[1], i+260, i+80);
             move_sprite (malo1[1], i+300, i+80);
             delay (30);
             Update_screen;
             end;

         {Fadeto(0,0,0);
         For i:= 1 to 63 do
             update_screen;}

         hide_sprite(c1);        { Escondemos el sprite de creditos }
         update_screen;
         show_sprite(c2);        { Metemos el 2do sprite de credito }
         Set_palette(pal);       { Re-incorporamos paleta           }

         For i:= 200 downto 1 do
             begin
             Move_sprite (c2, 1, i);
             delay (30);
             Update_screen;
             end;

         show_sprite(nave2);
         For i:= 1 to 60 do
             begin
             Move_sprite (nave2, i, 75);
             delay (30);
             Update_screen;
             end;

         delay(1000);
         show_sprite(sd);
         For i:= 60 to 400 do
             begin
             Move_sprite (sd, i, 75);
             update_screen;
             case i of
                    130: begin
                              hide_sprite(malo4[1]);
                              show_sprite(exp_m1);
                              move_sprite(exp_m1, 175, 80);

                              update_screen;
                              hide_sprite(exp_m1);
                              show_sprite(exp_m2);
                              move_sprite(exp_m2, 175, 80);

                              delay(15);
                              update_screen;
                              hide_sprite(exp_m2);
                              show_sprite(exp_m3);
                              move_sprite(exp_m3, 175, 80);

                              delay(15);
                              update_screen;
                              hide_sprite(exp_m3);
                              show_sprite(exp_m4);
                              move_sprite(exp_m4, 175, 80);
                              delay(15);
                              update_screen;
                              hide_sprite(exp_m4);
                         end;
                    170: begin
                              hide_sprite(malo3[1]);
                              show_sprite(exp_m1);
                              move_sprite(exp_m1, 215, 80);

                              update_screen;
                              hide_sprite(exp_m1);
                              show_sprite(exp_m2);
                              move_sprite(exp_m2, 215, 80);

                              delay(15);
                              update_screen;
                              hide_sprite(exp_m2);
                              show_sprite(exp_m3);
                              move_sprite(exp_m3, 215, 80);

                              delay(15);
                              update_screen;
                              hide_sprite(exp_m3);
                              show_sprite(exp_m4);
                              move_sprite(exp_m4, 215, 80);
                              delay(15);
                              update_screen;
                              hide_sprite(exp_m4);

                         end;
                    210: begin
                              hide_sprite(malo2[1]);
                              show_sprite(exp_m1);
                              move_sprite(exp_m1, 255, 80);
                              update_screen;
                              hide_sprite(exp_m1);
                              show_sprite(exp_m2);
                              move_sprite(exp_m2, 255, 80);

                              delay(15);
                              update_screen;
                              hide_sprite(exp_m2);
                              show_sprite(exp_m3);
                              move_sprite(exp_m3, 255, 80);

                              delay(15);
                              update_screen;
                              hide_sprite(exp_m3);
                              show_sprite(exp_m4);
                              move_sprite(exp_m4, 255, 80);
                              delay(15);
                              update_screen;
                              hide_sprite(exp_m4);
                         end;
                    250: begin
                              hide_sprite(malo1[1]);
                              show_sprite(exp_m1);
                              move_sprite(exp_m1, 295, 80);
                              update_screen;
                              hide_sprite(exp_m1);
                              show_sprite(exp_m2);
                              move_sprite(exp_m2, 295, 80);

                              delay(15);
                              update_screen;
                              hide_sprite(exp_m2);
                              show_sprite(exp_m3);
                              move_sprite(exp_m3, 295, 80);

                              delay(15);
                              update_screen;
                              hide_sprite(exp_m3);
                              show_sprite(exp_m4);
                              move_sprite(exp_m4, 295, 80);
                              delay(15);
                              update_screen;
                              hide_sprite(exp_m4);
                         end;
             end;
             end;

         For i:= 75 to 210 do
             begin
             Move_sprite (nave2, 60+i-75, i);
             delay (30);
             Update_screen;
             end;

         delay (2500);
         Shutdown_PSE;                { Cerramo graficos para liberar}
                                      {   memoria                    }
    end;
{----------------------------------------------------------------------------}

{----------------------=[Rutinas para el juego]=-----------------------------}
Procedure Choque;
          var
          p,q,r: integer;             { Variables de contadores          }

          begin
          If y=168 then               { Comprobacion de choque con minas }
                   For i:=1 to 5 do
                       for p:=1 to 16 do
                           If (z = (53*i-p)) and
                              minas [i]      then begin
                                                disparo:= false; { Desaparace el disparo }
                                                golpe:= true;    { Activa que hubo golpe }
                                                y:=182;          { Regresa el disparo    }
                                                end;
          For q:=1 to 16 do           { Comprobacion de choque con malos }
              for r:=0 to 3 do
                  If y = (k+25*r+q) then
                     For i:=1 to 7 do
                         for p:=1 to 8 do
                             If (z = ((i*40)-39+j-p)) or
                                (z = ((i*40)-39+j+p)) then
                                If malo [i,r] then begin
                                              malo [i,r]:= false;
                                              case r of
                                                   0: hide_sprite (malo4[i]);
                                                   1: hide_sprite (malo3[i]);
                                                   2: hide_sprite (malo2[i]);
                                                   3: hide_sprite (malo1[i]);
                                                   end;
                                              case r of
                                                   0: Inc (puntos,400);
                                                   1: Inc (puntos,200);
                                                   2: Inc (puntos,100);
                                                   3: Inc (puntos,50 );
                                                   end;
                                              explosion:= true;
                                              disparo:= false;
                                              golpe:= true;
                                              Inc (muertos);
                                              posicionx:= (i*40)-39+j-p;
                                              posiciony:= (k+25*r);
                                              y:=182;
                                              break;
                                              end;
          For q:=1 to 16 do
              for r:=0 to 3 do
                  If (k+25*r+q) = 150 then
                     for i:=1 to 7 do
                         for p:=1 to 5 do
                             If malo [i,r] and
                                minas [p]  then begin
                                           malo [i,r]:= false;
                                           case r of
                                                0: hide_sprite (malo4[i]);
                                                1: hide_sprite (malo3[i]);
                                                2: hide_sprite (malo2[i]);
                                                3: hide_sprite (malo1[i]);
                                                end;
                                           explosion:= true;
                                           golpe:= true;
                                           Inc (muertos);
                                           posicionx:= (i*40)-39+j;
                                           posiciony:= (k+25*r);
                                           break;
                                           end;
          end;

Procedure exp_nave;
          begin
          move_sprite (exp1,x,182);
          show_sprite (exp1);
          update_screen;
          delay (150);
          hide_sprite (exp1);
          move_sprite (exp2,x,182);
          show_sprite (exp2);
          update_screen;
          delay (150);
          hide_sprite (exp2);
          move_sprite (exp3,x,182);
          show_sprite (exp3);
          update_screen;
          delay (150);
          hide_sprite (exp3);
          end;

Procedure otro_choque;
          var
          p,q,r: integer;

          begin
          If s=150 then               { Comprobacion de choque con minas }
             For i:=1 to 5 do
                 for p:=1 to 8 do
                      If ((t = (53*i-p)) or
                         (t = (53*i+p))) and
                         minas [i]       then begin
                                              dis_mal:= false; { Desaparace el disparo }
                                              golpe:= true;    { Activa que hubo golpe }
                                              end;
          For i:= 182 to 200 do
              If s=i then
                 for p:= x to x+18 do
                     If t= p then begin
                                  hide_sprite (nave1);
                                  ex_nave:= true;
                                  salir:= true;
                                  end;

          end;


Procedure explosiones;
          begin
          Inc (l);
          case l of
               1: begin
                  move_sprite (exp_m1,posicionx,posiciony);
                  show_sprite (exp_m1);
                  end;
               2: begin
                  hide_sprite (exp_m1);
                  move_sprite (exp_m2,posicionx,posiciony);
                  show_sprite (exp_m2);
                  end;
               3: begin
                  hide_sprite (exp_m2);
                  move_sprite (exp_m3,posicionx,posiciony);
                  show_sprite (exp_m3);
                  end;
               4: begin
                  hide_sprite (exp_m3);
                  move_sprite (exp_m4,posicionx,posiciony+6);
                  show_sprite (exp_m4);
                  end;
               5: begin
                  hide_sprite (exp_m4);
                  explosion:= false;
                  l:=0;
                  end;
               end;
          end;

Procedure disparos;
          var
          a: integer;

          begin
          Inc (p);
          If disparo or dis_mal then
             for a:= 1 to 5 do
                 begin
                 If disparo then begin
                                 Dec(y);
                                 move_sprite (disparo1, z+5, y);  { Mueve el disparo                  }
                                 choque;                          { Manda a comprobar si hay choque   }
                                 end;
                 If dis_mal then begin
                                 Inc(s);
                                 vline (t,s,s+5,15);
                                 otro_choque;
                                 end;
                 delay (3);
                 If golpe then begin                              { Detiene el disparo si hubo choque }
                               golpe:= false;
                               break;
                               end;
             end
             else delay (15);

          If y<2 then begin                                    { Disparo fuera de la pantalla      }
                      disparo:= false;
                      y:=182;
                      end;
          If s>200 then dis_mal:= false;
          If (explosion) and (p in [1,5,9,13,17]) then explosiones;
          If p=13 then p:=0;
          end;


Procedure mover_malos;
          var
          p: integer;

          begin
          for i:=1 to 7 do
                  begin       { Mueve a los malos      }
                  move_sprite (malo4[i], ((i*40)-39+j),  1+k);
                  move_sprite (malo3[i], ((i*40)-39+j), 26+k);
                  move_sprite (malo2[i], ((i*40)-39+j), 51+k);
                  move_sprite (malo1[i], ((i*40)-39+j), 76+k);
                  end;
          For i:= 1 to 7 do
              begin
              limites:= true;
              for p:= 0 to 3 do
                  If (malo [i,p]) then limites:=false;
              If limites then lim_i:=-i*39
                         else break;
              end;
          For i:= 7 downto 1 do
              begin
              limites:= true;
              for p:= 0 to 3 do
                  If (malo [i,p]) then limites:=false;
              If limites then lim_d:=((8-i)*39)+60
                         else break;
              end;

          If j=lim_d then begin  { Limite de la derecha   }
                       regresar:= false;
                       Inc (k);
                       end;
          If j=lim_i then begin  { Limite de la izquierda }
                       regresar:= true;
                       Inc (k);
                       end;
          end;

Procedure mover_nave;
          var
          mover: char;

          begin
               while keypressed do begin
                     mover:= readkey;
                     case mover of                               { Lee la tecla presionada       }
                          '1': for x:= x downto (x-5) do         { Mueve la nave a la izquierda  }
                                   begin                         {   ademas de los otros sprites }
                                   If regresar then Inc (j)
                                               else Dec (j);
                                   If x<1 then break;
                                   mover_malos;
                                   move_sprite (nave1, x, 182);
                                   disparos;
                                   update_screen;
                                   end;
                          '3': for x:= x to (x+5) do             { Mueve la nave a la derecha    }
                                   begin                         {   ademas de los otros sprites }
                                   If regresar then Inc (j)
                                               else Dec (j);
                                   If x>303 then break;
                                   mover_malos;
                                   move_sprite (nave1, x, 182);
                                   disparos;
                                   update_screen;
                                   end;
                          'f': If not (disparo= true) then begin { Dispara                       }
                                                           disparo:= true;
                                                           z:= x;
                                                           end;
                          'q': salir:= true;
                          #27: salir:= true; { Activa la opcion de salir     }
                          end;
                     If x>303 then x:= 303;  { Limite derecho de la nave     }
                     If x<2   then x:= 1;    { Limite izquierdo de la nave   }
                     end;
          end;

Procedure malos;     { Rutina de movimiento mientras la nave esta quieta }
          var
          a,b,c: integer;

          begin
          a:= Random (15);
          If (a=1) and (muertos>1)
                   and (not dis_mal)  then begin
                                      repeat
                                            b:= random (7);
                                            c:= random (4);
                                            until malo [b,c];
                                      s:= (k+c*25+18);
                                      t:= ((b*40)+j+9);
                                      dis_mal:= true;
                                      vline (t,s,s+5,15);
                                      update_screen;
                                      end;
          If regresar then for j:= j to (j+5) do
                               begin
                               mover_malos;
                               disparos;
                               update_screen;
                               end
                      else for j:= j downto (j-5) do
                               begin
                               mover_malos;
                               disparos;
                               update_screen;
                               end;
          end;

Procedure continuar;
          var
          a: char;

          begin
          iniciar;
          n[0]:= add_sprite ('0.pix', 157, 120, 0, True);
          n[1]:= add_sprite ('1.pix', 157, 120, 0, True);
          n[2]:= add_sprite ('2.pix', 157, 120, 0, True);
          n[3]:= add_sprite ('3.pix', 157, 120, 0, True);
          n[4]:= add_sprite ('4.pix', 157, 120, 0, True);
          n[5]:= add_sprite ('5.pix', 157, 120, 0, True);
          n[6]:= add_sprite ('6.pix', 157, 120, 0, True);
          n[7]:= add_sprite ('7.pix', 157, 120, 0, True);
          n[8]:= add_sprite ('8.pix', 157, 120, 0, True);
          n[9]:= add_sprite ('9.pix', 157, 120, 0, False);
          hide_sprite (n[0]);
          hide_sprite (n[1]);
          hide_sprite (n[2]);
          hide_sprite (n[3]);
          hide_sprite (n[4]);
          hide_sprite (n[5]);
          hide_sprite (n[6]);
          hide_sprite (n[7]);
          hide_sprite (n[8]);


          For i:=9 downto 0 do
              begin
              continue:= add_sprite ('continue.pix', 110, 50, 0, True);
              hide_sprite (n[i+1]);
              show_sprite (n[i]);
              update_screen;
              If keypressed then begin
                                 a:= readkey;
                                 case a of
                                      'n','N': begin
                                               cont:= false;
                                               break;
                                               end;
                                      's','S': begin
                                               cont:= true;
                                               break;
                                               end;
                                      end;
                                 end;
              delay (750);
              If i=0 then cont:=false;
              end;
          delay (200);
          Shutdown_PSE;
          end;

Procedure numeros;
          begin
          case pix_puntos of
                       1 : begin
                           show_sprite(n[1]);
                           move_sprite(n[1], 80+20*i, 10+a*25);
                           end;
                       2 : begin
                           show_sprite(n[2]);
                           move_sprite(n[2], 80+20*i, 10+a*25);
                           end;
                       3 : begin
                           show_sprite(n[3]);
                           move_sprite(n[3], 80+20*i, 10+a*25);
                           end;
                       4 : begin
                           show_sprite(n[4]);
                           move_sprite(n[4], 80+20*i, 10+a*25);
                           end;
                       5 : begin
                           show_sprite(n[5]);
                           move_sprite(n[5], 80+20*i, 10+a*25);
                           end;
                       6 : begin
                           show_sprite(n[6]);
                           move_sprite(n[6], 80+20*i, 10+a*25);
                           end;
                       7 : begin
                           show_sprite(n[7]);
                           move_sprite(n[7], 80+20*i, 10+a*25);
                           end;                                                 8 : begin
                           show_sprite(n[8]);
                           move_sprite(n[8], 80+20*i, 10+a*25);
                           end;
                       9 : begin
                           show_sprite(n[9]);
                           move_sprite(n[9], 80+20*i, 10+a*25);
                           end;
                      else begin
                           show_sprite(n[0]);
                           move_sprite(n[0], 80+20*i, 10+a*25);
                           end;
                       end;
          end;

Procedure guardar_score;
          var
          texto: text;
          y, m1, d, dow  : Word;
          h, m2, s, hund : Word;

          begin
          GetDate(y,m1,d,dow);
          GetTime(h,m2,s,hund);
          assign (texto, 'records.txt');
          append (texto);
          writeln (texto,'Tu score para la fecha ',d,'-',m1,'-',a,' a las ',h,':',m2,':',s,' fue de:');
          writeln (texto,puntos:8, ' puntos');
          writeln (texto,total_muertos:8, ' muertos');
          writeln (texto,nivel:8,' nivel');
          writeln (texto,'');
          close (texto);
          end;

Procedure score;
          begin
          i:=0;
          a:=0;
          iniciar;
          n[0]:= add_sprite ('0.pix', 157, 120, 0, True);
          n[1]:= add_sprite ('1.pix', 157, 120, 0, True);
          n[2]:= add_sprite ('2.pix', 157, 120, 0, True);
          n[3]:= add_sprite ('3.pix', 157, 120, 0, True);
          n[4]:= add_sprite ('4.pix', 157, 120, 0, True);
          n[5]:= add_sprite ('5.pix', 157, 120, 0, True);
          n[6]:= add_sprite ('6.pix', 157, 120, 0, True);
          n[7]:= add_sprite ('7.pix', 157, 120, 0, True);
          n[8]:= add_sprite ('8.pix', 157, 120, 0, True);
          n[9]:= add_sprite ('9.pix', 157, 120, 0, False);
          scores:= add_sprite ('puntos.pix',10,10,0,true);
          hide_sprite (n[0]);
          hide_sprite (n[1]);
          hide_sprite (n[2]);
          hide_sprite (n[3]);
          hide_sprite (n[4]);
          hide_sprite (n[5]);
          hide_sprite (n[6]);
          hide_sprite (n[7]);
          hide_sprite (n[8]);
          hide_sprite (n[9]);
          update_screen;
          pix_puntos:= trunc(puntos/1000000);
          Inc (i);
          numeros;
          puntos:= puntos - (pix_puntos*1000000);
          pix_puntos:= trunc(puntos/100000);
          Inc (i);
          numeros;
          puntos:= puntos - (pix_puntos*100000);
          pix_puntos:= trunc(puntos/10000);
          Inc (i);
          numeros;
          puntos:= puntos - (pix_puntos*10000);
          pix_puntos:= trunc(puntos/1000);
          Inc (i);
          numeros;
          puntos:= puntos - (pix_puntos*1000);
          pix_puntos:= trunc(puntos/100);
          Inc (i);
          numeros;
          puntos:= puntos - (pix_puntos*100);
          pix_puntos:= trunc(puntos/10);
          Inc (i);
          numeros;
          puntos:= puntos - (pix_puntos*10);
          pix_puntos:= trunc(puntos/1);
          Inc (i);
          numeros;
          update_screen;
         {puntos total_muertos}
          i:=0;
          Inc (a);
          pix_muertos:= trunc(total_muertos/1000000);
          Inc (i);
          numeros;
          total_muertos:= total_muertos - (pix_muertos*1000000);
          pix_muertos:= trunc(total_muertos/100000);
          Inc (i);
          numeros;
          total_muertos:= total_muertos - (pix_muertos*100000);
          pix_muertos:= trunc(total_muertos/10000);
          Inc (i);
          numeros;
          total_muertos:= total_muertos - (pix_muertos*10000);
          pix_muertos:= trunc(total_muertos/1000);
          Inc (i);
          numeros;
          total_muertos:= total_muertos - (pix_muertos*1000);
          pix_muertos:= trunc(total_muertos/100);
          Inc (i);
          numeros;
          total_muertos:= total_muertos - (pix_muertos*100);
          pix_muertos:= trunc(total_muertos/10);
          Inc (i);
          numeros;
          total_muertos:= total_muertos - (pix_muertos*10);
          pix_muertos:= trunc(total_muertos/1);
          Inc (i);
          numeros;
          update_screen;
          readkey;
          Shutdown_PSE;
          end;

Procedure tunnel;
          const
               pi            = 3.1415927;
               some_value    = 8000;
          type
              lookup        = record u,v : byte end;
              alookup       = array[0..0] of lookup;
              texture       = array[0..0,0..255] of byte;

          function calc_tunnel(xsize,ysize,radius : integer) : pointer;
                   var
                   i,j,p         : integer;
                   t             : ^alookup;
                   a             : real;

                   begin
                   getmem(t,xsize*ysize*2);
                   p := 0;
                   for i := -ysize to -1 do begin
                       for j := -xsize to -1 do begin
                           a := arctan(i/(j+0.5));
                           t^[p].u := trunc(a*511/pi/2);
                           t^[p].v := trunc(cos(a)*radius/-(j+0.5)) and $ff;
                           inc(p)
                       end
                   end;
                   calc_tunnel := t;
                   end;

          var
             t             : ^alookup;
             b             : ^texture;
             i,j           : integer;
             screen        : array[0..99,0..319] of byte absolute $a000:0;

          Procedure Palette(ColNum,R,G,B:Byte); Assembler;
                    Asm
                    Mov dx,$3c8;
                    Mov al,ColNum;
                    Out dx,al;
                    Inc dx;
                    Mov al,R;
                    Out dx,al;
                    Mov al,B;
                    Out dx,al;
                    Mov al,B;
                    Out dx,al
                    End;

          procedure draw_tunnel(x,y : byte);
                    var
                       i,j           : integer;

                    begin
                    for i := 0 to 159 do
                        for j := 0 to 99 do
                            screen[j,i]     := b^[t^[i+j*160].u+x,-t^[i+j*160].v-y];
                    for i := 0 to 159 do
                        for j := 0 to 99 do
                            screen[j,319-i] := b^[t^[i+j*160].u-x,+t^[i+j*160].v+y];
                    for i := 0 to 159 do
                        for j := 0 to 99 do
                            screen[199-j,319-i] := b^[t^[i+j*160].u+x,-t^[i+j*160].v-y];
                    for i := 0 to 159 do
                        for j := 0 to 99 do
                            screen[199-j,i] := b^[t^[i+j*160].u-x,+t^[i+j*160].v+y];
                    end;

          var
             x,y           : integer;

          begin
               asm mov ax,13h; int 10h end;
               t := calc_tunnel(160,100,some_value);
               GetMem(b,65535);
               for i := 0 to 65
               do Palette(i,i,80+Round(I/1.4),1+Round(I/1.6));
               for j := 0 to 255 do
               For I:=0 To 255 Do For J:=0 To 255 Do
                   mem[Seg(b^):Ofs(b^)+Word(256*I)+J]:=
                   1+((Sqr(i-128) + Sqr(j-128)) DIV 520);
                   Mem[$A000:320*Round(1.25)]:=Mem[Seg(b^):Ofs(b^)+Word(256)];

               repeat
                     draw_tunnel(x,y);
                     Asm;
                     xor  ax,ax
                     add  ax,X
                     add  ax,0
                     mov  X,ax
                     xor  ax,ax
                     add  ax,Y
                     add  ax,5
                     mov  Y,ax
                     End;
                     until keypressed;
               freeMem(b,65535);
               asm mov ax,03h; int 10h end;
               end;

Procedure Juego;
          var
          a: integer;

          begin
          tunnel;
          nivel:=1;
          repeat
                iniciar;
                randomize;
                If ganar then begin
                              Inc (nivel);
                              ganar:= false;
                              total_muertos:= muertos + total_muertos;
                              muertos:= 0;
                              end
                         else begin
                              nivel:= 1;
                              muertos:= 0;
                              end;

                x:=150;           { Posiciones iniciales      }
                y:=182;
                j:=30;
                k:=0;
                l:=0;
                p:=0;
                lim_i:= 1;
                lim_d:=60;
                cont:= true;
                salir:= false;    { Condiciones iniciales     }
                limites:= false;
                disparo:= false;
                dis_mal:= false;
                ex_nave:= false;
                for i:=1 to 7 do
                    for a:=0 to 3 do
                        malo [i,a]:= true;
                for i:=1 to 7 do
                    minas [i]:= true;

                            { Inizialisamos los sprites }
                nave1:= add_sprite ('n1.pix', x, y, 0, True);
                disparo1:= add_sprite ('d1.pix', x+5, y-16, 0, True);

                for i:=1 to 7 do
                    begin
                    malo1[i]:= add_sprite ('m1.pix', ((i*40)-9), 76, 0, true);
                    malo2[i]:= add_sprite ('m2.pix', ((i*40)-9), 51, 0, true);
                    malo3[i]:= add_sprite ('m3.pix', ((i*40)-9), 26, 0, true);
                    malo4[i]:= add_sprite ('m4.pix', ((i*40)-9),  1, 0, true);
                    end;
                for i:=1 to 5 do
                    barrera[i]:= add_sprite ('b1.pix', ((i*53)-8), 150, 0, true);
                exp1:= add_sprite ('e1.pix', 1, 1, 0, true);
                exp2:= add_sprite ('e2.pix', 1, 1, 0, true);
                exp3:= add_sprite ('e3.pix', 1, 1, 0, true);
                exp_m1:= add_sprite ('em1.pix', 1, 1, 0, true);
                exp_m2:= add_sprite ('em2.pix', 1, 1, 0, true);
                exp_m3:= add_sprite ('em3.pix', 1, 1, 0, true);
                exp_m4:= add_sprite ('em4.pix', 1, 1, 0, true);
                hide_sprite (exp1);
                hide_sprite (exp2);
                hide_sprite (exp3);
                hide_sprite (exp_m1);
                hide_sprite (exp_m2);
                hide_sprite (exp_m3);
                hide_sprite (exp_m4);
                hide_sprite (disparo1);

                update_screen;
                readkey;
                repeat            { Loop principal del juego  }
                      If disparo then show_sprite (disparo1)
                                 else hide_sprite (disparo1);
                      malos;
                      choque;
                      If keypressed then mover_nave;
                      If muertos = 28 then begin
                                           ganar:= true;
                                           break;
                                           end;
                until salir;
                If ex_nave then exp_nave;
                Shutdown_PSE;     { Cerramo libreria grafica     }
                If not ganar then continuar;
          until not cont;
          total_muertos:= muertos + total_muertos;
          iniciar;
          fadeto (63,0,0);
          If not cont then
             for i:=1 to 63 do
                 begin
                 update_screen;
                 delay (3);
                 end;
          delay (500);
          Shutdown_PSE;
          end;
{----------------------------------------------------------------------------}

Begin
     Intro;                           { Rutina de la introduccion    }
     Juego;                           { Inicia el juego              }
     Guardar_score;
     Creditos;
End.

