Atari Action - Chapter 6

Procedures

by Sheila (Spencer) Robbins

This is the only chapter that was written of an unfinished, unpublished book about the Action! programming language.

 

Procedures and Functions, collectively referred to as "routines", are the heart of the Action! Language. (We will cover functions in Chapter 7.) A procedure is a group of statements, expressions, and/or commands that accomplish a certain task. See if you can tell what the following simple procedure is intended to do:

 

PROC Count_ten()

 

BYTE counter

 

FOR counter=1 TO 10

      DO

            PrintB(counter)

            Print(" ")

      OD

RETURN

 

If you were to type in the procedure, compile it and run it, this is what you would see on your screen:

 

1 2 3 4 5 6 7 8 9 10

 

Obviously, Procedure "Count_ten" is designed to print the BYTE numbers 1 through 10 (with a space between each number). That's all it does. Of course, most procedures will be more useful and probably longer, but the preceding example gives you an idea of how simple the procedure structure really is. The only requirements are a name for the procedure and a RETURN at the end.

 

NOTE: Don't leave out the RETURN! Terrible things can happen if you do, even if the program compiles without error. You will more than likely have to turn your computer off and back on again to regain control, thereby losing anything you may have had in the Editor. This by itself is reason enough to save your program to disk or cassette before each compile or run attempt.

 

The procedure name can contain any alpha-numeric characters you wish, including the underline, as long as it begins with a letter and isn't longer than 255 characters. The parentheses are also required, and later we will discuss passing parameters within those parentheses.

 

You could even have a procedure to do nothing at all if you wished, and in fact this is quite useful when you are writing a program that will contain a number of procedures. For example, if you were writing a program with several procedures, but you weren't ready to flesh them all out, you could still call them from your program without getting a compiler error. Here's an example of a "do-nothing" procedure:

 

PROC Do_Nothing()

RETURN

 

Calling a procedure is simplicity itself. Just type in the procedure's name at the point you wish it to be executed. This is almost exactly like calling a subroutine in BASIC. To call our previous two examples, we would enter the following:

 

PROC Main()

Count_ten()

Do_nothing()

RETURN

 

That's all there is to it!

 

Now that you know how to declare and call a procedure, you're ready to write your first real Action! Program. You will find suggestions for changes after we finish, so please type it in and save it to disk or cassette.

 

An excellent way to learn any new language is to analyze a simple BASIC program and then rewrite it in the new language. In order to make the translation, we first need to study the program so that its structure will become more obvious. This is a simple program, and even in BASIC the flow is easy to see. That will make it much easier for us to make our translation.

 

Here, in Atari BASIC, is the program that we will be taking apart and putting back together in Action!. It's called "The Great Butterfly Chase".

 

10         REM INITIALIZE

20         DIM MOVE$(1)

30         HCOL=1:HROW=1:BCOL=3:BROW=3:         REM INITIAL POSITIONS OF HUMAN & BUTTERFLY

40         REM 10 TURNS EACH GAME

50         FOR PLAYS=1 TO 10

60         REM DRAW THE "MAP"

70         FOR ROW=1 TO 5

80         FOR COL=1 TO 5

90         PRINT " ";

100       IF COL=BCOL AND ROW=BROW THEN PRINT "B";:GOTO 150: REM THE BUTTERFLY

110       IF COL=HCOL AND ROW=HROW THEN PRINT "H";:GOTO 150: REM THE HUMAN

140       PRINT".": REM NOBODY THERE

150       NEXT COL

160       PRINT

170       NEXT ROW

180       REM HUMAN MOVEMENT LOOP

190       PRINT:PRINT:PRINT "Move number ";PLAYS

200       PRINT "Direction (NSEW)";:INPUT MOVE$

210       IF MOVE$="N" THEN HROW=HROW-1: REM MOVED NORTH (UP)

220       IF MOVE$="S" THEN HROW=HROW+1 : REM MOVED SOUTH (DOWN)

230       IF MOVE$="E" THEN HCOL=HCOL+1: REM MOVED EAST (RIGHT)

240       IF MOVE$="W" THEN HCOL=HCOL-1: REM MOVED WEST (LEFT)

245       REM CHECK FOR "OUT OF BOUNDS"

250       IF HCOL>5 THEN HCOL=5:GOTO 300

260       IF HCOL<1 THEN HCOL=1:GOTO 300

270       IF HROW>5 THEN HROW=5:GOTO 300

280       IF HROW<1 THEN HROW=1:GOTO 300

290       GOTO 320

300       PRINT "You hit the wall!"

310       REM CHECK TO SEE IF HUMAN AND BUTTERFLY OCCUPY THE SAME SPACE

320       IF HCOL=BCOL AND HROW=BROW THEN GOTO 700

330       REM BUTTERFLY'S MOVE

340       REM THE BUTTERFLY IS "SMART"

350       REM AND WILL MOVE AWAY FROM YOU

360       REM BUT HE DOESN'T ALWAYS MAKE THE

370       REM PERFECT MOVE!

380       IF BCOL>HCOL AND BROW=HROW THEN BDIR=1

390       IF BCOL>HCOL AND BROW>HROW THEN BDIR=2

400       IF BCOL=HCOL AND BROW>HROW THEN BDIR=3

410       IF BCOL<HCOL AND BROW>HROW THEN BDIR=4

420       IF BCOL<HCOL AND BROW=HROW THEN BDIR=5

430       IF BCOL<HCOL AND BROW<HROW THEN BDIR=6

440       IF BCOL=HCOL AND BROW<HROW THEN BDIR=7

450       IF BCOL>HCOL AND BROW<HROW THEN BDIR=8

460       REM THROW IN SOME RANDOMNESS

470       CHANGE=INT(RND(0)*9)

480       IF CHANGE=0 THEN BDIR=BDIR+1

490       IF CHANGE=1 THEN BDIR=BDIR-1

500       IF BDIR=0 THEN BDIR=8

510       IF BDIR=9 THEN BDIR=1

520       GOTO BDIR*10+520

530       BCOL=BCOL+1:GOTO 610

540       BCOL=BCOL+1:BROW=BROW+1:GOTO 630

550       BROW=BROW+1:GOTO 610

560       BCOL=BCOL-1:BROW=BROW+1:GOTO 630

570       BCOL=BCOL-1:GOTO 610

580       BCOL=BCOL-1:BROW=BROW-1:GOTO 630

590       BROW=BROW-1:GOTO 610

600       BCOL=BCOL+1:BROW=BROW-1:GOTO 630

610       REM MAKE SURE THE BUTTERFLY

620       REM IS NOT OUT OF BOUNDS

630       IF BCOL>5 THEN BCOL=5

640       IF BCOL<1 THEN BCOL=1

650       IF BROW>5 THEN BROW=5

660       IF BROW<1 THEN BROW=1

670       REM SEE IF THE BUTTERFLY GOT HIMSELF CAUGHT

680       IF BCOL=HCOL AND BROW=HROW THEN GOTO 700: REM OUT OF THE LOOP

690       GOTO 710

700       PRINT "You got him!":GOTO 740: REM OUT OF THE LOOP

710       NEXT PLAYS

720       PRINT "He escaped!"

730       REM OPTION TO PLAY AGAIN

740       PRINT:PRINT "Want another game (Y/N)?";:OPEN #1,4,0,"K:":GET #1,KEY

750       PRINT CHR$(KEY):IF CHR$(KEY)="Y" THEN CLOSE #1:RUN

760       END

 

Let's take the BASIC program section by section:

 

Lines 20-30 set up the initial conditions of the game, setting the human's column and row to "1" and the butterfly's column and row to "3". "MOVE$" is also dimensioned here.

 

Line 50 starts the 10-play loop.

 

Lines 7-170 draw the map, printing an "H" for the human, a "B" for the butterfly, and a "." For an empty cell.

 

Line 190 prints the play number

 

Line 200 asks for player input.

 

Lines 210-240 calculate the human's new position, based on his input.

 

Lines 250-280 check to see if the human tried to pass through a wall and "bounces" him back to his previous position if he did.

 

Line 320 determines whether or not the human and butterfly are in the same place and exits from the loop if they are.

 

Lines 380-450 determine the best possible move for the butterfly.

 

Lines 470-490 add the random factor for the butterfly's move.

 

Lines 500-510 correct the butterfly's move – there is no direction 0 or direction 9.

 

Line 520 directs the program to the proper line according to the direction in which the butterfly will be moving.

 

Lines 530-600 calculate the butterfly's new position.

 

Lines 610-660 keep the butterfly from going out of bounds.

 

Line 680 is a repeat of line 320.

 

Line 710 moves us to the next play.

 

Line 720 declares the butterfly safe.

 

Lines 730-750 offer another game.

 

You might want to run this program in BASIC and then in Action! to see the improvement in speed of execution.

 

Here are the names of the procedures we will be using in our Action! translation:

 

PROC Draw_Map()

PROC Move_Human()

PROC Move_Fly()

PROC Check_Stat()

PROC More_Play()

 

Our first Action! program may look a little cumbersome compared with the BASIC program. But you can learn a great deal by modifying it later, after you learn some new tricks to make it more compact. Right now we're going to do an almost direct translation, though. We'll start with the procedure to draw the map:

 

PROC Draw_Map()

 

;Procedure to draw a five by five grid in Graphics 0

;(lines 60-170 in the BASIC program)

 

BYTE row, col          ;variables LOCAL to this procedure

 

FOR row=1 TO 5                                                             ;line 70

      DO

            FOR col=1 TO 5                                                  ;line 80

                  Print(" ")                                                     ;line 90

                  IF col=b_col AND row=b_row THEN                ;line 100

                        Print("B")                                             

                  ELSEIF col=h_col AND row=h_row THEN         ;line 110

                        Print "H")                                             

                  ELSE Print(".")                                            ;line 140

                  FI

      OD                                                                          ;line 150

      PutE()                                                                     ;line 160

 

RETURN

 

Now the section to allow the human's input and movement:

 

PROC Move_Human()

;Human movement section

;(lines 180-300 in the BASIC program)

 

BYTE move        ;"move" is LOCAL to this procedure

 

PutE()

PutE()

Print("Move number ")                                                    ;line 190

PrintBE(plays)

Print("Direction (NSEW)a")

Move=GetD(7)                                                                ;line 200

PrintF("%C",move)                                                         ;we want it printed as a Character

 

old_col=h_col                                                                ;save these variables in case

old_row=h_row                                                              ;the human goes out of bounds

 

IF move='N OR move='n THEN

      h_row==-1                                                               ;move him up (line 210)

ELSEIF move='S or move='s THEN

      h_row==+1                                                               ;move down (line 220)

ELSEIF move='E or move='e THEN

      h_col==_1                                                                ;move right (line 230)

ELSE h_col==-1                                                              ;move left (line 240)

FI

 

IF h_col<1 OR

      h_row<1 OR

      h_col>5 OR

      h_row>5 THEN

      h_col=old_col                                                          ;out of bounds

      h_row=old_row                                                        ;correction (lines 250-300)

FI

 

RETURN

 

The procedure to move the butterfly:

 

PROC Move_Fly()

 

;Procedure to move butterfly

;(Lines 330-600)

 

BYTE b_dir                                                                    ;LOCAL to this procedure

 

IF b_col>h_col AND b_row=h_row THEN

      b_dir=1                                                                   ;line 380

ELSEIF b_col>h_col AND b_row>h_row THEN

      b_dir=2                                                                   ;line 390

ELSEIF b_col<h_col AND b_row>h_row THEN

      b_dir=3                                                                   ;line 400

ELSEIF b_col<h_col AND b_row>h_row THEN

      b_dir=4                                                                   ;line 410

ELSEIF b_col<h_col and b_row=h_row THEN

      b_dir=5                                                                   ;line 420

ELSEIF b_col<h_col AND b_row<h_row THEN

      b_dir=6                                                                   ;line 430

ELSEIF b_col=h_col AND b_row<h_row THEN

      b_dir=7                                                                   ;line 440

ELSE b_dir=8                                                                 ;line 450

FI

 

Change=Rand(10)                                                            ;line 470 – "Rand" is a library function

                                                                                    ;to be discussed in a later chapter

IF change=1 THEN

      b_dir==+1                                                                ;line 480

ELSEIF change=0 THEN

      b_dir==-1                                                                 ;line 490

FI

 

IF b_dir=0 THEN

      b_dir=8                                                                   ;line 500

ELSEIF b_dir=9 THEN

      b_dir=1                                                                   ;line 510

FI

 

old_col=b_col

old_row=b_row

 

IF b_dir=1 THEN

      b_col==+1                                                                ;move it to the right (line 530)

ELSEIF b_dir=2 THEN

      b_col==+1                                                                ;move it to the right

      b_row==+1                                                               ;and down (line 540)

ELSEIF b_dir=3 THEN

      b_row==+1                                                               ;move it down (line 550)

ELSEIF b_dir=4 THEN

      b_col==-1                                                                ;move it to the left

      b_row==+1                                                               ;and down (line 560)

ELSEIF b_dir=5 THEN

      b_col==-1                                                                ;move it to the left (line 570)

ELSEIF b_dir=6 THEN

      b_col==-1                                                                ;move it to the left

      b_row==-1                                                               ;and up (line 580)

ELSEIF b_dir=7 THEN

      b_row==-1                                                               ;move up (line 590)

ELSE b_col==+1                                                             ;move right

      b_row==-1                                                               ;and up (line 600)

FI

 

IF b_col<1 OR

      b_row<1 OR

      b_col>5 OR

      b_row>5 THEN

      b_col=old_col                                                          ;correction for out of bounds

      b_row=old_row                                                        ;(lines 620-660)

FI

 

RETURN

 

We need a procedure to check the status of the human and the butterfly to see if they are trying to occupy the same space at the same time:

 

PROC Check_Stat()

 

;Procedure to see if the butterfly has been caught –

;serves the same function as lines 320 and 680 in BASIC

;No local variables

 

IF (h_row=b_row) AND (h_col=b_col) THEN                        ;lines 320 and 680

      PutE()

      PrintE("You got him!")                                              ;line 700

      Caught=1                                                                 ;the "flag" to indicate a catch

FI

 

RETURN

 

Now the procedure to offer another game:

 

PROC More_Play()

 

;This procedure determines if the player wants to quit or play again

;See lines 730-750 in BASIC

;No local variables

 

PutE()

PrintE("Do you want to play")

Print("another game (Y/N)?")                                           ;line 740

Decide=GetD(7)                                                              ;line 740

PrintF("%C",decide)                                                       ;line 750

PutE()

If decide='Y or decide='y THEN

      Decide=1                                                                 ;program will run again after the RETURN

ELSE decide=0                                                               ;program will end after the RETURN

FI

 

RETURN

 

And last, Procedure "Main" – the procedure that controls the whole program:

 

PROC (Main()

 

DO

      B_row=3                                                                  ;initial conditions (line 30)

      B_col=3

      H_row=1

      H_col=1

      Caught=0

      Decide=0

 

      FOR plays=1 to 10                                                    ;(line 50)

            DO

                  Draw_Map()                                                 ;call Procedure "Draw_Map" (lines 60-170)

                  Move_Human()                                             ;call Move_Human (lines 180=300)

                  Check_Stat()                                                ;call Check_Stat (line 320)

 

                  IF caught=1 THEN                                         ;"caught" is set by Procedure Check_Stat

                        EXIT                                                     ;get out of the loop

                  FI

 

                  Move_Fly()                                                   ;call Move_Fly (lines 330-600)

                  Check_Stat()                                                ;call Check_Stat (line 680)

 

                  IF caught=1 THEN

                        EXIT

                  FI

 

                  PutE()                                                         ;print a line with carriage return

            OD

 

            IF caught=0 THEN

                  PutE()

                  PrintE("He escaped!")                                  ;line 720

            FI

 

      More_Play()                                                             ;call More_Play (lines 730-750)

      UNTIL decide=0                                                        ;no more games

OD

 

RETURN

 

Let's take Procedure "Main" step by step.

 

There are two "DO" loops in this procedure, one nested inside the other. We'll look at the nested loop first and then we can work back to the original one.

 

Right after "FOR plays=1 TO 10" is the nested loop. It tells the program to do the following:

 

      1.   Draw the map

      2.   Let the human make a move

      3.   Check to see if the human caught the butterfly and EXIT if he did

      4.   Print a blank line

 

This loop will execute 10 times (10 plays) or until the butterfly is caught. The outer loop controls the inner loop as well as a few other things:

 

1.     It sets up the initial conditions – positions of human and butterfly – and initializes the variables "caught" and "decide" to 0.

2.     It tells you you lost if all 10 plays have passed without a "catch".

3.     It asks if you want another game.

4.     It does all this UNTIL you say "No" to another game.

 

We need to add one more section of code and our program will be ready to compile and run. This section is called simply "MODULE" and all it does is tell the compiler that we want to declare some global variables.

 

MODULE

;declaring global variables

 

BYTE h_col, h_row, b_col, b_row, old_col, old_row, plays, caught, decide

 

Go ahead and type this program in if you haven't already done so. Make sure that MODULE is the first piece of code, and Main the last. Otherwise the procedures can go in any order you like.*

 

After you have typed in the program in the Action! Editor and saved it <CTRL-SHIFT-W>, use <CTRL-SHIFT-M> to go to the Monitor, Compile the program, and Run it. If you have typed it in exactly as you see it here, it will compile and run without errors. If you do get an error, proofread your source carefully and make any necessary corrections, save the revised program, and try it again.

 

There's your first Action! program. To test what you've learned, try making the following changes:

 

1.     Enlarge the grid.

2.     "Teach" the butterfly not to let himself get cornered.

3.     Allow the human to make moves diagonally

4.     Make the starting positions random – include code to keep the human and butterfly from starting out in the same place or too close (within 1 square).

 

 

*NOTE: This is not always the case. In more complex programs, where routines call other routines, you will have to ensure that a procedure to be called precedes the calling procedure (or function). We will cover this in detail in a later chapter.

 


Return to Articles index