BASIC Code

Acey Ducey

Click on the game window below in order to type.

Acey-Ducey is a simple card game presented in David Ahl's 1973 book BASIC Computer Games, with the original author credited as Bill Palmby. I've converted and refactored it, creating the above build with the BASIC Anywhere Machine.

The Listing

10 PRINT TAB(11); "**********************************************************"
11 PRINT TAB(11); "**********************************************************"
12 PRINT TAB(11); "**                                                      **"
13 PRINT TAB(11); "**                     ACEY DUCEY                       **"
14 PRINT TAB(11); "**                                                      **"
15 PRINT TAB(11); "**     As seen in David Ahl's BASIC Computer Games      **"
16 PRINT TAB(11); "**     Converted and refactored by Michael Coorlim      **"
17 PRINT TAB(11); "**                                                      **"
18 PRINT TAB(11); "**********************************************************"
19 PRINT TAB(11); "**********************************************************"
20 ?:?
21 REM *********************
22 REM **  INSTRUCTIONS  **
23 REM *********************
30 PRINT"INSTRUCTIONS:"
31 ? "Each round you'll be dealt two cards, face up."
32 ? "Your job is to guess whether the third card will fall between their values."
33 ? "If you feel like it will, place a bet reflecting that confidence."
34 ? "If you don't think it will, bet $0 to skip the round."

I went ahead and gave the game a slightly fancier title screen, and rewrote the instructions slightly. More modern forms of BASIC let you shorten a PRINT statement to a question mark, and use colons to combine statements to a single line. I'll largely save that for multiple blank lines.

I'm also using REM statements to comment my code, which the original listing did not.

100 REM **********************
101 REM **  Initialization  **
102 REM **********************
110 MONEY = 100

The original listing used the variable Q for money. I'm not sure why, as even older forms of BASIC allowed you to have multiple letters in a variable name - even if they usually only payed attention to the first two. MONEY and MONKEY would, in most early BASICS, be seen as the same variable MO. But even that would be better than Q.

The original listing also initialized N to 100, but this is never used, so I eliminated it.

120 REM ******************
121 REM **  LOOP START  **
122 REM ******************
125 ?:? "CASH: $"; MONEY
130 ?
140 GOTO 200

At the top of every loop we tell the player how much money they have left. Note that I'm refactoring but not changing the basic structure of the code. If I were building it from scratch I probably wouldn't break the loop to make room for the outcome of the game's bets; it makes things harder to follow.

150 REM ****************
151 REM **  OUTCOMES  **
152 REM ****************
160 MONEY = MONEY + BET
165 GOTO 120
170 MONEY = MONEY - BET 
180 GOTO 120

Our earlier GOTO skips that block, and then we jump back to it in the future.

200 REM **********
201 REM ** DEAL **
202 REM **********
210 ?"DEALING CARDS: "
220 C1 = INT (13 * RND (1))+2
230 C2 = INT (13 * RND (1))+2

Our first two cards are dealt as random numbers between 2 and 14 - the number cards 2-10, Jacks, Queens, Kings, and Aces. My lines above are changed from the original INT (14 * RND (1))+2 which will give a number between 2 and 15 for some reason. It then checks to make sure the number's in range (2 to 14) which I was able to eliminate because our RND cannot come up with a number outside that range.

The original code then uses a series of IF THEN statements to check to see if we get an 11, 12, 13, or 14 to display the names of face cards... and it does this twice, once for each of C1 and C2. I not only combined this into a subroutine with GOSUB, but used the more advanced SELECT CASE conditional flow.

240 IF C1 >= C2 THEN 220
250 X = C1
260 GOSUB 300
270 X = C2
280 GOSUB 300
290 GOTO 400
300 REM ****************************
301 REM **  CHECK FOR FACE CARDS  **
302 REM ****************************
SELECT CASE X
	CASE 11
  	? "JACK"
  CASE 12
  	? "QUEEN"
  CASE 13
    ? "KING"
  CASE 14
  	? "ACE"
  CASE ELSE
  	? X
END SELECT
310 RETURN

This was shortened from 30+ lines. As you can see I assign each of C1 and C2 to the temporary variable X for the sole purpose of using a single SELECT CASE block for both of them. It does nothing with the card value but print it or its face card name.

400 REM ****************
401 REM **  TAKE BET  **
402 REM ****************
410 ?:?
420 INPUT "How much will you bet? (0 to skip)"; BET
430 IF BET > 0 THEN 500
440 ? "Skipping." : ?
450 GOTO 120
500 IF BET <= MONEY THEN 600
510 ? "You only have $"; MONEY;" left."
520 GOTO  400

The original listing used M as the bet amount variable. Ran into a snag here with a mistyped line number sending me into an endless loop, but I was able to resolve it with CharlieJV's help on the Basic Anywhere Machine Discord.

Thanks, Charlie!

600 REM  ***********************
601 REM  **  DRAW THIRD CARD  **
602 REM  ***********************
610 C3 = INT (13 * RND(1))+2
620 X = C3
630 GOSUB 300
640 IF C3 <= C1 THEN 700
650 if C3 > C2 THEN 700
660 ? "You Win!"
670 GOTO 160

We draw our third card and use the earlier subroutine to display it. We then check to see if it's within range of our first two cards. If it is, we jump back to our victory block.

700 ? "You Lose!"
710 IF BET < MONEY THEN 170
720 ?:?:? "Sorry, but you're out of money."
730 ?:?
740 INPUT "Play Again? (Yes or No)"; A$
750 ?:?
760 A$=LEFT$(A$,1)
770 IF A$ = "y" or A$ = "Y" THEN 100
780 ?"See you next time!"
800 END

If we lose we check to see if we have the money to cover our bet and give the player a chance to play again.

I use the LEFT$ keyword to isolate the first letter of the player's response, instead of the original code's requiring the player use the full string "YES" to play again.

There we have it: Acey-Ducey in just under 100 lines of code.

#David Ahl