Binary Numbers

Horse Race Game Demo

by Norman

Home

Game Tutorial

Pseudo Menubar

Binary Numbers

Designing Games

API Corner

JPEG.DLL

Graphics Text

Tip Corner

Installers

Demos

Submission Guide

Newsletter help

Index


The Usefulness of Binary Numbers

Let me say, right at the start, that I am not a hotshot programmer. In LB terms I am a novice. However, I was a reasonable Basic programmer some 30 years ago, but did not have to cope with textboxes, comboboxes or various windows. Everything was done on the main screen, and the coding was all done using a set of Basic commands (no DLLs or APIs etc.). After several years of NOT programming, I have been stimulated, by Liberty Basic, to give it another go.

Now that I have got that out of the way, I would just like to try to justify why I am doing this article. I believe that novices can do a great deal to help each other. They can recognise another novice's problems, and can often say how to overcome those problems in the kind of language that another novice will understand. Unfortunately, the more advanced the adviser, the less likely that the explanation will be easily understood by the novice. I have to confess that, upon reading some of the messages on the forum, I sometimes find that I don't even understand the question, never mind the answer. So, let's see if I can produce something useful here. If not, then there is nothing lost, and I will at least know that, in future, I should leave it to the experts.

In my early programming days, I became very interested in text adventure programs. I remember that I made extensive use of binary numbers in these programs. I cannot remember exactly how I used them but here is a rough idea of how they might have been used:

As you possibly already know, a binary number consists of 0s and 1s. These are called BInary-digiTS or bits. There are 8 bits in a byte. A byte can represent any decimal integer up to 255. Let's consider the binary equivalent of the number 15:

00001111

This is arrived at like this:

   0    0    0    0    1    1    1    1
 128   64   32   16    8    4    2    1

Add together the numbers below wherever there is a 1. It doesn't matter if this is not fully understood. The important thing is to understand that a byte is 8 binary-digits each of which can only be 0 or 1.

In my adventure programs I would use binary numbers to indicate which directions it was possible to move in from any location. Let's suppose you are in a cave/ tunnel system, and there are exits N, E, and SW.

  0    0    0   1    0   1    0    1
 SW   SE   NW  SW    W   E    S    N

You can see that the binary number above (equivalent to 21) clearly indicates that N, E, and SW are set to 1 which means that you can travel in those directions, while all other directions are set to 0 meaning that that way is blocked. So you are able to specify all the directions that it is possible to move in just by allocating a single number (21 in this case) to a variable. Of course, we need a routine to convert an integer to a binary number. That is where my memory has let me down. I cannot remember how I used to do that, so I have had to create a new routine which may not be the best way to do it. But at least it works. Take your decimal number and repeatedly divide by 2 and note the remainder.

 21 divide by 2 = 10 remainder = 1
 10 divide by 2 =  5 remainder = 0
  5 divide by 2 =  2 remainder = 1
  2 divide by 2 =  1 remainder = 0
  1 divide by 2 =  0 remainder = 1

As we have now got our decimal number down to zero, any further divisions will result in a zero remainder. Our example has given us 5 binary digits. So we need to add 3 zeros to bring it up to 8 bits. The result is 000 followed by 10101 or 00010101.

I hope the above makes some kind of sense. I have just realised how difficult it is to explain things like this. Never mind, I will continue and hope that it all comes together at the end.

Earlier, I showed how it was possible to use a binary number to indicate which of eight different directions was open for the adventurer to travel in. There is nothing fixed about this. For instance, in a house you might NOT want the NE, NW, SE, and SW directions. Instead, you might use N, S, E, W, U, D, O, M to indicate whether, or not, there is an exit north, south, east, west, up or down, and the final two digits O, P, indicating if there is an object or person in that particular room. Then another binary number could be used to give more detail. For example, the eight digits could represent key, dagger, oil can, torch, precious stone, exploding box, friendly person, unfriendly person. The choice is unlimited.

Binary Numbers in Use - a Horse Race Game

Well, that's enough background. Let's see if we can create a very simple program which makes use of binary numbers.

Instead of using them in exactly the same way as shown above, I thought I would try something just a little bit different. We will not be using the digits of a binary number to indicate whether, or not, there is something present (e.g. exit, object, person). Instead, we will try to create a very basic simulation of a horse race. There will be eight horses and the program will generate random numbers between 0 and 255. We will convert these numbers to binary and then use each digit to decide if a particular horse moves forward one pixel or stays where it is for that turn.

Lets start by creating the arrays that we will need:

   dim horse$(8)	'for our eight horses
   dim pos(8)		'for the current position of each horse
   dim winner(8)	'indicates multiple winners if there is a dead heat

For the purposes of this exercise, our horses will be A,B,C, etc. However, we will precede each character with a space. this is so that as a horse moves across the screen, it will not leave a trail behind it. The space will overwrite any trace of the previous character.

   for x=1 to 8
      horse$(x)=" "+chr$(64+x)	'horse character preceded by a space
      pos(x)=1			'place each horse at start position
      winner(x)=0		'no winners yet!
   next x

We will open a graphics window although, apart from drawing a finish line, we will be using text only. This is because I have not yet delved into using sprites etc. Also, it might be easier for people to follow the working if I keep it to simple LB text type commands (it will certainly be easier for me LOL).

   open "horserace" for graphics_fs_nsb as #w  'open graphic window full screen, no scroll-bar
   print #w, "trapclose [quit]"		        'close everything when user exits.
   print #w, "down"			        'get ready to draw
   print #w,"line 763 40 763 500"	        'draw finish line

That's our extremely primitive racecourse finished. Now, I think we will create a subroutine to convert the decimal number to a binary number. There may well be a more elegant way of doing it, but I am more at home with subroutines.

 [GETBIN]
   n=num	'in case we need num later on
   bin$=""	'set bin$ to null before beginning to assign the binary number to it
 [LOOP]
   if n/2=int(n/2)then	'if n/2 is an integer then
      bin$="0"+bin$	'remainder = 0. Use it to build binary number
   else			'if n/2 not an integer then
      bin$="1"+bin$	'remainder = 1. Use it to build binary number
   end if

   n=int(n/2)		'divide n by 2, ready for next calculation

   if n>0 then [LOOP]	'carry on until n =0
   lead$=""		'in case we need to add leading zeroes
   if len(bin$)<8 then	'check if our binary number has less than 8 digits
      for j=1 to 8-len(bin$)  		
         lead$=lead$+"0"	'add zeroes to lead$ if necessary 
      next j
   end if

   bin$=lead$+bin$	'concatenate lead$ and bin$ to create an 8 digit binary number
   RETURN

Phew! I made hard work of that!

All we need to do now is to use this binary number to move the horses that need moving. For example, the binary number "10000001" (129 decimal number) will indicate the horses in lanes 1 and 8 should move while all others remain stationary for this turn. Again. I will create a subroutine.

   [UPDATE]
      count=0		'used to count the number of winners in a race
      for k=1 to 8	'for each of the 8 horses
         pos(k)=pos(k) + val(mid$(bin$, k, 1))	'add value of binary-digit to position
         if pos(k)=750 then		'check if finish line has been reached
            win(k)=1			'indicate if a winner
            fin=1		'indicate that the race is over
            count=count+1	'count number of horses reaching finish together
         end if
      next k
   RETURN

Now we need to produce the main body of the program, which we will place above the two subroutines. We will need to call the above two subroutines and move the horses to their new positions. we will need to repeat this operation over and over again, until one, or more, horses reach the finish line.

   [REPEAT]
      num=int(rnd(1)*256)	'get a random number from 0 to 255
      gosub [GETBIN]		'convert it to a binary number
      gosub [UPDATE]		'calculate new positions of horses
      for j= 1 to 8
         print #w, "place ";pos(j);" ";50 + 50*j	'locate position for horse
         print #w, "\";horse$(j)			'print horse at this location
      next j

   if fin=0 then [REPEAT]		'keep going until the finish line is reached

Not much left to do now. We just need to declare the winner(s), and end the program.

   w$=" The winner is "		'use this if one winner

   if count>1 then
      w$="Dead heat: "	'use this if two or more winners dead heat.
   end if

   print #w, "place 50 500"	'prepare to print result at bottom of screen
   for j= 1 to 8
      if winner(j)=1 then
         print #w, "\";w$; horse$(j)	'print result
      end if
   next j

   wait

 [quit]
   close#w
   END

That should do it! You will notice that I have not put NOMAINWIN in this program yet. That is always the very last thing that I add to a program after I am satisfied that everything is working as I want it. If I have any problems with the program while testing, I will often use the main window to print out variable values etc. at various stages of the program, so that I can see what is happening. I know that I can use debug mode for this, and I do quite often, but I cannot get out of the habit, built up many years ago, whereby I use the main screen for checking that everything is as it should be.

I will now list the complete program (including NOMAINWIN) . As I said at the beginning, I am a novice LB programmer myself, and I am not sure if this article will be of any use to anyone. The program does not make use of sprites or other graphic commands, and the result looks nothing like a horse race. It just shows the letters A to H scurrying across the screen, with a different winner every time. You might decide to add to the program. Perhaps an option to play again or exit the program (at the moment you need to close the window to exit the program). You might want to create sprites to replace the letters A to H or to create a more realist racecourse. Or, you might just send it to the Recycle Bin.

Despite the very basic result, if this article proves useful to even just one or two people, then I will be happy.


Here is the full program:

   NOMAINWIN

   dim horse$(8)		'for our eight horses
   dim pos(8)			'for the current position of each horse
   dim winner(8)		'indicates multiple winners if there is a dead heat

   for x=1 to 8
      horse$(x)=" "+chr$(64+x)	'horse preceded by a space
      pos(x)=1			'place each horse at start position
      winner(x)=0		' no winners yet!
   next x

   open "horserace" for graphics_fs_nsb as #w  'open fullscreen without scroll-bar
   print #w, "trapclose [quit]"		        'close everything when user exits.
   print #w, "down"			        'get ready to draw
   print #w,"line 763 40 763 500"		        'draw finish line

 [REPEAT]
   num=int(rnd(1)*256)		'get a random number from 0 to 255
   gosub [GETBIN]		'convert it to a binary number
   gosub [UPDATE]		'calculate new positions of horses
   for j= 1 to 8
      print #w, "place ";pos(j);" ";50 + 50*j	'locate position of horse
      print #w, "\";horse$(j)			'print horse at this location
   next j

   if fin=0 then [REPEAT]	'keep going until the finish line is reached

   w$=" The winner is "		'use this if one winner
   if count>1 then
      w$="Dead heat: "		'use this if two or more winners dead heat.
   end if

   print #w, "place 50 500"	'prepare to print result at bottom of screen
   for j= 1 to 8
      if winner(j)=1 then
         print #w, "\";w$; horse$(j)	'print result
      end if
   next j

   wait

 [quit]
   close#w
	
   END

 [GETBIN]
   n=num	'in case we need num later on
   bin$=""	'set bin$ to null before assigning the binary number to it
 [LOOP]
   if n/2=int(n/2)then	'if n/2 is an integer then
      bin$="0"+bin$	'remainder = 0. Use to build binary number
   else			'if n/2 not an integer then
      bin$="1"+bin$	'remainder = 1. Use to build binary number
   end if

   n=int(n/2)		'divide n by 2, ready for next calculation

   if n>0 then [LOOP]	'carry on until n =0
   lead$=""		'in case we need to add leading zeroes

   if len(bin$)<8 then		'check if our binary number has 8 digits
      for j=1 to 8-len(bin$)  		
         lead$=lead$+"0"	'add zeroes lead$ if necessary 
      next j
   end if

   bin$=lead$+bin$		'add bin$ to lead$ to create an 8 digit binary number
   RETURN

 [UPDATE]
   count=0		'used to count the number of winners in a race
   for k=1 to 8		'for each of the 8 horses
      pos(k)=pos(k) + val(mid$(bin$, k, 1))	'add value of binary-digit to position
      if pos(k)=750 then			'check if finish line has been reached
         winner(k)=1				'indicate if a winner
         fin=1					'indicate that the race is over
         count=count+1		'count number of horses reaching finish together
      end if
   next k
   RETURN


Home

Game Tutorial

Pseudo Menubar

Binary Numbers

Designing Games

API Corner

JPEG.DLL

Graphics Text

Tip Corner

Installers

Demos

Submission Guide

Newsletter help

Index