!######################################################################## ! ! BUMPER.BAS ! ! by ! ! Hal S. Mothershed (PIG/AM) ! ! December 27, 1989 ! ! ! (Based on a dimly-remembered game from long ago) ! !######################################################################## ! ! Requires: INKEY.SBR ! !######################################################################## ! ! The object of the game is to guess the locations of 'bumpers' ! on the 10 X 24 position game board. A ball fired from a position ! on the side of the board will re-emerge at a point determined ! by the bounces it makes off of the hidden bumpers. There are ! only two types of bumpers, left (/) and right (\), and they have ! the following effects on the ball: ! ! ^ / ---<---* ! Left: | or | ! *--->--- / v ! ! *--->--- \ ^ ! Right: | or | ! v \ ---<---* ! ! ! Positions on the board are represented by a two-letter ! coordinate, in the format Rc, where R is the upper-case letter ! of the Row, and c is the lower-case letter of the column. ! ! The following commands are recognized: ! ! : Move to new firing position ! : Fire a ball ! G : Guess a bumper position ! : Quit ! !######################################################################## PROGRAM BUMPER,1.0A(100) ! 1.0A(100) HSM 27-DEC-89 ! !######################################################################## MAP 1 GRID(10,24),S,1 ! The Game board MAP 1 BUMPER'COUNT,F,6 ! Bumpers guessed MAP 1 NUM'BUMPERS,F,6 ! Total # of bumpers on board MAP 1 GUESSES,F,6 ! Guesses made MAP 1 BUMPER'MASK,S,20,"]0.................." ! Mask for creation of board MAP 1 PROB,B,1,20 ! Length of mask, bumper probability MAP 1 CURPOSX,B,1,1 ! Current firing row MAP 1 CURPOSY,B,1,0 ! Current firing column MAP 1 K$,S,1 ! Input from INKEY MAP 1 G$,S,2 ! Input guessed coordinate ! Constants: Keys input to INKEY MAP 1 UPARROW,S,1,CHR$(11) MAP 1 DNARROW,S,1,CHR$(10) MAP 1 LFARROW,S,1,CHR$(8) MAP 1 RTARROW,S,1,CHR$(12) MAP 1 ESCAPE,S,1,CHR$(27) MAP 1 GUESS,S,1,"G" MAP 1 SPC,S,1," " ON ERROR GOTO FINISHED PRINT TAB(-1,29); ! Turn off cursor ! Set up the grid RANDOMIZE BUMPER'COUNT=0 GUESSES=0 NUM'BUMPERS=0 FOR X=1 TO 10 FOR Y=1 TO 24 R=INT(RND(0)*PROB)+1 ! Bumper probability is 2/PROB GRID(X,Y)=BUMPER'MASK[R;1] IF R=1 OR R=2 NUM'BUMPERS=NUM'BUMPERS+1 NEXT Y NEXT X ! **** NOTE **** ! I have not implemented an algorithm for determining if there are ! any unreachable bumpers on the board. An unreachable bumper makes ! the game unwinnable. At the current level of complexity (PROB) this ! is rarely a problem. ! Draw the initial screen PRINT TAB(-1,0) PRINT TAB(-1,11); ! Reduced intensity ! Column labels FOR Y=1 TO 24 PRINT TAB(2,16+(Y-1)*2);CHR$(96+Y); PRINT TAB(24,16+(Y-1)*2);CHR$(96+Y); NEXT Y ! Row Labels (highlight initial position) FOR X=1 TO 10 IF X=CURPOSX PRINT TAB(-1,12); PRINT TAB(4+(X-1)*2,13);CHR$(64+X); IF X=CURPOSX PRINT TAB(-1,11); PRINT TAB(4+(X-1)*2,65);CHR$(64+X); NEXT X PRINT TAB(-1,12); ! Normal intensity ! Draw the game board FOR X=1 TO 10 FOR Y=1 TO 24 PRINT TAB(4+(X-1)*2,16+(Y-1)*2); PRINT TAB(-1,23);TAB(-1,51);TAB(-1,24); ! DIAGNOSTIC PRINT GRID(X,Y); NEXT Y NEXT X ! Legend PRINT TAB(4,1);"ENTER:"; PRINT TAB(5,1);"======"; PRINT TAB(6,1);"Cursor"; PRINT TAB(7,1);"Escape"; PRINT TAB(8,1);"Space"; PRINT TAB(9,1);" G"; ! Begin the game GET'A'KEY: IF GUESSES>0 & EFFICIENCY=(BUMPER'COUNT/GUESSES)*100 & ELSE & EFFICIENCY=0 PRINT TAB(1,66); PRINT USING " Finds: ##/##",BUMPER'COUNT,NUM'BUMPERS; PRINT TAB(2,66); PRINT USING "Guesses:####",GUESSES PRINT TAB(3,66); PRINT USING " Score: ###%",EFFICIENCY KEYIN: XCALL INKEY,K$ IF LEN(K$)=0 GOTO KEYIN IF K$=ESCAPE GOTO QUIT'GAME IF K$=UPARROW GOSUB UP'ARROW IF K$=DNARROW GOSUB DOWN'ARROW IF K$=LFARROW GOSUB LEFT'ARROW IF K$=RTARROW GOSUB RIGHT'ARROW IF K$=SPC GOSUB FIRE IF UCS(K$)=GUESS GOSUB MAKE'GUESS GOTO GET'A'KEY ! NOTE -- All of the cursor key actions could be written more ! elegantly, but for the sake of debugging it was convenient ! to be explicit, and therefore redundant. UP'ARROW: IF CURPOSX>1 AND CURPOSY=0 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,11);C$; : & CURPOSX=CURPOSX-1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,12);C$; : & GOTO UP'ARROW'RETURN IF CURPOSX>1 AND CURPOSY=25 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,11);C$; : & CURPOSX=CURPOSX-1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,12);C$; : & GOTO UP'ARROW'RETURN IF CURPOSX=1 AND CURPOSY=0 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,11);C$; : & CURPOSX=CURPOSX-1 : & CURPOSY=CURPOSY+1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO UP'ARROW'RETURN IF CURPOSX=1 AND CURPOSY=25 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,11);C$; : & CURPOSX=CURPOSX-1 : & CURPOSY=CURPOSY-1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO UP'ARROW'RETURN IF CURPOSX=11 AND CURPOSY=1 & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSX=CURPOSX-1 : & CURPOSY=CURPOSY-1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,12);C$; : & GOTO UP'ARROW'RETURN IF CURPOSX=11 AND CURPOSY=24 & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSX=CURPOSX-1 : & CURPOSY=CURPOSY+1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,12);C$; : & GOTO UP'ARROW'RETURN PRINT CHR$(7); UP'ARROW'RETURN: RETURN DOWN'ARROW: IF CURPOSX>0 AND CURPOSX<10 AND CURPOSY=0 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,11);C$; : & CURPOSX=CURPOSX+1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,12);C$; : & GOTO DOWN'ARROW'RETURN IF CURPOSX>0 AND CURPOSX<10 AND CURPOSY=25 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,11);C$; : & CURPOSX=CURPOSX+1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,12);C$; : & GOTO DOWN'ARROW'RETURN IF CURPOSX=0 AND CURPOSY=1 & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSX=CURPOSX+1 : & CURPOSY=CURPOSY-1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,12);C$; : & GOTO DOWN'ARROW'RETURN IF CURPOSX=0 AND CURPOSY=24 & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSX=CURPOSX+1 : & CURPOSY=CURPOSY+1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,12);C$; : & GOTO DOWN'ARROW'RETURN IF CURPOSX=10 AND CURPOSY=0 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,11);C$; : & CURPOSX=CURPOSX+1 : & CURPOSY=CURPOSY+1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO DOWN'ARROW'RETURN IF CURPOSX=10 AND CURPOSY=25 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,11);C$; : & CURPOSX=CURPOSX+1 : & CURPOSY=CURPOSY-1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO DOWN'ARROW'RETURN PRINT CHR$(7); DOWN'ARROW'RETURN: RETURN LEFT'ARROW: IF CURPOSY>1 AND CURPOSX=0 & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSY=CURPOSY-1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO LEFT'ARROW'RETURN IF CURPOSY>1 AND CURPOSX=11 & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSY=CURPOSY-1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO LEFT'ARROW'RETURN IF CURPOSY=1 AND CURPOSX=0 & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSX=CURPOSX+1 : & CURPOSY=CURPOSY-1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,12);C$; : & GOTO LEFT'ARROW'RETURN IF CURPOSY=24 AND CURPOSX=11 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,11);C$; : & CURPOSX=CURPOSX-1 : & CURPOSY=CURPOSY+1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO LEFT'ARROW'RETURN IF CURPOSY=1 AND CURPOSX=11 & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSX=CURPOSX-1 : & CURPOSY=CURPOSY-1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,12);C$; : & GOTO LEFT'ARROW'RETURN IF CURPOSY=25 AND CURPOSX=1 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,11);C$; : & CURPOSX=CURPOSX-1 : & CURPOSY=CURPOSY-1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO LEFT'ARROW'RETURN IF CURPOSY=25 AND CURPOSX=10 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,11);C$; : & CURPOSX=CURPOSX+1 : & CURPOSY=CURPOSY-1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO LEFT'ARROW'RETURN PRINT CHR$(7); LEFT'ARROW'RETURN: RETURN RIGHT'ARROW: IF CURPOSY>0 AND CURPOSY<24 AND CURPOSX=0 & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSY=CURPOSY+1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO RIGHT'ARROW'RETURN IF CURPOSY>0 AND CURPOSY<24 AND CURPOSX=11 & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSY=CURPOSY+1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO RIGHT'ARROW'RETURN IF CURPOSY=0 AND CURPOSX=1 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,11);C$; : & CURPOSX=CURPOSX-1 : & CURPOSY=CURPOSY+1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO RIGHT'ARROW'RETURN IF CURPOSY=0 AND CURPOSX=10 & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,13);TAB(-1,11);C$; : & CURPOSX=CURPOSX+1 : & CURPOSY=CURPOSY+1 : & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,12);C$; : & GOTO RIGHT'ARROW'RETURN IF CURPOSY=24 AND CURPOSX=0 & C$=CHR$(96+CURPOSY) : & PRINT TAB(2,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSX=CURPOSX+1 : & CURPOSY=CURPOSY+1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,12);C$; : & GOTO RIGHT'ARROW'RETURN IF CURPOSY=24 AND CURPOSX=11 & C$=CHR$(96+CURPOSY) : & PRINT TAB(24,16+(CURPOSY-1)*2);TAB(-1,11);C$; : & CURPOSX=CURPOSX-1 : & CURPOSY=CURPOSY+1 : & C$=CHR$(64+CURPOSX) : & PRINT TAB(4+(CURPOSX-1)*2,65);TAB(-1,12);C$; : & GOTO RIGHT'ARROW'RETURN PRINT CHR$(7); RIGHT'ARROW'RETURN: RETURN FIRE: ! Clear result of last fire. IF LPX>0 AND LPY>0 PRINT TAB(LPX,LPY);" "; ! Determine the initial direction. IF CURPOSX=0 DX=1 : DY=0 IF CURPOSX=11 DX=-1 : DY=0 IF CURPOSY=0 DX=0 : DY=1 IF CURPOSY=25 DX=0 : DY=-1 PX=CURPOSX : PY=CURPOSY FIRE'LOOP: PX=PX+DX : PY=PY+DY IF PX<1 OR PX>10 OR PY<1 OR PY>24 GOTO FIRE'EXIT IF GRID(PX,PY)="." GOTO FIRE'LOOP IF GRID(PX,PY)="0" OR GRID(PX,PY)="/" GOTO FIRE'LOOP'LEFT IF GRID(PX,PY)="]" OR GRID(PX,PY)="\" GOTO FIRE'LOOP'RIGHT FIRE'LOOP'LEFT: IF DX=0 AND DY=1 THEN DX=-1 : DY=0 : GOTO FIRE'LOOP IF DX=0 AND DY=-1 THEN DX=1 : DY=0 : GOTO FIRE'LOOP IF DX=1 AND DY=0 THEN DX=0 : DY=-1 : GOTO FIRE'LOOP IF DX=-1 AND DY=0 THEN DX=0 : DY=1 : GOTO FIRE'LOOP FIRE'LOOP'RIGHT: IF DX=0 AND DY=1 THEN DX=1 : DY=0 : GOTO FIRE'LOOP IF DX=0 AND DY=-1 THEN DX=-1 : DY=0 : GOTO FIRE'LOOP IF DX=1 AND DY=0 THEN DX=0 : DY=1 : GOTO FIRE'LOOP IF DX=-1 AND DY=0 THEN DX=0 : DY=-1 : GOTO FIRE'LOOP FIRE'EXIT: ! Determine position of re-emergence IF PX=0 & LPX=3 : LPY=16+(PY-1)*2 IF PX>10 & LPX=23 : LPY=16+(PY-1)*2 IF PY=0 & LPX=4+(PX-1)*2 : LPY=14 IF PY>24 & LPX=4+(PX-1)*2 : LPY=63 PRINT TAB(LPX,LPY);"*";CHR$(7); RETURN MAKE'GUESS: PRINT TAB(7,75);" "; PRINT TAB(7,67);"GUESS: "; G$="" PRINT TAB(-1,28); ! Turn on cursor INPUT "",G$ ! Abort if CR entered IF G$="" GOTO MAKE'GUESS'OUT ! Ensure proper format (Rc) IF LEN(G$)<2 GOTO MAKE'GUESS IF G$[1;1]<"A" OR G$[1;1]>"J" PRINT CHR$(7); : GOTO MAKE'GUESS IF G$[2;1]<"a" OR G$[2;1]>"x" PRINT CHR$(7); : GOTO MAKE'GUESS ! Derive grid coordinates PX=ASC(G$[1;1])-ASC("A")+1 PY=ASC(G$[2;1])-ASC("a")+1 ! If this position has already been correctly guessed, there is no ! penalty. IF GRID(PX,PY)="\" OR GRID(PX,PY)="/" & PRINT CHR$(7); : & GOTO MAKE'GUESS'OUT GUESSES=GUESSES+1 IF GRID(PX,PY)="0" OR GRID(PX,PY)="]" & PRINT TAB(4+(PX-1)*2,16+(PY-1)*2); : & C$=GRID(PX,PY) : C$=CHR$(ASC(C$)-1) : & GRID(PX,PY)=C$ : & PRINT GRID(PX,PY); : & BUMPER'COUNT=BUMPER'COUNT+1 IF BUMPER'COUNT=NUM'BUMPERS GOTO FINISHED MAKE'GUESS'OUT: PRINT TAB(-1,29); ! Turn off cursor PRINT TAB(7,66);TAB(-1,9); RETURN QUIT'GAME: PRINT TAB(23,1);"Are you sure you want to quit? "; INPUT "",C$ IF UCS(C$[1;1])="Y" GOTO FINISHED PRINT TAB(23,1);TAB(-1,9); GOTO GET'A'KEY FINISHED: ! Display the final score IF GUESSES>0 & EFFICIENCY=(BUMPER'COUNT/GUESSES)*100 & ELSE & EFFICIENCY=0 PRINT TAB(1,66); PRINT USING " Finds: ##/##",BUMPER'COUNT,NUM'BUMPERS; PRINT TAB(2,66); PRINT USING "Guesses:####",GUESSES PRINT TAB(3,66); PRINT USING " Score: ###%",EFFICIENCY ! Reveal the game board FOR X=1 TO 10 FOR Y=1 TO 24 PRINT TAB(4+(X-1)*2,16+(Y-1)*2); C$=GRID(X,Y) IF C$#"." AND C$#"\" AND C$#"/" C$=CHR$(ASC(C$)-1) PRINT C$; NEXT Y NEXT X PRINT TAB(-1,28); ! Turn on cursor PRINT TAB(-1,12); ! Normal intensity PRINT TAB(-1,14); ! Disable protected fields PRINT TAB(23,1) END