top of page
Search
  • Writer's picturechamutalz

Acey Ducey with Visual Basic

To Goto or not to Goto - that's the question


Acey Ducey game, visual basic from 101 games for BASIC

Once upon a time, when you wanted to play a computer game you had to code the game first. Games were available in magazines, books and programming manuals as prints of code and many children took the time to code and adapt the games for their own computers. In other words, playing games meant learning how to code. One of the most popular languages to create games at home was BASIC and the book BASIC Computer Games -101 Great Games to Play on Your Home Computer (in various editions) was very popular in particular. 


Here is a common question you’ve probably heard before: “what is the best/shortest way to learn a new/first programming language?” My favourite answer has always been “find a project and learn as you go along”. Translating BASIC games into another language sounded exactly like that sort of project. The games are fairly simple, so you can probably code them in any language without digging too deep in the documentation and checking the result is easy: if you can play the game, it works.


This blog is a documentation of translating 101 games for BASIC in to as many languages as I can. If you are intending to learn a new language I hope you will find it interesting, as I need to learn most of those from scratch in the process. If you are just interested in old games, you are welcome to take the result and use it (or adapt it further, for old time’s sake).  

I’m using the Microcomputer edition (1978) by David H. Ahl, Steve North and George Beker. If you desire the actual book you can probably get a version here or here and in many other places on the world wide web, I’m sure. As a reference dictionary I’m using the paperweight (it’s an actual hard cover) BASIC Keywords by Eddie Adamis (Hebrew edition by Arie Bloom, 1987).

 Before I begin, some translation notes: I’ll try to stick to the original code as much as possible unless it feels silly. If I don’t find a certain method/function/whatsit in the target language I will use something else that does what I need. The author of the book credited each game to its original programmer and I’m going to leave that as it is, if there is no credit, it’s because there wasn’t any in the text. Lastly, this isn’t a code beauty pageant. If the game runs - job done.

Title: Acey Ducey (Bill Palmby)

Target Language and IDE: Visual Basic, using Visual Studio Community 2017


Acey Ducey is a card game, where the computer deals two cards and you are supposed to bet (or not) if the next card will have a value between the two. The game should keep running until you lose all your money. It's a short, simple game. So is this post.

For the first language I chose the one with the closest name — Visual Basic, misguidedly thinking it will make things easier. I’m showing selected parts here to walk through my translation including initial mistakes, you can find the complete (and actually working) programme on GitHub (link above).


The most urgent translation point I had to address (as this is the first game in my project) was a somewhat contentious issue for a while. Here is a part of the process to draw two cards:

260 PRINT "HERE ARE YOUR NEXT TWO CARDS"
270 A = INT(14*RND(1))+2
280 IF A<2 THEN 270
290 IF A>14 THEN 270
.
.
.
400 PRINT A
410 GOTO 500
420 PRINT "JACK" 
430 GOTO 500

BASIC uses GoTo, which makes the code difficult to read. Visual Basic does have GoTo, as long as you label the lines but this is where I put my foot down and use functions. I did say I would try to stick to the original until it became silly. I consider confusing myself whilst writing as being silly. But not everybody agrees that this is a better choice. If you like academic cat fights here is a starter (the rightmost column) . Also, calling functions does create an inconvenience (more on that ahead).

Instead (of the code section above) I used a Draw() function and a Bet() function, intending to call them whenever I need them. The Draw() function includes a Rnd() method because that's what the original code uses but it's important to note that Random isn't exactly random here. (If you counted on playing the game and this is a spoiler, I'm sorry - just pretend the numbers are not the same and act surprised). For more information see links below.

And this is where I hit the first real snag. Originally the game play works in this order: the dealer draws, you are asked to bet and if the bet is 0 then you are a chicken ("CHICKEN!" to be exact) and then you Goto the line that draws and so on. I stuck that bit in an if statement (is the bet 0 or not)

Draw()
Bet()
If (M = 0) Then
     Console.WriteLine("CHICKEN!")
     Console.WriteLine("HERE ARE YOUR NEXT TWO CARDS")
 End If
 Draw()
 Bet()

But hold on! What if the user really is a chicken? I mean, what if the bet is 0 every time? I don't want a condition inside a condition, do I? So now I had to diverge from the original even further and include the Chicken if (that's a technical term) inside the Bet(). Only then if M = 0 , Draw would have to be called from Bet(). I bet you can see the problem here. This is where the Goto has an advantage: everything is within the same scope and you just travel up and down your code. This is the moment when a single round is born. I called it Play(). So unless the player keeps typing "0" we can move on. I put the rest of it inside a new function: Compare(). And then what? How do you arrange those functions like that long list of lines of BASIC code?


Clearly someone has to step in and manage this game. Assuming every game is a loop (not philosophically, I mean the game is a loop until it stops because you either win or lose) I put the rounds inside a loop - as long as the player has some money. Is it better then using Goto to go back to the top every time? I don't know but I think it's more readable this way.


I now had this:

While (Q > 0)
         Dim s1 = $"YOU NOW HAVE {Q} DOLLARS"
         Console.WriteLine(s1)
         Console.WriteLine()
         Draw()
         Bet()
         Play()
         If (drawAgain = False) Then
             Compare()
         End If
 End While

And here is how Play() looks like from the inside:

Sub Play()
      If (M = 0) Then
          Console.WriteLine("CHICKEN!")
          drawAgain = True
      End If
      If (M > Q) Then
          Console.WriteLine("SORRY, MY FRIEND BUT YOU BET TOO MUCH")
          Dim s2 = $"YOU HAVE ONLY {Q} DOLLARS TO BET"
          Console.WriteLine(s2)
          drawAgain = True
       End If
 End Sub

Combine these two together and you'll keep drawing and betting forever, but of course, I didn't see it coming. The game kept drawing and I had about 30 minutes of fun until I realised my mistake. I didn't un-flag my flag. drawAgain must be put to rest or the game won't go anywhere.

This is the right version:

While (Q > 0)
        Dim s1 = $"YOU NOW HAVE {Q} DOLLARS"
        Console.WriteLine(s1)
        Console.WriteLine()
        Draw()
        Bet()
        Play()
        If (drawAgain = False) Then
           Compare()
        End If
      drawAgain = False
End While

The next step is to make sure the game exits when the user doesn't want to continue or starts all over again if the user wants to try again. The entire game went into AceyDucy() which is called once the first time the program runs and is called again if the user chooses to play again.

Sub Main()                             
  AceyDucey()                            
   If (playAgain) Then                                  
     AceyDucey()                               
   End If                          
End Sub

Initially playAgain is set to false but it changes to true if the user chooses to play again. (It's like the drawAgain trick only this time I knew what I was doing).


Unrelated to my Goto dilemma, inside every round you can find the wonderful line:

1010 PRINT"SORRY,FRIEND BUT YOU BLEW YOUR WAD" 

Apart from assuming this line means you lost all your money (yes, amazing powers of deduction, I know) and a question to set playAgain should pop up, it got me curious. Here, I googled it for you.

Also, if you go through the code you'll notice I take inputs from the user after I turn them to lower case. This is because I don't trust the user to use lower case for inputs. In fact I don't trust the user to do anything right (hence the idea of a user who would be a chicken every time) and as a rule of thumb for the most basic of UI, neither should you.


Finally, after running up and down a BASIC code I had a playable game. Since it's a fairly straightforward text based game, I didn’t have to use any additional modules (libraries).

So, how was my first experience of translating a game from an ancient language?

Visual Basic wasn't that hard to handle, if you are familiar with Microsoft languages, it's pretty intuitive and even if you aren't, the documentation is nicely organised.

Even though it wasn't clear from the original code, it should have been obvious that a game ends with a condition (Game Over or Win) and yet, my translation still fell victim to this rookie mistake: I didn't see that in all the mess. And Goto is a mess - until you understand it's meaning: when you are in the same scope and you want to repeat lines of code you simply go there (again) and repeat those lines of code (revolutionary, until you learn to use functions, that is).


So, if you are a hard core gamer now is the time to check out this awesome game (full 20 seconds of game play guaranteed) and if you are just interested in taking a peek at the code to see how you would have done better, play it anyway.


Links for all:

In case you’ve always dreamed of learning Visual Basic, here is a tutorial for the essentials of the language. For a quick explanation about Random and Rnd() and how to properly randomize a number.

142 views0 comments
bottom of page