@L `}/j5  $% l0?$)$$Hȱ$ ShL$ `e$$%` h?/ `  !I PR@1 YL I`! S S) H$ЙH 0}Џ$%`@ $% CC$$%e%dU$% ]0%$% DDmLp   % J)Lz ;Here we use devices and files to;view a text file from disk.;Every 21 lines it stops and;asks if you want to see more.;}Press Q or q to stop and any other;for the next 21 linesMODULE CHAR ARRAY filename(30)PROC get_file() PrintE("Wh}at file do you want to view?") Print("-> ") InputS(filename)RETURNBYTE FUNC more();more() returns 1 to see more of} the;file and 0 if the user want to quit BYTE key, rval, i Print("more...") Close(2) Open(2,"K:",4,}0) key=GetD(2) ;get a key from the keyboard Close(2);this section erases the word more by;printing 7 delete character }s FOR i=1 TO 7 DO PrintF("%C",254) OD IF key='Q OR key='q THEN rval=0 ELSE rval=1 FI FOR i=1 TO }7 DO Put(126) ODRETURN(rval)PROC better_read() BYTE ARRAY line(50) BYTE num_lines num_lines=0 Close(1 }) ;make sure the file isn't already open Open(1,filename,4,0) WHILE EOF(1)=0 ;are we at the end? DO num }_lines=num_lines+1 InputSD(1,line) ; get a line PrintE(line) ; print it IF num_lines=21 THEN num_lines= }0 IF more()=0 THEN EXIT FI FI OD Close(1)RETURNPROC main() get_file() better_read()RETU}RN IF more()=0 THEN EXIT FI FI OD Close(1)RETURNPROC main() get_file() better_read()RETU;here, we assign our POINTER to a ;special memory location. This is;how we can use POINTERs like a POKE;statement. ;In }BASIC try this:; 10 POKE 710,0;and the same thing will happen.;The number 0 is the way the computer;knows black. And 710} is the ;address where your Atari keeps the;text background color.PROC background() BYTE POINTER bkgnd bkgnd=71}0 bkgnd^=0RETURN;Here I will show you how a POINTER;can change a parameter. Let's say;an employee wants to deduct $}20;from his salary for the United Way;every paycheck.;Now you can just send his salary;to this PROC and it will make this};decuction for you. ;I assume most of you think it;would be easier to use a global;salary variable.;Yes, that is anot}her way to do it ;but this PROC would loose its;"independence."PROC chng_value(CARD POINTER wage) PrintE("United Way d}eduction: $20") wage^=wage^-20RETURNPROC main() CARD salary background() salary=300 Print("Your salary is: "}) PrintCE(salary) ;Send the chng_value(@salary) ;deduction PROC ;the addr}ess of ;the variable Print("Your takehome pay is: ") PrintCE(salary) RETURN ;the addrn;This is a very, very simple adventure;type program. There are 10 rooms;numbered 0-9. In each room there;are exits and m}aybe a treasure.;The goal in this adventure is;to collect the treasures in the fewest;number of moves. When you think yo}u;have all the treasures, eXit the;game and see your score.;This is FAR from a real adventure;game and it really isn't c}hallenging;at all, but it does show the use;of ARRAYs of records.;Here is the record for each roomTYPE room=[BYTE north}, south, east, west, treasure]DEFINE size="5" ;5 bytes p}er roomBYTE ARRAY cave(50) ;save enough space ;for 10 roomsCARD score, turnsroom POINTER her}e ; our POINTERBYTE room_num ;This holds the current ;room number the player ;is in.P }ROC exits();*If a exit field in the record has; a 255, that means there is no; exit in that direction* PrintE("Exits: !}") IF here.north<>255 THEN Print("North ") FI IF here.south<>255 THEN Print("South ") FI IF here.east<>255 "}THEN Print("East ") FI IF here.west<>255 THEN Print("West ") FI PutE()RETURNPROC money();*Here we print #}how much treasure is; in the room* PrintF("%EThere is $%U here.%E",here.treasure)RETURNPROC description();*What does$} the room look like?* exits() money()RETURNBYTE FUNC get_command();*This is the controlling routine.; It gets a c%}ommand key and executes; it. It returns a 1 if the user; wants to quit, 0 otherwise. BYTE command turns = turns + 1&} PutE() Print("䠭 ") Open(1,"K:",4,0) command=GetD(1) Close(1);*I don't know if I mentioned this ; before'} or not. But when you GetD(); a key from the keyboard, the BYTE; returned is the ATASCII value of; that character. Examp(}le, if the; user press an A, command is set to; 65. A single quote before a; character means the ATASCII value; of that )}character. So 'A = 65 IF command='? THEN PrintE("Help") PutE() PrintE(" Commands") PrintE(" *} --------") PrintE(" N - Go North") PrintE(" S - Go South") PrintE(" E - Go East+}") PrintE(" W - Go West") PrintE(" T - Take Treasure") PrintE(" C - Current Score") P,}rintE(" R - Room Number") PrintE(" D - Room Description") PrintE(" X - Exit") PrintE(" -} ? - Help") PutE() ELSEIF command='R THEN PrintE("Room number") PrintF("%EYou are in room #%U%E",room_.}num) ELSEIF command='D THEN PrintE("Description") description() ELSEIF command='T THEN PrintE("Take Trea/}sure") IF here.treasure THEN score = score + here.treasure ;add the treasure to the score here.treasure=0 0} ;remove the treasure from athe room PrintE("Treasure taken!") ELSE PrintE("There is no treasure to take!") 1} FI ELSEIF command='C THEN PrintE("Current Score") PrintF("%EYou have $%U in %U moves.%E",score,turns) ELSEIF2} command='N THEN PrintE("North") IF here.north<>255 THEN room_num=here.north here = cave + (room_num * si3}ze) description() ELSE PrintE("There is no exit in that direction.") FI ELSEIF command='S THEN P4}rintE("South") IF here.south<>255 THEN room_num=here.south here = cave + (room_num * size) description(5}) ELSE PrintE("There is no exit in that direction.") FI ELSEIF command='E THEN PrintE("East") IF h6}ere.east <>255 THEN room_num=here.east here = cave + (room_num * size) description() ELSE Print7}E("There is no exit in that direction.") FI ELSEIF command='W THEN PrintE("West") IF here.west<>255 THEN 8} room_num=here.west here = cave + (room_num * size) description() ELSE PrintE("There is no exit in th9}at direction.") FI ELSEIF command='X THEN PrintE("Exit") PrintF("%EYour final score is:%E $%U in %U moves.%E",:}score,turns) RETURN(1) ELSE Put(command) PutE() PrintE("I don't know that command!") PrintE("Use ? for;} help.") FIRETURN(0)PROC place_treasure();*Put a random amout of treasure in; a random room. BYTE rnd1, <}rnd2, counter room POINTER temp rnd2=Rand(6)+1 ; how many rooms will have treasure FOR counter=1 TO rnd2 D=}O rnd1=Rand(10) ;which room? temp = cave + (rnd1 * size) rnd1=Rand(240) ;how much money? temp.treasure=rnd>}1 ODRETURNPROC init();*Now we have to read in the whole; cave in from the disk and initialize; some variables to th?}eir starting; values.;When we read the cave in from the ;data file on the disk, this is the;order it is read in: north, @}south,;east, west and the treasure amount.;Here's an example:; 255; 255; 6; 8; 0;This means thA}ere is no exit north;or south. Room 6 is to the east.;Room 8 is to the west. There is no;treasure. Actually, all the roB}oms;have 0 treasure. We put the treasure;in later. BYTE i turns=0 score=0 Open(2,"D:APROG12.DAT",4,0) FOR i=0C} TO 9 DO here = cave + (i * size) here.north=InputBD(2) here.south=InputBD(2) here.east=InputBD(2) hereD}.west=InputBD(2) here.treasure=InputBD(2) OD Close(2) place_treasure();Let's start in room 4 room_num=4 hereE} = cave + (room_num * size)RETURNPROC main() BYTE rval init() description() DO rval=get_command() UNTIL rF}val ODRETURN m * size)RETURNPROC main() BYTE rval init() description() DO rval=get_command() UNTIL r;************************************;* Atari Phone book *;* by *;* H}Tom Johnson *;* for the Action!/PRO tutorial *;* *;* Originally transI}lated to *;* the Atari in BASIC XL *;* *;* based on TI Mailing List J} *;* by *;* Doug Hapeman *;* in *;* K} July 1983 Compute! *;* *;* Thanks to Ray Hill for *;* the ReadItemL} and WriteItem *;* routines *;* *;*This program is too big toM} compile*;*like normal. You must compile it *;*from disk. Like this: *;* *;N}*Go to the monitor and type: *;* *;* C "D:APROG12.002" *;* O} *;*Don't forget the second " at the *;*end. *;* P} *;************************************ MODULEDEFINE Cls = "Put(125)" ;clear the screen ;****Q}********************************;* The following are the starting *;* places for each field *;***************R}*********************DEFINE Lastname = "0"DEFINE Firstname = "13"DEFINE Address = "23"DEFINE City_state= S}"63"DEFINE Zipcode = "103"DEFINE Phone = "114";------------------------------------DEFINE Max = "10T}0" ;max number of peopleDEFINE Datasize = "128" ;byte per personDEFINE Totalsize = "12800" ;room for 100 pU}eople ;gotton by ;Datasize*MaxBYTE V} Choice, ;catch all variable ;for user input NumPeople W};number of people currently ;in the database BYTE ARRAY Data_area(Totalsize), X} search_person(13)PROC ReadItem(BYTE num);************************************;* This procedure prints item #num *Y};* to the screen *;************************************ BYTE POINTER ptr ptr = Data_area + (num * DZ}atasize) PrintF("Name: %S",ptr+Firstname) PrintF(" %S%E",ptr+Lastname) PrintF("Address: %S%E",ptr+Address) [} PrintF("City, State: %S%E",ptr+City_state) PrintF("Zipcode: %S%E",ptr+Zipcode) PrintF("(P) %S%E",ptr+Phone)\}RETURNPROC WriteItem(BYTE num);************************************;* This procedure writes data into *;* item #num]} from the keyboard *;************************************ BYTE POINTER ptr ptr = Data_area + (num * Datasize) ^} Print(" Last name: ") InputS(ptr+Lastname) Print(" First name: ") InputS(ptr+Firstname) Print(" Address: ") InputS_}(ptr+Address) Print(" City, State: ") InputS(ptr+City_state) Print(" Zipcode: ") InputS(ptr+Zipcode) Print(" Phone:`} ") InputS(ptr+Phone) RETURNBYTE FUNC Getkey();************************************;* This function returns the ATa}ASCII*;* value of the key pressed *;************************************ BYTE key Close(1) Open(1,"K:",4,b}0) key=GetD(1) Close(1)RETURN(key)PROC Skip(BYTE lines);************************************;* This procedure placc}es "lines" *;* EOLNs on the display for better *;* better screen formatting *;********************************d}**** BYTE counter FOR counter=1 TO lines DO PutE() ODRETURNBYTE FUNC look();****************************e}********;*Here we get a last name and if *;*the person is in the list, we *;*return their number. Return a 0 *;*f}otherwise. *;************************************ BYTE num, found, key, rvalg} BYTE POINTER ptr Cls num=0 found=0 Skip(5) Print("Last name? ") InputS(search_person) DO num==+1 pth}r = Data_area + (num * Datasize) IF Scompare(ptr+Lastname,search_person)=0 THEN PrintE("Is the person:") Skipi}(2) Print(" ") PrintE(ptr+Firstname) Print(" ") PrintE(ptr+Lastname) Skip(2) Print("(j}Y/N) ") key=Getkey() IF (key='Y) OR (key='y) THEN found=1 EXIT ELSE PrintE("No") k} PutE() FI FI UNTIL num=NumPeople OD IF found=1 THEN rval=num ELSE rval=0 FIRETURN(rval)l}PROC Change();************************************;* Procedure to change any of the *;* data for any person in the listm}. *;* Requires the catch-all global *;* variable called Choice *;************************************ BYTn}E num, key BYTE POINTER ptr DO num=look() IF num THEN DO DO Cls o}ReadItem(num) PutE() PrintE("Press to change") Skip(2) PrintE(" 1 = Last name"p}) PrintE(" 2 = First name(s)") PrintE(" 3 = Street address") PrintE(" 4 = City / Stateq}") PrintE(" 5 = Zipcode") PrintE(" 6 = Phone number") PrintE(" 7 = No change") r} Skip(5) Print("Your choice: ") Choice=InputB() UNTIL (Choice>0) AND (Choice<8) OD s} ptr = Data_area + (num * Datasize) IF Choice=1 THEN Print("Last name was: ") PrintE(ptr+Lastnt}ame) Skip(2) PrintE("What is the new last name?") InputS(ptr+Lastname) ELSEIF Choice=2 u}THEN Print("First name was: ") PrintE(ptr+Firstname) Skip(2) PrintE("What is the new v}first name?") InputS(ptr+Firstname) ELSEIF Choice=3 THEN Print("Address was: ") PrintE(w}ptr+Address) Skip(2) PrintE("What is the new address?") InputS(ptr+Address) ELSEIF Choix}ce=4 THEN Print("City / State was: ") PrintE(ptr+City_state) Skip(2) PrintE("What is y}the new city / state?") InputS(ptr+City_state) ELSEIF Choice=5 THEN Print("Zipcode was: ") z} PrintE(ptr+Zipcode) Skip(2) PrintE("What is the new zipcode?") InputS(ptr+Zipcode) {}ELSEIF Choice=6 THEN Print("Phone number was: ") PrintE(ptr+Phone) Skip(2) PrintE("Wh|}at is the new phone number?") InputS(ptr+Phone) FI Skip(2) PrintE("Are there more changes f}}or") PrintF("%S %S ?",ptr+Firstname,ptr+Lastname) PutE() Print("(Y/N) ") key=Getkey() U~}NTIL (key='n) OR (key='N) OD PrintE("No") FI PutE() PrintE("Change data for other names?") PrintE}("(Y/N) ") key=Getkey() UNTIL (key='n) OR (key='N) OD RETURNPROC View();************************************};* This procedure allows the user to*;* see the whole list 2 people at a *;* time. The user can also exit to *;* the mai}n menu at any time. *;************************************ BYTE counter=[0], two_counter=[0], tem}pkey, flag Cls flag=0 FOR counter=1 TO NumPeople STEP 2 DO two_counter=0 DO ReadItem(counte}r+two_counter) Skip(3) two_counter==+1 UNTIL (two_counter=2) OR (counter+two_counter > NumPeople) OD }PrintE(" *Press to continue*") PrintE(" * for Main Index*") Skip(3) tempkey=Getkey() IF (tempkey='R)} OR (tempkey='r) THEN flag=1 EXIT FI OD IF flag=0 THEN PrintE(" *End of File*") PrintE(" *} Press to continue*") tempkey=Getkey() FIRETURN ;Here is the first time we reassign;the default device. }What does that;mean? Everytime you compile your;Action! programs, Action! declares;a few variable for you. You saw that};the EOF array was one of them.;Here's another one. BYTE device ;When you do a Print or any other;print type command (Pr}intBE, PrintF; etc.), the output goes to your;screen. If you Open() a file and;assign device to that channel, all;the ou}tput will go there instead of;the screen. Example:;; Open(3,"D:FILE",8,0); device=3; ;All Print routines wil}l print to;that file. You should save the;value of device before you reassign;it. That way, you can put it back;to norm}al. That is what happens in;the Search() routine below and in;PrintL() later on.PROC Search();***********************}*************;* This procedure searches the list *;* for a matching last name. If the *;* correct person is not found, the} *;* search continues until found or *;* out of data. *;************************************ BYTE }num, key, holddev BYTE POINTER ptr CARD temperr Cls DO num=look() IF num THEN Cls } ReadItem(num) Skip(4) PrintE("Do you want to print this") PrintE("out on your printer?") PutE()} Print("(y/n) ") key=Getkey() IF (key='Y) OR (key='y) THEN PrintE("Yes") holddev=device ;}save the normal Close(1) Open(1,"P:",8,0) device=1 ;reassign output to the printer R}eadItem(num) Skip(2) Close(1) device=holddev ;put everything back to normal ELSE Pri}ntE("No") FI ELSE Skip(3) Print(" The ") Print(search_person) PrintE(" you are looking fo}r") PrintE(" is not in this file.") FI Skip(3) PrintE("Search more names?") Print("(Y/N) ") key=G}etkey() IF (key='y) OR (key='Y) THEN PrintE("Yes") FI UNTIL (key='n) OR (key='N) ODRETURNPROC Add();}************************************;* This procedure adds people to the*;* end of the list. *;***********}************************* BYTE key BYTE POINTER ptr DO Cls Skip(2) Print("Enter data: ") NumPeople==}+1 PrintBE(NumPeople) WriteItem(NumPeople);************************************;* Verify the entry } *;************************************ Cls Print("Entry #") PrintBE(NumPeople) Skip(3) ReadItem(NumPeo}ple) Skip(5) PrintE("Add more names?") Print("(Y/N) ") key=Getkey() UNTIL (key='n) OR (key='N) OR (NumPeopl}e=Max) ODRETURNPROC Delete();************************************;* This procedure finds a person in *;* the list a}nd deletes him. It then*;* move all persons after the *;* deleted one physically forward in*;* the list. The speed o}f Action! *;* really shines in this PROC. *;************************************ BYTE num, key, cou}nter BYTE POINTER ptr, ptr2 Cls DO num=look() IF num THEN FOR counter=num TO NumPeople } DO ptr = Data_area + (counter * Datasize) ptr2 = Data_area + ((counter+1) * Datasize) Scopy(ptr+L}astname,ptr2+Lastname) Scopy(ptr+Firstname,ptr2+Firstname) Scopy(ptr+Address,ptr2+Address) Scopy(ptr+}City_state,ptr2+City_state) Scopy(ptr+Zipcode,ptr2+Zipcode) Scopy(ptr+Phone,ptr2+Phone) OD NumPeo}ple==-1 ELSE Skip(3) Print(" The ") Print(search_person) PrintE(" you are looking for") Pr}intE(" is not in this file.") FI Skip(3) PrintE("More deletions?") Print("(Y/N) ") key=Getkey() IF (}key='y) OR (key='Y) THEN PrintE("Yes") FI UNTIL (key='n) OR (key='N) ODRETURNPROC Switch(BYTE x,i);******}******************************;* Procedure to switch all the *;* elements of person x with person *;* i. } *;************************************ BYTE ARRAY n(40) BYTE POINTER ptr, ptr2 pt}r = Data_area + (x * Datasize) ptr2 = Data_area + (i * Datasize) SCopy(n,ptr+Lastname) SCopy(ptr+Lastname,ptr2+Lastname}) SCopy(ptr2+Lastname,n) SCopy(n,ptr+Firstname) SCopy(ptr+Firstname,ptr2+Firstname) SCopy(ptr2+Firstname,n) SCopy(n},ptr+Address) SCopy(ptr+Address,ptr2+Address) SCopy(ptr2+Address,n) SCopy(n,ptr+City_state) SCopy(ptr+City_state,ptr2}+City_state) SCopy(ptr2+City_state,n) SCopy(n,ptr+Zipcode) SCopy(ptr+Zipcode,ptr2+Zipcode) SCopy(ptr2+Zipcode,n) SC}opy(n,ptr+Phone) SCopy(ptr+Phone,ptr2+Phone) SCopy(ptr2+Phone,n)RETURNPROC Alphabetize();**************************}**********;* It was too hard to figure out *;* what was going on in the alpha- *;* betize routine in the original. *};* When I originally translated *;* the TI version into BASIC XL, *;* I used the same algorithm. *;* But to t}ranslate it into struc- *;* tured code was hopeless! *;* So, I used a Selection Sort *;* instead. I realize }that a *;* selection sort isn't exactly the *;* fastest sort method available but*;* it gets the job done. } *;* Don't worry if you don't *;* understand this PROC, I got it *;* out of a book. After you get a *;* bet}ter handle on Action! you will*;* be able to figure it out. *;************************************ BYTE first, } current, least BYTE POINTER ptr, ptr2 Cls Skip(5) PrintE(" Please wait...") P}rintE(" The list is begin arranged") FOR first=1 TO (NumPeople-1) DO least=first FOR current=(first+1) TO NumPeo}ple DO ptr = Data_area + (current * Datasize) ptr2 = Data_area + (least * Datasize) IF (SCompare(ptr+La}stname,ptr2+Lastname)<0) OR ((SCompare(ptr+Firstname,ptr2+Lastname)=0) AND (SCompare(ptr+Firstname,ptr2+Firs}tname)<0)) THEN least=current Switch(least,first) FI OD ODRETURNPROC Save();***************}*********************;* This procedure saves the data to *;* the filename entered. For disk *;* users the D: or D2: must} be *;* entered. *;* *;* The first thing in the data file *};* is the number of people in the *;* list. This is just a BYTE. *;* The comes the actual data about *;* each per}son. *;************************************ BYTE ARRAY filename(15) BYTE POINTER ptr BYTE num} Cls PrintE("What is the name of your") PrintE("storage device?") Skip(2) PrintE("Example:") PrintE(" C:") Pri}ntE(" or") PrintE(" D:FILE.DAT ") PutE() PrintE("Disk user, be sure to") PrintE("include the D: or D2: ") Skip(}2) Print("Filename: ") InputS(filename) IF filename(0)>0 THEN ;* check to see if filename is empty Close(1) } Open(1,filename,8,0) PrintBDE(1,NumPeople) FOR num=1 to NumPeople DO ptr = Data_area + (num * Datasize) } PrintDE(1,ptr+Lastname) PrintDE(1,ptr+Firstname) PrintDE(1,ptr+Address) PrintDE(1,ptr+City_state) } PrintDE(1,ptr+Zipcode) PrintDE(1,ptr+Phone) OD Close(1) FI RETURNPROC Load();*********************}***************;* This procedure loads the data *;* from the filename entered. For *;* disk users the D: or D2: must }be *;* entered. *;************************************ BYTE ARRAY filename(15) BYTE POINTER pt}r BYTE num, key Cls PrintE("What is the name of your") PrintE("storage device?") Skip(2) PrintE("Examp}le:") PrintE(" C:") PrintE(" or") PrintE(" D:FILE.DAT ") PutE() PrintE("Disk user, be sure to") PrintE("inc}lude the D: or D2: ") Skip(2) Print("Filename: ") InputS(filename) IF filename(0)>0 THEN ;* check to see if filen}ame is empty Close(1) Open(1,filename,4,0) NumPeople=InputBD(1) FOR num=1 TO NumPeople DO ptr = Dat}a_area + (num * Datasize) InputSD(1,ptr+Lastname) InputSD(1,ptr+Firstname) InputSD(1,ptr+Address) Inp}utSD(1,ptr+City_state) InputSD(1,ptr+Zipcode) InputSD(1,ptr+Phone) OD Close(1) Cls PrintF(" %S%E}",filename) Skip(2) Print("This file has ") PrintB(NumPeople) PrintE(" entries.") Skip(2) Print(" * }") PrintB(Max) PrintE(" entries maximum * ") Skip(12) Print(" Press to continue") key=Getkey() }FI RETURNPROC PrintL() ;************************************;* This procedure dumps the all the *;* data to the pri}nter. *;************************************ BYTE num, holddev, key CARD temperr holddev}=device ;save the normal output device Close(1) Open(1,"P:",8,0) Cls Skip(11) PrintE(" Please wait..}.") PrintE(" while printer is working") device=1 FOR num=1 TO NumPeople DO ReadItem(num) Skip(2) OD} Close(1) device=holddev ;put the output back the way it was Skip(3) Print(" Press to continue") key=Getke}y()RETURNPROC Main() BYTE POINTER fgnd, bgnd fgnd=709 bgnd=710 NumPeople=0 Graphics(0) bgn}d^=0 ;Turn background to black fgnd^=12 ;And characters to white Zero(Data_area,Totalsize) ;Clear out t}he data area PrintE(" * ATARI Phone book *") PutE() PrintE(" by") PutE() PrintE(" Thomas M. John}son") PutE() PrintE(" Available from") PutE() PrintE("Villa Video's Bargain Cellar") PrintE(" (414) 265-5}149") PrintE(" ExpressNet Node X11") Skip(11) Print(" Press to begin") Choice=Getkey() DO DO } Cls PrintE(" Main Index") Skip(4) PrintE("Press To") Skip(3) PrintE(" 1 = View nam}es list") PrintE(" 2 = Search for a name") PrintE(" 3 = Add a name") PrintE(" 4 = Change a name")} PrintE(" 5 = Delete a name") PrintE(" 6 = Alphabetize the list") PrintE(" 7 = Save the data file")} PrintE(" 8 = Load the data file") PrintE(" 9 = Print the list") PrintE(" 10 = Finish the session")} Skip(4) Print("Your choice: ") Choice=InputB() UNTIL (Choice>0) AND (Choice<11) OD IF Choice=1} THEN View() ELSEIF Choice=2 THEN Search() ELSEIF Choice=3 THEN Add() ELSEIF Choice=4 THEN } Change() ELSEIF Choice=5 THEN Delete() ELSEIF Choice=6 THEN Alphabetize() ELSEIF Choice=7 THEN } Save() ELSEIF Choice=8 THEN Load() ELSEIF Choice=9 THEN PrintL() ELSEIF Choice=10 THEN Cls } Skip(3) PrintE("Are you sure you want to") PrintE("end this session?") Print("(Y/N) ") Choice=Get}key() IF (Choice='Y) OR (Choice='y) THEN PrintE("Yes") Skip(5) PrintE("Have a nice day!") } FI FI UNTIL (Choice='Y) OR (Choice='y) ODRETURNtE("Yes") Skip(5) PrintE("Have a nice day!") ;PROC main() INT first_var, second_var, answer Print("First number? ") first_var=InputI() Print("SecondL} number? ") second_var=InputI() PutE() PrintI(first_var) Print(" + ") PrintI(second_var) Print(" = ") answer =L} first_var + second_var PrintIE(answer) PutE() PrintI(first_var) Print(" - ") PrintI(second_var) Print(" = ") L}answer = first_var - second_var PrintIE(answer) PutE() PrintI(first_var) Print(" * ") PrintI(second_var) Print("L} = ") answer = first_var * second_var PrintIE(answer) PutE() PrintI(first_var) Print(" / ") PrintI(second_var) L} Print(" = ") answer = first_var / second_var PrintIE(answer) Print(" With a remainder of ") answer = first_var MOD sL}econd_var PrintI(answer) PutE()RETURN r PrintIE(answer) Print(" With a remainder of ") answer = first_var MOD sL.PROC main() INT first_var, second_var Print("First number: ") first_var=InputI() PutE() Print("Second numbP}er: ") second_var=InputI() PutE() IF first_var = second_var THEN PrintI(first_var) Print(" and ") PrintI(sP}econd_var) PrintE(" are equal!") PutE() FI IF first_var <> second_var THEN PrintI(first_var) Print(" andP} ") PrintI(second_var) PrintE(" are not equal!") PutE() FI IF first_var > second_var THEN PrintI(first_vP}ar) Print(" is greater than ") PrintIE(second_var) PutE() FI IF first_var >= second_var THEN PrintI(firsP}t_var) Print(" is greater than or equal to ") PrintIE(second_var) PutE() FI IF first_var < second_var THEN P} PrintI(first_var) Print(" is less than ") PrintIE(second_var) PutE() FI IF first_var <= second_var THEN P} PrintI(first_var) Print(" is less than or equal to ") PrintIE(second_var) PutE() FIRETURN ond_var THEN PoPROC main() BYTE i, j j=0 Print("Press 1 to continue... ") i=InputB() WHILE i<>0 DO PutE() PrinX}tE("Give me a number: ") PrintE("Enter a 0 to exit") i=InputB() j=j+i OD Print("The sum of your numbers is: "X}) PrintBE(j)RETURN PrintE("Enter a 0 to exit") i=InputB() j=j+i OD Print("The sum of your numbers is: "XPROC main() CARD big_num BYTE divide PutE() PrintE("Give me a big number but") PrintE("it has to be less than 65,\}000") big_num = InputC() DO PutE() PrintE("What do you want to divide") Print("into ") PrintC(big_num) \} PrintE(" ?") divide = InputB() IF divide=0 THEN EXIT FI big_num = big_num / divide UNTIL \}big_num < 10 OD IF big_num > 10 THEN PutE() PrintE("You can't divide by zero!!!") FI PutE() Print("Big nu\}mber now equals ") PrintCE(big_num)RETURN tE() PrintE("You can't divide by zero!!!") FI PutE() Print("Big nu\0PROC main() CARD big_num BYTE divide PutE() PrintE("Give me a big number but") PrintE("it has to be less than 65,`}000") big_num = InputC() DO PutE() PrintE("What do you want to divide") Print("into ") PrintC(big_num) `} PrintE(" ?") divide = InputB() IF divide=0 THEN EXIT FI big_num = big_num / divide UNTIL `}big_num < 10 OD IF big_num > 10 THEN PutE() PrintE("You can't divide by zero!!!") FI PutE() Print("Big nu`}mber now equals ") PrintCE(big_num)RETURN tE() PrintE("You can't divide by zero!!!") FI PutE() Print("Big nu`0;Here are a few examples of what you;can do with PrintF().PROC main() CARD dollars1, dollars2, total Bh}YTE cents1, cents2, total_cents CARD questions, correct PutE() PrintF("%E%EHow many dollars inh} your account:%E $") dollars1=InputC() PrintF("%EAnd how many cents: $ 0.") cents1=InputB();If the user enters morei} than $0.99;then add 1 to the dollar amount. We;have to do this twice in case they;enter a number over 200. Remember,;a i}BYTE can be up to 255 IF cents1>99 THEN cents1= cents1 - 100 dollars1 = dollars1 + 1 FI IF cents1>99 THEN i} cents1= cents1 - 100 dollars1 = dollars1 + 1 FI PrintF("%EAnd how many dollars are you%Edepositing: $") dollarsi}2=InputC() PrintF("%EAnd how many cents: $ 0.") cents2=InputB() IF cents2>99 THEN cents2 = cents2 - 100 dollari}s2 = dollars2 + 1 FI IF cents2>99 THEN cents2= cents2 - 100 dollars2 = dollars2 + 1 FI total = dollars1 + doi}llars2 total_cents = cents1 + cents2 IF total_cents>99 THEN total_cents = total_cents - 100 total = total + 1 i}FI IF total_cents>99 THEN total_cents= total_cents - 100 total = total + 1 FI PrintF("%E%EYou now have $%U.%U i}in your%Eaccount.%E",total,total_cents);************************************;If you were to write the above line;without i}a PrintF and just use our;normal routines, you would have;this:;; PutE(); PutE(); Print("You now have $"i }); PrintC(total); Print("."); PrintB(total_cents); PrintE(" in your"); PrintE("account.");;Thi }is will give the EXACT same output;as the 1 PrintF line. If you want;to try it, just erase the ";" at;the start of the ini }dented lines.;***********************************;Now lets do a conversion with the;%H option PrintF("%E%E%EConvert i }to Hex%E--------------%E%E") Print("Give me a CARD: ") total=InputC() PrintF("%EIn Hex %U is %H%E",total,total);One i }last example, to use the % sign;you have to use "%%";The UNTIL loop makes sure the values;make sense.;IMPORTANT!!!!!!;Whi}en calculating percentages, always;multiply by 100 before you divide.;Here an example: If you go 10 out;of 100 it should i}be 10%;Since Action! doesn't have decimals;if you divide first you get:;;10/100 = 0 (NOT .1);0 * 100 = 0;You get ai} 0% instead of 10% DO PrintF("%E%EThis will give you test results%E") PrintF("%EHow many points possible: ") qi}uestions=InputC() PrintF("%E%EAnd how many correct: ") correct=InputC() IF correct>questions THEN Pri}intF("%EYou can't have more correct than%Etotal possible!%E") FI UNTIL correct36 THEN ;are we out of range? new_xpos=3u%} ;Yes, position '*' on the left FI ELSE ;x_rnum was a 0 so new_xpos==-1 ;we u&}move left IF new_xpos<3 THEN ;are we out of range? new_xpos=36 ;yes, move '*' to the right FI u'} FI old_ypos=new_ypos;also so we can erase the old '*' IF y_rnum=1 THEN ;should we move down? nu(}ew_ypos==+1 ;yes IF new_ypos>21 THEN ;too far down? new_ypos=2 ;reset to top of screen Fu)}I ELSE new_ypos==-1 ;no, we have to move up IF new_ypos<1 THEN ;can't above the top of the screen u*} new_ypos=21 ;move to the bottom FI FI ;here's where we move the '*';we send it old_xpos and oldu+}_ypos so;the old '*' can be erased. move(old_xpos, old_ypos, new_xpos, new_ypos);here we just delay the program by;u,}giving it something useless to do;for a while. Like counting from 1;to 3000. You can delete these lines;to see how fast iu-}t runs without;the delay FOR delay=1 TO 3000 DO OD OD ;end of the infinite loop ;RESET to endRETu.}URN without;the delay FOR delay=1 TO 3000 DO OD OD ;end of the infinite loop ;RESET to endRETt;This is a simple graphing program; ;This FUNC gets the value that we;are going to plot. The 2 %C and;254s in the "Fr}0}om 2 to 18:" line;are to erase the old value from the;screen that was input the last time;the FUNC was calledBYTE FUNC }1}get_input() BYTE how_many DO Position(2,21) PrintE("What is the upper Y limit?") PrintF("From 0 to 18: %C%C}2}",254,254) how_many=InputB() UNTIL how_many<19 ODRETURN(how_many)PROC main() BYTE i, j, y, }3} value Print("}") ; clear the screen;* Set up the chart * FOR i=1 TO 4 DO PrintF("|%E|%E|%E|%E%E") OD}4} PrintE("") PrintE(" 1 2 3") ;* Get 3 values to plot and then; plot the}5}m * FOR j=1 TO 3 DO y=18 value = get_input() FOR i=1 TO value DO Position(7*j+2,y) Print(}6}"*") y = y - 1 OD ODRETURN lue = get_input() FOR i=1 TO value DO Position(7*j+2,y) Print(|+;Here you play TIC-TAC-TOE against;the computer. The computer plays;by picking a random spot on the;board. If it is used8}, it picks;another until it finds an unused;place to play.MODULE;use a global because the board is;used by a number o9}f different;routines and each may or may not;change it. And we want that change;to affect the board everywhere.;;The AR:}RAY goes from 1 to 9. If that;spot has a 0, that means it is unused.;If it has a 1 that means the player;has an X there. ;} A 2 means the computer;placed a O there.BYTE ARRAY board(10);This PROC draws the board with the;X's and O's in the<}ir proper places,PROC print_screen() BYTE i, j, k k=0 PutE() FOR j=1 TO 3 DO FOR i=1 TO 3 =} DO k = k + 1 IF board(k)=1 THEN Print("X") ELSEIF board(k)=2 THEN Print("O") ELSE >} Print(" ") FI IF i<>3 THEN Print("|") FI OD PutE() IF j<>3 THEN PrintE("?}") FI ODRETURN;Here we clear out the board by putting;0's in all the placesPROC clear_board() BYTE i F@}OR i=1 TO 10 DO board(i)=0 ODRETURN;Print a help screen so the player;knows how to choose his positionPROC helA}p() PutE() PrintE("The board is set up this:") PutE() PrintE(" 1|2|3") PrintE(" ") PrintE(" B} 4|5|6") PrintE(" ") PrintE(" 7|8|9") PutE() PrintE("Enter 0 for help.") PutE()RETURN;HC}ere we check all the possible ways to;win, vertical, horizontal and diagonal;to see it the player has 3 1's in a row.;It rD}eturns a 1 if the player has won;and a 0 otherwise.BYTE FUNC player_won() BYTE rval rval=0 IF board(1)=1 AND boE}ard(2)=1 AND board(3)=1 THEN rval=1 FI IF board(4)=1 AND board(5)=1 AND board(6)=1 THEN rval=1 FI IF board(7)F}=1 AND board(8)=1 AND board(9)=1 THEN rval=1 FI IF board(1)=1 AND board(4)=1 AND board(7)=1 THEN rval=1 FI IFG} board(2)=1 AND board(5)=1 AND board(8)=1 THEN rval=1 FI IF board(3)=1 AND board(6)=1 AND board(9)=1 THEN rval=1H} FI IF board(1)=1 AND board(5)=1 AND board(9)=1 THEN rval=1 FI IF board(3)=1 AND board(5)=1 AND board(7)=1 THEN I} rval=1 FIRETURN(rval);Same thing as the above except it sees;if the computer has placed 3 2's in;a rowBYTE FUNCJ} computer_won() BYTE rval rval=0 IF board(1)=2 AND board(2)=2 AND board(3)=2 THEN rval=1 FI IF board(4)=2 K}AND board(5)=2 AND board(6)=2 THEN rval=1 FI IF board(7)=2 AND board(8)=2 AND board(9)=2 THEN rval=1 FI IF boL}ard(1)=2 AND board(4)=2 AND board(7)=2 THEN rval=1 FI IF board(2)=2 AND board(5)=2 AND board(8)=2 THEN rval=1 FM}I IF board(3)=2 AND board(6)=2 AND board(9)=2 THEN rval=1 FI IF board(1)=2 AND board(5)=2 AND board(9)=2 THEN rN}val=1 FI IF board(3)=2 AND board(5)=2 AND board(7)=2 THEN rval=1 FIRETURN(rval);Here the computer comes up witO}h a;random move. If it is unused, it;returns where it wants to move. If;it chooses a spot already taken, it;picks untilP} it finds a empty spot.;After 30 tries, if it didn't find a;empty spot, it just thinks the game is;a tie ("Cat's game") anQ}d clears the;board to start overBYTE FUNC computer_turn() BYTE rnum, i i=0 DO rnum=Rand(9)+1 i = i R}+ 1 IF i>30 THEN PutE() PrintE("Cat's game. We'll start over.") PutE() clear_board() EXITS} FI UNTIL board(rnum)=0 ODRETURN(rnum)PROC main() CHAR ARRAY name(20) BYTE move, winner;* Set eveT}rything up * clear_board() Print("What is your name? ") InputS(name) PrintF("%EOk %S, you are X's.%E",name) help()U} winner=0 DO print_screen();*Get the player's move* DO PrintF("%E%S's turn: ",name) move=InputB()V} UNTIL move<10 OD ;*Do they need help?* IF move=0 THEN help() DO PrintF("%E%S's turn: ",naW}me) move=InputB() UNTIL move<10 OD FI;*check to see if the spot is empty or not* IF board(moveX})<>0 THEN PrintE("That space is already taken!") ELSE board(move)=1 FI print_screen() ;*Did the Y}player win?* IF player_won() THEN winner=1 EXIT FI;*Did the computer win? If not get it's move* IZ}F computer_won() THEN winner=0 ELSE move=computer_turn() board(move)=2 FI PrintF("%EComputer's [}turn: %U%E",move) UNTIL computer_won() OD;*If we get here, either the computer; won or the player did (if the player\}; won we EXIT out of the loop and the; computer just used an UNTIL loop)* print_screen() IF winner=1 THEN PrintF("]}%E%EYou Won!!!!!%E") ELSE PrintF("%E%ESorry, the computer beat you.%E") FIRETURN IF winner=1 THEN PrintF("];This program prints 2 words in;alphabetical order.PROC main() CHAR ARRAY first(20), second(20) Print_}E("Enter EXIT for the first word to end") PutE() DO Print("Give me a word: ") InputS(first) Print("Give me a`}nother word: ") InputS(second) PutE() PrintE("Alphabetized they are:") IF SCompare(first,second)<0 THEN a} PrintF(" %S %S%E%E",first,second) ELSEIF SCompare(first,second)>0 THEN PrintF(" %S %S%E%E",second,first)b} ELSE PrintF("They are equal!%E%E") FI UNTIL SCompare(first,"EXIT")=0 ODRETURN %S%E%E",second,first)d Action! and BBS Express! PRO Tutorial by Thomas M. d}Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet Node}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copyf}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 2g}) All of the above information is intact.--------------------------------------Welcome to the Action!/PRO tuq}`-----------`ΠĠ`Щ`à֠`-----------b$cATUTOR 001b#ATUTOR 002b%ATUTOR 003b$ATUTOR 004#6TATUTOR 005bATUTOR 006bATUTOR 007b#3ATUTOR 008b.VATUTOR 009b?ATUTOR 010#)ATUTOR 011#CATUTOR 012#$0ATUTOR 013`-----------bAPROG 301bAPROG 302`-----------bAPROG 401bAPROG 402bAPROG 403`-----------bAPROG 601`-----------bAPROG 701bAPROG 702`-----------b/APROG 801`-----------b'7APROG 901b^APROG 902`-----------b APROG10 001`-----------b APROG11 001`-----------b.APROG12 001bGAPROG12 002`-----------torial.In it, I plan to teach you how towrite command modules for BBS Express!PRO. But to write these, you mustknow the r}Action! programming language.So this is a 2 for the price of 1tutorial.I strongly suggest you print the filesof this tuts}orial out. There are anumber of programs that accompany thetext part (the part you are readingnow) and smaller program int}cluded inthe text part that may take a longexplanation. So instead of tryingto view this on the screen and paging aroundu} looking for what I amtalking about, having it on paperwould make things easier.First thing you should do is turn onyouv}r computer with the Action! cartridge plugged in.You should see a flashing cursor in the upper left hand corner of thescw}reen and the words "ACTION! (c)1983 ASC" in inverse letters at thebottom. This is the EDITOR mode.This is where you enterx} and edit yourprogram. The Action! editor is veryversitile. I am using it right nowto write this tutorial.I guess we sy}hould start with the"standard" first program that you seein ANY book that teaches a programminglanguage. The infamous "Hez}llo, World"example.To set aside parts of this text thatshould be entered into the editor, Iwill indent from here on in.{} PROC main() PrintE("Hello, World") RETURNOK, so now what does it mean? The word PROC is a Action! re|}served word(that means you can't name a variable,procedure or function that name).PROC is short for PROCedure and thatsi}}mply means it is a section of code.The word "main" comes down to us fromthe language C. A short digression isneeded. In~} the language Pascal, thelast procedure is the controllingprocedure. It can calls all the otherprocedures and it is not n}amed.In C, the controlling procedure is the one called "main". But it canbe anywhere in the program.In Action!, we com}promise. It is named like C, but it must be lastlike Pascal. But in Action!, we don'thave to call it "main", we can call}it anything we want. But most programmers call it main.Then comes the "()". This mean thereare no parameters. The mai}n PROCcan NEVER have any parameters. If you are wondering what parameters are,we will cover them in a later lesson.Next} is the "PrintE()" line. Thisis part of the Action! library. Itprints what ever is between the quotesand puts the cursor} on the left sideof the screen on the next line down.Why is the PrintE() line indented?In Action!, indention and capitali}zationdo nothing. "PRINTE()", "printe()"and "PrintE()" are exactly the samething. But to keep programs from1 programmer} to another looking thesame, the "PrintE" is used. And it is indented to show that it belongs tothe PROCecude "main".La}stly, is the word "RETURN". This signifies the end of a procedure.When it occures at the end of the"main" procedure, your} programreturns control back to the Action!cartridge.How do you run this program? Whenit is typed into the editor exact}lyas shown, you press the CONTROL key,the SHIFT key and the M key at thesame time (I will abrieviate this asM).Yo}u will hear a buzz and the screen will go blank. There will be ainverse line at the top of the screen.You are now in the }MONITOR mode. Fromhere you must Compile your program.You press C then the RETURN key. Ifthere are errors, you will get }amessage telling you so. If you haveerrors, press E and the RETURN keyto go back to the Editor. If not,you press R and }the RETURN key toRun you program.This is a good place to end lessonone. If you want to experiment untilthe next lesson,} try adding some morePrintE lines in the program. Like: PROC main() PrintE("Hello World!") PrintE("I a}m programming in") PrintE("Action!") RETURNUntil the next lesson... rintE("Hello World!") PrintE("I aU Action! and BBS Express! PRO Tutorial by Thomas M. }Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet Nod}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copy}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 2}) All of the above information is intact.--------------------------------------In the last lesson, we went ov}er howto compile and run a Action! program.We also learned that the last PROCin a program is the first one thatis run. F}inally, we learned our first Action! library PROC - PrintE.Now we are going to cover varibles.In Action!, you must know w}hat typeof values a variable will take onbefore you can use it. This is sothe compiler can set aside the rightamount of }space for that variable.In Action!, we have 3 basic variabletypes: BYTE, INT and CARD.Note: the keywords BYTE and CHAR a}reidentical and can ALWAYS be used inplace of each other.First the BYTE. A BYTE can have avalue from 0 to 255 and that }is all.When you add 1 to a BYTE with avalue of 255 you get 0. The same whenyou subtract 1 from 0 you get 255.BYTE value}s are used for loops andmost other general values.The next basic type is a INT. INTs can have values from -32768 to 3276}7.If you need to use negative numbers,a INT is the only way to do it.Lastly we have a CARD. CARDs can havevalues from 0} to 65535. Use CARDswhen you need larger numbers. But65535 is the largest number you canhave. When you add 1 to 65535 y}ouget 0 for an answer.The are no real numbers like 5.7in Action!. Nor are there scientificnotation like 5.8E4.Why doe}s Action! have these restric-tions? I know BASIC programmers aresay "In BASIC we don't have to declare variables and they} can bereal and larger than 65535."But in BASIC, EVERY variable takesup 6 bytes of memory. In Action!,a BYTE takes up 1} byte and INTs andCARDs take up only 2. And thisis the way the computer reallylooks at numbers. The floatingpoint packa}ge is the thing that reallyslows BASIC down.So we have this chart: size inname bytes low val. high val-}------------------------------------BYTE 1 0 255INT 2 -32768 32767CARD 2 } 0 65535Ok, so how do you use them? Here is a sample program. PROC main() BYTE i Print("Give me a} number. ") i=InputB() PrintBE(i) RETURNThe first line we know. It is required by all Action! progra}m todefine a PROC.The next line declares i and j asvariable of type BYTE. They will onlyhave a value from 0 to 255.Th}e Print statement prints what isbetween the quotes without returningthe carriage after.The i=InputB() line inputs a BYTE}from the keyboard and places its valuein i.j=i set the value of j to be the sameas the value in i. PrintBE(j) prints t}he value of j asa BYTE and returns the carriage. If a number larger than 255 is enteredthe Action! system will take w}hat iscalled the "least significant byte" ofthat number and place that in i. Iwon't go into LSB right now. But ifyou wa}nt to experiment...What if you wanted INTs instead ofBYTEs? PROC main() INT i Print("Give me a number. ") } i=InputI() PrintIE(i) RETURNOK, the last thing I will do in thislesson is the related Input andPrint functi}ons. BYTE bCARD cINT iJust declaring some dummy variables.i=InputI() input a INT c=InputC() input a }CARDb=InputB() input a BYTEPrint("hi") print string without the carriage returnPrintE("hi") print }the string with the carriage returnPrintB(b) print a BYTE without the CR PrintBE(b) pr}int a BYTE with a CRPrintC(c) print a CARD without a CRPrintCE(c) print a CARD with a CRPrintI(i) } print a INT without a carriage returnPrintIE(i) print a INT with a CRNext we will go into expression}s andthe IF statement. carriage returnPrintIE(i) print a INT with a CRNext we will go into expression Action! and BBS Express! PRO Tutorial by Thomas M. }Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet Nod}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copy}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 2}) All of the above information is intact.--------------------------------------In the last lesson we went ove}r variables. The name of a variabledoesn't have to a name like the "i" Iused in the examples. In fact, theyshouldn't} be like that. Variablenames should be descriptive to youknow what their purpose is. InAction!, the only restriction is }thatvariable names start with a letter.They may contain letters and the underline "_" character later in thename. Which }is easier to understand?t=(p*x)+p ortotal_price = (price * tax) + priceThis brings us to our next subject,expressi}ons.Action! supports the following operators. - as in negative numbers. Remember only INT can be negative. } * multiply / divide. This is integer division because Action! doesn't have real numbers. So when you } take 5/2 it is equal to 2 NOT 2.5 MOD This is the remainer when you divide. 5 MOD 2 equals 1 because 5/}2=2 with a remainder of 1 + addition - subtraction Action! also has a number of bit-wiseoperators but we will co}ver those later.I guess a sample program would begood about now. This sample programis a little too long for you to hav}eto type in to your editor. So Iguess this is a good time to say thatwhen this occures, the sample programwill be called} APROG.301This means it is a program with theATUTOR series. It goes with lesson3 and it is the 01 (first) program.To l}oad the program into your Action!editor, you press at the same time. The bottom lineof the editor will} print "Read?"Here you type in the filename and itwill load. Then you can compile and run the program like normal.You }will notice that the variblesare of type INT. I did this so youcan see how Action! handles negativenumbers. Try -32767 a}nd 4 forsample numbers once.You will see that Action! does someweird things when you try to gopast the boundries of the }variabletype. In this case, INT can onlybe -32768 to 32767.Try some nicer numbers to show theprogram works fine. Like }10 and 6.Or any other number you may want totry. You will have to recompile andrerun the program for each differentset o}f values.You may have noticed a PutE() commandin the program. This places acarriage return on the screen. Inother word}s, it just puts a blankline on the screen. I just put itin there to make it easier to read.The next things we will cover} arerelationals. Relationals yield avalue of TRUE or FALSE. An examplemight be: 4=7. This is false.Here is a list of t}he Action!relationals: a=b tells if a and b are equala<>b tests to see if a and b are not equal a#b the same as a}<>b a>b is a greater than ba>=b is a greater than or equal to b a THEN statement statement statement FI}If the relational expression betweenthe brackets is true, Action! willexecute all the statements betweenthe IF line and }the FI line.If the relational is false, Action!will skip all the statments betweenthe IF and FI and start with thestatem}ent after the FI.The statements between the IF and theFI should be indented a few spacesto show that they are dependent o}nthe IF statement. And it also makesit alot easier to read!try this program: PROC main() IF 4>9 THEN Pr}intE("4 is greater than 9") PrintE("Do you believe it?!?") FI PrintE("done") RETURNThe above program }should just printthe word "done". If 4 should happento be equal to 9 today (maybe itsFriday the 13th?) then it would prin}tthe other 2 lines followed by the word"done".This is the end of lesson 3, I willleave you with another program thatis }too big to print here. It iscalled: APROG.302 This is the end of lesson 3, I willleave you with another program thatis 2 Action! and BBS Express! PRO Tutorial by Thomas M. !}Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet Nod!}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copy!}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 2!}) All of the above information is intact.--------------------------------------Well, I guess its time we star!}tedtalking about loops. Loops give usthe ability to repeat a section ofcode over and over again untilwe want it to stop.!}The section of code we want to repeatis marked off with a DO at the startand a OD at the end. PROC main() DO !} Print("Hello!! ") OD RETURNThis is print Hello!! over and overand there is no way to stop it otherthan pressing t!}he BREAK key orthe RESET key. So we need a wayto control the number of timesa loop get executed. Action!provides us wit!}h 3 ways.The first and probably the leastpowerful is the FOR loop. It is themost used loop. Then why do I sayit is the!} least powerful? Becauseit executes a loop a fixed number oftimes. PROC main() BYTE i FOR i=1 TO 8 DO !} PrintBE(i) OD RETURNThis program just prints the numbers1 to 8 vertically on the screen. ANYcommands can be!} places between theDO and the OD and they will getexecuted 8 times.The next loop controller Action!gives us it the WHILE!} loop. It lookslike this: WHILE (a condition is true) DO ODThe WHILE loop evaluates its condition at the top of !}the loop, soif the condition is FALSE to beginwith, the loop will never execute.Try program APROG.401 to see.The last ty!}pe of loop control Action!gives us is the UNTIL loop. DO statements UNTIL (condition is true) ODThe major diffe!}rence between the WHILEand the UNTIL is that the UNTIL getevaluated at the bottom of the loop.This means it will be execut!}ed atonce. After it is executed once, ifthe condition is FALSE it will getexecuted again. DO PutE() PrintE("Pr!}ess any key or 0") PrintE("to exit") i=InputB() UNTIL i=0 ODIf the condition i=0 is TRUE the loopexits.The l!}ast loop command I saved for lastto mention because in theory, it isnever needed. I say in theory becausein the REAL worl!}d it can be useful.The command name is EXIT. Letssay your program has to input alarge number. And the next numbersare !}divided into the bug numberuntil the answer gets down below10. But if the user inputs a 0 todivide into, the is very bad !}sincea division by 0 doesn't exist.Look at program APROG.402 for thisprogram. You will notice that thedivison is not wh!}at you would expect.That is because Action! only has wholenumbers.In Action! if you: PrintBE( 1 / 3)That is take 1 d!}ivided by 3, you willget 0, NOT .33333Action! has no decimal notation.I am getting of the subject but Ifeel that since i!}t is used in the program it is a good idea to explainit.Anyway, the EXIT command is good whenyou use it in emergency sit!}uations,when you have to get out of a loopin a hurry.A EXIT is also useful when you havealot of conditions on when to en!}da loop.Like: UNTIL (the user answers yes ANDthe record number =0 AND you haven'treached the end of the file AND youare!}n't running out of memory space)I haven't gone into the actual Action!statements of those situation yet soI put them in w!}ords. But you getthe picture, there are 4 conditionsto end this loop.The better thing to do is just have 1or 2 conditio!}ns in the UNTIL statementand put the others in IF FI withcan EXIT.MOST other times, if you must havean EXIT in your loop!} to make it workright, you have chosen the wrongtype of loop.APROG.403 compares doing the sameloop with the 3 looping st!}atements.Remember, each time a program mustdo a loop, it is up to you, theprogrammer, do decide which type ofloop to use.!} For APROG.403, tryand guess which one is BEST. Theyall work, but one is best for whatI am trying to accomplish.That's!} it for Action!'s looping commands. In the next file, wewon't be going into any new Action!commands. It will cover some!}editor and monitor commands that willmake your writing and debugging ofAction! programs faster and easier. ll cover some o Action! and BBS Express! PRO Tutorial by Thomas M. )}Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet Nod)}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copy)}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 2*}) All of the above information is intact.--------------------------------------Well, now it is time to cover *}the mostpowerful of all the Action! Printroutines. It is called PrintF forprint formatted.This baby does it all!The f*}irst thing PrintF must have ita string in "quotes." If PrintF isused like this, it is just likePrint.command *} output------------------------------PrintF("Hello") HelloPrint("Hello") HelloBut if some special charact*}ers appearinside the "quotes", PrintF can doanything you want.The first of the special charactersis the %E. That is a pe*}rcent signfollowed by an E. This can appearanywhere in the "quotes" and Action!will do a RETURN where the %E appears.He*}re is a comparison of the old wayversus PrintFold way-------PutE()PrintE("What is your name?")PrintE("Only 10 charact*}ers please.")PutE()new way-------PrintF("%EWhat is your name?%EOnly 10 characters please.%E")It may look a little ha*}rder to readbut it actually takes up less memoryand time. Why? Because with eachcall to an output procedure, Action!must* } open a channel to the screen,print what you want and then close thescreen. So the old way there are 4opens and closes. * }With PrintF thereis only 1.The next special character is the %U.What does the U stand for? It meansUnsigned. INTs are * }signed with a +/-so it must be used by BYTEs and CARDs.But how does it know what value toprint where the %U is?Assume a * }and b are BYTES. a=5 b=10old way-------PutE()Print("The sum of ")PrintB(a)Print(" and ")PrintB(10)Print(" is ")Pr* }intBE(a+b)new way-------PrintF("%EThe sum of %U and %U is %U%E",a,b,a+b)Both print the line:The sum of 5 and 10 is 1*}5After the second quote, there is acomma and then the BYTEs that getsubstituted. The first BYTE in thatlist goes with t*}he first %U. And soon with the rest.Then what does a %C stand for? %Cprints the value associated with itas a character.*} The ATASCII valuefor the letter 'A' is 65. So,PrintF("The letter %C.%E",65)will print:The letter A.This may not s*}eem very useful but when you want to print specialgraphics characters it is real nice.Here is a list of special characte*}rsand how they output the data in thelist.%I - INT%U - CARD (the U stands for Unsigned) and BYTE %C - print as a c*}haracter%H - a Hexdecimal number%E - the RETURN character%% - output the percent sign%S - output as a string (we'll cover*} this in a later lesson)So what is wrong with PrintF? Well,it can only print to the screen.Not to a external device *}like adisk or your printer. Don't worryabout that now, we'll cover that ina later lesson also.Try APROG.601 for an exam*}ple of usingPrintF for handling some complexoutput formats.Well that's is for this installment.Short, sweet and to the p*}oint. Next,we will go into the heart of Action!,the ability to call PROCs. or this installment.Short, sweet and to the p(O Action! and BBS Express! PRO Tutorial by Thomas M. .}Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet Nod.}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copy.}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 2.}) All of the above information is intact.--------------------------------------Now its time to learn about PR.}OCs.What is a PROC? We already know aboutPROC main() but what else is there?A PROC is an independent block ofcode that .}can be called. Ideally,a PROC should use only local variablesand not global. We'll get into that in a minute.You defin.}e a PROC the same way youdefine main(). PROC my_proc() local variables statementsRETURN The "my_proc" c. }an be any name thatisn't already used by the Action!system.For you BASIC programmers, a PROC islike a GOSUB. But much m.!}ore powerful.PrintE and the most of the otherroutines we've looked at so far arePROCs that are built in to the Action!ca."}rtridge.Let's take a look at a sample.PROC my_proc() BYTE a a=10 PutE() PrintBE(a) RETURNPROC main() .#} BYTE a a=5 PutE() PrintBE(a) my_proc() PutE() PrintBE(a)RETURNCan you guess what will be printed?The outpu.$}t will look like this:5105First 'a' is set to 5 in main().Remember that the last PROC is alwaysthe first one run. Th.%}e value of'a' is then printed. Then when thecomputer gets to the line "my_proc()"it goes up to the spot where "PROC .&}my_proc()" is and starts runningthere. Ok, now we have another 'BYTE a'and we already declared a BYTE a.These .'}2 "a's" are as different asapples and oranges. They are localto the PROC they were declared in.So 'a' is set to 10 and i.(}s printed.When the RETURN statement is executed,the computer goes to the next lineafter the call to the PROC. In thiscas.)}e it will print 'a' again.And it prints 5. But in my_proc weset a=10. Once again, these are2 different variables becaus.*}e eachcan only be used by the PROC it isdefined in.A even more powerful feature of PROCsit the ability to pass it parame.+}ters.Parameters and local variables allowPROCs to not know or care anythingabout the outside program. A PROCwill have a .,}specific task and itwon't care what called it or why.Take a look at APROG.701 for anexample.The call to the PROC in main.-}() lookslike "square(num)". Action! takeswhatever num is equal to and placesin the variable "number" inPROC square(BYTE ..}number).You can have a number of parametersand they can be any type. You caneven mix types. To pass 2 BYTEs and1 CARD ./}to a PROC use this:PROC m(BYTE a,b CARD c)and the call would look like:m(10,30,5000)There are commas between like var.0}iabletypes and a space between differenttypes.You can have PROCs call other PROCs.It's important to understand the useo.1}f local variables and PROCs. Evenmore so of the PROCs. Next timewe will cover FUNCs, which are similarto PROCs, and the .2}opposite of localvariables, globals. so of the PROCs. Next timewe will cover FUNCs, which are similarto PROCs, and the ,( Action! and BBS Express! PRO Tutorial by Thomas M. 24}Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet Nod25}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copy26}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 227}) All of the above information is intact.--------------------------------------Do you remember what a functio28}n isfrom high school algebra? It takean number, performs some operation onit and return only 1 number back.Like:y = f(29}x)where f(x) = x^2So if x=3 then y=9.In Action!, a function is like a PROConly it has a type associated with it.We ca2:}n write the x^2 function inAction! like this.CARD FUNC squared(BYTE x) CARD y y = x * xRETURN(y)PROC main() 2;}CARD answer answer = squared(3) PrintCE(answer)RETURNAnd it will output a 9.Notice that there is a variable typeb2<}efore the word FUNC. This tellswhat is going to be returned. A BYTE,CARD or INT can be used. As you cansee, the rest is 2=}alot like a PROC.The next different thing is theRETURN statement.Whatever is on the left side of theequals sign in the c2>}all, in thiscase the variable 'answer' willget the same value as what is insidethe () after the word RETURN in theFUNC.2?}You can see that the input routineswe've been using so far are really FUNCs. When you do a: value = InputB()the firs2@}t line of InputB in realitylooks like this.BYTE FUNC InputB()meaning it returns a BYTE to value.When we first talked a2A}bout IF FI, I said that the conditional after theIF returned a TRUE or a FALSE. Inreality, the FALSE is the number 0.An2B}d TRUE is actually any other number.The most common values for TRUE are1 or 255 but ANY positive value willdue.So if you2C} wrote a FUNC that returnsa 0 or a 1, you could use it inplace of a conditional. This is apowerful use of FUNCs.BYTE F2D}UNC values_match(BYTE x,y) BYTE rval rval=0 IF x=10 AND y=20 THEN rval=1 FIRETURN(rval)PROC main() BYTE 2E}v1, v2 PrintE("Please give me 2 numbers.") Print("v1 = ") v1=InputB() Print("v2 = ") v2=InputB() IF valu2F}es_match(v1,v2) THEN PrintE("Your values match!!") FIRETURNThis is almost a trivial sample of the power this typ2G}e of construct.If you have seen a program I wroterunning on BBS Express! PRO called"The Wheel", 50% of that program isBYT2H}E FUNCs that return a 1 or a 0 toIF FI statements.Now, what if you need a variable thatwill be used by alot of PROCs and 2I}FUNCs? Do you keep sending it asa parameter? Well, you could, butusing globals would be better.We know that using a lo2J}cal variabledoesn't affect any of the othervariable used outside that PROC orFUNC. What if we want to changesomething in2K} the outside program?Again, global variables are theanswer.A global variable is a variable thatis not declared between a2L} PROC andits RETURN or a FUNC and its RETURN.They are declared at the start of theprogram and between PROCs and FUNCs.Th2M}e compiler knows a variable is a global by use of the work MODULE.The word MODULE is assumed asthe first line your program2N}. But itnever hurts to put it in. If youdeclare globals anywhere else in yourprogram (like between PROCs etc.) thenyou 2O}MUST have the MODULE there.MODULE BYTE score PROC you_win() PrintE("You won this game!!!") score = 2P}score +100 RETURN PROC main() you_win() PutE() Print("Your score is: ") PrintCE(score) RETURNYou2Q} can see that the value of scorein the main() was increased by the"score = score +100" in you_win().You can't do this with2R} localsbecause when you change a local (thisincludes parameters too) it is onlychanged within that PROC or FUNC.Try to r2S}esist the urge to use allglobals in your programs. Globalsmake bugs nearly impossible to find.And there are times when yo2T}u don'tNEED a variable to change in theoutside program.When I first introduced PROCs I saidthat they were independent bl2U}ocksof code. Using globals makes a PROCdependent on the rest of the program. PROCs I saidthat they were independent bl0R Action! and BBS Express! PRO Tutorial by Thomas M. 6W}Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet Nod6X}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copy6Y}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 26Z}) All of the above information is intact.--------------------------------------An ARRAY is a group of numbers6[} thatare the same type. Whether that meansthey are a BYTE, INT or CARD.A string is something like this:"Hello, how are 6\}you today?"So why are these 2 concepts begin presented in the same lesson? Becauseto a computer, they are the samething6]}. A string is just an ARRAY ofBYTE values. But since a BYTE anda CHAR are EXACTLY the same thing,we will use CHAR just s6^}o we knowthat we are using that ARRAY as a string instead of just holdingnumbers. There is one smalldifference between s6_}trings andBYTE ARRAYs and we cover that in alittle bit.An ARRAY is a indexed group ofnumbers. Lets say you have 4 peopl6`}eplaying a game and you want to keeptrack of all their scores. Youcould use 4 different variableslike this:PROC print_6a}score() BYTE score1, score2, score3, score4 PrintF("Score 1: %U",score1) PrintF("Score 2: %U",sc6b}ore2) PrintF("Score 3: %U",score3) PrintF("Score 4: %U",score4)RETURNEverytime you needed to do somethingwith a perso6c}ns score, you have tofigure out who is playing and thenuse their particular score variable.A better way is to use an ARRA6d}Y.PROC print_score() BYTE ARRAY score(5) BYTE player FOR player=1 TO 4 DO PrintF("Score %U: %U",player,scor6e}e(player)) ODRETURNNow anytime you need a persons score,you just place that player's numberin score( ) and it is given6f} to you.The declaration of an ARRAY istype ARRAY name(dimension)type can be any of the fundamentaltypes; BYTE (CHAR), 6g}INT or CARD.The dimension is how big the ARRAY isgoing to be. In Action!, ARRAYs gofrom 0 to dimension-1. That is whywe6h} declared score(5), now the playernumbers go from 0 to 4. We could haveused score(4) but then the numberswould go from 0 6i}to 3 and humansusually don't think that way.The type has nothing to do with howbig an ARRAY can be. The type iswhat the6j} ARRAY will hold. Forexample, you can have this:BYTE ARRAY total_pay(5000)Now you can have 5000 employees buteach can 6k}only have a pay of 0 to 255.(Sounds familiar huh?)total_pay(1) = 210total_pay(2) = 170total_pay(3) = 250total_pay(4) = 6l}100 . . .total_pay(4999) = 30If you want to input a number intoan array you could use:PROC main6m}() CARD ARRAY lottery(10) BYTE i FOR i=1 TO 9 DO lottery(i)=InputB() ODRETURNYou use ARRAY just like any 6n}normalvariable, but you must subscript"(i) or something" each time youuse it.So, what is the difference between aARRAY6o} of BYTEs and a string? Thezeroth (0th) BYTE of a string holdsits length. For this reason, youcan't do a direct assignme6p}nt, thecompiler won't let you. Here's what I mean: CHAR ARRAY prompt(30) prompt="What is your guess? "That is ille6q}gal. Instead, Action!provides you with a ton of PROCs andFUNCs to make working with stringseasy.To assign a string vari6r}able sometext, you use:SCopy(prompt,"What is your guess? ")This just copies what ever is secondinto what ever is first.6s} So you canalso use:SCopy(again,prompt)This will make the variable "again"equal to the same text as the variable"prom6t}pt". This is assuming that"again" was dimensioned to the samesize or bigger than "prompt".Printing strings is easy, we j6u}ustuse the normal Print() and PrintE()we have always been using. Just now,you use the string name inplace ofthe text. 6v} PrintE(prompt)Inputing strings is a little differentthat inputing normal variables.Here we use:InputS(prompt)N6w}otice that it is a PROC and not a FUNC.Action! also has PROCs that takepart of one string and copy theminto another (sub6x}strings) and takinga string and copying into part ofanother (appending or inserting).Look in you Action! manual on howto 6y}use these PROCs.Another thing you can't do in Action!is compare string like this:IF prompt=again THEN ...You must use 6z}a built in FUNC thatdoes this for you.SCompare(prompt, again)This FUNC returns an INT value. Itreturn a number <0 if p6{}rompt is lessthan again. It return 0 if theyare equal. And it returns a number>0 if prompt is greater than again.This 6|}is great for alphabetization. Infact, APROG.902 does a littlealphabetizing.Before I let you go I have to tellyou a litt6}}le somthing I left off ofATUTOR.003.In an IF statement, if the conditionalis not true you can have an ELSEstatment.IF 6~}a>b THEN PrintE("A is less than B")ELSE PrintE("A is greater than or") PrintE("equal to B")FIAction! will execute t6}he second partonly if the first is not true. Youcan also have multiple IFs.IF a>b THEN PrintE("A is less than B")ELSE6} IF a=b THEN PrintE("A is equal to B") ELSE PrintE("A is greater than or") FIFIIn fact, this happens so oft6}en thatwe have a special statement for it:the ELSEIF. The next example isthe exact same thing as the above one.IF a>b TH6}EN PrintE("A is less than B")ELSEIF a=b THEN PrintE("A is equal to B")ELSE PrintE("A is greater than or")FIThe rea6}son I am mentioning this nowis APROG.901 uses both the ELSE andthe ELSEIF. E PrintE("A is greater than or")FIThe rea4O Action! and BBS Express! PRO Tutorial by Thomas M. :}Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet Nod:}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copy:}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 2:}) All of the above information is intact.--------------------------------------Well, I guess its time to talk:} aboutfiles. Now, when I say files, I meanboth files and devices. The onlyAtari device that uses files is thedisk drive:}. But when it comes downto using files and devices, thingsare done the same.Your Atari has a few devices built into it :}when you turn it on.E: - input and output - This is the standard Atari editor that is used. When you do a Pri:}ntE() or other simple output, this is the device it goes to. Also, when you do a InputB() this is the device i:}t comes from. It is the screen and the keyboard combined.C: - input and output - This is the cassette player.:}P: - output only - This was originally meant to stand for parallel but Atarians now know it as printer. It mak:}es sense that it is for output only, right?S: - output only - This is the screen. This is the device th:}at is opened by the Atari when you do a Graphics command. (We'll cover Graphics later in the tutorial.)K: -:} input only - The keyboard. When you input information from the keyboard, nothing is echoed on the screen.:}There are 2 more devices that we callstandard, even though they aren't built in to you computer. They haveto be loaded :}in before you can usethem.D: - input and output - Your disk drive. DOS must be loaded before you can use it. :} Also, a filename must be supplied when you first open this device.R: - input and output - The RS232 port on the 85:}0 or P:R: Connection. This is used by modems that need the interface.There is also 1 custom device thati:}s "famous" enough to merit mementioning it here.T: - input and output - This is your 1030 or XM301 modem.OK, those ar:}e the devices. How do youuse them? Good thing you asked. Thefirst thing you must do before youcan use a device, is open:} it.Open(1,"K:",4,0)The number "1" is the device number.After you open a device, from the thenon you refer to it by its:} devicenumber.The "K:" is what device you want toopen. It is a string and must eitherbe in "quotes" or a CHAR ARRAYvari:}able.The next number is the command. Usethis chart to find out which commandto use.Input Only - 4Output Only :} - 8Input and output - 12Append to end of file - 9Disk drive directory - 6Since a K: device can o:}nly do input,the number "4" is an easy choice.Just because a device can do inputand output DOES NOT mean you shouldchoos:}e the number 12. If you wantto output to a disk file use 8.The reason the command number 12 isthere is in a situation lik:}e this:If you want to change the 5th BYTEin a file, you read the first 4and then over write the 5th.The last number "0":} is required andthere must always be a "0" there.If you know BASIC, you will see thereis a little difference between the :}order Action! uses and the orderBASIC uses.In BASIC it is like this:OPEN #1,4,0,"K:"The arguments mean the same thing:}s,just a different order.To output to a file, you use thestandard Atari Print PROCs exceptyou put a D (for device) at th:}eend in the proper place. For example,if you want to print a string witha carriage return on the endto a device, you'd u:}se:PrintDE(2,"Hi there")The number "2" is the device numberyou assigned it in the Open(). Thiscan be done to any devic:}e that cando output and the statement will beexactly the same.Here are the output PROCs. PrintD - stringPrintDE :} - string with CRPrintBD - BYTEPrintBDE - BYTE with CRPrintCD - CARDPrintCDE - CARD with CRPrintID - INTPrintI:}DE - INT with CRThe input statements are close to thenormal input FUNCs as well.b=InputBD(1)Input a byte from device :}number 1.Here are the input FUNCs.InputBD - BYTEInputCD - CARDInputID - INTAnd for strings:InputSD(3,name)This get:} a string from device number3 and places it in name.There are 3 more statements you canuse with devices.c=GetD(1) - ge:}t a single character from device number 1PutD(1,c) - put a single character on device 1.PutDE(1:},c) - same but CR afterInputMD(3,name,20) - Get a string from device number 1 and:} only 20 characters long.When you are done with a device, youmust always close it.Close(4) - close :}device number 4.There are a few things that are different when you use D:The first is you must supply afilename. It :}can be 8 characterslong with a 3 character extension.Open(3,"D:MYFILE.DAT",8,0)If you use a DOS that hassubdirectories,:} they can be includedin the device string as well.If you use Open a disk file witha command number of 8, it willcreate a:} new file if it does notalready exist or erase the old fileif it does.When you Open a disk file withcommand number 4, it:} always startsreading at the beginning.It is a good idea to get in the habitof close a device number beforeyou open it j:}ust to make sure it isok to use. If you try to open a device number when it is alreadyopen, you program will bomb.The d:}evice numbers that you are allowed to use are 1 though 7.Lastly, every time you compile anAction! program, a BYTE ARR:}AY isautomaticly declared for you. TheARRAY is called "EOF". EOF holdseither a 0 or a 1 so it can be usedin a IF, WHILE:} or UNTIL statement.When using disk or cassette files,you cannot try to read past the endof the file. If you do try, the:}program will crash.So you have 2 choices, either youhave to save the number of entriesin that file and use a FOR loopto:} read in exactly that number ofentries. Or use EOF.EOF holds a 1 if you are at the endof file and 0 otherwise. Forexam:}ple:EOF(2)If device number 2 is at the end ofthe file, then this will be a 1. Thebest way to use EOF is in a WHILEloo:}p because a WHILE loop checksbefore the loop is run the firsttime.PROC read() BYTE character Close(1) Open(1,"D1:}:ATUTOR.001",4,0) WHILE EOF(1)=0 DO character=GetD(1) Put(character) OD Close(1)RETURNThis PROC prints AT:}UTOR.001 on thescreen character by character. Thefile ATUTOR.001 must be on the disk indisk drive #1 for this program to :}work. Also, you may have noticed thatI didn't call it main() this time.Remember, you don't have to callit main().This :}type of PROC might be good ifyou wrote a game and this will printthe instruction file to the screenfor the user.You may :}also have noticed that readingcharacter by character is not the mostefficient way to do this. A betterway would have been:} to read the wholeline in with a InputSD() and echoit with a PrintE(). But to so this the last line must end with a CRbe:}fore the end of file. If you KNOWthat it does, you can use the nextPROC instead. But, if you areunsure, you don't want t:}o makeassumptions. (By the way, ATUTOR.001does have a CR before the end of fileso it is OK to use this PROC)PROC better:}_read() BYTE ARRAY line(50) Close(1) Open(1,"D1:ATUTOR.001",4,0) WHILE EOF(1)=0 DO InputSD(1,line) Print:}E(line) OD Close(1)RETURN Close(1) Open(1,"D1:ATUTOR.001",4,0) WHILE EOF(1)=0 DO InputSD(1,line) Print8! Action! and BBS Express! PRO Tutorial by Thomas M. >}Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet Nod>}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copy>}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 2>}) All of the above information is intact.--------------------------------------We have just finished pretty m>}uch ofthe basics of Action! Now it's timeto get into the more advanced topicthat Action! offers.The first of these is t>}he POINTER.A POINTER does not hold a value likea "normal" variable. Instead it tellsus where that value physically is in>}side your Atari. To declare a POINTER we first have to declare whattype it will point to.BYTE POINTER aCARD POINTER b>}There are 2 new operators that canbe used with POINTERS. If we havea variable i of type INT we canuse this:INT POINTER >}g g=@iThis means g points to i. Well, itreally mean that we have assignedg to point to the same memory locationas i.>} g holds the memory locationof i.Another new operator we now have is: g^=5This says to put the value 5 intothe memo>}ry location that g points to.Try APROG11.001 and try and followwhat is going on. You can see thatPOINTERs are a nice way>} of simulatingthe BASIC POKE command. But Action!has even better ways to accomplishthat.They say "A picture is worth a>}thousand words" to I'll try it now.I'll try and show you this PROCgraphicly. PROC m() CARD c CARD POINTER cp c=1>}0 cp=@c cp^=6RETURNOk, we have 2 objects to begin with: I'll use ? to mean we don't know forsure that these va>}lue hold since wedidn't assign them to anything yet. ? ? cp c When the assignment c=10 c>}ome upthe variable look like this: ? 10 cp cWhen cp=@c is executed, cp is assignedto poin>}t to the memory location thatc occupies. NOT to the value in c. -------| 10 cp -------> cThen, we change >}the value in thelocation cp points to to 6. -------| 6 cp -------> cI hope that helped a little.Have yo>}u ever wanted to change thevalue of parameter you passed to aPROC or FUNC? Well, before now youhave to create a global an>}d not usea parameter at all. POINTERs allowyou to keep PROCs and FUNCsindependent by not using globalsand allowing you t>}o change the valueof a parameter outside of the PROC. PROC add(BYTE POINTER a) a^==+10RETURNPROC main() BYTE a >}a=5 PrintBE(a) add(@a) PrintBE(a)RETURNWell, I bet you are saying, "That'snice, I MIGHT use that once in awhile, >}but big deal otherwise." I amgoing to introduce 2 more types ofnew Action! ideas then you will seethe importance of POINT>}ERs. We are going to leave POINTER for amoment to talk about 2 things. Thefirst is VERY short. It is the Action! dire>}ctive DEFINE. You useDEFINE to clarify your programs andmake them easier to read. And theytake up no extra memory so you>} canuse tons of them without any overhead.DEFINEs simply substitute one thingfor another. We know from a previousAPROG >}that Put(125) clears the screen.But you really can't tell that justby looking at it can you? But CLSlooks like it might m>}ean clear screen.So we can use:DEFINE CLS = "Put(125)"PROC m() CLS Print("hi")Or you can use it like this:DEFIN>}E MAX = "25"PROC any() FOR i=1 TO MAX DO ;read in values OD FOR i=1 TO MAX DO ;print out values OD>}This way, if you want to increase themaximum number of entries, you onlyhave to change the value in MAX, andall the times >}it is used are changed.The next thing is records. You mayhave noticed that when you declarean ARRAY, all the items have >}to bethe same type. All INTs, all CARDsetc. Records allow us to mix typesinto one object.TYPE new = [ BYTE player_numb>}er, points_per_game CARD season_total, lifetime_total ] new bball_player>}We have just made a new type ofvariable. When we use thenew bball_playerit is just likeINT g"new" is the type and >}bball_player isthe variable name. To use a recordwe have "dot notation". That is justa fancy way of saying we do this:>}bball_player.player_number=12bball_player.points_per_game=28bball_player.season_total=300bball_player.lifetime_total=Input>}C()And to retrieve this information wecan just:PrintBE(bball_player.player_number)I think this is a good time to stop.>}We have gone over alot in a shorttime and this stuff is pretty hard toget the hang of right away. And itis probably hard>} to think of whatyou can use this for. And youralso saying, "Hey, you said there would be more with POINTERs!" We'llgo>} over how to get more out ofrecords using POINTERs next time. ey, you said there would be more with POINTERs!" We'llgo<A Action! and BBS Express! PRO Tutorial by Thomas M. B}Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet NodB}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copyB}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 2B}) All of the above information is intact.--------------------------------------Well, as you probably noticed B}in thelast file that POINTERs and recordsaren't all that usefull by themselves.In fact, I decided not to includea sample B}program about records becauseI couldn't think of a good example.But, when you mix POINTERs and records you get alot of poB}wer. Youmay have tried to make a ARRAY ofrecords. This is illegal in Action!But, if you use POINTERs to accomplishthis B}it will work.Also, you cannot have a ARRAY as afield in a record. Since strings arejust CHAR ARRAYs, you can't, forexamB}ple, associate a name with otherinformation about a person. Again,POINTERs make this possible too.Even more, you can't hB}ave ARRAYs ofstrings. You guessed it, POINTERs tothe rescue again. I will be coveringall of these in this lesson. YoudB}on't have to fully understand recordsand POINTERs to use the concepts I amintroducing. You can just copy theroutines, etcB}. and modify them forwhatever use you have in mind. But,a good understanding of POINTERs willallow you to even more powerB}ful thingsin Action!First, how do you make an ARRAY ofrecords in Action!? First you haveto decide what your record willB} looklike. TYPE employee=[CARD ssnumber1 BYTE ssnumber2 CARD ssnumber3 B} BYTE department, salary ]Now we have to count up the totalnumber of bytes in the record. CARDsand B}INTs take up 2 bytes and BYTEstake up 1. So, here we have 2 CARDsand 3 BYTEs for a total of 7. DEFINE size = "7"We haB}ve to decide how many records wewant to hold. Our company is kind ofsmall, we only have 6 employees. So,6 employees eachB} taking up 7 bytes.We have to reserve 42 bytes of memoryto hold our information because6*7=42. BYTE ARRAY company(42)C}Now its time to make that POINTER Ihave been talking about. employee POINTER info 'employee' is the type of record thaC}tthe POINTER will point to. 'info' isthe name of the POINTER.Lastly, you need an equation tofigure out where in memory C}this reallyis. This equation is the same one wewill use for all advanced record andPOINTER manipulations. info = compaC}ny + (counter * size)That's it!info - The name we gave our POINTERcompany - The ARRAY we used to reserve meC}mory.counter - This is the record number we wish to look at. Since we have 6 employees this wiC}ll be a number from 0 to 5. This can be a constant like 3 or a variable like in a FOR loop.siC}ze - The number of bytes in a record in our DEFINE line.Ok, so how do you use it? Easy...If we want to enterC} employee number3's information. info = company + ( 3 * size) info.ssnumber1 = 392 info.ssnumber2 = 80 info.ssnumbeC}r3 = 4593 info.department = 3 info.salary = 7And if employee #2 got a raise topaycode #10 info = company + ( 4 * siC }ze) info.salary = 10 If you want to print employee #0'ssocial security number: info = company + ( 0 * size) PrintC(C } info.ssnumber1) Print("-") PrintB( info.ssnumber2) Print("-") PrintCE( info.ssnumber3)The numbers in the record caC }n be usedjust like any other variable. info.department = 4 * 5Or whatever. Here is a little picturethat I hope will hC }elp you to see whatis going on. In case you didn't know,when you declare a ARRAY in Action!,the ARRAY name is actually a C }POINTERto where the ARRAY is in memory.So, let's say our ARRAY starts atmemory location 16000. Also, I'lluse - to represC}ent bytes. So a CARDwould have 2 bytes, --. TYPE employee=[CARD ssnumber1 BYTE ssnumber2 C} CARD ssnumber3 BYTE department, salary ]record 0 record 1 record 2-- - --C} - -|-- - -- - -|-- - -- - -|^|16000To get record 1 we use this formula: info = company + ( 1 * size)Sticking in thC}e numbers: info = 16000 + ( 1 * 7) info = 16007So, we move our pointer over 7 bytesto location 16007.record 0 C} record 1 record 2-- - -- - -|-- - -- - -|-- - -- - -| ^ | 16007To get record 2: C} info = 16000 + ( 2 * 7) info = 16014So, we move our pointer over 14 bytesfrom location 16000 to 16014record 0 rC}ecord 1 record 2-- - -- - -|-- - -- - -|-- - -- - -| ^ | C} 16014But records can't contain strings. SoPOINTERs must be used again to trickAction!What if you wrote a game C}where thereare multiple levels. When the firstplayer dies, the second player takesover, right where he left off. Well,yC}ou have to keep track of the playersscore, level and name. The score andlevel are easy with records, but thename? We'd uC}se this: TYPE record = [BYTE level CARD score BYTE name]Why only 1 BYTE for the name?C} Thisis just the first BYTE of the playersname. We'll save more space for itin a second. Count up the bytes withoutC} the name BYTE. 1 BYTE and1 CARD = 3 bytes DEFINE offset = "3"We'll save 20 bytes for the name. Soadd the length of thC}e name and theoffset value for the size. DEFINE size = "23"How many players maximum can play ourgame? We'll just say C}8. So,8 * 23 = 184 BYTE ARRAY players(184)Now we need 2 POINTERs. One likenormal, and 1 to point to the name. recC}ord POINTER active_player CHAR POINTER his_nameThe first POINTER we use just likewe have been before. active_player C}= players + (count * size)But to get the name we use: his_name = active_player + offsetThat's it! We'll so some assC}ignmentsto record number 4. active_player = players + (4 * size) his_name = active_player + offset active_player.levC }el=1 active_player.score=0 InputS(his_name)Now lets output player 6. active_player = players + (6 * size) his_nameC!} = active_player + offset Print("Level: ") PrintBE(active_player.level) Print("Score: ") PrintCE(active_player.scoreC"}) Print("Name: ") PrintE(his_name)Ok, the last situation like theseis if you need an ARRAY of differentsize strings.C#} Let's say a you needa program to keep track of yourcustomers first name, lastname andthe last date the ordered from you.C$}We'll say the date is of the formmm/dd/yy.How big to we want each field?field size in bytes---------------C%}------------------firstname 11lastname 14date 9Try to declare your sizes 1 biC&}ggerbecause strings go from 0 to 1 lessthan their size. This is neededbecause, remember, the 0th byte is thelength of thC'}e string.There are no records involved thisconstruct. Here we just usePOINTERs to get around. The firstDEFINE always sC(}tarts at 0. DEFINE firstname = "0"If you want to the firstname to be11 bytes, the lastname must startat the 12th byte.C)} 0 + 12 = 12 DEFINE lastname = "12"If the lastname is 14 bytes long thedate must start 15 bytes later thanthe lastnamC*}e. This means the 27 byteoverall. 12 + 15 = 27 DEFINE date = "27"The total size is 27 + 9 = 36 DEFINE size = "36"C+}How many customers do you have? Let'sjust say 100. 100 * 27 = 2700 BYTE ARRAY data(2700)Since we don't have a recordC,} only characters, our POINTER is just: CHAR POINTER ptrThe POINTER is just like normal ptr = data + (counter * sizeC-})Once again, that's it! For customer#53: ptr = data + (53 * size) Print("First name: ") InputS(ptr + firstname)C.} Print("Last name: ") InputS(ptr + lastname) Print("Last order date: ") InputS(ptr + date)APROG12.002 is a full C/}featured phonebook based on this last subject. Print("Last order date: ") InputS(ptr + date)APROG12.002 is a full @2 Action! and BBS Express! PRO Tutorial by Thomas M. G1}Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet NodG2}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copyG3}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 2G4}) All of the above information is intact.--------------------------------------Well, here we are at the last G5}lessonof Part 1. And I have to apologizefor this one. There are a lot oflittle things I want to mention. Mostof them haG6}ve nothing to do with any of the others.The first has to do with assigningvariables and routines to specificmemory locatG7}ions. You saw how youcan use POINTERs to change memorylocations (like the backgroundcolor of the screen). But thereis aG8} better way. When you declarea variable, you can assign it to alocation. BYTE bkgnd=710Now any change you make to bkgG9}nd willgo into location 710. bkgnd=0This will change the background colorto black. You can also assignPROCs to speciG:}fic memory locationstoo. That way, if there is a routineloaded into memory, you can callit easily. PROC machine_routG;}ine=$3500 (BYTE ARRAY s)In Part 2 of this tutorial we will usethis quite a bit.There is another thing you can do withvaG<}riables where you declare them. Youcan assign them to a value using[square brackets]. INT i=[-32] BYTE b=[0]So, if G=}you do a: PrintIE(i) PrintBE(b)you will get -32 0Square brackets are also used forinserting machine langG>}uage subroutinesin Action! programs. You can usehex values or decimal. You can evenaccess Action! variable. Here's aneG?}xample: [$A9 my_val $2A $8D $CD $04]Action! is very fast but sometimesyou can use that little extra burstfrom machine G@}language.If you want your Action! code to compile to a specific memory locationyou just insert this at the start ofyour GA}program. SET 14 = $4000 SET $491 = $4000Now you program will compile to location $4000.SET IS NOT LIKE A POKE! SETGB} CHANGESMEMORY LOCATIONS AT COMPILE TIME, NOTWHILE IT IS RUNNING!!!If you create a bunch of globalroutines that you in aGC}ll your programs,you don't have to type them in eachtime. They can be loaded in whilethe program is compiling. That wayGD}they are compiled in with your code.You can INCLUDE a file anywhere aslong as if is above whatever PROCsare going to call GE}them. You usually INCLUDE files after the globalvariable and before your first PROC.I have included a Public DomainruntGF}ime package. If you INCLUDEthis when you compile your programs,they will work without the Action!cartridge. It would looGG}k like: INT global1, global2 INCLUDE "D:RUNTIME.ACT" PROC My_first_proc() . . . RETURNGH}I mentioned that Action! predeclaressome variables for you. There is animportant one that HAS to be mentioned.NormallyGI}, if you Action! programfinds an error, it aborts. Yourcan trap errors by making PROCs thatwill execute when an error occGJ}ures. PROC my_error(BYTE errno) Print("I found an Error number ") PrintBE(errno) RETURNA BYTE parameter is alGK}ways needed.To make Action! go to this PROC instead of aborting, you just put in: Error = my_errorLastly, Action! has GL}the same graphicscommand built in as BASIC. I amnot going to go into great detailon graphics. There have been thousandsGM}of magazine articles written on thesubject. I will just list the BASICgraphics command and their Action!equivalents.BASGN}IC Action!-------------------------GRAPHICS 0 Graphics(0)SETCOLOR 1,0,0 SetColor(1,0,0)COLOR 2 GO} color=2POSITION 3,4 Position(3,4)PLOT 10,10 Plot(10,10)DRAWTO 20,20 DrawTo(20,20)I have not listed all tGP}he routinesin the Action! library. There are sound and game controller routines aswell as a ton more.Take a look at youGQ}r Action! manualagain. Hopefully you will understandit better than the first time youopened it and said "What does thatmGR}ean?!?"Well, I hope you all have enjoyedthis tutorial. Action! is a great programming language and Action!programmers aGS}re very friendly.Stay tuned for Part 2, writingprograms for BBS Express! Pro. Tomn!programmers aDm Action! and BBS Express! PRO Tutorial by Thomas M. 'U}Johnson Available from Villa Video's Bargain Cellar (414) 265-5149 ExpressNet Nod'V}e X11 Action! is copyright of ACS, OSS, ICD.BBS Express! PRO is copyright OrionMicro Systems. This tutorial is copy'W}right Thomas M.Johnson.This tutorial can be distributed underthe following conditions: 1) It is free. 2'X}) All of the above information is intact.--------------------------------------As promised, now we are going 'Y}to talkabout advanced editor and monitorcommands. Knowing these will makeyour writing, editing and debuggingof Action! p'Z}rograms many times fasterand easier.In this file, when I use somethinglike this: M That means to press the Co'[}ntrol, theShift and the M keys at the sametime. And we all know that doingthat will take us into the monitor.There are '\}more commands to helpyou than I can possibly list. If Idid it would take me over 100K. I amjust going to cover the ones ']}I usemost. I use almost all the commandsat sometime or another. Please lookat your Action! manual and carefullyread ove'^}r the sections on thesecommands. They are very important.I guess we should dive right in withsome editor commands. You '_}alreadyknow R and W for readingand writing to and from the editor.Pressing - and = (theseare the'`} arrow keys) will jump youaround the editor 1 screen at a time.You can really get around the editorfast using these. If'a} you are looking for a certainword or words in you Action! program,the editor has the F command.Action! will ask you'b} for the stringto search for. And zip you are thereor a not found message appear. Thisonly searches from the point youa'c}re in, downward. So if you are atthe end of your file, no matterwhat you search for you won't find itbecause there is not'd}hing below it.S will also find a string ofcharacters but it will also replaceit with another string. This willcom'e}e in very handy when we startprogramming for BBS Express! PRO.A word of caution, when yousubstitute, use a word that does'f} nothave the old string contained in it.Let's say you want to change all theoccurences of the word 'score' in your progr'g}am into 'u_score'. Changingthe first occurence is great. Thecursor will be on the 'u' in 'u_score'.The next occurence i'h}t will find is the'score' in 'u_score' so you will get 'u_u_score'.If you change a existing line but havenot yet pressed'i} the RETURN key,U will restore it back as goodas new.To delete a line just press . To delete'j} a bunch ofline just hold this key down. Oh no!You just deleted the wrong line, wellP will put the entire block of'k}deleted lines back.This is also how you move and copyblocks of text. Just delete them,and go to where you want to appear'l}.Press P and it is moved.If you just want a copy somewhereelse, make sure you P it inthe same spot where you'm} deletedit, the move and P again.To erase you file, does the trick.Remember, look in the Action! ma'n}nualand read over the commands I did notcover. They are very useful!Now the monitor. You already knowthe C command com'o}piles a Action!program and R runs it.B reboots the Action! system withouthaving to turn your computer off andon. This e'p}rases anything you havein the editor and starts you fromscratch.O takes you to the options menu. Inhere you can change 'q}some featuresof the Action! system and also turnon some debugging flags.The first option is the Displayoption. When you'r} turn this on,it speeds up reading and writingto the disk and printer. It alsospeeds up compiling your program. Itdoes 's}this by turning the screen offwhile doing these operations. Thefirst thing I always do then I loadmy Action! cartridge it't} turn thison.If that stupid bell is driving younuts every time you go to the monitoror come across an error while co'u}mpiling, the Bell flag can turnthis off.The Case Insensitive flag can turnon the.... well I better show you.In Action!,'v} the variables: score Score SCORE sCoReare all the same. Turning this onw'w}ill make them all differentvarialbles. It will also make youspell the Action! routines correctlytoo. PrintE is spelled w'x}ith acap P and a cap E. If this is off,the default, you can spell it anyway.The Trace flag prints the PROCor FUNC you a'y}re currently enteringwhen you run your program. We haven'tcovered PROCs and FUNCs yet but Iwill say this is VERY, VERY us'z}efulwhen debugging.Most of the time when Action! findsan error while it is compiling, itwill take you right to the spot '{}in theeditor where the error occured.Sometimes Action! doesn't know wherethe error is and setting List to y will print ea'|}ch line to the screenwhile that line if being compiled.This in only useful when theDisplay flag is on. Compile a sample '}}program with this on tosee what it does.Window size, Line size and Left marginwe won't go into.EOF character will chang'~}e the lastcharacter of each line from a blankspace to something you can see.The Action! manual say it will "aidvisualizat'}ion of the program."That's it for the Options menu. Backto the monitor commands. D willtake you to DOS. If you areusi'}ng DOS 2.0 or 2.5 the editorwill be erased so be sure to saveit before you use this. If you haveDOS XL or SpartaDOS, the '}editorremains. To get back to Action! fromDOS use the B (to cartridge) commandin DOS 2.0-2.5 and CAR in DOS XL andSparta'}DOS.You can compile a Action! sourceprogram without having to loadit into the editor. Just put a filename after the C f'}or compile.Make sure you use the whole filenameand device and make sure there are"quotes" on both ends of the filename.C'} "D:APROG.402"will compile APROG.402 off disk drive#1. This is useful when your programwon't compile because it is out o'}fmemory.W "D:MYPROG.CMD" will write thecompiled code to disk. That wayyou don't have to recompile it eachtime. Using '}R "D:MYPROG.CMD" willload and run your Action! program ifit was saved using W.If you have the Action! runtimepackage, th'}is is how you write programs that don't need the cart.to run.This is also how you save BBS Express!PRO command mod'}ules.Well that's about it for now. I havebarely scratched the surface with thenumber of commands you have availableto y'}ou. But, These bare minimums willhelp you get around easier. surface with thenumber of commands you have availableto y$A?v