program canon; {$R+} {$I GRAPHICS} var ColorMap: Cmap; ScrollMap: Smap; label DemoLoop,quit,skip; const black: byte=0; green: byte=1; red: byte=2; yellow: byte=3; blue: byte=4; turquoise: byte=5; redviolet: byte=6; white: byte=7; grey: byte=8; avacado: byte=9; darkred: byte=10; orange: byte=11; purple: byte=12; brown: byte=13; burgandy: byte=14; pink: byte=15; var one_char:char; wind,charge,terrainslope,time:real; theta,ball_x,ball_y,P,Q,R,S,errors,angle: integer; sine: array[0..256] of real; rad_conv,rad_angle,V: real; a_sin: array [0..180] of real; My_terrain, Their_terrain, direction,Their_X, Their_Y, My_X, My_Y: integer; function KBDkill: boolean; var C: char; begin if KeyPressed then begin read(kbd,C,C); if C=' ' then KBDkill:=false else KBDkill:=true end else KBDkill:=false end; function anymore: boolean; var answer: longstring; begin charcursor(10,10); cursoron; charscale(5,7,6,14); repeat answer:='More? '; drawstring(answer); conread(answer,1); answer[1]:=Upcase(answer[1]); until (answer[1]='Y') or (answer[1]='N'); anymore:=(Upcase(answer[1])='Y'); end; procedure setup; const left=300; right=600; var my_center, their_center:integer; arrow: longstring; begin Direction:=-direction; If direction=1 then begin My_center:=300; their_center:=600 end else begin their_center:=300; My_center:=600 end; if random<0.5 then My_x:=My_center+random(120) else My_x:=My_center-random(120); if random<0.5 then My_y:=198+random(40) else My_y:=198-random(40); if random<0.5 then Their_x:=Their_center+random(120) else Their_x:=Their_center-random(120); if random<0.5 then Their_y:=198+random(40) else Their_y:=198-random(40); if random<0.5 then wind:=random(40) else wind:=-random(40); clearallplanes; {draw terrain} my_terrain:=my_x+direction*random(abs(my_x-my_center)); { My_terrain:=my_x+trunc(direction*(abs(My_x-My_center))*(0.2*random(3))); Their_terrain:=their_x+trunc(-direction*(abs(their_x-their_center))*(0.2*random(3))); } their_terrain:=their_x+-direction*random(abs(their_x-their_center)); terrainslope:=direction*(their_Y-My_y)/(their_terrain-My_terrain); if direction=1 then begin drawline(100,my_y,My_terrain,my_y); drawline(My_terrain,my_y,their_terrain,their_y); drawline(Their_terrain,their_y,799,their_y); end else begin drawline(799,my_y,My_terrain,my_y); drawline(My_terrain,my_y,Their_terrain,their_y); drawline(Their_terrain,their_y,100,their_y); end; drawbar(My_x-4,my_x+4,My_y-8,my_y); drawbar(Their_x-4,their_x+4,their_y-8,their_y); cursoroff; charcursor(390,120); charscale(10,12,20,24); if direction=1 then arrow:='->' else arrow:='<-'; drawstring(arrow); charscale(6,7,10,12); charcursor(390,30); if wind<0 then begin str(-wind:2:0,arrow); arrow:=concat(concat('<-wind: ',arrow),' mph') end else begin str(wind:2:0,arrow); arrow:=concat(concat('wind: ',arrow),' mph->'); end; drawstring(arrow); end; procedure get_input; var question,answer: longstring; code: integer; begin charscale(5,7,6,14); cursoron; repeat question:='Angle[0-180]? '; charcursor(600,10); drawstring(question); question:='Angle[0-180]? '; charcursor(600,10); drawstring(question); conread(answer,3); if length(answer)=0 then theta:=-1 else Val(answer,theta,code); until (code=0) and ((theta>=0) and (theta<=180)) ; repeat question:='Charge[1-1000]? '; charcursor(600,40); drawstring(question); question:='Charge[1-1000]? '; charcursor(600,40); drawstring(question); conread(answer,4); if length(answer)=0 then charge:=-1 else Val(answer,charge,code); until (code=0) and ((charge>0) and (charge<=1000)); end; procedure fire; const drag=0.35; var old_ball_x, old_ball_y,i: integer; rad_theta: real; fly: boolean; drag_time: real; wind_effect: integer; function signum(x: real): integer; begin if x<0 then signum:=-1 else if x=0 then signum:=0 else signum:=1 end; function inbound(x,y: integer): boolean; begin inbound:=(((x<799) and (x>0)) and (y>0) and (y<240)) end; begin wind:=wind*1.5; wind_effect:=signum(wind)*signum(direction); repeat get_input; rad_theta:=theta*rad_conv; old_ball_x:=my_x; old_ball_y:=My_y; ball_x:=my_x+direction; ball_y:=my_y-1; fly:=true; time:=0.01; while fly do begin drag_time:=1-exp(-drag*time); ball_x:=My_x+trunc((direction*charge* (cos(rad_theta)/drag)*drag_time)+ wind_effect*(sin(rad_theta)*abs(wind)*drag)/20); charge:=charge+wind_effect*(abs(wind)*drag)/20; ball_y:=My_y-trunc((-32.2*time/drag)+(1/drag)*((charge*sin(rad_theta))+32.2/drag) *drag_time); if inbound(ball_x,ball_y) then drawline(old_ball_x,old_ball_y,ball_x,ball_y); if direction=1 then begin if (ball_x<=My_terrain) and (ball_y>My_y) then begin { writeln(lst,'stop 1'); } fly:=false; end else if (ball_x>=Their_terrain) and (ball_y>their_y) then begin { writeln(lst,'stop 2'); } fly:=false; end else if (ball_x>My_Terrain) and (ball_xMy_terrain) and (ball_y>My_y) then begin { writeln(lst,'stop 4'); } fly:=false end else if (ball_xtheir_y) then begin fly:=false; { writeln(lst,'stop 5'); } end else if (ball_xtheir_terrain) then if terrainslope<((ball_y-My_y)/-(ball_x-My_Terrain)) then begin { writeln(lst,'stop 6'); } fly:=false; end end; if (ball_y>240) or (ball_x>800) or (ball_x<1) then begin { writeln(lst,'stop 7'); } fly:=false; end; time:=time+0.05; old_ball_x:=ball_x; old_ball_y:=ball_y end; until (ball_xtheir_x-4); operation(2,15); for i:=1 to 15 do drawarc(Their_x,Their_y,i,0,128); operation(0,15); end; procedure instruct; begin Clrscr; writeln(' Canon is a DEC RAINBOW High Resolution game which simulates the'); writeln('firing of a canon. It is much like the usual BASIC games, with the'); writeln('addition of a wind factor, somewhat more enhanced terrain, and of'); writeln('course, hi-res graphics to trace out the path of the shot.'); writeln; writeln(' The object is to destroy the enemy''s fort by bombarding it and '); writeln('hitting the munitions dump at it''s center. For now, his scientific'); writeln('evolution has not developed balistics, so you are at a decided advantage'); writeln('To wit, he won''t shoot back at you.'); writeln; writeln(' The screen will show the terrain (two plateaus) with fortresses'); writeln('(currently rectangles). You are shooting in the direction of the arrow'); writeln('which appears roughly centerscreen. The wind direction and velocity'); writeln('is indicated at the top center of the screen. You are prompted (in the '); writeln('upper right corner) for the angle to tilt the cannon and then the charge'); writeln('to put in with the shot. The angle is in the range 0 (horizontal towards'); writeln('the enemy fort) to 180 (horizontal away from the enemy). The charge is '); writeln('a value in the range 1 to 1000. Usually a value from 100-300 is in order.'); writeln('Input the values, followed by RETURN. If you use all the digits allowed'); writeln('you won''t need to press return. The game re-prompts if you enter an'); writeln('invalid value.'); writeln(' Press any key to continue....'); read(kbd,one_char); Clrscr; writeln(' Through trial and error you should be able to gauge the proper input'); writeln('that will land the projectile on it''s target. After you enter the charge'); writeln('value, the projectile is fired, and you see a trace of it''s motion in the '); writeln('sky. You are encouraged to make whistling noises that increase in pitch'); writeln('with the height of the projectile, it helps heighten the drama.'); writeln; writeln(' If you miss, you will be re-prompted for the next set of angle and charge'); writeln('settings. When you hit the target, a mushroom-like cloud will billow'); writeln('forth from the enemy''s fort. You will be prompted (in the upper left hand'); writeln('corner of the screen) to see if you want to play more. Answer either'); writeln('with a Y or N (no carriage return necessary).'); writeln; writeln(' If the projectile goes off the screen horizontally, the simulation'); writeln('will stop. If it goes off vertically, the simulation continues and the '); writeln('projectile will reappear on the downside as long as it doesn''t break the'); writeln('horizontal rule.'); writeln; writeln(' To stave off boredom, the terrain will change and the arrow (indicating '); writeln('the direction that you shoot, remember) will reverse for the next game'); writeln(' Press any key to continue....'); read(kbd,one_char); Clrscr; end; begin { required initialization } Write('Welcome to Canon. Instructions?[Y/N] '); read(kbd,one_char); one_char:=Upcase(one_char); writeln(one_char); while not (one_char in ['Y','N']) do begin write('Instructions?[Y/N] '); read(kbd,one_char); one_char:=Upcase(one_char); writeln(one_char); end; if one_char='Y' then instruct; writeln('Initializing...please wait...'); for P:=0 to 64 do Gsine[P]:=sin(P*0.0245437); { used by DrawArc } LeftMargin:=15;RightMargin:=15; { used by DrawString } TopMargin:=10;BottomMargin:=10; { used by DrawString } for P:=0 to 255 do ScrollMap[P]:=P; ColorMap[00]:=$00; ColorMap[16]:=$00; { 0 black } ColorMap[01]:=$0F; ColorMap[17]:=$F0; { 1 green } ColorMap[02]:=$F0; ColorMap[18]:=$06; { 2 red } ColorMap[03]:=$FF; ColorMap[19]:=$F0; { 3 yellow } ColorMap[04]:=$00; ColorMap[20]:=$0F; { 4 blue } ColorMap[05]:=$0F; ColorMap[21]:=$FD; { 5 turquoise } ColorMap[06]:=$F0; ColorMap[22]:=$0F; { 6 red-violet } ColorMap[07]:=$FF; ColorMap[23]:=$FF; { 7 white } ColorMap[08]:=$88; ColorMap[24]:=$88; { 8 grey } ColorMap[09]:=$58; ColorMap[25]:=$81; { 9 avacado } ColorMap[10]:=$90; ColorMap[26]:=$02; { 10 dark red } ColorMap[11]:=$F7; ColorMap[27]:=$70; { 11 orange } ColorMap[12]:=$80; ColorMap[28]:=$0B; { 12 purple } ColorMap[13]:=$B7; ColorMap[29]:=$75; { 13 brown } ColorMap[14]:=$B1; ColorMap[30]:=$16; { 14 burgandy } ColorMap[15]:=$FB; ColorMap[31]:=$BB; { 15 pink } HighResolution:=true; { Change to 'true' for high resolution demo } Ginitialize; { Initialize } LoadScrollMap(ScrollMap); { Load scroll map } LoadColorMap(ColorMap); { Load color map } DualMonitor:=false; { Dual CRTs } { end of required initialization } ClearAllPlanes; Operation(0,15); { REPLACE write to all planes } Pattern(255,4); { Draw all lines as solid lines } preblanking:=true; for P:=0 to 64 do begin V:=Gsine[P]; sine[P]:=V; sine[128-P]:=V; sine[128+P]:=-V; sine[256-P]:=-V end; rad_conv:=(pi*2)/360.0; rad_angle:=0; for angle:=0 to 180 do begin a_sin[angle]:=sin(rad_angle); rad_angle:=rad_angle+rad_conv end; Graphicson; direction:=-1; repeat setup; Fire; until not anymore; graphicsoff end.