Example: Bomb Squad (*Create Version)
|
10 ! *********************************************************************
20 ! Example: Bomb Squad (*CREATE Version)
30 !
40 ! This program demonstrates the use of the CLOCK widget in TIMER mode
50 ! by playing a game in which the user has to disarm a bomb by cutting
60 ! wires. There are 10 wires - you must cut the correct four to disarm
70 ! the bomb. Of the six wires left, four are don't-cares and two wires
80 ! cause the bomb go off immediately.
90 !
100 ! The wires are represented by 10 TOGGLEBUTTONs. This program uses the
110 ! SYSTEM widget to create the TOGGLEBUTTONs. This is convenient since
120 ! otherwise you would have to have some degree of separate code for
130 ! each TOGGLEBUTTON. The fact that you only get one event for all
140 ! 10 TOGGLEBUTTONs is all right, too, since each time a TOGGLEBUTTON
150 ! event happens, the program scans through all the TOGGLEBUTTONs to
160 ! check their VALUEs.
170 !
180 ! ********************************************************************
190 !
200 RANDOMIZE INT(10^7*FRACT(TIMEDATE)) ! Set random seed
210 !
220 ! Miscellaneous general-purpose variables
230 !
240 INTEGER N,V
250 DIM S$[256],B$(1:1)[64],Eol$[2]
260 Eol$=CHR$(13)
270 !
280 ! Variables for display and widget handling
290 !
300 INTEGER Nlines,D(1:4) ! Used for display setup
310 REAL Dw,Dh ! Display dimensions
320 REAL Px,Py,Pw,Ph,Iw,Ih ! Main PANEL parameters
330 REAL Gap,Bh,Bw,Ch,Cw,Cx,Cy ! Button/Clock dimensions
340 REAL Prh,Prw,Prx,Pry ! Printer widget dimensions
350 !
360 ! Various variables for playing the game
370 !
380 INTEGER Playgame ! Indicates game in progress
390 INTEGER Wires(1:10) ! Designates wire settings
400 INTEGER Live,Kill,Dontcare,Cut ! Wire values
410 DATA 1,2,3,4
420 READ Live,Deadly,Dontcare,Cut
430 INTEGER Livewires,Lethal ! Number of live/deadly wires
440 !
450 ! Set up display
460 !
470 CLEAR SCREEN
480 STATUS CRT,13;Nlines ! Get number of display lines
490 GESCAPE CRT,3;D(*) ! Get BASIC display size
500 Dw=D(3)-D(1) ! Display width
510 Dh=(D(4)-D(2))*((Nlines-7)/Nlines) ! Display height above softkeys
520 !
530 ! Set up PANEL coordinates
540 !
550 Pw=Dw*.7
560 Ph=Dh*.9
570 Px=(Dw-Pw)/2
580 Py=(Dh-Ph)/2
590 !
600 ! Create a SYSTEM widget
610 !
620 COM @Sys
630 ASSIGN @Sys TO WIDGET "SYSTEM"
640 !
650 ! Create a PANEL on the SYSTEM widget with SYSTEM MENU attribute
660 !
670 CONTROL @Sys;SET ("*NAME":"Main","*CREATE":"PANEL","VISIBLE":0)
680 CONTROL @Sys;SET ("RESIZABLE":0,"MAXIMIZABLE":0)
690 CONTROL @Sys;SET ("X":Px,"Y":Py,"WIDTH":Pw,"HEIGHT":Ph)
700 CONTROL @Sys;SET ("TITLE":" Example: Bomb Squad (*CREATE)")
710 CONTROL @Sys;SET ("SYSTEM MENU":"Quit")
720 !
730 ! Get interior dimensions of PANEL
740 !
750 STATUS @Sys;RETURN ("INSIDE WIDTH":Iw,"INSIDE HEIGHT":Ih)
760 !
770 ! Set up widget coordinates and dimensions
780 !
790 Gap=Ih*.03 ! Vertical gap
800 Bh=Ih*.1 ! Button height
810 Bw=Iw*.2 ! Button width
820 !
830 Ch=Iw*.20 ! Clock height
840 Cw=Ch ! Clock Width
850 Cx=Bw+((Iw-Bw)-Cw)/2 ! Clock X location
860 Cy=Gap ! Clock Y coordinate
870 !
880 Prh=Ih-(Ch+3*Gap) ! Printer height
890 Prw=((Iw-Bw)-2*Gap) ! Printer width
900 Prx=Bw+Gap ! Printer X coordinate
910 Pry=Ch+2*Gap ! Printer Y coordinate
920 !
930 ! Set up buttons in PANEL. The SYSTEM widget is used
940 ! to good advantage here, since the same code can
950 ! create all ten TOGGLEBUTTONS.
960 !
970 FOR N=1 TO 10
980 S$=VAL$(N)
990 CONTROL @Sys;SET ("*NAME":"Main/T"&S$,"*CREATE":"TOGGLEBUTTON")
1000 CONTROL @Sys;SET ("X":0,"Y":(N-1)*Bh,"WIDTH":Bw,"HEIGHT":Bh)
1010 CONTROL @Sys;SET ("LABEL":"Wire "&S$)
1020 NEXT N
1030 !
1040 ! Create CLOCK, set up as down-counting TIMER. The TIMER
1050 ! limit does not have to be set - it is 0 by default.
1060 !
1070 CONTROL @Sys;SET ("*NAME":"Main/Clock","*CREATE":"CLOCK")
1080 CONTROL @Sys;SET ("X":Cx,"Y":Cy,"WIDTH":Cw,"HEIGHT":Ch)
1090 CONTROL @Sys;SET ("TYPE":"TIMER","TIMER DIRECTION":"DOWN")
1100 !
1110 ! Create PRINTER
1120 !
1130 CONTROL @Sys;SET ("*NAME":"Main/Printer","*CREATE":"PRINTER")
1140 CONTROL @Sys;SET ("X":Prx,"Y":Pry,"WIDTH":Prw,"HEIGHT":Prh)
1150 !
1160 ! Set up events for SYSTEM MENU, TOGGLEBUTTONS, and CLOCK
1170 !
1180 ON EVENT @Sys,"SYSTEM MENU",15 GOTO Finis
1190 ON EVENT @Sys,"CHANGED" GOSUB Cutwire
1200 ON EVENT @Sys,"TIMER" GOSUB Boomboom
1210 !
1220 ! Turn on panel
1230 !
1240 CONTROL @Sys;SET ("*NAME":"Main","VISIBLE":1)
1250 !
1260 ! Display instructions using a DIALOG
1270 !
1280 S$="Disarm the bomb before the clock times out"&Eol$
1290 S$=S$&Eol$
1300 S$=S$&"The bomb has ten wires:"&Eol$
1310 S$=S$&Eol$
1320 S$=S$&" - 4 wires are inert."&Eol$
1330 S$=S$&" - 4 wires must be cut to disarm the bomb."&Eol$
1340 S$=S$&" - 2 wires are triggers: cut both, "&Eol$
1350 S$=S$&" and the bomb goes off."&Eol$
1360 S$=S$&Eol$
1370 S$=S$&"GOOD LUCK!"&Eol$
1380 !
1390 B$(1)="Click Here To Begin Game"
1400 !
1410 DIALOG "INFORMATION",S$;SET ("TITLE":" Bomb Squad Instructions","JUSTIFICATION":"LEFT","BACKGROUND":9,"PEN":0,"DIALOG BUTTONS":B$(*))
1420 !
1430 ! Main game loop
1440 !
1450 LOOP
1460 !
1470 ! Clear PRINTER widget, set up all the "wires"
1480 !
1490 DISABLE
1500 CONTROL @Sys;SET ("*NAME":"Main/Printer","TEXT":"")
1510 CALL Pr(" Welcome to BOMB SQUAD.")
1520 CALL Pr("")
1530 !
1540 FOR N=1 TO 10
1550 Wires(N)=Dontcare
1560 S$=VAL$(N)
1570 CONTROL @Sys;SET ("*NAME":"Main/T"&S$)
1580 CONTROL @Sys;SET ("SENSITIVE":1,"VALUE":0)
1590 NEXT N
1600 !
1610 ! Set up the deadly wires
1620 !
1630 Lethal=0
1640 REPEAT
1650 N=1+INT(10*RND)
1660 IF Wires(N)=Dontcare THEN
1670 Wires(N)=Deadly
1680 Lethal=Lethal+1
1690 END IF
1700 UNTIL (Lethal=2)
1710 !
1720 ! Set up the live wires
1730 !
1740 Livewires=0
1750 REPEAT
1760 N=1+INT(10*RND)
1770 IF Wires(N)=Dontcare THEN
1780 Wires(N)=Live
1790 Livewires=Livewires+1
1800 END IF
1810 UNTIL (Livewires=4)
1820 !
1830 ! Set the timer to 30 seconds, and start it running
1840 !
1850 CONTROL @Sys;SET ("*NAME":"Main/Clock")
1860 CONTROL @Sys;SET ("TIMER VALUE":30000,"TIMER STATE":"RUNNING")
1870 !
1880 ! Loop until game over. Note how the "Playgame" variable is
1890 ! set to 1 by EVENT-driven routines to tell the main routine
1900 ! that the game is over and that a new one should be started
1910 ! (by returning to the top of the loop).
1920 !
1930 ENABLE
1940 Playgame=0
1950 REPEAT
1960 UNTIL (Playgame=1)
1970 !
1980 END LOOP
1990 STOP
2000 !
2010 ! This routine checks the status of the "wire" togglebuttons.
2020 ! It relies on the "Wires" array to track the condition
2030 ! of the wire set at any time.
2040 !
2050 ! The following comments may help explain the routine.
2060 !
2070 Cutwire: !
2080 !
2090 ! Check status of all ten wires
2100 !
2110 FOR N=1 TO 10
2120 !
2130 ! Ignore the wire if it has been cut
2140 !
2150 IF Wires(N)<>Cut THEN
2160 !
2170 ! Otherwise, query the togglebutton value
2180 !
2190 S$=VAL$(N)
2200 CONTROL @Sys;SET ("*NAME":"Main/T"&S$)
2210 STATUS @Sys;RETURN ("VALUE":V)
2220 !
2230 ! Ignore the button if it is not set, otherwise ...
2240 !
2250 IF V=1 THEN
2260 !
2270 ! ... disable the button ...
2280 !
2290 CONTROL @Sys;SET ("SENSITIVE":0)
2300 !
2310 ! ... and take the appropriate measures for the wire value
2320 !
2330 SELECT Wires(N)
2340 !
2350 ! Don't care, just say so
2360 !
2370 CASE Dontcare
2380 CALL Pr("Inert wire.")
2390 !
2400 ! Live wire: decrement the live-wire count - if it reaches 0,
2410 ! you win. Use a DIALOG to indicate the matter and query to see
2420 ! if the user wants to play another game. If it is not 0,
2430 ! announce the wire has been cut and list the number of wires
2440 ! remaining.
2450 !
2460 CASE Live
2470 Livewires=Livewires-1
2480 IF Livewires=0 THEN
2490 CONTROL @Sys;SET ("*NAME":"Main/Clock")
2500 CONTROL @Sys;SET ("TIMER STATE":"STOPPED")
2510 S$="Play another game?"
2520 DIALOG "QUESTION",S$,Btn;SET ("TITLE":" Bomb Disarmed !!")
2530 SELECT Btn
2540 CASE 0
2550 Playgame=1 ! Start new game
2560 RETURN
2570 CASE 1
2580 GOTO Finis ! Quit program
2590 END SELECT
2600 ELSE
2610 S$=VAL$(Livewires)
2620 CALL Pr("LIVE WIRE -- "&S$&" wires left.")
2630 END IF
2640 !
2650 ! Is deadly -- count down deadly wires, if zero, you are dead
2660 !
2670 CASE Deadly
2680 Lethal=Lethal-1
2690 IF Lethal=0 THEN
2700 GOSUB Boomboom
2710 RETURN
2720 ELSE
2730 CALL Pr("DANGER -- trigger wire, one left!")
2740 END IF
2750 END SELECT
2760 !
2770 ! If you have not either won or been killed, mark this wire as
2780 ! being "cut".
2790 !
2800 Wires(N)=Cut
2810 !
2820 END IF
2830 END IF
2840 NEXT N
2850 RETURN
2860 !
2870 ! This routine tells you that you are dead
2880 !
2890 Boomboom: !
2900 CONTROL @Sys;SET ("*NAME":"Main/Clock","TIMER STATE":"STOPPED")
2910 S$="YOU'RE DEAD!"
2920 S$=S$&Eol$&Eol$
2930 S$=S$&"Play another game?"
2940 DIALOG "QUESTION",S$,Btn;SET ("TITLE":" Bomb Exploded !!")
2950 IF Btn=0 THEN
2960 Playgame=1
2970 RETURN
2980 ELSE
2990 GOTO Finis
3000 END IF
3010 RETURN
3020 !
3030 ! Go here when done
3040 !
3050 Finis: !
3060 ASSIGN @Sys TO * ! Delete SYSTEM widget
3070 END
3080 !
3090 ! *************** End of Main Program ***********************
3100 !
3110 ! Routine to print string in PRINTER widget
3120 !
3130 SUB Pr(S$)
3140 COM @Sys
3150 CONTROL @Sys;SET ("*NAME":"Main/Printer","APPEND TEXT":S$)
3160 SUBEND