INTRO 'DPD echo study originally written for the Commodore 128, rewritten in 'Turbo BASIC for the IBM on January 11, 1992 by W. Anthony Marsh. WIDTH "LPT1:",80 'set printer width at 80 columns. END INTRO ' DEFINE.VARIABLES DEFINT A-Z pi#=3.141592653589793238462643383 DIM milliseconds(22), corrected.milliseconds(22), elapsed.milliseconds(22) DIM elapsed.feet(22), calculated.distance(22), deviation(22), matches(22) DIM echo.feet(27), calculated.feet(27), object.x(27), object.y(27), object$(27) DIM sum.of.squares(9,9) c$=chr$(8):c2$=c$+c$:c3$=c2$+c$:c4$=c3$+c$:c5$=c4$+c$:c6$=c5$+c$:c7$=c6$+c$:c8$=c7$+c$ END DEFINE.VARIABLES ' GET.VARIABLES CLS LOCATE1,1:PRINT" DPD Echo Study "; LOCATE2,1:PRINT"This program will automatically compute matches betweeen the Dallas Police Dept."; LOCATE3,1:PRINT"recording of Ch.1 on Nov.22,1963 and estimated echoes using variables that you "; LOCATE4,1:PRINT"input, then print out the results. After computation, you can send the results "; LOCATE5,1:PRINT"to the printer by pressing P, or do 81 expanded calculations around the rifle "; LOCATE6,1:PRINT"and cycle positions by pressing B. Press N to start a new study, or Q to QUIT. "; LOCATE7,1:PRINT"To input the default values as shown, press RETURN or type in a new value." ' WHICH.SHOT LOCATE8,1:PRINT"Which shot do you want to study, 1, 2, or 5?" LOCATE9,1:PRINT" "; LOCATE9,1:PRINT"Shot? 1";c3$;:INPUT shot IF shot<1 or shot>5 or shot=3 or shot=4 THEN PRINT"1, 2 or 5 only!":GOTO WHICH.SHOT END WHICH.SHOT ' FIND.RIFLE LOCATE10,1:PRINT"From which window was it fired (0-14)?" LOCATE11,1:PRINT"Window #0 is in the DAL-TEX building." LOCATE12,1:PRINT"Window #1 is Oswald's nest in the TSBD." LOCATE13,1:PRINT"Windows 2 through 9 were closed." LOCATE14,1:PRINT"Windows 10 through 14 were open." LOCATE15,1:PRINT" "; LOCATE15,1:PRINT"Window? 1";c3$;:INPUT rifle.location SELECT CASE rifle.location CASE <0, >14 PRINT"Between 0-14 only!":GOTO FIND.RIFLE CASE 0 PRINT"Rifle X coordinate? 350.0";c7$;:INPUT start.rifle.x PRINT"Rifle Y coordinate? -41.0";c7$;:INPUT start.rifle.y rifle.z=172.4 CASE 1 PRINT"Rifle X coordinate? 321.25";c8$;:INPUT start.rifle.x PRINT"Rifle Y coordinate? 46.1";c6$;:INPUT start.rifle.y rifle.z=161.9 CASE 10 PRINT"Rifle X coordinate? 321.3";c7$;:INPUT start.rifle.x PRINT"Rifle Y coordinate? 106.7";c7$;:INPUT start.rifle.y rifle.z=162.3 CASE 11 PRINT"Rifle X coordinate? 321.1";c7$;:INPUT start.rifle.x PRINT"Rifle Y coordinate? 116.8";c7$;:INPUT start.rifle.y rifle.z=161.3 CASE 12 PRINT"Rifle X coordinate? 321.25";c8$;:INPUT start.rifle.x PRINT"Rifle Y coordinate? 121.2";c7$;:INPUT start.rifle.y rifle.z=161.7 CASE 13 PRINT"Rifle X coordinate? 321.6";c7$;:INPUT start.rifle.x PRINT"Rifle Y coordinate? 130.8";c7$;:INPUT start.rifle.y rifle.z=163.2 CASE 14 PRINT"Rifle X coordinate? 321.3";c7$;:INPUT start.rifle.x PRINT"Rifle Y coordinate? 134.0";c7$;:INPUT start.rifle.y rifle.z=161.5 CASE ELSE PRINT"Rifle X coordinate? 321.5";c7$;:input start.rifle.x PRINT"Rifle Y coordinate?";39+INT(rifle.location*6.7+.5);c5$;:INPUT start.rifle.y rifle.z=161.5 END SELECT END FIND.RIFLE ' SELECT CASE SHOT CASE 1 PRINT"Cycle X coordinate? 213.5";c7$;:INPUT start.cycle.x PRINT"Cycle Y coordinate? 21.0";c6$;:INPUT start.cycle.y cycle.z=100.1 CASE 2 PRINT"Cycle X coordinate? 232.0";c7$;:INPUT start.cycle.x PRINT"Cycle Y coordinate? 28.0";c6$;:INPUT start.cycle.y cycle.z=100.1 CASE 5 PRINT"Cycle X coordinate? 208.3";c7$;:INPUT start.cycle.x PRINT"Cycle Y coordinate? 129.5";c7$;:INPUT start.cycle.y cycle.z=95.1 END SELECT ' elevation=rifle.z-(cycle.z+3.0) 'open microphone is 3 feet above ground elevation ' GUESS.CYCLE.SPEED LOCATE 20,1:PRINT"Cycle speed in MPH? 8.5";c5$;:INPUT cycle.speed.mph IF cycle.speed.mph>35 THEN PRINT"Too fast for an escort! 5< MPH <35":GOTO GUESS.CYCLE.SPEED cycle.speed.fps=1.46666666666666667*cycle.speed.mph END GUESS.CYCLE.SPEED ' GUESS.CYCLE.ANGLE LOCATE 21,1:PRINT"Cycle deviation in degrees? "; SELECT CASE shot CASE 1 PRINT"12";c4$;:input cycle.angle CASE 2 PRINT"16";c4$;:input cycle.angle CASE 5 PRINT"35";c4$;:input cycle.angle END SELECT IF cycle.angle>45 THEN PRINT"Unlikely that it's over 45 degrees yet!":GOTO GUESS.CYCLE.ANGLE 'reasonable values: shot#1(8-18), shot#2(20-34), shot#5(35+90=125) END GUESS.CYCLE.ANGLE ' GUESS.TAPE.SPEED LOCATE 22,1:PRINT"Correction factor for tape speed? 1.043";c7$;:INPUT tape.correction.factor IF tape.correction.factor<.9 THEN PRINT"There's no evidence it's less than .9.":GOTO GUESS.TAPE.SPEED IF tape.correction.factor>1.1 THEN PRINT"There's no evidence it's more than 1.1.":GOTO GUESS.TAPE.SPEED LOCATE 23,1:PRINT" "; END GUESS.TAPE.SPEED ' radians=(pi#/2.0)-((cycle.angle/180)*pi#) ' GUESS.SOUND.SPEED LOCATE 23,1:PRINT"Speed of sound in FPS? 1123";c6$;:INPUT speed.of.sound.fps IF speed.of.sound.fps<1100 THEN PRINT"It wasn't that cold!":GOTO GUESS.SOUND.SPEED IF speed.of.sound.fps>1150 THEN PRINT"It wasn't that hot!":GOTO GUESS.SOUND.SPEED END GUESS.SOUND.SPEED ' RESTORE ' FOR I = 0 to 27 READ object.x(I), object.y(I), object$(I) NEXT DATA 320,40.3," No Match " DATA 276,72.5,"Trf. light" DATA 202.5,32.5,"TrafficBox" DATA 211,56.25," Pool tip " DATA 199.5,44.75," Pool, NE " DATA 272.5,97," Tree A " DATA 201.5,79.25," Column B " DATA 239.83333333,-40.3333333," DCRB, NW " DATA 265.75,113.1666666," Column A " DATA 319.5,-39,"DAL-TEX,SW" DATA 174,82," Tree N " DATA 248.5,142,"Wall A,NE " DATA 296.5,149," Tree D " DATA 179,120.25," Tree B " DATA 158.5,-40.3333333," DCRB, SW " DATA 132.5,31," Neon #1 " DATA 129.8333333,-39," DCCB, NW " DATA 227.5,182," Tree C " DATA 100.5,96," Column D " DATA 71,65.5," Monument " DATA 262,235," N.Shelter" DATA 39.25,76.5," Column C " DATA 38.5,-39," DCCB, SW " DATA 205,291," S.Shelter" DATA 161,287," Retn.wall" DATA -11,80," City bus " DATA -40,-40,"Old Court." DATA -315,50," P.O., NE " ' best.match = 25.0 'start with maximum default value rifle.x=start.rifle.x:rifle.y=start.rifle.y cycle.x=start.cycle.x:cycle.y=start.cycle.y 'main routine calculates echo paths ' IF shot=5 THEN shot=3 'to make it easier to read data statements FOR J = 1 TO shot FOR I = 1 TO 22 READ milliseconds IF J = shot THEN milliseconds(I) = ABS(milliseconds) NEXTI:NEXTJ ' shot#1 data DATA 30.625:rem hsca#1 DATA 41.875:rem marsh 1a rem 46.875 rem 51.25 DATA 56.25:rem marsh 1b rem 65 rem 68.75 rem 75 DATA 93.125:rem hsca#2 DATA 150:rem hsca#3 DATA 218.75:rem hsca#4 DATA 229.375:rem hsca#5 DATA 237.5:rem hsca#6 DATA 275:rem hsca#7 DATA 288.75:rem hsca#8 DATA 312.5:rem hsca#9 DATA 358.75:rem hsca#10 DATA 381.875:rem hsca#11 DATA 393.75 :rem marsh 11a DATA 424.375:rem hsca#12 DATA 465.625:rem hsca#13 DATA 480.625:rem hsca#14 DATA 633.75:rem marsh 14a DATA 653.75:rem hsca#15 DATA 682.5:rem marsh 15a DATA 1046.875:rem hsca#16 DATA 1106.25:rem hsca#17 ' last echo on chart ' ' shot#2 data DATA 15.625:rem hsca#1 DATA 25:rem hsca#2 DATA 34:rem marsh 2a DATA 41:rem marsh 2b DATA 47:rem hsca#3 rem 56 DATA 69:rem hsca#4 rem 79 rem 89 rem 94 rem 104 DATA 115.5:rem hsca#5 rem 138 rem 151 DATA 158:rem hsca#6 DATA 166:rem hsca#7 rem 172 rem 180 rem 189 rem 193 rem 198 rem 204 DATA 220:rem hsca#8 DATA 239:rem hsca#9 DATA 245:rem hsca#10 DATA 304.375:rem marsh 10a DATA 445:rem hsca#11 DATA 476.875:rem marsh 11a DATA 565:rem hsca#12 DATA 646.875:rem marsh 12a DATA 712.5:rem marsh 12b DATA 772.5:rem marsh 12c DATA 793.125:rem hsca#13 DATA 913.125:rem hsca#14 DATA 935.625:rem hsca#15 'last echo on tape ' rem shot#3 data not available rem shot#4 data not applicable ' shot#5 data DATA 48.75:rem hsca#1 DATA 62.5:rem marsh 1a DATA 67.5:rem marsh 1b DATA 74.375:rem hsca#2 DATA 79.375:rem marsh 2a DATA 87.5:rem hsca#3 DATA 110:rem marsh 3a DATA 158.75:rem hsca#4 DATA 186.875:rem marsh 4a DATA 220:rem hsca#5 DATA 234.375:rem marsh 5a DATA 246.875:rem marsh 5b DATA 254.375:rem hsca#6 DATA 286.25:rem marsh 6a DATA 322.5:rem hsca#7 DATA 336.25:rem hsca#8 DATA 368.125:rem marsh #9 DATA 403.125:rem marsh #10 DATA 428.75:rem marsh #11 DATA 462.5:rem marsh #12 DATA 473.125:rem marsh #13 DATA 493.75:rem marsh #14 ' last echo on chart ' FOR I = 1 to 22 corrected.milliseconds(I) = (tape.correction.factor*milliseconds(I)/1000) NEXTI LOCATE 24,1:PRINT"Each calculation takes a few seconds before results are printed out. WORKING......"; ' COMPUTE.ECHOES ' map.distance=SQR((rifle.x-cycle.x)*(rifle.x-cycle.x)+(rifle.y-cycle.y)*(rifle.y-cycle.y)) airblast=SQR(map.distance*map.distance+elevation*elevation) 'use Pythagorean theorem to calculate travel distance of gunshot blast factor=(airblast/speed.of.sound.fps)-corrected.milliseconds(1) 'how many milliseconds must be added to first echo to match blast time elapsed.milliseconds(0)=factor FOR I = 1 to 22 elapsed.milliseconds(I)=corrected.milliseconds(I)+factor elapsed.feet(I)=elapsed.milliseconds(I)*speed.of.sound.fps NEXTI calculated.feet(1)=elapsed.feet(1) 'now we calculate echo paths and look for matches FOR I = 2 to 22 echo.feet(I)=5.0:deviation(I)=5.0:matches(I)=0 cycle.travel=(elapsed.milliseconds(I)-elapsed.milliseconds(1))*cycle.speed.fps move.cycle.x=cycle.travel*COS(radians):IF shot=3 THEN move.cycle.x=-move.cycle.x move.cycle.y=cycle.travel*SIN(radians) next.cycle.x=cycle.x+move.cycle.x next.cycle.y=cycle.y+move.cycle.y 'cycle has moved since blast FOR echo = 1 to 27 first.half.x=rifle.x-object.x(echo) first.half.y=rifle.y-object.y(echo) first.half=SQR(first.half.x*first.half.x+first.half.y*first.half.y) last.half.x=next.cycle.x-object.x(echo) last.half.y=next.cycle.y-object.y(echo) last.half=SQR(last.half.x*last.half.x+last.half.y*last.half.y) total.path=first.half+last.half calculated.feet(echo)=SQR(total.path*total.path+elevation*elevation) echo.feet(echo)=ABS(elapsed.feet(I)-calculated.feet(echo)) IF echo.feet(echo)0 THEN PRINT"Rifle in TSBD # ";INT(rifle.location);" at"; PRINT USING "####.## ";rifle.x;:PRINT"x";:PRINT USING "####.## ";rifle.y"; PRINT" . Cycle X,Y at blast: "; PRINT USING "####.## ";cycle.x;:PRINT"x";:PRINT USING "####.## ";cycle.y"; LOCATE 1,80:PRINT"." LOCATE 2,1:PRINT"Millisecs Corrected Elapsed ms Elapsed ft Calc.feet Deviation Matches " LOCATE 3,1 FOR I = 1 to 22 PRINT USING "#####.## ";milliseconds(I); PRINT USING "##.###### ";corrected.milliseconds(I); PRINT USING "##.###### ";elapsed.milliseconds(I); PRINT USING "#####.#### ";elapsed.feet(I); PRINT USING "#####.#### #;calculated.distance(I); IF I=1 THEN PRINT USING "###.### ";deviation(1); IF I>1 IF deviation(I)>5.0 THEN PRINT"OVER 5.0 "; ELSE PRINT USING "###.#### ";deviation(I); END IF IF I=1 THEN PRINT" **BLAST** " ELSE PRINT object$(matches(I)) END IF NEXTI LOCATE 25,1:PRINT"Press P for PRINTOUT, B for 81 calculations, N to do a new study, or Q to QUIT."; END DISPLAY.RESULTS ' CHOOSE.OPTIONS a$="":a$=GETKEY$ IF a$="P" OR a$="p" THEN GOTO PRINT.RESULTS IF a$="B" OR a$="b" THEN GOTO BERNOULLI IF a$="N" OR a$="n" THEN GOTO GET.VARIABLES IF a$="Q" OR a$="q" THEN END GOTO CHOOSE.OPTIONS END CHOOSE.OPTIONS END ' PRINT.RESULTS IF rifle.location=0 THEN LPRINT"Rifle in DAL-TEX Building." IF rifle.location>0 THEN LPRINT"Rifle in window ";INT(rifle.location);" at"; PRINT USING "####.## ";rifle.x;:PRINT"x";:PRINT USING "####.## ";rifle.y"; PRINT" . Cycle X,Y at blast: "; PRINT USING "####.## ";cycle.x;:PRINT"x";:PRINT USING "####.## ";cycle.y"; LOCATE 1,80:PRINT"." LOCATE 2,1:PRINT"Millisecs Corrected Elapsed ms Elapsed ft Calc.feet Deviation Matches " LOCATE 3,1 FOR I = 1 to 22 PRINT USING "#####.## ";milliseconds(I); PRINT USING "##.###### ";corrected.milliseconds(I); PRINT USING "##.###### ";elapsed.milliseconds(I); PRINT USING "#####.#### ";elapsed.feet(I); PRINT USING "#####.#### #;calculated.distance(I); IF I=1 THEN PRINT USING "###.### ";deviation(1); IF I>1 IF deviation(I)>5.0 THEN PRINT"OVER 5.0 "; ELSE PRINT USING "###.#### ";deviation(I); END IF IF I=1 THEN PRINT" **BLAST** " ELSE PRINT object$(matches(I)) END IF NEXTI 604 if j=4 then rx=gx+.5:ry=gy-.5 605 if j=5 then rx=gx:ry=gy-.5 606 if j=6 then rx=gx-.5:ry=gy-.5 607 if j=7 then rx=gx-.5:ry=gy 608 if j=8 then rx=gx-.5:ry=gy+.5 609 if j=9 then rx=gx:ry=gy+.5 610 if rx<320 then rx=320 611 for k=1 to 9 612 if k=1 then nx=cx:ny=cy 613 if k=2 then nx=cx+.5:ny=cy+.5 614 if k=3 then nx=cx+.5:ny=cy 615 if k=4 then nx=cx+.5:ny=cy-.5 616 if k=5 then nx=cx:ny=cy-.5 617 if k=6 then nx=cx-.5:ny=cy-.5 618 if k=7 then nx=cx-.5:ny=cy 619 if k=8 then nx=cx-.5:ny=cy+.5 620 if k=9 then nx=cx:ny=cy+.5 621 rem move starting positions for rifle & cycle,then compute each sd 625 gosub 400 626 printchr$(19);:for i= 1 to 24: printchr$(17);:nexti:print" "; 627 printchr$(19);:for i= 1 to 24: printchr$(17);:nexti 628 print" J=";j;" Rifle at";:print using "####.##";rx;:print" by";:print using "####.##";ry; 629 print" : K=";k;"Cycle at";:print using "####.##";nx;:print" by";:print using "####.##";ny;:print""; 630 sd(j,k)=f(1) 632 if sd(j,k)=5 then print"OVER 5.0 ";:else print using"###.#### ";f(i); 845 if i=1 then print" **BLAST** ":else print o$(g(i)) 846 next i 847 printchr$(19); 848 for i= 1 to 24 : printchr$(17);:nexti 849 print"Press P to print out results, B for expanded calculations, or Q to QUIT. "; 850 if peek(145)=127 then end : rem stop key 851 if peek(212)=41 then gosub 860 : rem p for printout 852 if peek(212)=62 then end : rem q for quit 853 if peek(212)<>28 then 850 : rem b for bernoulli calculations 854 gx=rx:gy=ry:cx=nx:cy=ny 855 printchr$(19); 856 for i= 1 to 24 : printchr$(17);:nexti 857 print"Performing 81 Bernoulli calculations, each .5 feet away from starting positions"; 859 goto600 860 open4,4,7 861 print#4,"DPD Echo Study":ifshot=3thenprint#4,"Shot #5":goto 863 862 print#4,"Shot#";shot 863 ifwi=0thenprint#4,"Rifle in Dal-Tex Building.":goto 865 864 print#4,"Rifle in Window #"wi"on the sixth floor of the Texas School Book Depository" 865 print#4,"Rifle Coordinates:"rx"x"ry 866 print#4,"Cycle Coordinates at Blast:"nx"x"ny 867 print#4,"Cycle's initial speed"mph"mph." 868 print#4,"Cycle's path deviating "; 869 if shot<3 then print#4,"west from north by" ac "degrees." 870 if shot>2 then print#4,"south from west by" ac "degrees." 872 print#4,"Correction factor used for tape speed:"cf 873 print#4,"Speed of sound:"fps"fps.":print#4," " 874 print#4,"Millisec. Corrected Elapsed ms Elapsed ft Calc. feet Deviation Matches " 875 fori=1 to p 876 print#4,using "#####.### ";a(i); 877 print#4,using "##.####### ";b(i); 878 print#4,using "##.####### ";c(i); 879 print#4,using "#####.#### ";d(i); 880 print#4,using "#####.#### ";e(i); 881 if i=1 then print#4,using "###.#### ";f(1);:goto 885 882 if f(i)>=5 then print#4,"OVER 5.0 ";:else print#4,using "###.#### ";f(i); 885 if i=1 then print#4," **BLAST** ":else print#4,o$(g(i)) 889 next i 895 print#4,chr$(12):close4 899 return