10 REM EXPLORE FOR OBJECT 20 REM Keith Anderson 30 REM (c) CET 1983 Published by BBC Publications 40 REM version 2.0 50 : 60 REM PORT SETUP 70 port = &FE60 :REM User port (see manual for details). 80 ?&FE62 = 15 :REM 00001111; 0 = input; 1 = output 90 PROCmotors_on 100 : 110 REM USER AREA 120 Xfactor = 1.175 :REM Adjust slightly on inaccurate TV sets 130 speedcontrol = 8 140 : 150 REM MAIN PROGRAM 160 REM Detect arrow keys 170 *FX 4,1 180 MODE 7 190 PROCsetup_general 200 PROCsetup_program 210 : 220 ON ERROR IF ERR=17 THEN GOTO 240 ELSE PROCend:REPORT:PRINT " on line"ERL:END 230 PROCintroduction 240 MODE7 250 IF (?port AND 32) THEN PROCnogo : PROCend : END :REM Check if Buggy connected 260 PROCoff :REM Cursor off 270 REPEAT 280 VDU 26 :REM Reset text & graphics windows 290 CLS 300 PROCmenu 310 IF option=1 THEN MODE 4 : PROCgo1 : MODE 7 320 UNTIL option=2 330 : 340 MODE 7 350 PROCcomplete 360 END 370 : 380 : 390 REM PROCEDURES SPECIFICALLY FOR "EXPLORE FOR OBJECT" 400 DEF PROCanti_clock_search 410 FOR side = 1 TO 3 420 PROChitobject 430 PROCcrash (hit) 440 PROCmove_bug (right,90,bumpers) 450 PROCmove_bug (forwards,sidestep,bumpers) 460 IF hit THEN ENDPROC :REM boundary 470 PROCmove_bug (backwards,safedistance,nosensors) 480 PROCmove_bug (left,90,bumpers) 490 PROCmove_bug (forwards,safedistance+20,bumpers) 500 IF hit THEN GOTO 430 510 REM Found corner 520 PROCmove_bug (backwards,safedistance+20,nosensors) 530 PROCmove_bug (right,90,bumpers) 540 PROCmove_bug (forwards,15,bumpers) 550 PROCmove_bug (left,90,bumpers) 560 PROCmove_bug (forwards,safedistance+(BF/FWD)+10,bumpers) 570 PROCmove_bug (left,90,bumpers) 580 PROCmove_bug (forwards,sidestep*1.5,bumpers) 590 NEXT side 600 PROChitobject 610 PROCcrash (hit) 620 ENDPROC 630 : 640 DEF PROCclock_search 650 PROCcrash (hit) 660 PROCmove_bug (left,180,bumpers) 670 PROCmove_bug (forwards,BW/FWD,bumpers) 680 PROCmove_bug (right,90,bumpers) 690 PROCmove_bug (forwards,BW/FWD,bumpers) 700 FOR try = 1 TO 3 710 PROChitobject 720 PROCcrash (hit) 730 PROCmove_bug (left,90,bumpers) 740 PROCmove_bu on line"ž:à 230 PROCintroduction 240 MODE7 250 IF (?port AND 32) THEN PROCnogo : PROCend : END :REM Check if Buggy connected 260 PROCoff :REM Cursor off 270 REPEAT 280 VDU 26 :REM Reset text & graphics windows 290 CLS 300 PROCmenu 310 IF option=1 THEN MODE 4 : PROCgo1 : MODE 7 320 UNTIL option=2 330 : 340 MODE 7 350 PROCcomplete 360 END 370 : 380 : 390 REM PROCEDURES SPECIFICALLY FOR "EXPLORE FOR OBJECT" 400 DEF PROCanti_clock_search 410 FOR side = 1 TO 3 420 PROChitobject 430 PROCcrash (hit) 440 PROCmove_bug (right,90,bumpers) 450 PROCmove_bug (forwards,sidestep,bumpers) 460 IF hit THEN ENDPROC :REM boundary 470 PROCmove_bug (backwards,safedistance,nosensors) 480 PROCmove_bug (left,90,bumpers) 490 PROCmove_bug (forwards,safedistance+20,bumpers) 500 IF hit THEN GOTO 430 510 REM Found corner 520 PROCmove_bug (backwards,safedistance+20,nosensors) 530 PROCmove_bug (right,90,bumpers) 540 PROCmove_bug (forwards,15,bumpers) 550 PROCmove_bug (left,90,bumpers) 560 PROCmove_bug (forwards,safedistance+(BF/FWD)+10,bumpers) 570 PROCmove_bug (left,90,bumpers) 580 PROCmove_bug (forwards,sidestep*1.5,bumpers) 590 NEXT side 600 PROChitobject 610 PROCcrash (hit) 620 ENDPROC 630 : 640 DEF PROCclock_search 650 PROCcrash (hit) 660 PROCmove_bug (left,180,bumpers) 670 PROCmove_bug (forwards,BW/FWD,bumpers) 680 PROCmove_bug (right,90,bumpers) 690 PROCmove_bug (forwards,BW/FWD,bumpers) 700 FOR try = 1 TO 3 710 PROChitobject 720 PROCcrash (hit) 730 PROCmove_bug (left,90,bumpers) 740 PROCmove_bug (forwards,(BW*2)/FWD,bumpers) 750 IF hit THEN ENDPROC 760 PROCmove_bug (backwards,safedistance,nosensors) 770 PROCmove_bug (right,90,bumpers) 780 PROCmove_bug (forwards,safedistance+(BF/FWD),bumpers) 790 IF hit THEN GOTO 720 800 PROCmove_bug (right,90,bumpers) 810 PROCmove_bug (forwards,(BW*3)/FWD,bumpers) 820 NEXT try 830 PROChitobject 840 PROCcrash (hit) 850 ENDPROC 860 : 870 DEF PROCdraw_object 880 MOVE KLX,KLY 890 MOVE KHX,KLY 900 PLOT 85, KHX,KHY 910 MOVE KLX,KHY 920 PLOT 85, KLX,KLY 930 ENDPROC 940 : 950 DEF PROCexplore_object 960 KHX = horiz * Xscale 970 KHY = vert * scale 980 KLX = 0 990 KLY = 0 1000 PROCupdate 1010 PROCcentre ("Press ESCAPE to exit program.",4) 1020 grid_end = FALSE 1030 PROCgrid_search 1040 IF off_screen THEN grid_end = TRUE 1050 IF grid_end THEN ENDPROC 1060 PROCanti_clock_search 1070 IF side<3 THEN PROCclock_search 1080 PROCdraw_object 1090 PROCcentre ("Object found, I want to go home!",4) 1100 SOUND 1,-15,200,20 1110 PROCspace (6) 1120 PROCcentre ("",6) 1130 ENDPROC 1140 : 1150 DEF PROCgo_home 1160 LOCAL count,left_side,bottom 1170 left_side = FALSE 1180 bottom = FALSE 1190 count = 0 1200 REPEAT 1210 count = count + 1 1220 IF angle<>270 THEN PROCmove_bug (right,270-angle,bumpers) 1230 PROCmove_bug (backwards,(14-BGX)/FWD,nosensors) 1240 PROCmove_bug (forwards,(BGX-14)/FWD,bumpers) 1250 IF hit=0 THEN left_side = TRUE 1260 IF hit THEN PROCmove_bug (backwards,safedistance,nosensors) 1270 IF left_side=TRUE AND bottom=FALSE AND count>1 AND KHX1 AND KHY 4 1350 PROCmove_bug (right,180,bumpers) 1360 IF count > 4 THEN SOUND 1,-15,200,20 : PROCcentre ("Someone is trying to confuse me !",4):PROCspace (6) 1370 SOUND 1,-15,200,20 1380 ENDPROC 1390 : 1400 DEF PROCget_ready1 1410 VDU 26 :REM Reset text and graphics windows 1420 CLS 1430 PROCscreen :REM Draw "Instrument panel" 1440 VDU 26 :REM Reset text and graphics windows 1450 PROCcentre (program_name$,1) 1460 VDU 29,640-(horiz DIV 2*Xscale);320;:REM Set Graphics origin 1470 PROCboundary (0,0,horiz,vert) 1480 VDU 28,0,31,39,24 :REM Text window 1490 PROCcalcpos 1500 PROCcalcbug (GRX,GRY,0) 1510 PROCdrawbug 1520 ENDPROC 1530 : 1540 DEF PROCgo1 1550 PROCscale 1560 VDU 19,1,7;0; :REM white foreground 1570 VDU 19,0,1;0; :REM red background 1580 BGX = 14 1590 BGY = 14 1600 off_screen = FALSE 1610 PROCget_ready1 1620 PROCspace (6) 1630 REPEAT UNTIL INKEY(nokey) 1640 VDU 19,0,7,0,0,0 :REM White background 1650 VDU 19,1,4,0,0,0 :REM Blue foreground 1660 PROCcentre ("",6) 1670 angle = 0 1680 distance = 0 1690 PROCexplore_object 1700 PROCmove_bug (backwards,safedistance,nosensors) 1710 PROCgo_home 1720 PROCget_ready1 1730 IF NOT grid_end THEN PROCdraw_object 1740 IF NOT grid_end THEN PROCcentre ("Object is approx. "+STR$(INT((KHX-KLX)/Xscale+0.5))+" by "+STR$(INT((KHY-KLY)/scale+0.5))+" cms.",4) 1750 IF grid_end THEN PROCcentre ("No object found.",4) 1760 PROCupdate 1770 PROCspace (6) 1780 ENDPROC 1790 : 1800 DEF PROCgrid_search 1810 LOCAL sweep1,sweep2 1820 grid_end = FALSE 1830 sweep1 = (vert-(BGY+BF+1))/FWD 1840 sweep2 = (vert-(safedistance*FWD+(BF+1)*2))/FWD 1850 sidestep = (BW*2)/FWD 1860 PROCmove_bug (forwards,sweep1,bumpers) 1870 IF hit OR off_screen THEN ENDPROC 1880 PROCmove_bug (backwards,safedistance,nosensors) 1890 PROCmove_bug (right,90,bumpers) 1900 PROCmove_bug (forwards,sidestep,bumpers) 1910 IF hit OR off_screen THEN ENDPROC 1920 PROCmove_bug (right,90,bumpers) 1930 PROCmove_bug (forwards,sweep2,bumpers) 1940 IF hit OR off_screen THEN ENDPROC 1950 PROCmove_bug (backwards,safedistance,nosensors) 1960 PROCmove_bug (left,90,bumpers) 1970 PROCmove_bug (forwards,sidestep,bumpers) 1980 IF hit OR off_screen THEN ENDPROC 1990 PROCmove_bug (left,90,bumpers) 2000 PROCmove_bug (forwards,sweep2,bumpers) 2010 GOTO 1870 2020 : 2030 DEF PROChitobject 2040 IF angle=0 THEN KLY = FMY 2050 IF angle=90 THEN KLX = FMX 2060 IF angle=180 THEN KHY = FMY 2070 IF angle=270 THEN KHX = FMX 2080 ENDPROC 2090 : 2100 DEF PROCintroduction 2110 CLS 2120 PROCoff 2130 PROCdouble (CHR$130 +program_name$ +CHR$135,-1,5) 2140 PROCcentre ("The Buggy will search its",12) 2150 PROCcentre ("territory for an object,",14) 2160 PROCcentre ("map it, and return home.",16) 2170 PROCspace ( 21 ) 2180 ENDPROC 2190 DEF PROCmenu 2200 CLS 2210 PRINT TAB(0,1) CHR$130 +"BBC Buggy" 2220 PRINT TAB(7,10) "1. " +program_name$ +"." 2230 PRINT TAB(7,12) "2. Exit program." 2240 PRINT TAB(3,20) "Your choice: "; 2250 option = VAL( FNinput (1,"12")) 2260 ENDPROC 2270 : 2280 DEF PROCscale 2290 scale = 10 2300 Xscale = scale * Xfactor 2310 VDU 19,1,7;0; :REM white foreground 2320 VDU 19,0,1;0; :REM red background 2330 CLS 2340 PROCcentre ("Put Buggy as shown in corner of area;",2) 2350 PROCcentre (" centre of track 14 cms from the edh flag 2750 off_screen = FALSE :REM Out-of-limits flag 2760 ENDPROC 2770 : 2780 REM UNIVERSAL BUGGY PROCEDURES 2790 DEF PROCboundary (X1,Y1,X2,Y2) 2800 X1 = X1 * Xscale 2810 X2 = X2 * Xscale 2820 Y1 = Y1 * scale 2830 Y2 = Y2 * scale 2840 PROCrectangle (X1,Y1,X2,Y2) 2850 VDU 24,X1;Y1;X2;Y2; :REM Graphics window 2860 ENDPROC 2870 : 2880 DEF PROCbug 2890 PROCdrawbug 2900 PROCcalcpos 2910 PROCcalcbug (GRX,GRY,angle) 2920 PROCdrawbug 2930 IF FNlimit (BGX,BGY,BF,BF,horiz-BF,vert-BF) THEN PROCwarn ("The Buggy is going off the screen!") :hit = 1 :off_screen = TRUE ELSE PROCcentre ("Press ESCAPE to exit program",4) 2940 ENDPROC 2950 : 2960 DEF PROCcalcbug (X,Y,angle) 2970 REM Accesses BF,BR,CW,BW,scale,Xscale 2980 REM Alters Buggy screen co-ordinates 2990 LOCAL SN,CS,leftoffset,rightoffset,frontoffset,rearoffset 3000 frontoffset = RAD angle 3010 rearoffset = RAD (angle-180) 3020 leftoffset = RAD (angle- 90) 3030 rightoffset = RAD (angle+ 90) 3040 REM Front middle of bumpers 3050 FMX = X + BF * SIN frontoffset * Xscale 3060 FMY = Y + BF * COS frontoffset * scale 3070 REM Rear middle of chassis 3080 RMX = X + BR * SIN rearoffset * Xscale 3090 RMY = Y + BR * COS rearoffset * scale 3100 REM Left side of buggy 3110 SN = SIN leftoffset * Xscale 3120 CS = COS leftoffset * scale 3130 REM Left bumper 3140 LBX = FMX + BW * SN 3150 LBY = FMY + BW * CS 3160 REM Front left corner 3170 FLX = FMX + CW * SN 3180 FLY = FMY + CW * CS 3190 REM Rear left corner 3200 RLX = RMX + CW * SN 3210 RLY = RMY + CW * CS 3220 REM Right side of buggy 3230 SN = SIN rightoffset * Xscale 3240 CS = COS rightoffset * scale 3250 REM Right bumper 3260 RBX = FMX + BW * SN 3270 RBY = FMY + BW * CS 3280 REM Front right corner 3290 FRX = FMX + CW * SN 3300 FRY = FMY + CW * CS 3310 REM Rear right corner 3320 RRX = RMX + CW * SN 3330 RRY = RMY + CW * CS 3340 ENDPROC 3350 : 3360 DEF PROCcalcpos 3370 REM Updates Buggy co-ordinates 3380 LOCAL A 3390 angle = angle + turn 3400 A = RAD angle 3410 BGX = BGX + distance * FWD * SIN A 3420 BGY = BGY + distance * FWD * COS A 3430 GRX = BGX * Xscale 3440 GRY = BGY * scale 3450 distance = 0 3460 turn = 0 3470 ENDPROC 3480 : 3490 DEF PROCcrash (bumper) 3500 IF (bumper AND leftbumper)<>0 THEN MOVE LBX,LBY:PLOT 6,FMX,FMY:hit = -1 3510 IF (bumper AND rightbumper)<>0 THEN MOVE RBX,RBY:PLOT 6,FMX,FMY:hit = 1 3520 SOUND 0,-15,9+hit,4 :REM Different sound for each bumper 3530 VDU 29,0;0; :REM Graphics origin 3540 VDU 24,510;220;800;700; :REM Graphics window 3550 MOVE 510,270 : MOVE 580,270 3560 PLOT 86+hit,580,220 :REM Only the relevant triangle is filled 3570 MOVE 730,270 : MOVE 800,270 3580 PLOT 86-hit,730,220 3590 VDU 29,640-horiz DIV 2 * Xscale;320;:REM Graphics origin 3600 PROCboundary (0,0,horiz,vert) 3610 PROCmove_bug (backwards,safedistance,nosensors) 3620 VDU 29,0;0; :REM Graphics origin 3630 VDU 24,510;220;800;700; :REM Graphics window 3640 MOVE 510,270 : MOVE 580,270 3650 PLOT 87,580,220 :REM Delete both triangles 3660 MOVE 730,270 : MOVE 800,270 3670 PLOT 87,730,220 3680 VDU 29,640-horiz DIV 2 * Xscale;320;:REM Graphics origin 3690 PROCboundary (0,0,horiz,vert) 3700 ENDPROC 3710 : 3720 DEF PROCdrawbug 3730 REM Ensures good corners at rear 3740 MOVE LBX,LBY 3750 PLOT 6,RBX,RBY 3760 MOVE RLX,RLY 3770 PLOT 30,FLX,FLY 3780 MOVE RLX,RLY 3790 PLOT 30,RRX,RRY 3800 PLOT 30,FRX,FRY 3810 PLOT 70,RLX,RLY 3820 ENDPROC 3830 : 3840 DEF PROCend 3850 REM Switches motors off, resets cursor, EDIT & ESCAPE keys, buffers, and PRINT format 3860 PROCmotors_off 3870 PROCon 3880 *FX 4 3890 *FX 229 3900 *FX 15 3910 @% = 10 3920 ENDPROC 3930 : 3940 DEF PROCmotors_off 3950 ?port = 8 3960 ENDPROC 3970 : 3980 DEF PROCmotors_on 3990 ?port = 0 4000 ENDPROC 4010 : 4020 DEF PROCmove_bug (direction,move,sensors) 4030 LOCAL count 4040 count = 0 4050 hit = 0 4060 REPEAT 4070 count = count + 1 4080 ?port = direction :PROCdelay (speedcontrol) 4090 ?port = direction OR 2:PROCdelay (speedcontrol) 4100 hit = (?port AND sensors) 4110 UNTIL hit OR count>=move 4120 ?port=0 4130 IF direction = left THEN turn = turn - count 4140 IF direction = right THEN turn = turn + count 4150 IF direction = backwards THEN distance = distance - count 4160 IF direction = forwards THEN distance = distance + count 4170 PROCbug 4180 PROCupdate 4190 ENDPROC 4200 : 4210 DEF PROCnogo 4220 PROCcentre ("Buggy not connected, END OF PROGRAM.",21) 4230 PRINT 4240 ENDPROC 4250 : 4260 DEF PROCscreen 4270 REM "Instrument panel" 4280 VDU 28,0,30,39,24 :REM Text window 4290 CLS 4300 RESTORE 4310 FOR index = 1 TO 14 4320 READ M1,M2,D1,D2 4330 MOVE M1,M2 4340 DRAW D1,D2 4350 NEXT index 4360 PRINT TAB(6,0) "Position" 4370 PRINT TAB(19,0) "Deg" 4380 DATA 6, 280,1270, 280, 6, 210, 500, 210, 590, 210, 720, 210 4390 DATA 810, 210,1010, 210, 6, 140,1270, 140, 1070, 210,1270, 210 4400 DATA 150, 280, 150, 140, 500, 280, 500, 140, 590, 280, 590, 140 4410 DATA 720, 280, 720, 140, 810, 280, 810, 140, 1010, 280,1010, 140 4420 DATA 1070, 280,1070, 140, 1170, 280,1170, 210 4430 PROCedge 4440 ENDPROC 4450 : 4460 DEF PROCsetup_general 4470 REM Buggy dimensions are in centimetres 4480 BF = 3.9 :REM Buggy centre to bumper 4490 BR = 9 :REM Buggy centre to chassis rear 4500 CW = 6 :REM Half chassis width 4510 BW = 9 :REM Bumper width (1 side) 4520 FWD = 0.1431944:REM Travel (cms/pulse) 4530 safedistance = ( INT( SQR( BR*BR + CW*CW ) -BF )) / FWD +14 4540 REM Values to compare with port 4550 bumpers = 192 4560 leftbumper = 128 4570 rightbumper = 64 4580 nosensors = 0 4590 REM Keyboard control words 4600 uparrow = -58 4610 downarrow = -42 4620 leftarrow = -26 4630 rightarrow = -122 4640 space = -99 4650 nokey = -129 4660 escape = -113 4670 REM Port values for Buggy movement 4680 forwards = 0 4690 backwards = 5 4700 left = 4 4710 right = 1 4720 digit$ = "1234567890" :REM Acceptable characters for numeric input 4730 space$ = STRING$(36," ") 4740 @% = &303 :REM Print format 4750 ENVELOPE 3,1,5,-5,5,10,10,10,5,0,-1,-1,126,0 4760 ENDPROC 4770 : 4780 DEF PROCupdate 4790 PRINT TAB(6,2) INT(BGX+0.5) "," INT(BGY+0.5) 4800 angle = (360+angle) MOD 360 4810 PRINT TAB(19,2) angle 4820 ENDPROC 4830 : 4840 DEF PROCwarn (text$) 4850 PROCcentre (text$,4) 4860 SOUND &103,3,100,10 4870 SOUND &102,3,117,10 4880 ENDPROC 4890 : 4900 REM UTILITIES 4910 DEF PROCcentre(t$,l):PRINT TAB(1,l)SPC38:PRINT TAB(FNcentre(t$),l)t$;:ENDPROC 4920 DEF FNcentre(t$)=19-LEN(t$)DIV2 4930 DEF PROCcomplete:CLS:PROCdouble(CHR$131+"Mission completed.",-1,10):PROCend:ENDPROC 4940 DEF PROCdelay(p):LOCAL i:FOR i=1TO p:NEXT:ENDPROC 4950 DEF PROCdouble(t$,X,Y):IF X<0 THEN X=FNcentre(t$) 4960 PRINT TAB(X-1,Y)CHR$141;t$;TAB(X-1,Y+1)CHR$141;t$:ENDPROC 4970 DEF PROCedge:PROCrectangle(6,6,1274,1018):ENDPROC 4980 : 4990 DEF FNinput(l,a$):LOCAL i$,c 5000 PRINT STRING$(l,".");STRING$(l,CHR$8);:PROCon:*FX 15 5010 REPEAT:c=ASC FNwait:IF c=127 AND LEN(i$)>0 THEN i$=LEFT$(i$,LEN(i$)-1):VDU c 5020 IF INSTR(a$,CHR$ c) AND LEN(i$)13 AND c<>127 THEN c=7 5030 IF c=13 AND LEN(i$)<1 THEN c=7 5040 IF c=127 THEN VDU46,8 ELSE VDU c 5050 UNTIL c=13:PRINT:PROCoff 5060 =i$ 5070 DEF FNlimit(X,Y,X1,Y1,X2,Y2):IF X>X1 AND XY1 AND YB THEN=A ELSE=B 5090 DEF FNmin(A,B):IF A"" 5220 *FX 4 5230 =I$ 5240 :