home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / CAVE.ZIP / LDOOM3.PAS < prev    next >
Pascal/Delphi Source File  |  1995-07-17  |  44KB  |  1,543 lines

  1. PROGRAM LDOOM;
  2. {$G+}
  3.  
  4. uses variable,pong2,thegraph,dos,pcx,crt,ctvoice;
  5.  
  6.  
  7. (*---------------------- Procedure init_d_sound ----------------------------*)
  8.  
  9. PROCEDURE fade;
  10.  
  11. VAR counter:integer;
  12.     facts:rgb_color_typ;
  13.     done:boolean;
  14.  
  15. BEGIN
  16. REPEAT
  17.   FOR counter:=1 TO 255 DO
  18.   BEGIN
  19.     get_palette_register(counter,facts);
  20.     IF facts.red-5<0 THEN facts.red:=0 ELSE facts.red:=facts.red-5;
  21.     IF facts.blue-5<0 THEN facts.blue:=0 ELSE facts.blue:=facts.blue-5;
  22.     IF facts.green-5<0 THEN facts.green:=0 ELSE facts.green:=facts.green-5;
  23.     IF (facts.red=0) AND (facts.green=0) AND (facts.blue=0) THEN done:=true
  24.     ELSE done:=false;
  25.     set_palette_register(counter,facts);
  26.   END;
  27.   delay(75);
  28.   UNTIL done;
  29. END;
  30.  
  31. PROCEDURE init_sound;
  32. BEGIN
  33.   loadctdriver('ct-voice.drv');
  34.   useport($220);
  35.   useirq(5);
  36.   usechannel(1);
  37.   initializedriver;
  38. END;
  39.  
  40. (*------------------- Procedure play_sound --------------------------------*)
  41.  
  42.  
  43. PROCEDURE play_sound(sound:voctp);
  44.  
  45. VAR sample:voctp;
  46.  
  47. begin
  48.   stopvprocess;
  49.   sbioresult:=callok;
  50.   if sbioresult=callok then begin
  51.   if statusword=0 then playblock(sound);
  52.   end;
  53. end;
  54.  
  55.  
  56. (*------------------PROCEDURE SEARCH-----------------------------------*)
  57.  
  58.  
  59. PROCEDURE search(first:enemypointer; xer,yer:byte; var Last,Next:enemypointer);
  60. BEGIN
  61.   next:=first^.link;
  62.   last:=first;
  63.   while ((next^.enemy.xpos<>xer) OR (next^.enemy.ypos<>yer)) AND
  64.         (next^.link<>nil) do
  65.   begin
  66.       last:=next;
  67.       next:=next^.link
  68.   end;
  69. END;
  70.  
  71. PROCEDURE del_enemy(first:enemypointer; xer,yer:byte);
  72.  
  73. VAR last,next:enemypointer;
  74.  
  75. BEGIN
  76.   next:=first^.link;
  77.   if next<>nil THEN
  78.   BEGIN
  79.     search(first,xer,yer,last,next);
  80.     if (next^.enemy.xpos=xer) AND (next^.enemy.ypos=yer) THEN
  81.     BEGIN
  82.       last^.link:=next^.link;
  83.       dispose(next);
  84.     END
  85.   END;
  86. END;
  87.  
  88. PROCEDURE add_enemy(VAR head:enemypointer; num,xer,yer:byte);
  89.  
  90. var newnode:enemypointer;
  91.  
  92. begin
  93.   new(newnode);
  94.   newnode^.enemy.xpos:=xer;
  95.   newnode^.enemy.ypos:=yer;
  96.   newnode^.enemy.curframe:=1;
  97.   CASE num OF
  98.    11:BEGIN
  99.         newnode^.enemy.numhp:=3;
  100.         newnode^.enemy.daminflict:=3
  101.       END;
  102.    12:BEGIN
  103.         newnode^.enemy.numhp:=5;
  104.         newnode^.enemy.daminflict:=6
  105.       END;
  106.    END;
  107. newnode^.link:=head^.link;
  108. head^.link:=newnode;
  109. END;
  110.  
  111.  
  112. (*----------------------- Procedure Load_World ---------------------------*)
  113.  
  114.  
  115. PROCEDURE Load_World(worldfile:string);
  116.  
  117. VAR  infile:text;
  118.      row,column,times:INTEGER;
  119.      ch:char;
  120.      temp:integer;
  121.      res,ans:byte;
  122.  
  123. BEGIN
  124. check_file(worldfile);
  125. assign(infile,worldfile);
  126. reset(infile);
  127. for row:=0  TO WORLD_ROWS-1 DO
  128. BEGIN
  129.   for column:=1 TO WORLD_COLUMNS DO
  130.   BEGIN
  131.   ans:=0;
  132.   FOR  times:=1 TO 2 DO
  133.   BEGIN
  134.     read(infile,ch);
  135.     IF ch=' ' THEN res :=0
  136.     ELSE
  137.     val(ch,res,temp);
  138.     IF times=1 THEN res:=res*10;
  139.     ans:=ans+res
  140.   END;
  141.   IF ans>10 THEN add_enemy(enemylist,ans,column,world_rows-row);
  142.     world[world_rows-row,column] := ans;
  143.   END;
  144.    readln(infile);
  145. END;
  146. close(infile);
  147. END;
  148.  
  149.  
  150. (*------------- Procedure Save_World ----------------------------*)
  151. PROCEDURE Save_World(position:word);
  152.  
  153. VAR  infile:text;
  154.      row,column:INTEGER;
  155.      ch:char;
  156.      res:byte;
  157.      filename:string;
  158.  
  159. BEGIN
  160. CASE position OF
  161. 1:filename:='Cave1.sav';
  162. 2:filename:='Cave2.sav';
  163. 3:filename:='Cave3.sav';
  164. 4:filename:='Cave4.sav';
  165. 5:filename:='Cave5.sav';
  166. END;
  167. assign(infile,filename);
  168. rewrite(infile);
  169. for row:=0  TO WORLD_ROWS-1 DO
  170. BEGIN
  171.   for column:=1 TO WORLD_COLUMNS DO
  172.   BEGIN
  173.     res:=world[world_rows-row,column];
  174.     IF res=0 THEN ch:=' '
  175.     ELSE
  176.     BEGIN
  177.     str(res,filename);
  178.     ch:=filename[1];
  179.     END;
  180.     write(infile,ch);
  181.   END;
  182.    writeln(infile);
  183. END;
  184. close(infile);
  185. END;
  186.  
  187. (*------------- Procedure Create_Scale_Data ---------------------*)
  188.  
  189.  
  190.  
  191. Procedure Create_Scale_Data(scale:INTEGER; VAR row:pcximage);
  192.  
  193. VAR  y,roff,rseg,temp:INTEGER;
  194.       y_scale_index,y_scale_step:real;
  195.  
  196. BEGIN
  197. y_scale_index:=0;
  198. y_scale_step := 64/scale;
  199. y_scale_index:=y_scale_index+y_scale_step;
  200. roff:=ofs(row^); rseg:=seg(row^);
  201. for y:=0 TO scale-1 DO
  202. BEGIN
  203.    temp:=TRUNC((y_scale_index+0.5)) * CELL_X_SIZE;
  204.    move(temp,mem[rseg:roff+(y*2)],2);
  205.   if  ( temp> 63*CELL_X_SIZE) THEN
  206.   BEGIN
  207.    temp := 63*CELL_X_SIZE;
  208.    move(temp,mem[rseg:roff+(y*2)],2);
  209.   END;
  210.     y_scale_index:=y_scale_index+y_scale_step;
  211. END
  212. END;
  213.  
  214.  
  215. (*---------------------- Procedure Build_Tables --------------------------*)
  216.  
  217.  
  218. PROCEDURE Build_Tables;
  219.  
  220. VAR temp,rad_angle:real;
  221.     scale:integer;
  222.     ang:INTEGER;
  223. BEGIN
  224. check_mem(tan_table,6*angle_360);
  225. check_mem(inv_tan_table,6*angle_360);
  226. check_mem(y_step,6*angle_360);
  227. check_mem(x_step,6*angle_360);
  228. check_mem(cos_table,6*angle_360);
  229. check_mem(inv_cos_table,6*angle_360);
  230. check_mem(inv_sin_table,6*angle_360);
  231. toff:=ofs(tan_table^); tseg:=seg(tan_table^);
  232. ioff:=ofs(inv_tan_table^); iseg:=seg(inv_tan_table^);
  233. yoff:=ofs(y_step^); yseg:=seg(y_step^);
  234. xoff:=ofs(x_step^); xseg:=seg(x_step^);
  235. icoff:=ofs(inv_cos_table^); icseg:=seg(inv_cos_table^);
  236. isoff:=ofs(inv_sin_table^); isseg:=seg(inv_sin_table^);
  237. coff:=ofs(cos_table^); cseg:=seg(cos_table^);
  238. FOR ang:=ANGLE_0 TO ANGLE_360 DO
  239. BEGIN
  240.   rad_angle := ((3.72e-4)+ang*2*3.141592654/ANGLE_360);
  241.   temp:=sin(rad_angle)/cos(rad_angle);
  242.   move(temp,mem[tseg:toff+ang*6],6);
  243.   temp:=1/temp;
  244.   move(temp,mem[iseg:ioff+ang*6],6);
  245.   if (ang>=ANGLE_0) AND (ang<ANGLE_180) THEN
  246.   BEGIN
  247.     move(mem[tseg:toff+ang*6],temp,6);
  248.     temp:=ABS(temp*CELL_Y_SIZE);
  249.     move(temp,mem[yseg:yoff+ang*6],6)
  250.   END
  251.     else
  252.        BEGIN
  253.          move(mem[tseg:toff+ang*6],temp,6);
  254.          temp:=-(ABS(temp*CELL_Y_SIZE));
  255.          move(temp,mem[yseg:yoff+ang*6],6)
  256.        END;
  257.  
  258.     if (ang>=ANGLE_90) AND (ang<ANGLE_270) THEN
  259.     BEGIN
  260.       move(mem[iseg:ioff+ang*6],temp,6);
  261.       temp:=-(ABS(temp*CELL_X_SIZE));
  262.       move(temp,mem[xseg:xoff+ang*6],6)
  263.     END
  264.     else
  265.     BEGIN
  266.       move(mem[iseg:ioff+ang*6],temp,6);
  267.       temp:=(ABS(temp*CELL_X_SIZE));
  268.       move(temp,mem[xseg:xoff+ang*6],6)
  269.     END;
  270.     temp:=1/cos(rad_angle);
  271.     move(temp,mem[icseg:icoff+ang*6],6);
  272.     temp:=1/sin(rad_angle);
  273.     move(temp,mem[isseg:isoff+ang*6],6);
  274. END;
  275. FOR ang:=-Angle_30 to Angle_30 DO
  276. BEGIN
  277.   rad_angle := ((3.72e-4)+ang*2*3.141592654/ANGLE_360);
  278.   temp:=VERTICAL_SCALE/cos(rad_angle);
  279.   move(temp,mem[cseg:coff+((ang +ANGLE_30)*6)],6);
  280. END;
  281. for scale:=1 TO MAX_SCALE DO
  282. BEGIN
  283.   check_mem(scales[scale],scale*2);
  284.   create_scale_data(scale,scales[scale]);
  285. END;
  286. END;
  287.  
  288.  
  289.  
  290. (*---------------------- Procedure free_scale_data -------------------*)
  291.  
  292.  
  293. PROCEDURE free_scale_data;
  294.  
  295. VAR y:INTEGER;
  296.  
  297. bEGIN
  298.  FOR y:=1 TO MAX_SCALE DO
  299.   freemem(scales[y],y*2);
  300. END;
  301.  
  302.  
  303. (*----------------------- Procedure Render_Sliver ------------------------*)
  304.  
  305.  
  306. PROCEDURE fast_render;
  307.  
  308. VAR soff,sseg:word;
  309.  
  310. BEGIN
  311.  soff:=ofs(sliver_texture^);
  312.  sseg:=seg(sliver_texture^);
  313.  asm
  314.    push si
  315.    push di
  316.    mov di, doff
  317.    mov dx,sliver_column
  318.    mov si,soff
  319.    mov bx,sliver_top
  320.    shl bx,8
  321.    mov ax,bx
  322.    shr bx,2
  323.    add bx,ax
  324.    add bx,sliver_ray
  325.    add di,bx
  326.    mov bx,sliver_clip
  327.    mov ax,sliver_scale
  328.    add ax,bx
  329. @Sliver_Loop:
  330.       xchg dx,bx
  331.       mov es,sseg
  332.       mov cl, BYTE PTR es:[si+bx]
  333.       mov es,dseg
  334.       mov es:[di], cl
  335.       xchg dx,bx
  336.       mov cx,bx
  337.       mov dx,scaleoff
  338.       mov es,scaleseg
  339.       shl bx,1
  340.       add bx,dx
  341.       mov dx, WORD PTR es:[bx]
  342.       add dx,sliver_column
  343.       mov bx,cx
  344.       add di,320
  345.       inc bx
  346.       cmp bx, ax
  347.       jne @Sliver_Loop
  348.       pop di
  349.       pop si
  350. END;
  351. END;
  352.  
  353. PROCEDURE fast_render_blit;
  354.  
  355. VAR soff,sseg,goff,gseg:word;
  356.  
  357. BEGIN
  358.  soff:=ofs(sliver_texture^);
  359.  sseg:=seg(sliver_texture^);
  360.  asm
  361.  jmp @start
  362. @draw_it:
  363.    mov es,dseg
  364.    mov es:[di], cl
  365. jmp @begins
  366. @start:
  367.    push si
  368.    push di
  369.    mov di, doff
  370.    mov dx,sliver_column
  371.    mov si,soff
  372.    mov bx,sliver_top
  373.    shl bx,8
  374.    mov ax,bx
  375.    shr bx,2
  376.    add bx,ax
  377.    add bx,sliver_ray
  378.    add di,bx
  379.    mov bx,sliver_clip
  380.    mov ax,sliver_scale
  381.    add ax,bx
  382. @Sliver_Loop:
  383.       xchg dx,bx
  384.       mov es,sseg
  385.       mov cl, BYTE PTR es:[si+bx]
  386.       cmp cl,0
  387.       jne @draw_it
  388.   @begins:
  389.       xchg dx,bx
  390.       mov cx,bx
  391.       mov dx,scaleoff
  392.       mov es,scaleseg
  393.       shl bx,1
  394.       add bx,dx
  395.       mov dx, WORD PTR es:[bx]
  396.       add dx,sliver_column
  397.       mov bx,cx
  398.       add di,320
  399.       inc bx
  400.       cmp bx, ax
  401.       jne @Sliver_Loop
  402.       pop di
  403.       pop si
  404. END;
  405. END;
  406.  
  407. PROCEDURE hit_guy(xer,yer:word);
  408.  
  409. VAR next,last:enemypointer;
  410.  
  411. BEGIN
  412.   search(enemylist,xer,yer,next,last);
  413.   bloodon:=true;
  414.   IF sniper THEN last^.enemy.numhp:=0
  415.   ELSE
  416.   last^.enemy.numhp:=last^.enemy.numhp-1;
  417.   IF last^.enemy.numhp=0 THEN
  418.   BEGIN
  419.     IF last^.enemy.daminflict=6 THEN gatesdead:=true;
  420.     world[yer,xer]:=0;
  421.     play_sound(ugh);
  422.     del_enemy(enemylist,xer,yer);
  423.   END;
  424. END;
  425.  
  426. PROCEDURE move_guy(guyx,guyy,playerx,playery:word);
  427.  
  428. VAR moved:boolean;
  429.     next,last:enemypointer;
  430. BEGIN
  431.   playerx:=playerx SHR 6;
  432.   playery:=playery SHR 6;
  433.   search(enemylist,guyx,guyy,next,last);
  434.   moved:=false;
  435.  { IF random(5)=3 THEN
  436.   BEGIN
  437.   IF (world[guyy,guyx-1]=0) AND (playerx<guyx) AND
  438.   ((guyx-1<>playerx) OR (playery<>guyy)) THEN
  439.   BEGIN
  440.     moved:=true;
  441.     world[guyy,guyx]:=0;
  442.     world[guyy,guyx-1]:=11;
  443.     last^.enemy.xpos:=guyx-1;
  444.   END
  445.   ELSE
  446.   IF (world[guyy,guyx+1]=0) AND (playerx>guyx)
  447.   AND ((guyx+1<>playerx) OR (playery<>guyy)) THEN
  448.   BEGIN
  449.     moved:=true;
  450.     world[guyy,guyx]:=0;
  451.     world[guyy,guyx+1]:=11;
  452.     last^.enemy.xpos:=guyx+1;
  453.   END
  454.   ELSE
  455.   IF (world[guyy-1,guyx]=0) AND (playery<guyy)
  456.   AND ((guyy-1<>playery) OR (playerx<>guyx)) THEN
  457.   BEGIN
  458.     moved:=true;
  459.     world[guyy,guyx]:=0;
  460.     world[guyy-1,guyx]:=11;
  461.     last^.enemy.ypos:=guyy-1;
  462.   END
  463.   ELSE
  464.   IF (world[guyy+1,guyx]=0) AND (playery>guyy)
  465.   AND ((guyy+1<>playery) OR (playerx<>guyx)) THEN
  466.   BEGIN
  467.     moved:=true;
  468.     world[guyy,guyx]:=0;
  469.     world[guyy+1,guyx]:=11;
  470.     last^.enemy.ypos:=guyy+1;
  471.   END;
  472.   END;
  473.   IF moved THEN }
  474.   IF monster.cur_frame<3 THEN INC(monster.cur_frame)
  475.   ELSE monster.cur_frame:=1;
  476.   enmove:=true;
  477.   IF (guyx+1=playerx)  OR (guyx-1=playerx) OR (guyy-1=playery)
  478.   OR (guyy+1=playery) THEN
  479.   IF (RANDOM(6)+1=3) THEN
  480.   BEGIN
  481.     monster.cur_frame:=4;
  482.     IF not(touch) THEN life:=life-3
  483.   END;
  484. END;
  485.  
  486. PROCEDURE GUY_Caster(x,y,view_angle:LONGINT);
  487.  
  488. VAR
  489. cell_x,cell_y,ray,casting,x_hit_type,y_hit_type,x_bound,y_bound,
  490. next_y_cell,next_x_cell,xray,yray,x_delta,y_delta,xb_save,yb_save,
  491. xi_save,yi_save,scale:INTEGER;
  492. dist_x,dist_y:longint;
  493. xi,yi,temp:REAL;
  494.  
  495. BEGIN
  496. xray:=0;
  497. yray:=0;
  498. casting:=2;
  499. view_angle:=view_angle-angle_30;
  500. if (view_angle< 0) THEN view_angle:=ANGLE_360 + view_angle;
  501. for ray:=319 downto 0 DO
  502. BEGIN
  503.   if (view_angle >= ANGLE_0) AND (view_angle < ANGLE_180) THEN
  504.   BEGIN
  505.     y_bound := (CELL_Y_SIZE + (y AND $ffc0));
  506.     y_delta := CELL_Y_SIZE;
  507.     move(mem[iseg:ioff+(view_angle*6)],temp,6);
  508.     xi:=temp*(y_bound-y)+x;
  509.     next_y_cell := 0;
  510.   END
  511.     else
  512.     BEGIN
  513.        y_bound := (y AND $ffc0);
  514.        y_delta := -CELL_Y_SIZE;
  515.        move(mem[iseg:ioff+(view_angle*6)],temp,6);
  516.        xi := temp * (y_bound - y) + x;
  517.        next_y_cell := -1;
  518.     ENd;
  519.    if (view_angle < ANGLE_90) OR (view_angle >= ANGLE_270)  THEN
  520.    BEGIN
  521.      x_bound := (CELL_X_SIZE + (x AND $ffc0));
  522.      x_delta := CELL_X_SIZE;
  523.      move(mem[tseg:toff+(view_angle*6)],temp,6);
  524.      yi:=temp*(x_bound-x)+y;
  525.      next_x_cell := 0;
  526.    END
  527.    else
  528.    BEGIN
  529.      x_bound := (x AND $ffc0);
  530.      x_delta := -CELL_X_SIZE;
  531.      move(mem[tseg:toff+(view_angle*6)],temp,6);
  532.      yi := temp * (x_bound - x) + y;
  533.      next_x_cell := -1;
  534.    END;
  535.  casting:= 2;
  536.  xray:= 0;
  537.  yray:=0;
  538.  while casting>0 DO
  539.  BEGIN
  540.    if (xray<>INTERSECTION_FOUND) THEN
  541.    BEGIN
  542.    cell_x := ( (x_bound+next_x_cell) SHR CELL_X_SIZE_FP);
  543.      cell_y := trunc(yi);
  544.      cell_y:=cell_y SHR CELL_Y_SIZE_FP;
  545.      x_hit_type:=world[cell_y,cell_x];
  546.      if (x_hit_type>0) THEN
  547.      BEGIN
  548.         move(mem[isseg:isoff+(view_angle*6)],temp,6);
  549.        dist_x  := round((yi - y) * temp);
  550.        yi_save := trunc(yi);
  551.        xb_save := x_bound;
  552.        xray := INTERSECTION_FOUND;
  553.        dec(casting);
  554.     END
  555.     else
  556.     BEGIN
  557.      move(mem[yseg:yoff+(view_angle*6)],temp,6);
  558.       yi:=yi+temp;
  559.       x_bound:=x_bound+x_delta;
  560.     END;
  561.   END;
  562.   if (yray<>INTERSECTION_FOUND) THEN
  563.   BEGIN
  564.     cell_x :=trunc(xi);
  565.     cell_x:=cell_x SHR CELL_X_SIZE_FP;
  566.     cell_y := ( (y_bound + next_y_cell) SHR CELL_Y_SIZE_FP);
  567.     y_hit_type := world[cell_y,cell_x];
  568.     if (y_hit_type>0 ) THEN
  569.     BEGIN
  570.       move(mem[icseg:icoff+(view_angle*6)],temp,6);
  571.       dist_y  := round((xi- x) * temp);
  572.       xi_save := trunc(xi);
  573.       yb_save := y_bound;
  574.       yray := INTERSECTION_FOUND;
  575.       dec(casting);
  576.     END
  577.      else
  578.      BEGIN
  579.         move(mem[xseg:xoff+(view_angle*6)],temp,6);
  580.        xi :=xi+temp;
  581.        y_bound :=y_bound+ y_delta;
  582.      END;
  583.   END;
  584. END;
  585.  if (dist_x < dist_y) AND ((x_hit_type>10) OR (y_hit_type>10)) THEN
  586.  BEGIN
  587.    move(mem[cseg:coff+(ray*6)],temp,6);
  588.    scale := trunc((temp/dist_x));
  589.    if (scale>(MAX_SCALE)) THEN scale:=(MAX_SCALE);
  590.    scaleoff := ofs(scales[scale]^);
  591.    scaleseg := seg(scales[scale]^);
  592.    if (scale>WINDOW_HEIGHT) THEN
  593.    BEGIN
  594.      sliver_clip := (scale-WINDOW_HEIGHT) SHR 1;
  595.      scale:=WINDOW_HEIGHT;
  596.    END
  597.    else
  598.     sliver_clip := 0;
  599.    sliver_scale   := scale;
  600.    CASE x_hit_type OF
  601.        11:sliver_texture:= monster.frames[monster.cur_frame];
  602.        12:sliver_texture:=gates.frames[1];
  603.        13:sliver_texture:=waldo.frames[1];
  604.    END;
  605.    sliver_column  := (yi_save AND $003f);
  606.    sliver_top     := WINDOW_MIDDLE - (scale SHR 1);
  607.    sliver_ray     := ray;
  608.    IF (x_hit_type>10) AND
  609.    (((player_view_angle>=720) AND (player_view_angle<=1200))
  610.    OR ((player_view_angle>=1680) OR (player_view_angle<=240)))
  611.    THEN fast_Render_blit;
  612.   END
  613.     else
  614.     BEGIN
  615.       move(mem[cseg:coff+(ray*6)],temp,6);
  616.       scale := trunc((temp/dist_y));
  617.        if (scale>(MAX_SCALE)) THEN scale:=(MAX_SCALE);
  618.         scaleoff := ofs(scales[scale]^);
  619.         scaleseg := seg(scales[scale]^);
  620.        if (scale>WINDOW_HEIGHT) THEN
  621.        BEGIN
  622.          sliver_clip := (scale-WINDOW_HEIGHT) SHR 1;
  623.           scale:=WINDOW_HEIGHT;
  624.        END
  625.       else
  626.        sliver_clip := 0;
  627.        sliver_scale:= scale;
  628.        CASE y_hit_type OF
  629.        11:sliver_texture:= monster.frames[monster.cur_frame];
  630.        12:sliver_texture:=gates.frames[1];
  631.        13:sliver_texture:=waldo.frames[1];
  632.        END;
  633.        sliver_column:= (xi_save AND $003f);
  634.        sliver_top:= WINDOW_MIDDLE - (scale SHR 1);
  635.        sliver_ray:= ray;
  636.        IF (y_hit_type>10) AND
  637.        ((player_view_angle>1200) AND (player_view_angle<1680)
  638.        OR (player_view_angle>240) AND (player_view_angle<720))
  639.        THEN fast_Render_blit;
  640.     END;
  641.     view_angle:=view_angle+1;
  642.     if (view_angle>=ANGLE_360) THEN view_angle:=0;
  643.   END;
  644. END;
  645.  
  646. PROCEDURE Ray_Caster(x,y,view_angle:LONGINT);
  647.  
  648. VAR
  649. cell_x,cell_y,ray,casting,x_hit_type,y_hit_type,x_bound,y_bound,
  650. next_y_cell,next_x_cell,xray,yray,x_delta,y_delta,xb_save,yb_save,
  651. xi_save,yi_save,scale:INTEGER;
  652. dist_x,dist_y:longint;
  653. xi,yi,temp:REAL;
  654.  
  655. BEGIN
  656. xray:=0;
  657. yray:=0;
  658. casting:=2;
  659. view_angle:=view_angle-angle_30;
  660. if (view_angle< 0) THEN view_angle:=ANGLE_360 + view_angle;
  661. for ray:=319 downto 0 DO
  662. BEGIN
  663.   if (view_angle >= ANGLE_0) AND (view_angle < ANGLE_180) THEN
  664.   BEGIN
  665.     y_bound := (CELL_Y_SIZE + (y AND $ffc0));
  666.     y_delta := CELL_Y_SIZE;
  667.     move(mem[iseg:ioff+(view_angle*6)],temp,6);
  668.     xi:=temp*(y_bound-y)+x;
  669.     next_y_cell := 0;
  670.   END
  671.     else
  672.     BEGIN
  673.        y_bound := (y AND $ffc0);
  674.        y_delta := -CELL_Y_SIZE;
  675.        move(mem[iseg:ioff+(view_angle*6)],temp,6);
  676.        xi := temp * (y_bound - y) + x;
  677.        next_y_cell := -1;
  678.     ENd;
  679.    if (view_angle < ANGLE_90) OR (view_angle >= ANGLE_270)  THEN
  680.    BEGIN
  681.      x_bound := (CELL_X_SIZE + (x AND $ffc0));
  682.      x_delta := CELL_X_SIZE;
  683.      move(mem[tseg:toff+(view_angle*6)],temp,6);
  684.      yi:=temp*(x_bound-x)+y;
  685.      next_x_cell := 0;
  686.    END
  687.    else
  688.    BEGIN
  689.      x_bound := (x AND $ffc0);
  690.      x_delta := -CELL_X_SIZE;
  691.      move(mem[tseg:toff+(view_angle*6)],temp,6);
  692.      yi := temp * (x_bound - x) + y;
  693.      next_x_cell := -1;
  694.    END;
  695.  casting:= 2;
  696.  xray:= 0;
  697.  yray:=0;
  698.  while casting>0 DO
  699.  BEGIN
  700.    if (xray<>INTERSECTION_FOUND) THEN
  701.    BEGIN
  702.    cell_x := ( (x_bound+next_x_cell) SHR CELL_X_SIZE_FP);
  703.      cell_y := trunc(yi);
  704.      cell_y:=cell_y SHR CELL_Y_SIZE_FP;
  705.      x_hit_type:=world[cell_y,cell_x];
  706.      IF not(enmove) AND (x_hit_type=11) THEN move_guy(cell_x,cell_y,x,y);
  707.      IF x_hit_type>10 THEN dg:=true;
  708.      if (x_hit_type>0) AND (x_hit_type<11) THEN
  709.      BEGIN
  710.         move(mem[isseg:isoff+(view_angle*6)],temp,6);
  711.        dist_x  := round((yi - y) * temp);
  712.        yi_save := trunc(yi);
  713.        xb_save := x_bound;
  714.        xray := INTERSECTION_FOUND;
  715.        DEC(casting);
  716.     END
  717.     else
  718.     BEGIN
  719.      move(mem[yseg:yoff+(view_angle*6)],temp,6);
  720.       yi:=yi+temp;
  721.       x_bound:=x_bound+x_delta;
  722.     END;
  723.   END;
  724.   if (yray<>INTERSECTION_FOUND) THEN
  725.   BEGIN
  726.     cell_x :=trunc(xi);
  727.     cell_x:=cell_x SHR CELL_X_SIZE_FP;
  728.     cell_y := ( (y_bound + next_y_cell) SHR CELL_Y_SIZE_FP);
  729.     y_hit_type := world[cell_y,cell_x];
  730.     IF not(enmove) AND (y_hit_type=11) THEN move_guy(cell_x,cell_y,x,y);
  731.     IF y_hit_type>10 THEN dg:=true;
  732.     if (y_hit_type>0) AND (y_hit_type<11) THEN
  733.     BEGIN
  734.       move(mem[icseg:icoff+(view_angle*6)],temp,6);
  735.       dist_y  := round((xi- x) * temp);
  736.       xi_save := trunc(xi);
  737.       yb_save := y_bound;
  738.       yray := INTERSECTION_FOUND;
  739.       DEC(casting);
  740.     END
  741.      else
  742.      BEGIN
  743.         move(mem[xseg:xoff+(view_angle*6)],temp,6);
  744.        xi :=xi+temp;
  745.        y_bound :=y_bound+ y_delta;
  746.      END;
  747.   END;
  748. END;
  749.  if (dist_x < dist_y) THEN
  750.  BEGIN
  751.    move(mem[cseg:coff+(ray*6)],temp,6);
  752.    scale := trunc((temp/dist_x));
  753.    if (scale>(MAX_SCALE)) THEN scale:=(MAX_SCALE);
  754.    scaleoff := ofs(scales[scale]^);
  755.    scaleseg := seg(scales[scale]^);
  756.    if (scale>WINDOW_HEIGHT) THEN
  757.    BEGIN
  758.      sliver_clip := (scale-WINDOW_HEIGHT) SHR 1;
  759.      scale:=WINDOW_HEIGHT;
  760.    END
  761.    else
  762.     sliver_clip := 0;
  763.    sliver_scale   := scale;
  764.    sliver_texture:= sprite.frames[x_hit_type];
  765.    sliver_column  := (yi_save AND $003f);
  766.    sliver_top     := WINDOW_MIDDLE - (scale SHR 1);
  767.    sliver_ray     := ray;
  768.    fast_Render;
  769.   END
  770.     else
  771.     BEGIN
  772.       move(mem[cseg:coff+(ray*6)],temp,6);
  773.       scale := trunc((temp/dist_y));
  774.        if (scale>(MAX_SCALE)) THEN scale:=(MAX_SCALE);
  775.         scaleoff := ofs(scales[scale]^);
  776.         scaleseg := seg(scales[scale]^);
  777.        if (scale>WINDOW_HEIGHT) THEN
  778.        BEGIN
  779.          sliver_clip := (scale-WINDOW_HEIGHT) SHR 1;
  780.           scale:=WINDOW_HEIGHT;
  781.        END
  782.       else
  783.          sliver_clip := 0;
  784.        sliver_scale:= scale;
  785.        sliver_texture:= sprite.frames[y_hit_type+1];
  786.        sliver_column:= (xi_save AND $003f);
  787.        sliver_top:= WINDOW_MIDDLE - (scale SHR 1);
  788.        sliver_ray:= ray;
  789.        fast_Render;
  790.     END;
  791.     view_angle:=view_angle+1;
  792.     if (view_angle>=ANGLE_360) THEN view_angle:=0;
  793.   END;
  794. END;
  795.  
  796.  
  797. (*------------------ Procedure Draw_ground -------------------------------*)
  798.  
  799.  
  800.  
  801. PROCEDURE Draw_Ground;
  802. BEGIN
  803. move(mem[seg(floor^):ofs(floor^)],
  804.      mem[seg(double_buffer^):ofs(double_buffer^)],48640);
  805. END;
  806.  
  807.  
  808. (*--------------------- Function Get_Input ------------------------------*)
  809.  
  810. FUNCTION Get_Input:INTEGER;
  811.  
  812. VAR demo_data:char;
  813.  
  814. BEGIN
  815.   if (key_table[0]<>0) OR (key_table[1]<>0) OR (key_table[2]<>0)
  816.   OR (key_table[3]<>0) THEN
  817.       get_input:=1
  818.   else
  819.       get_input:=0;
  820. END;
  821.  
  822.  
  823.  
  824. (*------------------ Procedure New_Key_Int -------------------------------*)
  825.  
  826.  
  827. PROCEDURE New_Key_Int;interrupt;
  828.  
  829. VAR temp1,temp2,temp3:word;
  830.     test:string;
  831. BEGIN
  832.  asm
  833.    sti                    {re-enable interrups }
  834.    in al, KEY_BUFFER      {get the key that was pressed}
  835.    xor ah,ah              {zero out upper 8 bits of AX}
  836.    mov raw_key, ax        {store the key in global}
  837.    in al, KEY_CONTROL     {set the control register}
  838.    or al, 82h             {set the proper bits to reset the FF}
  839.    out KEY_CONTROL,al     {send the new data back to the control register}
  840.    and al,7fh
  841.    out KEY_CONTROL,al     {complete the reset}
  842.    mov al,20h
  843.    out INT_CONTROL,al     {re-enable interrupts}
  844.  end;
  845. CASE raw_key OF
  846.  MAKE_UP:key_table[INDEX_UP]:= 1;
  847.  MAKE_DOWN:key_table[INDEX_DOWN]:=1;
  848.  MAKE_RIGHT:key_table[INDEX_RIGHT]:=1;
  849.  MAKE_LEFT:key_table[INDEX_LEFT]:=1;
  850.  BREAK_UP:key_table[INDEX_UP]:=0;
  851.  BREAK_DOWN:key_table[INDEX_DOWN]:=0;
  852.  BREAK_RIGHT:key_table[INDEX_RIGHT]:=0;
  853.  BREAK_LEFT:key_table[INDEX_LEFT]:=0;
  854.  ELSE pressed:=true;
  855. END;
  856.  bloodon:=false;
  857.  if (raw_key=1) THEN
  858.  BEGIN
  859.    done:=1;
  860.  END
  861.  ELSE
  862.  if (raw_key=57)  THEN
  863.  begin
  864.    door_x := trunc(player_x + cos(6.28*player_view_angle/ANGLE_360)*6*15);
  865.    door_y := trunc(player_y + sin(6.28*player_view_angle/ANGLE_360)*6*15);
  866.    x_cell := (door_x DIV CELL_X_SIZE);
  867.    y_cell := (door_y DIV CELL_Y_SIZE);
  868.    IF ((x_cell=49) AND (y_cell=52)) OR ((x_cell=49) AND (y_cell=57)) OR
  869.    ((x_cell=50) AND (y_cell=60)) THEN world[y_cell,x_cell]:=0;
  870.    IF (x_cell=61) AND (y_cell=62) THEN
  871.    BEGIN
  872.      fade;
  873.      cls;
  874.      viewpcxfile('title.pcx');
  875.      setintvec(KEYBOARD_INT, Old_Key_Isr); {Get Normal Keyboard Interrupt}
  876.      blit_string(10,100,4,'YOU HAVE FOUND A WALDO',TRUE);
  877.      blit_string(10,110,4,'BUT NOT THE ONE WITHOUT SHOES',TRUE);
  878.      blit_string(10,120,4,'MAYBE HE''S ON THE NEXT LEVEL!!!',TRUE);
  879.      blit_string(10,130,4,'PRESS ENTER TO CONTINUE',TRUE);
  880.      REPEAT
  881.      UNTIL keypressed;
  882.      done:=1;
  883.    END;
  884.    IF (x_cell=58) AND (y_cell=62) THEN
  885.    BEGIN
  886.      IF gatesdead THEN world[y_cell,x_cell]:=0;
  887.    END
  888.    ELSE
  889.    if (world[y_cell,x_cell] = 9) OR (world[y_cell,x_cell] = 10) THEN
  890.    world[y_cell,x_cell]:=0;
  891.    IF world[y_cell,x_cell]>10 THEN hit_guy(x_cell,y_cell);
  892.    hand.cur_frame:=2;
  893.    hancount:=0;
  894.   end;
  895.   gettime(temp1,temp2,newtime,temp3);
  896.  IF newtime-lasttime>1 THEN BEGIN lasttime:=newtime; code:='' END;
  897.  IF (pressed) AND (raw_key=19) THEN
  898.  IF step_length=50 THEN step_length:=30 ELSE step_length:=50;
  899.  IF pressed AND (raw_char(raw_key)>'0') THEN
  900.  BEGIN
  901.    pressed:=false;
  902.    gettime(temp1,temp2,newtime,temp3);
  903.    lasttime:=newtime;
  904.    insert(raw_char(raw_key),code,length(code)+1);;
  905.  END;
  906. END;
  907.  
  908.  
  909.  
  910. (*----------------- Procedure do_code -------------------------------------*)
  911.  
  912.  
  913.  
  914. Procedure do_code;
  915.  
  916. VAR temp1,temp2,temp3:word;
  917.  
  918. BEGIN
  919.   IF code='canttouchthis' THEN
  920.         BEGIN
  921.           code:='';
  922.           touch:=not(touch);
  923.           gettime(temp1,temp2,lasttime,temp3);
  924.         END;
  925.         IF code='pong' THEN
  926.         BEGIN
  927.           code:='';
  928.           pong_main;
  929.           dseg:=seg(double_buffer^);            {Get segment of buffer}
  930.           doff:=ofs(double_buffer^);
  931.           viewpcxfile('panel.pcx');
  932.         END;
  933.         IF code='rambo' THEN
  934.         BEGIN
  935.           code:='';
  936.           rambo:=not(rambo);
  937.           gettime(temp1,temp2,lasttime,temp3);
  938.        END;
  939.          IF code='lizard' THEN
  940.         BEGIN
  941.           code:='';
  942.           lizard:=not(lizard);
  943.           gettime(temp1,temp2,lasttime,temp3);
  944.         END;
  945.         IF code='sniper' THEN
  946.         BEGIN
  947.           code:='';
  948.           sniper:=not(sniper);
  949.           gettime(temp1,temp2,lasttime,temp3);
  950.        END;
  951.        IF rambo THEN blit_string_d(70,10,10,'UNLIMITED AMMO');
  952.        IF touch THEN blit_string_d(70,20,10,'INVINCIBLE');
  953.        IF sniper THEN blit_string_d(70,30,10,'ONE-HIT KILLS');
  954.        IF lizard THEN
  955.        BEGIN
  956.          IF life<100 THEN life:=life+1;
  957.          blit_string_d(70,40,10,'REGENERATION');
  958.        END;
  959. END;
  960.  
  961.  
  962. (*-------------------- Proedure do_map ------------------------------------*)
  963.  
  964.  
  965. Procedure do_map(VAR x,y:INTEGER);
  966.  
  967. VAR c1,c2:INTEGER;
  968.  
  969. BEGIN
  970.   FOR c1:=-20 TO 19 DO
  971.   FOR c2:=-19 TO 20 DO
  972.     IF (c1+y<65) AND (c1+y>0) AND (c2+x>0) AND (c2+x<65) THEN
  973.     BEGIN
  974.     IF world[c1+y,c2+x]>8 THEN plot_pixel_fast(269+c1,175+c2,3)
  975.     ELSE IF world[c1+y,c2+x]>0 THEN plot_pixel_fast(269+c1,175+c2,4)
  976.     ELSE plot_pixel_fast(269+c1,175+c2,0);
  977.     END
  978.     ELSE plot_pixel_fast(269+c1,175+c2,0);
  979.     plot_pixel_fast(269,175,10);
  980. END;
  981.  
  982.  
  983.  
  984. (*---------------------- Procedure Global_Init --------------------------*)
  985.  
  986.  
  987.  
  988. PROCEDURE global_init;
  989.  
  990. VAR spriteim:pcximage;
  991.  
  992. BEGIN
  993. check_mem(spriteim,64000);
  994. loadpcxfile('waldo.pcx',spriteim);
  995. Sprite_Init(waldo,0,0,0,0,0,0,64,64);
  996. Get_sprite(spriteim,waldo,1,0,0);
  997. freemem(spriteim,64000);
  998. check_mem(spriteim,64000);
  999. loadpcxfile('gates.pcx',spriteim);
  1000. Sprite_Init(gates,0,0,0,0,0,0,64,64);
  1001. Get_sprite(spriteim,gates,1,0,0);
  1002. freemem(spriteim,64000);
  1003. check_mem(spriteim,64000);
  1004. loadpcxfile('monster.pcx',spriteim);
  1005. Sprite_Init(monster,0,0,0,0,0,0,64,64);
  1006. Get_sprite(spriteim,monster,1,0,0);
  1007. Get_sprite(spriteim,monster,2,1,0);
  1008. Get_sprite(spriteim,monster,3,2,0);
  1009. Get_sprite(spriteim,monster,4,3,0);
  1010. freemem(spriteim,64000);
  1011. check_mem(spriteim,64000);
  1012. loadpcxfile('wall3.pcx',spriteim);
  1013. Sprite_Init(sprite,0,0,0,0,0,0,64,64);
  1014. Get_sprite(spriteim,sprite,1,0,0);
  1015. Get_sprite(spriteim,sprite,2,1,0);
  1016. Get_sprite(spriteim,sprite,3,2,0);
  1017. Get_sprite(spriteim,sprite,4,3,0);
  1018. Get_sprite(spriteim,sprite,5,0,1);
  1019. Get_sprite(spriteim,sprite,6,1,1);
  1020. Get_sprite(spriteim,sprite,7,2,1);
  1021. Get_sprite(spriteim,sprite,8,3,1);
  1022. Get_sprite(spriteim,sprite,9,0,2);
  1023. Get_sprite(spriteim,sprite,10,1,2);
  1024. freemem(spriteim,64000);
  1025. check_mem(spriteim,64000);
  1026. loadpcxfile('light.pcx',spriteim);
  1027. Sprite_Init(light,0,0,0,0,0,0,50,45);
  1028. Get_sprite(spriteim,light,1,0,0);
  1029. freemem(spriteim,64000);
  1030. check_mem(spriteim,64000);
  1031. loadpcxfile('blood.pcx',spriteim);
  1032. Sprite_Init(blood,110,40,0,0,0,0,64,64);
  1033. Get_sprite(spriteim,blood,1,0,0);
  1034. freemem(spriteim,64000);
  1035. check_mem(spriteim,64000);
  1036. loadpcxfile('dagger.pcx',spriteim);
  1037. sprite_init(hand,150,55,0,0,0,0,108,101);
  1038. get_sprite(spriteim,hand,1,0,0);
  1039. get_sprite(spriteim,hand,2,1,0);
  1040. freemem(spriteim,64000);
  1041. check_mem(spriteim,64000);
  1042. loadpcxfile('arrow.pcx',spriteim);
  1043. Sprite_Init(arrow,78,170,0,0,0,0,13,13);
  1044. Get_sprite_coord(spriteim,arrow,1,0,0);
  1045. Get_sprite_coord(spriteim,arrow,2,14,0);
  1046. Get_sprite_coord(spriteim,arrow,3,28,0);
  1047. Get_sprite_coord(spriteim,arrow,4,41,0);
  1048. freemem(spriteim,64000);
  1049. check_mem(floor,64000);
  1050. loadpcxfile('back.pcx',floor);
  1051. Load_World('level1.dat');
  1052. life:=100;
  1053. step_length:=30;
  1054. pressed:=false;
  1055. loadvocfile('light.voc',lights);
  1056. loadvocfile('ugh.voc',ugh);
  1057. viewpcxfile('panel.pcx');
  1058. sprite.cur_frame := 1;
  1059. sprite.x          := 0;
  1060. sprite.y          := 0;
  1061. player_x:=53*64+25;
  1062. player_y:=14*64+25;
  1063. player_view_angle:=ANGLE_60;
  1064. code:='';
  1065. rambo:=false;
  1066. touch:=false;
  1067. lizard:=false;
  1068. sniper:=false;
  1069. lcounter:=20;
  1070. lx:=RANDOM(320);
  1071. light.y:=1;
  1072. behind_sprite_VB(arrow);
  1073. gatesdead:=false;
  1074. enmove:=false;
  1075. END;
  1076.  
  1077.  
  1078. PROCEDURE do_light;
  1079. BEGIN
  1080.   IF lcounter=0 THEN
  1081.   BEGIN
  1082.     lx:=RANDOM(320);
  1083.     lcounter:=40;
  1084.   END;
  1085.   IF lcounter=4 THEN
  1086.   play_sound(lights);
  1087.   IF lcounter<4 THEN
  1088.   BEGIN
  1089.     light.x:=lx;
  1090.     draw_sprite_f(light)
  1091.   END;
  1092.   lcounter:=lcounter-1;
  1093. END;
  1094.  
  1095.  
  1096. (*---------------- PROCEDURE MAIN --------------------------------------*)
  1097.  
  1098.  
  1099.  
  1100. PROCEDURE main;
  1101.  
  1102. VAR x_sub_cell,y_sub_cell:INTEGER;
  1103.     holder,dx,dy:real;
  1104.     test:string;
  1105.  
  1106. BEGIN
  1107. global_init;
  1108. Draw_Ground;
  1109. Ray_Caster(player_x,player_y,player_view_angle);
  1110. show_double_buffer_h;
  1111. setintvec(KEYBOARD_INT, ADDR(New_Key_Int));
  1112. while done<>1 DO
  1113. BEGIN
  1114.   if Get_Input=1 THEN
  1115.   begin
  1116.     dx:=0; dy:=0;
  1117.     if (key_table[INDEX_RIGHT]=1) THEN
  1118.     BEGIN
  1119.       player_view_angle:=player_view_angle-ANGLE_6;
  1120.       if (player_view_angle<ANGLE_0) THEN
  1121.           player_view_angle:=ANGLE_360;
  1122.     END
  1123.         else
  1124.         if (key_table[INDEX_LEFT]=1) THEN
  1125.         BEGIN
  1126.           player_view_angle:=player_view_angle+angle_6;
  1127.            if (player_view_angle>=ANGLE_360) THEN
  1128.               player_view_angle:=ANGLE_0;
  1129.         END;
  1130.         holder:=6.28*player_view_angle/ANGLE_360;
  1131.         if (key_table[INDEX_UP]=1) THEN
  1132.         BEGIN
  1133.            dx:=(cos(holder)*STEP_LENGTH);
  1134.            dy:=(sin(holder)*STEP_LENGTH);
  1135.         END
  1136.         else
  1137.         if (key_table[INDEX_DOWN]=1) THEN
  1138.         BEGIN
  1139.            dx:=(-cos(holder)*STEP_LENGTH);
  1140.            dy:=(-sin(holder)*STEP_LENGTH);
  1141.         END;
  1142.         player_x:= trunc((player_x+dx));
  1143.         player_y:= trunc((player_y+dy));
  1144.         x_cell := (player_x DIV CELL_X_SIZE);
  1145.         y_cell := (player_y DIV CELL_Y_SIZE);
  1146.         x_sub_cell := player_x MOD CELL_X_SIZE;
  1147.         y_sub_cell := player_y MOD CELL_Y_SIZE;
  1148.         if dx>0 THEN
  1149.         BEGIN
  1150.            if ( (world[y_cell,x_cell+1] <> 0) AND
  1151.                 (x_sub_cell > (CELL_X_SIZE-OVERBOARD)))
  1152.             THEN
  1153.             BEGIN
  1154.                 player_x:=player_x-(x_sub_cell-(CELL_X_SIZE-OVERBOARD ));
  1155.             END;
  1156.         END
  1157.         else
  1158.           BEGIN
  1159.             if ( (world[y_cell,x_cell-1] <> 0) AND
  1160.                 (x_sub_cell < (OVERBOARD) ) )  THEN
  1161.             BEGIN
  1162.               player_x:=player_x+ (OVERBOARD-x_sub_cell) ;
  1163.             END;
  1164.           END;
  1165.         if (dy>0 ) THEN
  1166.            BEGIN
  1167.            if ( (world[y_cell+1,x_cell] <> 0)  AND
  1168.                 (y_sub_cell > (CELL_Y_SIZE-OVERBOARD))) THEN
  1169.                 BEGIN
  1170.                 player_y:=player_y-(y_sub_cell-(CELL_Y_SIZE-OVERBOARD ));
  1171.            END;
  1172.         END
  1173.         else
  1174.           BEGIN
  1175.            if ( (world[y_cell-1,x_cell] <> 0) AND
  1176.                 (y_sub_cell < (OVERBOARD) ) )  THEN
  1177.              BEGIN
  1178.                 player_y:= player_y+(OVERBOARD-y_sub_cell);
  1179.             END
  1180.          end;
  1181.         end;
  1182.         Draw_Ground;
  1183.         do_light;
  1184.         dg:=false;
  1185.         Ray_Caster(player_x,player_y,player_view_angle);
  1186.         IF dg THEN Guy_CASTER(player_x,player_y,player_view_angle);
  1187.         IF bloodon THEN draw_sprite(blood);
  1188.         do_code;
  1189.         x_cell := (player_x DIV CELL_X_SIZE);
  1190.         y_cell := (player_y DIV CELL_Y_SIZE);
  1191.        do_map(x_cell,y_cell);
  1192.        IF ((player_view_angle<=240) OR (player_view_angle>=1680))
  1193.           AND (arrow.cur_frame<>1)  THEN
  1194.        BEGIN
  1195.          erase_sprite_VB(arrow);
  1196.          arrow.cur_frame:=1;
  1197.          behind_sprite_VB(arrow);
  1198.          draw_sprite_VBF(arrow);
  1199.        END;
  1200.        IF (player_view_angle>=720) AND (player_view_angle<=1200)
  1201.           AND (arrow.cur_frame<>2) THEN
  1202.        BEGIN
  1203.          erase_sprite_VB(arrow);
  1204.          arrow.cur_frame:=2;
  1205.          behind_sprite_VB(arrow);
  1206.          draw_sprite_VBF(arrow);
  1207.        END;
  1208.        IF (player_view_angle>240) AND (player_view_angle<720)
  1209.           AND (arrow.cur_frame<>3) THEN
  1210.        BEGIN
  1211.          erase_sprite_VB(arrow);
  1212.          arrow.cur_frame:=3;
  1213.          behind_sprite_VB(arrow);
  1214.          draw_sprite_VBF(arrow);
  1215.        END;
  1216.        IF (player_view_angle>1200) AND (player_view_angle<1680)
  1217.           AND (arrow.cur_frame<>4) THEN
  1218.        BEGIN
  1219.          erase_sprite_VB(arrow);
  1220.          arrow.cur_frame:=4;
  1221.          behind_sprite_VB(arrow);
  1222.          draw_sprite_VBF(arrow);
  1223.        END;
  1224.        IF (life<1) OR (life>100) THEN done:=1;
  1225.         str(life:3,test);
  1226.         test:=test+'%';
  1227.        IF step_length=30 THEN  blit_string_d(200,10,10,'Run Mode Off')
  1228.        ELSE   blit_string_d(200,10,10,'Run Mode On');
  1229.        IF (life>0) AND (life<=100) THEN blit_string(9,173,4,test,false);
  1230.        IF hand.cur_frame=2 THEN hancount:=hancount+1;
  1231.        IF hancount=3 THEN hand.cur_frame:=1;
  1232.        draw_sprite_f(hand);
  1233.        show_double_buffer_h;
  1234.        enmove:=false;
  1235. END;
  1236. fade;
  1237. free_scale_data;
  1238. setintvec(KEYBOARD_INT, Old_Key_Isr);
  1239. freemem(tan_table,6*angle_360);
  1240. freemem(inv_tan_table,6*angle_360);
  1241. freemem(y_step,6*angle_360);
  1242. freemem(x_step,6*angle_360);
  1243. freemem(cos_table,6*angle_360);
  1244. freemem(inv_cos_table,6*angle_360);
  1245. freemem(inv_sin_table,6*angle_360);
  1246. textmode(3);
  1247. END;
  1248.  
  1249.  
  1250. (*-------------------- Proceudre Opening --------------------------------*)
  1251.  
  1252. PROCEDURE opening;
  1253.  
  1254. VAR counter:INTEGER;
  1255.     holder:char;
  1256.  
  1257. BEGIN
  1258.   clrscr;
  1259.   Randomize;
  1260.   textcolor(white);
  1261.   textbackground(blue);
  1262.   gotoxy(1,1);
  1263.   write('           Cave Dweller-     Beta v',RANDOM(9),'.',RANDOM(9));
  1264.   write(RANDOM(9),RANDOM(9),RANDOM(9),RANDOM(9),RANDOM(9),
  1265.         RANDOM(9),'                                    ');
  1266.   textbackground(black);
  1267.   gotoxy(1,4);
  1268.   writeln('Memory Required: 320000');
  1269.   writeln('Memory Available: ',Memavail);
  1270.   IF memavail<320000 THEN errors(1);
  1271.   write('Initializing Black Dog Dos Protected Mode Runtime Interface .');
  1272.   build_tables;
  1273.   counter:=1;
  1274.   REPEAT
  1275.     delay(300);
  1276.     write('.');
  1277.     INC(counter);
  1278.   UNTIL counter=10;
  1279.   writeln;
  1280.   writeln('.....Uhh Sorry Can''t Initialize It, It''s Protected.');
  1281.   writeln('Initializing Cave Dweller Refresh Daemon [............]');
  1282.   writeln('By The Way, What Exactly Is A Refresh Daemon?????');
  1283.   writeln;
  1284.   writeln;
  1285.   write('Press Any Key To Continue.');
  1286.   Repeat Until Keypressed;
  1287.  
  1288.   holder:=readkey;
  1289.   init256graph;
  1290. END;
  1291.  
  1292.  
  1293. (*------------------ Procedure Blit_Char_DB ------------------------------*)
  1294.  
  1295.  
  1296. PROCEDURE Blit_Char_DB(xc,yc:INTEGER; c:char; color:INTEGER);
  1297.  
  1298. VAR offset,x,y,doff,dseg:INTEGER;
  1299.     work_char:byte;
  1300.     bit_mask:byte;
  1301.  
  1302. BEGIN
  1303. doff:=ofs(double_buffer^);
  1304. dseg:=seg(double_buffer^);
  1305. work_char:=mem[$f000:$fa6e+ (ord(c) * char_height-1)];
  1306. offset := (yc SHL 8) + (yc SHL 6) + xc;
  1307. for y:=0 to CHAR_HEIGHT-1 DO
  1308. BEGIN
  1309.   bit_mask:=$80;
  1310.   for x:=0 to CHAR_WIDTH-1 DO
  1311.   BEGIN
  1312.     if (work_char AND bit_mask)<>0 THEN
  1313.     mem[dseg:doff+offset+x]:=color;
  1314.     bit_mask:=(bit_mask SHR 1);
  1315.   END;
  1316.   offset := offset + SCREEN_WIDTH;
  1317.   work_char:=mem[$f000:$fa6e+ (ord(c) * char_height)+y];
  1318. END;
  1319. END;
  1320.  
  1321.  
  1322. (*------------------ Procedure Blit_String_DB ------------------------------*)
  1323.  
  1324.  
  1325. PROCEDURE Blit_String_DB(x,y,color:INTEGER; word:string);
  1326.  
  1327. VAR index:integer;
  1328.  
  1329. BEGIN
  1330.   FOR index:=1 TO length(word) DO
  1331.   BEGIN
  1332.     Blit_Char_DB(x+(index SHL 3),y,word[index],color);
  1333.   END;
  1334. END;
  1335.  
  1336.  
  1337. (*----------------------- Procedure Build_Path --------------------------*)
  1338.  
  1339.  
  1340. procedure buildpath;
  1341.    var
  1342.       count     : byte;
  1343.       currangle : real;
  1344.    begin
  1345.       currangle := pi;
  1346.       for count := 0 to 199 do
  1347.          begin
  1348.             path[count] := 320 + round(radius*sin(currangle));
  1349.  
  1350.             { the sin path _must_ lie on an even number }
  1351.             { otherwise the picture will be garbage     }
  1352.  
  1353.             if path[count] mod 2 <> 0 then
  1354.                if path[count] > 320 then
  1355.                   dec(path[count])            { round down }
  1356.                else
  1357.                   inc(path[count]);           { round up   }
  1358.  
  1359.             { the path is rounded to the closest even number to 320 }
  1360.  
  1361.             currangle := currangle + angleinc;
  1362.          end;
  1363.    end;
  1364.  
  1365.  
  1366. (*--------------------- Procedure Main_Menu ----------------------------*)
  1367.  
  1368.  
  1369. Procedure main_menu;
  1370.  
  1371. VAR choice,color,lchoice:byte;
  1372.     get:char;
  1373.     temp:rgb_color_typ;
  1374. begin
  1375.   setintvec(KEYBOARD_INT, Old_Key_Isr); {Get Normal Keyboard Interrupt}
  1376.   init_double_buffer;                   {Initialize Off Screen Buffer}
  1377.   dseg:=seg(double_buffer^);            {Get segment of buffer}
  1378.   doff:=ofs(double_buffer^);            {Get offset of buffer}
  1379.   check_mem(pcxim,64000);      {Check Memory, Available: Allocate; Not: Error}
  1380.   loadpcxfile('main.pcx',pcxim); {Load pcx file into pcxim}
  1381.   Sprite_Init(menu,31,8,0,0,0,0,263,26);{Initialize width and posistion}
  1382.   Get_sprite_coord(pcxim,menu,1,32,8);  {Grab sprite from pcxim}
  1383.   freemem(pcxim,64000);                 {Give back memory}
  1384.   randomize;
  1385.   buildpath;
  1386.   choice:=1;                            {initialize menu choice to first one}
  1387.   asm
  1388.      xor   ax,ax               { ; AX := 0                              }
  1389.      mov   cx,768              { ; CX := # of palette entries           }
  1390.      mov   dx,03C8h            { ; DX := VGA Port                       }
  1391.      mov   si,offset palette   { ; SI := palette[0]                     }
  1392.  
  1393.      out   dx,al               { ; send zero to index port              }
  1394.      inc   dx                  { ; inc to write port                    }
  1395.  
  1396.    @l1:
  1397.  
  1398.      mov   bl,[si]             { ; set palette entry                    }
  1399.      shr   bl,2                { ; divide by 4                          }
  1400.      mov   [si],bl             { ; save entry                           }
  1401.      outsb                     { ; and write to port                    }
  1402.      dec   cx                  { ; CX := CX - 1                         }
  1403.      jnz   @l1                 { ; if not done then loop                }
  1404.  
  1405.      mov   ax,seg buffer       { ; AX := segment of buffer              }
  1406.      mov   es,ax               { ; ES := AX                             }
  1407.      mov   di,offset buffer    { ; DI := buffer[0]                      }
  1408.      mov   cx,8109             { ; CX := sizeof(buffer) div 2           }
  1409.      xor   ax,ax               { ; AX := 0                              }
  1410.      rep   stosw               { ; clear every element in buffer to zero}
  1411.   end;
  1412.  
  1413.   repeat
  1414.  
  1415.      asm
  1416.         mov   bx,1             { ; BX := 1                              }
  1417.         mov   si,offset path   { ; SI := path[0]                        }
  1418.  
  1419.         mov   cx,16160         { ; CX := # of elements to change        }
  1420.         mov   di,offset buffer { ; DI := buffer[0]                      }
  1421.         add   di,320           { ; DI := buffer[320] (0,1)              }
  1422.  
  1423.      @l2:
  1424.  
  1425.         mov   ax,ds:[di-2]     { ; AX := buffer[DI-2]    (x-1,y)        }
  1426.         add   ax,ds:[di]       { ; AX += buffer[DI]      (x  ,y)        }
  1427.         add   ax,ds:[di+2]     { ; AX += buffer[DI+2]    (x+1,y)        }
  1428.         add   ax,ds:[di+320]   { ; AX += buffer[DI+320]  (x,y+1)        }
  1429.         shr   ax,2             { ; AX := AX div 4 (calc average)        }
  1430.  
  1431.         jz    @l3              { ; if AX = 0 then skip next line        }
  1432.         dec   ax               { ; else AX--                            }
  1433.  
  1434.      @l3:
  1435.  
  1436.         push  di               { ; save DI                              }
  1437.         sub   di,ds:[si]       { ; DI := (x + or - sin,y-1)             }
  1438.         mov   word ptr ds:[di],ax { store AX somewhere one line up      }
  1439.         pop   di               { ; restore DI                           }
  1440.  
  1441.         inc   di               { ; DI++                                 }
  1442.         inc   di               { ; DI++ (move to next word)             }
  1443.  
  1444.         inc   bx               { ; BX++                                 }
  1445.         cmp   bx,320           { ; if bx <> 320                         }
  1446.         jle   @l4              { ; then jump to @l4                     }
  1447.         mov   bx,1             { ; else BX := 1 (we're on a new line)   }
  1448.         inc   si               { ; point SI to next element in path     }
  1449.         inc   si               { ;                                      }
  1450.  
  1451.      @l4:
  1452.         dec   cx               { ; CX--                                 }
  1453.         jnz   @l2              { ; if CX <> 0 then loop                 }
  1454.      end;
  1455.  
  1456.      for count := 0 to 159 do {set new bottom line}
  1457.         begin
  1458.            if random < 0.4 then
  1459.               delta := random(2)*255;
  1460.            buffer[101,count] := delta;
  1461.            buffer[102,count] := delta;
  1462.         end;
  1463.  
  1464.      asm
  1465.         mov   si,offset buffer { ; SI := buffer[0]                      }
  1466.         mov   es,dseg            { ; ES := AX                             }
  1467.         mov   di,doff            { ; DI := 0                              }
  1468.         mov   dx,100           { ; DX := 100 (# of rows div 2)          }
  1469.  
  1470.      @l5:
  1471.         mov   bx,2             { ; BX := 2                              }
  1472.  
  1473.      @l6:
  1474.         mov   cx,160           { ; CX := 160 (# of cols div 2)          }
  1475.  
  1476.      @l7:
  1477.         mov   al,ds:[si]       { ; AL := buffer[si]                     }
  1478.         mov   ah,al            { ; AH := AL (replicate byte)            }
  1479.         mov   es:[di],ax       { ; store two bytes into video memory    }
  1480.         inc   di               { ; move to next word in VRAM            }
  1481.         inc   di               { ;                                      }
  1482.         inc   si               { ; move to next word in buffer          }
  1483.         inc   si               { ;                                      }
  1484.         dec   cx               { ; CX--                                 }
  1485.         jnz   @l7              { ; repeat until done with column        }
  1486.  
  1487.         sub   si,320           { ; go back to start of line in buffer   }
  1488.         dec   bx               { ; BX--                                 }
  1489.         jnz   @l6              { ; repeat until two columns filled      }
  1490.  
  1491.         add   si,320           { ; restore position in buffer           }
  1492.         dec   dx               { ; DX--                                 }
  1493.         jnz   @l5              { ; repeat until 100 rows filled         }
  1494.      end;
  1495.      IF lchoice<>choice THEN   {Did the choice change?}
  1496.      BEGIN
  1497.      color:=255;               {if so change the palette}
  1498.      temp.red   := 25 SHR 2;
  1499.      temp.green := 80 SHR 2;
  1500.      temp.blue  := 25 SHR 2;
  1501.      FOR color:=color DOWNTO 252 DO
  1502.         Set_Palette_Register(color,temp);
  1503.      temp.red   := 10 SHR 2;
  1504.      temp.green := 220 SHR 2;
  1505.      temp.blue  :=  25 SHR 2;
  1506.      CASE choice OF                    {highlight new choice}
  1507.       1: Set_Palette_Register(255,temp);
  1508.       2: Set_Palette_Register(254,temp);
  1509.       3: Set_Palette_Register(253,temp);
  1510.       4: Set_Palette_Register(252,temp);
  1511.      END;
  1512.      END;
  1513.      lchoice:=choice;
  1514.      IF keypressed THEN get:=readkey;        {If key was pressed, get it}
  1515.      IF get=char($50) THEN INC(choice); {IF up arrow increment choice}
  1516.      IF get=char($48) THEN DEC(choice); {IF down arrow decrement choice}
  1517.      IF choice<1 THEN choice:=4;        {IF out of limits loop}
  1518.      IF choice>4 THEN choice:=1;
  1519.      IF get<>chr(13) THEN get:=' ';     {IF input not enter clear it}
  1520.      draw_sprite_f(menu);                 {Draw Title on Screen, Over flames}
  1521.      blit_string_db(90,60,255,'START GAME');  {Write Menu Choices}
  1522.      blit_string_db(90,70,254,'SAVE GAME');
  1523.      blit_string_db(90,80,253,'LOAD GAME');
  1524.      blit_string_db(90,90,252,'QUIT');
  1525.      show_double_buffer_a;                   {Move buffer to Screen}
  1526.   until get=chr(13);                  {Until Enter}
  1527.   freemem(menu.frames[1],263*26);     {Deallocate Sprite Memory}
  1528.   fade;
  1529.   cls;
  1530.   IF choice=1 THEN main;              {Start Game}
  1531. end;
  1532.  
  1533. {------------------- MAIN PROGRAM ---------------------}
  1534.  
  1535. BEGIN
  1536. init_sound;
  1537. opening;
  1538. main_menu;
  1539. {main;}
  1540. fade;
  1541. END.
  1542.  
  1543.