10 REM EXPLORE FOR WALL 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 = 2 :REM Higher values make Buggy slower 140 : 150 REM MAIN PROGRAM 160 ON ERROR IF ERR=17 THEN GOTO 360 ELSE PROCend:REPORT:PRINT " at line "ERL:END 170 : 180 MODE 7 190 PROCsetup_general 200 PROCsetup_program 210 PROCintroduction 220 IF (?port AND 32) THEN PROCnogo : PROCend : END:REM Check if Buggy connected 230 : 240 MODE 4 250 PROCoff :REM Cursor off 260 VDU 19 , 1 , 7 ; 0 ;:REM White foreground 270 VDU 19 , 0 , 1 ; 0 ;:REM Red background 280 REPEAT UNTIL NOT INKEY(space) 290 PROCprepare 300 VDU 19 , 1 , 4 ; 0 ;:REM Blue foreground 310 VDU 19 , 0 , 7 ; 0 ;:REM White background 320 REM Disable edit keys 330 *FX 4,1 340 PROCexwall 350 : 360 MODE 7 370 PROCerror 380 END 390 : 400 REM PROCEDURES SPECIFICALLY FOR "EXPLORE FOR WALLS" 410 DEF PROCerror 420 LOCAL answer 430 CLS 440 PRINT TAB(0,1) CHR$130 +"BBC Buggy" 450 PRINT TAB(7,10)"1. " +program_name$ +"." 460 PRINT TAB(7,12)"2. Exit program." 470 PRINT TAB(3,20)"Your choice: "; 480 IF VAL(FNinput(1,"12")) = 1 THEN RUN 490 PROCcomplete 500 ENDPROC 510 : 520 DEF PROCprepare 530 PROCcentre (program_name$,1) 540 PROCscreen :REM Draw "Instrument panel" 550 VDU 28,0,31,39,24 :REM Text window 560 BGX = horiz DIV 2 570 BGY = vert DIV 2 580 VDU 29,640-(horiz DIV 2 * Xscale);320;:REM Graphics origin 590 PROCboundary (0,0,horiz,vert) 600 PROCcalcpos 610 PROCcalcbug (GRX,GRY,0) 620 PROCdrawbug 630 LX=GRX:LY=GRY:HX=GRX:HY=GRY 640 PROCcentre ("Put Buggy in centre of area as shown.",4) 650 PROCspace (6) 660 ENDPROC 670 : 680 DEF PROCexwall 690 PROCupdate 700 PROCcentre ("Press ESCAPE to exit program",4) 710 PROCcentre ("",6) 720 FOR boundary=1 TO 4 730 REPEAT 740 PROCmove_buggy (forwards,seekdistance,speedcontrol,bumpers) 750 UNTIL hit 760 IF angle= 0 THEN HY=FMY 770 IF angle= 90 THEN HX=FMX 780 IF angle=180 THEN LY=FMY 790 IF angle=270 THEN LX=FMX 800 PROCcrash (hit) 810 IF angle=270 THEN PROCrectangle (LX,LY,HX,HY) 820 IF boundary<4 THEN PROCmove_buggy (right,90,speedcontrol,nosensors) 830 NEXT boundary 840 PROCmove_buggy (left,270,speedcontrol,nosensors) :REM Unwind cable 850 horiz = (HX-LX)/Xscale 860 vert = (HY-LY)/ scale 870 VDU 26 :REM Reset text and graphics windows 880 CLS 890 PROCscreen 900 VDU 26 :REM Reset text and graphics windows 910 SOUND 1,-15,200,20 920 PROCcentre (" BOUNDARIES FOUND AND SCALED",1) 930 scale = 630/FNmax (horiz/1.776*Xfactor,vert) 940 Xscale = scale * Xfactor 950 VDU 29,640-(horiz DIV 2 * Xscale);320;:REM Graphics origin 960 PROCboundary (0,0,horiz,vert) 970 VDU 28,0,31,39,24:REM Text window 980 BGX = safedistance*FWD+BF 990 BGY = BGX 1000 PROCcalcpos 1010 PROCcalcbug (GRX,GRY,0) 1020 PROCdrawbug 1030 PROCcentre ("Area is approx. "+STR$(INT(horiz+0.5))+" cms by "+STR$(INT(vert+0.5))+" cms.",4) 1040 PROCupdate 1050 PROCspace (6) 1060 ENDPROC 1070 : 1080 DEF PROCintroduction 1090 CLS 1100 PROCoff 1110 PROCdouble (CHR$ 130 +program_name$ +CHR$ 135,-1,5) 1120 PROCcentre ("The Buggy will find the walls",12) 1130 PROCcentre ("surrounding its territory,",14) 1140 PROCcentre ("and draw on screen to scale.",16) 1150 PROCspace (21) 1160 ENDPROC 1170 : 1180 DEF PROCsetup_program 1190 program_name$= "EXPLORE FOR WALLS" 1200 angle = 0 :REM Buggy's compass bearing 1210 turn = 0 :REM temporary angle 1220 distance = 0 :REM default value 1230 seekdistance = 200 1240 hit = 0 :REM flag for bumpers 1250 LX=0:LY=0:HX=0:HY=0 1260 safedistance = (14-BF)/FWD 1270 scale = 2.5 :REM default value 1280 Xscale = scale * Xfactor :REM Xfactor set up in user area 1290 horiz = 1100 / Xscale 1300 vert = 600 / scale 1310 ENDPROC 1320 : 1330 REM UNIVERSAL BUGGY PROCEDURES 1340 DEF PROCboundary (X1,Y1,X2,Y2) 1350 X1 = X1 * Xscale 1360 X2 = X2 * Xscale 1370 Y1 = Y1 * scale 1380 Y2 = Y2 * scale 1390 PROCrectangle (X1,Y1,X2,Y2) 1400 VDU 24,X1;Y1;X2;Y2; :REM Graphics window 1410 ENDPROC 1420 : 1430 DEF PROCbug 1440 PROCdrawbug 1450 PROCcalcpos 1460 PROCcalcbug (GRX,GRY,angle) 1470 PROCdrawbug 1480 IF FNlimit (BGX,BGY,BF,BF,horiz-BF,vert-BF) THEN PROCwarn ("The Buggy is going off the screen!") ELSE PROCcentre ("Press ESCAPE to exit program",4) 1490 ENDPROC 1500 : 1510 DEF PROCcalcbug (X,Y,angle) 1520 REM Accesses BF,BR,CW,BW,scale,Xscale 1530 REM Alters Buggy screen co-ordinates 1540 LOCAL SN,CS,leftoffset,rightoffset,frontoffset,rearoffset 1550 frontoffset = RAD angle 1560 rearoffset = RAD (angle-180) 1570 leftoffset = RAD (angle- 90) 1580 rightoffset = RAD (angle+ 90) 1590 REM Front middle of bumpers 1600 FMX = X + BF * SIN frontoffset * Xscale 1610 FMY = Y + BF * COS frontoffset * scale 1620 REM Rear middle of chassis 1630 RMX = X + BR * SIN rearoffset * Xscale 1640 RMY = Y + BR * COS rearoffset * scale 1650 REM Left side of buggy 1660 SN = SIN leftoffset * Xscale 1670 CS = COS leftoffset * scale 1680 REM Left bumper 1690 LBX = FMX + BW * SN 1700 LBY = FMY + BW * CS 1710 REM Front left corner 1720 FLX = FMX + CW * SN 1730 FLY = FMY + CW * CS 1740 REM Rear left corner 1750 RLX = RMX + CW * SN 1760 RLY = RMY + CW * CS 1770 REM Right side of buggy 1780 SN = SIN rightoffset * Xscale 1790 CS = COS rightoffset * scale 1800 REM Right bumper 1810 RBX = FMX + BW * SN 1820 RBY = FMY + BW * CS 1830 REM Front right corner 1840 FRX = FMX + CW * SN 1850 FRY = FMY + CW * CS 1860 REM Rear right corner 1870 RRX = RMX + CW * SN 1880 RRY = RMY + CW * CS 1890 ENDPROC 1900 : 1910 DEF PROCcalcpos 1920 REM Updates Buggy co-ordinates 1930 LOCAL A 1940 angle = angle + turn 1950 A = RAD angle 1960 BGX = BGX + distance * FWD * SIN A 1970 BGY = BGY + distance * FWD * COS A 1980 GRX = BGX * Xscale 1990 GRY = BGY * scale 2000 distance = 0 2010 turn = 0 2020 ENDPROC 2030 : 2040 DEF PROCcrash (bumper) 2050 IF (bumper AND leftbumper)<>0 THEN MOVE LBX,LBY:PLOT 6,FMX,FMY:hit = -1 2060 IF (bumper AND rightbumper)<>0 THEN MOVE RBX,RBY:PLOT 6,FMX,FMY:hit = 1 2070 SOUND 0,-15,9+hit,4 :REM Different sound for each bumper 2080 VDU 29,0;0; :REM Graphics origin 2090 VDU 24,510;220;800;700; :REM Graphics window 2100 MOVE 510,270 : MOVE 580,270 2110 PLOT 86+hit,580,220 :REM Only the relevant triangle is filled 2120 MOVE 730,270 : MOVE 800,270 2130 PLOT 86-hit,730,220 2140 VDU 29,640-horiz DIV 2 * Xscale;320;:REM Graphics origin 2150 PROCboundary (0,0,horiz,vert) 2160 PROCmove_buggy (backwards,safedistance,speedcontrol,nosensors) 2170 VDU 29,0;0; :REM Graphics origin 2180 VDU 24,510;220;800;700; :REM Graphics window 2190 MOVE 510,270 : MOVE 580,270 2200 PLOT 87,580,220 :REM Delete both triangles 2210 MOVE 730,270 : MOVE 800,270 2220 PLOT 87,730,220 2230 VDU 29,640-horiz DIV 2 * Xscale;320;:REM Graphics origin 2240 PROCboundary (0,0,horiz,vert) 2250 ENDPROC 2260 : 2270 DEF PROCdrawbug 2280 REM Ensures good corners at rear 2290 MOVE LBX,LBY 2300 PLOT 6,RBX,RBY 2310 MOVE RLX,RLY 2320 PLOT 30,FLX,FLY 2330 MOVE RLX,RLY 2340 PLOT 30,RRX,RRY 2350 PLOT 30,FRX,FRY 2360 PLOT 70,RLX,RLY 2370 ENDPROC 2380 : 2390 DEF PROCend 2400 REM Switches motors off, resets cursor, EDIT & ESCAPE keys, buffers, and PRINT format 2410 PROCmotors_off 2420 PROCon 2430 *FX 4 2440 *FX 229 2450 *FX 15 2460 @% = 10 2470 ENDPROC 2480 : 2490 DEF PROCmotors_off 2500 ?port = 8 2510 ENDPROC 2520 : 2530 DEF PROCmotors_on 2540 ?port = 0 2550 ENDPROC 2560 : 2570 DEF PROCmove_buggy (direction,move,speed,sensors) 2580 count = 0 2590 hit = 0 2600 REPEAT 2610 count = count + 1 2620 ?port = direction :PROCdelay (speed) 2630 ?port = direction OR 2:PROCdelay (speed) 2640 hit = (?port AND sensors) 2650 UNTIL hit OR count>=move 2660 ?port=0 2670 IF direction = left THEN turn = turn - count 2680 IF direction = right THEN turn = turn + count 2690 IF direction = backwards THEN distance = distance - count 2700 IF direction = forwards THEN distance = distance + count 2710 PROCbug 2720 PROCupdate 2730 ENDPROC 2740 : 2750 DEF PROCnogo 2760 PROCcentre ("Buggy not connected, END OF PROGRAM.",21) 2770 PRINT 2780 ENDPROC 2790 : 2800 DEF PROCscreen 2810 REM "Instrument panel" 2820 VDU 28,0,30,39,24 :REM Text window 2830 CLS 2840 RESTORE 2850 FOR index = 1 TO 14 2860 READ M1,M2,D1,D2 2870 MOVE M1,M2 2880 DRAW D1,D2 2890 NEXT index 2900 PRINT TAB(6,0) "Position" 2910 PRINT TAB(19,0) "Deg" 2920 DATA 6, 280,1270, 280, 6, 210, 500, 210, 590, 210, 720, 210 2930 DATA 810, 210,1010, 210, 6, 140,1270, 140, 1070, 210,1270, 210 2940 DATA 150, 280, 150, 140, 500, 280, 500, 140, 590, 280, 590, 140 2950 DATA 720, 280, 720, 140, 810, 280, 810, 140, 1010, 280,1010, 140 2960 DATA 1070, 280,1070, 140, 1170, 280,1170, 210 2970 PROCedge 2980 ENDPROC 2990 : 3000 DEF PROCsetup_general 3010 REM Buggy dimensions are in centimetres 3020 BF = 3.9 :REM Buggy centre to bumper 3030 BR = 9 :REM Buggy centre to chassis rear 3040 CW = 6 :REM Half chassis width 3050 BW = 9 :REM Bumper width (1 side) 3060 FWD = 0.1431944:REM Travel (cms/pulse) 3070 safedistance = ( INT( SQR( BR*BR + CW*CW ) -BF )) / FWD +14 3080 REM Values to compare with port 3090 bumpers = 192 3100 leftbumper = 128 3110 rightbumper = 64 3120 nosensors = 0 3130 REM Keyboard control words 3140 uparrow = -58 3150 downarrow = -42 3160 leftarrow = -26 3170 rightarrow = -122 3180 space = -99 3190 nokey = -129 3200 escape = -113 3210 REM Port values for Buggy movement 3220 forwards = 0 3230 backwards = 5 3240 left = 4 3250 right = 1 3260 digit$ = "1234567890" :REM Acceptable characters for numeric input 3270 space$ = STRING$(36," ") 3280 @% = &303 :REM Print format 3290 ENVELOPE 3,1,5,-5,5,10,10,10,5,0,-1,-1,126,0 3300 ENDPROC 3310 : 3320 DEF PROCupdate 3330 PRINT TAB(6,2) INT(BGX+0.5) "," INT(BGY+0.5) 3340 angle = (360+angle) MOD 360 3350 PRINT TAB(19,2) angle 3360 ENDPROC 3370 : 3380 DEF PROCwarn (text$) 3390 PROCcentre (text$,4) 3400 SOUND &103,3,100,10 3410 SOUND &102,3,117,10 3420 ENDPROC 3430 : 3440 : 3450 REM UTILITIES 3460 DEF PROCcentre (text$,line) 3470 PRINT TAB(1,line) SPC 38 3480 PRINT TAB( FNcentre (text$),line) text$; 3490 ENDPROC 3500 : 3510 DEF FNcentre (text$) =19-LEN(text$) DIV 2 3520 : 3530 DEF PROCcomplete 3540 CLS 3550 PROCdouble (CHR$ 131 +"Mission completed.",-1,10) 3560 PROCend 3570 ENDPROC 3580 : 3590 DEF PROCdelay (period) 3600 LOCAL index 3610 FOR index = 1 TO period : NEXT index 3620 ENDPROC 3630 : 3640 DEF PROCdouble (text$,X,Y) 3650 IF X<0 THEN X = FNcentre (text$) 3660 PRINT TAB(X-1,Y ) CHR$ 141;text$ 3670 PRINT TAB(X-1,Y+1) CHR$ 141;text$ 3680 ENDPROC 3690 : 3700 DEF PROCedge 3710 PROCrectangle (6,6,1274,1018) 3720 ENDPROC 3730 : 3740 DEF FNinput (length,allowed$) 3750 LOCAL input$,ascii 3760 PRINT STRING$(length,".");STRING$(length,CHR$ 8); 3770 PROCon:*FX 15 3780 REPEAT ascii = ASC FNwait 3790 IF ascii=127 AND LEN(input$)>0 THEN input$ = LEFT$(input$,LEN(input$)-1):VDU ascii 3800 IF INSTR(allowed$,CHR$ ascii) AND LEN(input$)13 AND ascii<>127 THEN ascii = 7 3810 IF ascii=13 AND LEN(input$)<1 THEN ascii = 7 3820 IF ascii=127 THEN VDU 46,8 ELSE VDU ascii 3830 UNTIL ascii=13:PRINT:PROCoff 3840 =input$ 3850 : 3860 DEF FNlimit (X,Y,X1,Y1,X2,Y2) 3870 IF X>X1 AND XY1 AND YB THEN =A ELSE =B 3910 : 3920 DEF FNmin (A,B) 3930 IF A"" 4190 *FX 4 4200 =I$ 4210 :