home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / WALLGAME.ZIP / WALL.PAS < prev   
Pascal/Delphi Source File  |  1991-02-07  |  18KB  |  765 lines

  1. (***********************************************************************)
  2. (*                                                                     *)
  3. (*                              WALLGAME                               *)
  4. (*                                                                     *)
  5. (*               A version of The Old Favorite - BREAKOUT              *)
  6. (*                   Copyright Jari Karjala 1987-1990                  *)
  7. (*                                                                     *)
  8. (*                                                                     *)
  9. (*                     This is a FreeWare Program.                     *)
  10. (*               You may copy it to your friends, but if               *)
  11. (*               you change it, don't leave my name out.               *)
  12. (*               This is not begware, so you need not pay              *)
  13. (*               anything to play with this.                           *)
  14. (*                                                                     *)
  15. (***********************************************************************)
  16.  
  17. { This version will compile without changes only with Turbo Pascal 5.0. }
  18. { If you change something, please mark the changes clearly.             }
  19.  
  20. {$R-,S-,I-,D-,A-,F-,V-,B+,L-,N- }
  21.  
  22. Uses
  23.   crt,dos;
  24.  
  25. const
  26.   Max_Wall = 10;
  27.   Max_His = 8;
  28.   Bonus_Brick = 10;
  29.   Extra_Ball_Brick = 11;
  30.  
  31. type
  32.   str20 = string[20];
  33.   walltype = array[0..7] of string[20];
  34.   AllWalls = array[1..max_wall] of record
  35.                                  wall:walltype;
  36.                                  msg:string[50];
  37.                                  count:integer
  38.                                end;
  39.   HiScoresType = array [1..Max_His] of record
  40.                                          Name : str20;
  41.                                          Score : real;
  42.                                        end;
  43.  
  44. var
  45.   a,b,
  46.   max_walls_read,
  47.   Wall_no, Balls_left, Bricks_hit, Hit_Count, brick_hit_count,
  48.   Paddle_x, Paddle_move_dir,
  49.   Brick_x, Brick_y, Brick_move_dir, Brick_Type,
  50.   Sav_x_inc, Sav_y_inc, bonus,
  51.   Ball_x, Ball_y, Ball_x_inc, Ball_y_inc : integer;
  52.   Score : real;
  53.   Missed, May_Turn, FX, moving, Quiet, HasMouse : boolean;
  54.   walls : AllWalls;
  55.   wall : walltype;
  56.   HiScores : HiScoresType;
  57.   message : string[255];
  58.   mouse_x,mouse_y : word;
  59.  
  60.  
  61. { Procedures for direct handling of PCompatible hardware }
  62.  
  63. const
  64.   inverse = $70;
  65.   normal = $f;
  66.  
  67.   screenseg : word = $B800;
  68.   bmax = 11;
  69.  
  70.   { 0 1 2 3 4 5 6 7 8 9 : ; < > ? @ A  ... }
  71.   Bricks:array[0..bmax] of string[8] = (#32#7#32#7#32#7#32#7,
  72.                                         #178#$70#178#$70#178#$70#178#$70,
  73.                                         #177#$70#177#$70#177#$70#177#$70,
  74.                                         #176#$70#176#$70#176#$70#176#$70,
  75.                                         #219#$7#219#$7#219#$7#219#$7,
  76.                                         #176#$7f#176#$7f#176#$7f#176#$7f,
  77.                                         #177#$7f#177#$7f#177#$7f#177#$7f,
  78.                                         #178#$7f#178#$7f#178#$7f#178#$7f,
  79.                                         #219#$7f#219#$7f#219#$7f#219#$7f,
  80.                                         #$19#$70#$19#$70#$19#$70#$19#$70,
  81.                                         #219#$7#50#$70#88#$70#219#$7,
  82.                                         #66#$78#65#$78#76#$78#76#$78
  83.                                        );
  84.               {01234567890123}
  85.                      
  86.   Paddle:string[16] = '   ▀▀▀▀▀▀▀▀   ';
  87.   Empty_name:str20 = '             ';
  88.  
  89. Procedure InitHardWare;
  90. var    regs:registers;
  91. begin
  92.   regs.ax:=0;
  93.   regs.bx:=0;
  94.   intr($33,regs);
  95.   if regs.ax<>0 then begin
  96.     HasMouse := true;
  97.     regs.ax:=2;
  98.     intr($33,regs);    { hide cursor }
  99.     regs.ax:=4;
  100.     regs.cx := 40;
  101.     regs.dx := 0;
  102.     mouse_x := regs.cx;
  103.     mouse_y := regs.dx;
  104.     intr($33,regs);    { set location }
  105.     regs.ax:=$f;
  106.     regs.cx := 2;
  107.     regs.dx := 20;
  108.     intr($33,regs);    { set mickeys }
  109.   end
  110.   else
  111.      HasMouse := false;
  112.  
  113.   if lastmode=mono then screenseg:=$B000 else screenseg:=$B800;
  114.   
  115. end;
  116.  
  117. Function Get_Brick(x,y:integer):integer;
  118. { Returns the number of the brick in given position. }
  119. begin
  120.   x:=succ(x shr 4); y:=y shr 3;
  121.   Get_Brick:=ord(wall[y][x])-ord('0');
  122. end;
  123.  
  124. Procedure Put_Brick(x,y,a:integer);
  125. { A=type of brick.  If a=0 then brick is empty. }
  126. { X,Y are aligned to brick boundary.            }
  127. var
  128.   address,b:integer;
  129.   brk:string[8];
  130. begin
  131.   address:=y shr 3 * 160 + x shr 1 and $F8;
  132.   brk:=bricks[a];
  133.   for b:=0 to 7 do mem[screenseg:address+b] := ord(brk[succ(b)]);
  134.   if y<64 then wall[y shr 3][succ(x shr 4)]:=chr(ord('0')+a);
  135. end;
  136.  
  137. Procedure Put_Paddle(x:integer);
  138. var
  139.   address,a,b:integer;
  140. begin
  141.   address:=3680+x shr 1 and $FE - 2*3 { three spaces };
  142.   b := length(Paddle) - 1;
  143.   if address + b > 3680+160 then b := b - (address - 3680 - 160);
  144.   for a:=0 to b do 
  145.     memw[screenseg:address+a shl 1] := ord(Paddle[succ(a)])+$F00;
  146. end;
  147.  
  148. Procedure Put_Ball(x,y,color:integer);
  149. { If color is 0 then ball is erased.   }
  150. var
  151.   address:integer;
  152. begin
  153.   address:=x shr 1 and $FE + y shr 3*160;
  154.   if color<>0 then
  155.     if odd(y shr 2) then mem[screenseg:address]:=220
  156.                     else mem[screenseg:address]:=223
  157.               else mem[screenseg:address]:=32;
  158.   mem[screenseg:address+1]:=$F;
  159. end;
  160.  
  161. Procedure WriteXY(x,y,attr:integer; str:string);
  162. var
  163.   a,address:integer;
  164. begin
  165.   address:=y*160 + x shl 1 - 2;
  166.   for a:=1 to length(str) do
  167.     memw[screenseg:address+a shl 1]:=attr shl 8 or ord(str[a]);
  168. end;
  169.  
  170. procedure clrline(y:integer);
  171. const line:string[80]=
  172. '                                                                                ';
  173. begin
  174.   WriteXY(0,y,normal,line)
  175. end;
  176.  
  177. procedure cls;
  178. var
  179.   a:integer;
  180. begin
  181.   for a:=24 downto 0 do clrline(a)
  182. end;
  183.  
  184. Function Get_Direction:integer;
  185. { Returns value:   -2 if left shift + alt
  186.                    -1 if left shift
  187.                     0 if nothing
  188.                     1 if right shift
  189.                     2 if right shift + alt
  190.                     Halt, if Ctrl + Alt pressed.  }
  191. var
  192.   a,b:integer;
  193.   regs:registers;
  194. begin
  195.   regs.ax:=$200;
  196.   intr(22,regs);
  197.   a:=regs.ax;
  198.   if a and 1 =1 then b:=1 else
  199.   if a and 2 =2 then b:=-1 else
  200.     b:=0;
  201.   if a and 8 =8 then b:=b shl 1;
  202.   if a and $c=$c then halt;
  203.   Get_direction:=b;
  204.  
  205.   if HasMouse then begin
  206.     regs.ax:=3;
  207.     regs.cx:=0;
  208.     intr($33,regs); { get cursor }
  209.     if (regs.cx<>mouse_x) then begin
  210.       if (regs.cx > mouse_x) then begin
  211.         a := (regs.cx - mouse_x) div 2;
  212.     if a>6 then
  213.       a := 6;
  214.       end
  215.       else begin
  216.         a := -((mouse_x - regs.cx) div 2);
  217.     if a < -6 then
  218.       a := -6;
  219.       end;
  220.       regs.ax:=4;
  221.       regs.cx:=40;
  222.       mouse_x := regs.cx;
  223.       intr($33,regs);    { set cursor }
  224.       Get_direction := a;
  225.     end;
  226.   end;
  227. end;
  228.  
  229. Procedure Sound_on(f:integer);
  230. begin
  231.   if not Quiet then Sound(f);
  232. end;
  233.  
  234. Procedure Sound_off;
  235. begin
  236.   nosound
  237. end;
  238.  
  239. {******** Portable routines ********}
  240.  
  241. Procedure Beep(f,t:integer);
  242. begin
  243.   Sound_on(f);
  244.   delay(t);
  245.   Sound_off
  246. end;
  247.  
  248. function strs(a:real; b:integer):string;
  249. var
  250.   s:string;
  251. begin
  252.   str(a:b:0,s);
  253.   strs:=s;
  254. end;
  255.  
  256. function sgn(a:integer):integer;
  257. begin
  258. if a<0 then sgn:=-1 else if a>0 then sgn:=1 else sgn:=0
  259. end;
  260.  
  261. function exist(var a:text):boolean;
  262. begin
  263.   {$I-}
  264.   reset(a);
  265.   {$I+}
  266.   exist:=(ioresult=0)
  267. end;
  268.  
  269. Procedure Load_Walls;
  270. var
  271.   a,b,c,d:integer;
  272.   source:text;
  273. begin
  274.   assign(source,'WALL DAT.A');
  275.   if not exist(source) then
  276.     begin Writeln('ERROR: File WALL DAT.A not found.');halt end;
  277.   reset(source);
  278.   readln(source,message);
  279.   a:=1;
  280.   while not eof(source) and (a<=max_wall) do
  281.   with walls[a] do
  282.   begin
  283.     readln(source,msg);
  284.     for b:=0 to 7 do readln(source,wall[b]);
  285.     count:=0;
  286.     for c:=0 to 7 do
  287.       for d:=1 to 20 do
  288.         if wall[c][d]<>'0' then count:=succ(count);
  289.     a:=succ(a)
  290.   end;
  291.   max_walls_read:=pred(a);
  292.   close(source);
  293. end;
  294.  
  295. procedure load_hiscores;
  296. var
  297.   a,b:integer;
  298.   st:string[8];
  299.   source:text;
  300.   line:string[28];
  301. begin
  302.   assign(source,'WALL SCO.RES');
  303.   if not exist(source) then
  304.     for a:=1 to max_his do
  305.       with HiScores[a] do
  306.         begin
  307.           name:='*****   JPK   *****';
  308.           score:=10000-1234*a;
  309.         end
  310.   else
  311.     begin
  312.       reset(source);
  313.       for a:=1 to max_his do
  314.         with HiScores[a] do
  315.           readln(source,name,score);
  316.     end;
  317.   close(source);
  318. end;
  319.  
  320. procedure save_hiscores;
  321. var
  322.   a,b:integer;
  323.   dest:text;
  324.   line:string[28];
  325. begin
  326.   assign(dest,'WALL SCO.RES');
  327.   rewrite(dest);
  328.   for a:=1 to max_his do
  329.     with HiScores[a] do
  330.       writeln(dest,name,score:8:0);
  331.   close(dest);
  332. end;
  333.  
  334. Procedure Print_HiScores;
  335. var
  336.   a:integer;
  337. begin
  338.   for a:=0 to 19 do
  339.   begin
  340.     put_brick(a shl 4,8,5);
  341.     put_brick(a shl 4,184,5);
  342.     put_brick(a shl 4,16,5);
  343.     put_brick(a shl 4,176,5);
  344.     put_brick(0,16+a shl 3,5);
  345.     put_brick(312,16+a shl 3,5);
  346.   end;
  347.   writexy(28,4,inverse,' WALLGAME  Hall of Fame ');
  348.   for a:=1 to Max_His do
  349.     with HiScores[a] do
  350.       writexy(25,4+a shl 1,normal,copy(name+empty_name,1,20)+'  '+strs(score,8));
  351. end;
  352.  
  353. Procedure ReadNameXY(x,y,attr:integer; var st:str20);
  354. var
  355.   a:integer;
  356.   ch:char;
  357. begin
  358.   while keypressed do ch:=readkey;
  359.   a:=1;
  360.   writexy(x,y,attr,st);
  361.   repeat
  362.     ch:=readkey;
  363.     if (ch>chr(31))and(a<21) then
  364.       begin
  365.         st[a]:=ch;
  366.         a:=a+1;
  367.         writeXY(x+a-2,y,attr,ch);
  368.       end
  369.     else
  370.       if ch=^H then
  371.         if a>1 then
  372.           begin
  373.             a:=pred(a);
  374.             st[a]:=' ';
  375.             writexy(x,y,attr,st);
  376.           end
  377.   until ch=^M;
  378.  
  379.   if st=Empty_Name then
  380.     st:=' Unknown ';
  381. end;
  382.  
  383. procedure Insert_HiScore(sc:real);
  384. var
  385.   a,b:integer;
  386. begin
  387.   a:=max_his;
  388.   while (sc>HiScores[a].score) and (a>1) do a:=pred(a);
  389.   if sc<HiScores[1].score then a:=succ(a);
  390.   for b:=pred(max_his) downto a do
  391.     HiScores[succ(b)]:=HiScores[b];
  392.   HiScores[a].score:=sc;
  393.   HiScores[a].name:=Empty_name;
  394.   cls;
  395.   Writexy(15,24,inverse,'CONGRATULATIONS  --  You made it into Hall of Fame');
  396.   Print_HiScores;
  397.   ReadNameXY(25,4+a shl 1,inverse,HiScores[a].name);
  398.   Save_HiScores;
  399. end;
  400.  
  401. procedure Print_Wall;
  402. var
  403.   a,b:integer;
  404. begin
  405.   Cls;
  406.   wall:=walls[wall_no].wall;
  407.   for a:=0 to 7 do
  408.     for b:=0 to 19 do
  409.       put_brick(b*16,a*8,ord(wall[a][succ(b)])-ord('0'));
  410.   bricks_hit:=0;
  411. end;
  412.  
  413. Procedure pause(b:integer);
  414. var
  415.   a:integer;
  416. begin
  417.   a:=0;
  418.   while (a<b) and (abs(Get_Direction)<>1) do
  419.     begin
  420.       a:=a+1;
  421.       delay(1);
  422.     end;
  423. end;
  424.  
  425. procedure Scroll_message;
  426. begin
  427.   writeXY(0,0,normal,copy(message,1,80));
  428.   message:=copy(message,2,length(message))+message[1];
  429.   beep(1000,1);
  430.   delay(100);
  431. end;
  432.  
  433. Procedure Init_All;
  434. begin
  435.   InitHardware;
  436.   Cls;
  437.   Load_Walls;
  438.   Load_HiScores;
  439. end;
  440.  
  441. procedure Init_Game;
  442. var
  443.   a:integer;
  444. begin
  445.   Clrline(24);
  446.   WriteXY(19,24,inverse,' Press Shift to start, Ctrl+Alt to end. ');
  447.   Print_HiScores;
  448.   repeat
  449.     Scroll_message;
  450.   until abs(get_direction)>0;
  451.   wall_no:=1;
  452.   if get_direction=2 then begin
  453.       write('Press enter'); 
  454.       a:=ord(readkey)-ord('0'); if a>0 then wall_no:=a;
  455.   end;
  456.   balls_left:=5;
  457.   score:=0;
  458.   Cls;
  459.   Print_Wall;
  460.   gotoxy(1,25);
  461. end;
  462.  
  463. procedure Init_Specials;
  464. begin
  465.   moving:=false;
  466.   hit_count:=0;
  467.   bonus:=1;
  468. end;
  469.  
  470. procedure Init_Ball;
  471. begin
  472.   WriteXY(2,24,normal,' SCORE '+strs(score,7)+'  BALLS'+strs(balls_left,2));
  473.   writexy(0,24,inverse,strs(1 shl pred(bonus),1)+'X');
  474.   WriteXY(30,24,normal,walls[wall_no].msg);
  475.   Paddle_x:=130;
  476.   Ball_x:=80+random(160);
  477.   Ball_y:=100;
  478.   if random(2)=1 then Ball_x_inc:=4 else Ball_x_inc:=-4;
  479.   Ball_y_inc:=2;
  480.   Missed:=false;
  481.   May_Turn:=true;
  482.   FX:=false;
  483.   put_ball(ball_x,ball_y,1);
  484.   put_paddle(paddle_x);
  485.   for a:=500 to 1000 do
  486.     begin sound_on(a); delay(1) end;
  487.   beep(300,50);
  488.   brick_hit_count:=0;
  489. end;
  490.  
  491. Procedure End_Move;
  492. begin
  493.   if moving then put_brick(brick_x,brick_y,0);
  494.   moving:=false;
  495. end;
  496.  
  497. Procedure End_Short_Special;
  498. { End special effects which work only until first hit into the paddle. }
  499. begin
  500.   if Paddle_move_dir>0 then Ball_x_inc:=4 else Ball_x_inc:=-4;
  501.   Ball_y_inc:=2;
  502.   Sound_off;
  503.   FX:=false;
  504. end;
  505.  
  506. Procedure End_Ball;
  507. { End special effects which work until the ball is missed. }
  508. begin
  509.   clrline(23); Beep(100,400);
  510.   end_move;
  511.   Sound_off;
  512. end;
  513.  
  514. Procedure Do_Shooter;
  515.  begin
  516.    ball_y_inc:=11-Ball_y shr 3;
  517.    Ball_x_inc:=0;
  518.    fx:=true;
  519.  end;
  520.  
  521. Procedure Do_bonus;
  522. begin
  523.   end_move;
  524.   brick_hit_count:=0;
  525.   if bonus<5 then bonus:=succ(bonus);
  526.   writexy(0,24,inverse,strs(1 shl pred(bonus),1)+'X');
  527. end;
  528.  
  529. Procedure Do_Extra_Ball;
  530. begin
  531.   end_move;
  532.   hit_count:=0;
  533.   balls_left:=succ(balls_left);
  534.   writexy(24,24,normal,strs(balls_left,2));
  535. end;
  536.  
  537. Procedure Move_Paddle;
  538. var
  539.   a:integer;
  540. begin
  541.   a:=Get_Direction;
  542.   if a=0 then
  543.     Paddle_Move_Dir:=0
  544.   else
  545.     begin
  546.       if a>0 then
  547.         if Paddle_x+a<284 then Paddle_Move_Dir:=a 
  548.               else Paddle_Move_Dir:=284-Paddle_x
  549.       else
  550.         if Paddle_x+a>0 then Paddle_Move_Dir:=a 
  551.             else Paddle_Move_Dir:= -Paddle_x;
  552.       if HasMouse then
  553.           Paddle_x:=Paddle_x+Paddle_Move_Dir
  554.       else
  555.           Paddle_x:=Paddle_x+Paddle_Move_Dir shl 1;
  556.     end;
  557.   Put_Paddle(Paddle_x);
  558. end;
  559.  
  560. Procedure Start_Moving(brk:integer);
  561. begin
  562.   moving:=true;
  563.   brick_x:=paddle_x shr 1 + 80; brick_y:=0;
  564.   if get_brick(brick_x,0)<>0 then brick_x:=0;
  565.   if sgn(paddle_move_dir)>0 then brick_move_dir:=1 else brick_move_dir:=-1;
  566.   Brick_type:=brk;
  567. end;
  568.  
  569. Procedure Move_Brick;
  570. var
  571.   a:integer;
  572. begin
  573.   if brick_x<303 then
  574.     if brick_x>16 then
  575.       if get_brick((brick_x+brick_move_dir shl 4), brick_y)=0 then
  576.         begin
  577.           a:=brick_x;
  578.           brick_x:=brick_x+brick_move_dir;
  579.           put_brick(brick_x, brick_y, brick_type);
  580.           if brick_x shr 4<>a shr 4 then put_brick(a, brick_y, 0);
  581.         end
  582.       else
  583.         brick_move_dir:=-brick_move_dir
  584.     else
  585.       begin
  586.         brick_move_dir:=-brick_move_dir;
  587.         brick_x:=17;
  588.       end
  589.   else
  590.     begin
  591.       brick_move_dir:=-brick_move_dir;
  592.       brick_x:=302;
  593.     end;
  594. end;
  595.  
  596. procedure move_bricks;
  597. begin
  598.   If moving then
  599.     Move_brick
  600.   else
  601.     if brick_hit_count > 40 then
  602.       begin
  603.         if bonus<5 then
  604.           Start_moving(Bonus_brick)
  605.       end
  606.     else
  607.       if hit_count > 100 then
  608.         Start_moving(Extra_Ball_Brick)
  609.       else
  610.         delay(2);
  611. end;
  612.  
  613. Procedure Move_Ball;
  614. var
  615.   a,tx,ty,brick:integer;
  616. begin
  617.  
  618. {*** Hit into Side Walls ***}
  619.   tx:=Ball_x+Ball_x_inc;
  620.   if tx>319 then
  621.     begin
  622.       Ball_x_inc:=-Ball_x_inc;
  623.       tx:=319;
  624.       ty:=ty and $fc
  625.     end else
  626.   if tx<0 then
  627.     begin
  628.       ball_x_inc:=-ball_x_inc;
  629.       tx:=0;
  630.       ty:=ty and $fc
  631.     end;
  632.  
  633. {*** Hit into Paddle or Roof ***}
  634.   ty:=Ball_y+Ball_y_inc;
  635.   if ty>183 then
  636.     if (tx>=Paddle_x) and (tx<=Paddle_x+40) then
  637.       begin
  638.         if FX then End_Short_Special;
  639.         Ball_y_inc:=-Ball_y_inc;
  640.         if Paddle_move_dir<>0 then
  641.           if sgn(paddle_move_dir)=sgn(ball_x_inc) then
  642.           begin
  643.             ball_y_inc:=pred(ball_y_inc);
  644.             if ball_y_inc<-4 then
  645.               begin
  646.                 ball_y_inc:=-4;
  647.               end;
  648.           end
  649.           else
  650.           begin
  651.             ball_y_inc:=succ(ball_y_inc);
  652.             if ball_y_inc>-1 then
  653.               begin
  654.                 ball_y_inc:=-1;
  655.               end;
  656.           end;
  657.         ty:=183;
  658.         beep(200,5);
  659.         if not moving then
  660.           begin
  661.             brick_hit_count:=succ(brick_hit_count);
  662.             hit_count:=succ(hit_count);
  663.           end
  664.       end
  665.     else
  666.       begin
  667.         Missed:=true;
  668.         Balls_Left:=Pred(Balls_Left);
  669.       end
  670.   else
  671.   if ty<0 then
  672.     begin
  673.       ball_y_inc:=-ball_y_inc;
  674.       ty:=0;
  675.     end;
  676.  
  677. {*** Hit into Brick ***}
  678.   if ty<64 then
  679.   begin
  680.     brick:=get_brick(tx,ty);
  681.     if brick<>0 then
  682.     begin
  683.       Put_Brick(tx,ty,0);
  684.       score:=score+brick shl bonus;
  685.       WriteXY(9,24,normal,strs(score,7));
  686.       if brick<10 then
  687.       begin
  688.         bricks_hit:=succ(bricks_hit);
  689.         if bricks_hit>=walls[wall_no].count then
  690.         begin
  691.           for a:=300 to 500 do beep(a,2);
  692.           wall_no:=succ(wall_no);
  693.           if wall_no>max_walls_read then wall_no:=1;
  694.           print_wall;
  695.           init_ball;
  696.           exit;
  697.         end;
  698.         if may_turn or (ball_y_inc>0) then Ball_y_inc:=-Ball_y_inc;
  699.         may_turn:=false;
  700.         ty:=ty and $f8+7;
  701.         if brick=9 then Do_Shooter;
  702.       end
  703.       else
  704.       Case brick of
  705.         Bonus_Brick      : Do_Bonus;
  706.         Extra_Ball_Brick : Do_extra_ball;
  707.         else beep(1000+200*brick,200)
  708.       end;
  709.       beep(440+70*brick,10);
  710.     end else may_turn:=true;
  711.   end;
  712.  
  713.   if fx then sound_on(400+ball_y*100);
  714.   Put_Ball(tx,ty,1);
  715.   if (tx shr 2 <> ball_x shr 2) or (ty shr 3 <> ball_y shr 3)
  716.     then Put_Ball(ball_x,ball_y,0);
  717.   Ball_x:=tx; Ball_y:=ty;
  718. end;
  719.  
  720. Procedure Game_Over;
  721. var
  722.   a:integer;
  723. begin
  724.   for a:=22 downto 9 do
  725.   begin
  726.     sound_on(40*a);
  727.     WriteXY(29,a,inverse,'>>>> Game  Over <<<<');
  728.     delay(50);
  729.     sound_on(40*a+20);
  730.     clrline(succ(a))
  731.   end;
  732.   for a:=44 to 88 do beep(a*10,5);
  733. end;
  734.  
  735.  
  736. { *****   Main loop   ***** }
  737.  
  738. begin
  739.   if paramstr(1)='/q' then Quiet := true else Quiet := false;
  740.   Init_All;
  741.   repeat
  742.     Init_Game;
  743.     repeat
  744.       Init_Specials;
  745.       Init_Ball;
  746.       repeat
  747.         Move_Paddle;
  748.         Move_Ball;
  749.         Move_Paddle;
  750.         Move_Bricks;
  751.         Delay(30);
  752.       until Missed;
  753.       End_Ball;
  754.     until Balls_left=0;
  755.     Game_Over;
  756.     if Score>HiScores[max_his].score then
  757.       Insert_HiScore(Score)
  758.     else
  759.       begin
  760.         Pause(5000);
  761.         cls;
  762.       end;
  763.   until false;
  764. end.
  765.