Byte Works / Ordering / Apple IIGS / Apple ][ / APDA / HyperStudio / Books / System Software
You may read or print this page for your own use in any way you like, but it cannot be reproduced for anything except your personal use without the written permission of the publisher. Please feel free to point other people to this resource so they can get their own copy!
The stacks and scripts that accompany this project are public domain, although the images used in the stacks are not. You may use the scripts any way you like, including using them in your own HyperStudio projects. The images are from the HyperStudio CD, and are used here with permission; refer to the publisher of HyperStudio for permission to use those images in your own stacks.
Download the Stacks
Random Cards
Random Cards shows how to create stacks that visit all of the cards in a stack, but visit them in a random order. The project shows how to visit the cards exactly one time, too.
You can use this technique in combination with other ideas to create a variety of dynamic stacks. You might want to create a series of flash cards to help remember key information, but of course, flash cards are more effective if they show up in random order. You may be creating a test, and want the questions to show up in random order to minimize cheating. You may be creating a travel game and want to drop the player into a random country. The list goes on an on.
This particular project starts on a title card that describes the stack. When you click on the right arrow at the bottom right of the card, you are taken to a random card that displays an outline of one of the seven continents. Each of these cards also has a right arrow at the bottom right of the card, and clicking on that arrow takes you to a new, random continent. Once you visit all seven continents, clicking on the right arrow takes you back to the title card.
Random Cards is a relatively simple stack, so we'll use it to explore scripting concepts and ideas that you'll need to effectively write longer scripts. Specifically, you will see:
You will also see one effective way to organize your stack.
Before diving into the project itself, let's meet the key players&emdash;the commands you will use to create the script.
Since this is an intermediate scripting class, I hope some of these are already familiar to you. If so, skim the material quickly. You won't need the descriptions of the commands you already know, but the command descriptions also serve as an overview of the project itself.
Reading about a command is like reading about a kiss. You can learn something from reading, but no amount of reading is a substitute for actual experience! To really get to know a command, you need to experiment a bit.
There are two ways to experiment with commands. The HyperLogo Run Box works best for commands like MOVETOCARD that manipulate cards or card objects. Give this a try by pulling down the Extras menu and selecting HyperLogo RunBox. You get a small window where you can type HyperLogo commands. As soon as you press return, the command is executed. Give that a try with this command:
movetocard "asia
You can use the Run Box for most commands that don't manipulate HyperStudio cards or objects, too, but there's another way to experiment with commands that tends to work better. It's the Text Window, a complete text interactive HyperLogo environment built right into HyperStudio. It's a little harder to get to, but in many cases the effort is worth it. To open a HyperLogo text window, follow these steps:
1. Enter the HyperLogo scripting environment by creating a new button and adding a script, or by editing a script in an existing button.2. Pull down the file menu and select New Text Window.
From here you can type commands, just like in the Run Box, but the commands don't vanish when you type a new command, and you can see the results of your text commands right in the window. For example, try these commands:
make "four 2 + 2 print :four
As you can see, the PRINT command shows the contents of the variable. A handy shortcut is to place the cursor at the end of an old command you want to execute again, or to select several commands you want to execute again, and then press the return key. The results of the command are printed at the end of the text window.
Use one of these methods to try out any of the commands you see below that are not familiar to you!
The goal for our project is to move to a random card. Obviously, we need to know how to move to some card, random or not, before we can move to a random card! The MOVETOCARD command moves to any card in your stack. The command takes a single parameter which is the name of the card.
Try this command from the HyperLogo Run Box:
MoveToCard "Europe
This moves to the card with the picture of Europe. Of course, the script doesn't really know the card has a picture of Europe; you could put a photo of Addy on the card and the command would still take you to the card. Europe happens to be the name of the card. To see that, pull down the Objects menu and select About this Card You must give a card a name before you can use MOVETOCARD to move to that card.
Some of the card names contain a space. One example is North America. HyperLogo uses a space to separate the words in a command, though, so you need a way to tell HyperLogo that North America, which it thinks is two words, is really a single sequence of characters that is the name of a card. You do that by placing a backslash character right before the space, like this:
MoveToCard "North\ America
The original card also has a name. Use the command
MoveToCard "Title
to move back to the start of the stack.
Variables are used to store information in a script. In our case, we'll be storing the names of all of the cards in a list. Open a HyperLogo text window to see how this works. Once you have the window open, type this command. Pay particular attention to the backslash and space characters; there should be exactly one space after the backslash character. Also, while the command spans more than one line in this handout, you should not press return; instead, type the entire command as a single line. It's OK if the HyperLogo editor has to display the command on multiple lines, but you must not type a return key to force the text onto more than one line.
Make "cardNames [Antarctica Africa Asia Australia Europe North\ America South\ America]
This command creates a new variable called cardNames. Variables are used to store any kind of information HyperLogo can manipulate, including numbers, sequences of characters, or in this case, lists. The stuff between the bracket characters is a list. A list is just a set of information, in this case the character sequences for the names of seven cards in our stack. You can use anything as an element of a list, though, including numbers or other lists.
The variable cardNames is a global variable. We can use it anywhere in the current stack. Let's use it now with the PRINT command, which will dump the list to the text window so we can look at it.
Print :cardNames
There is an important and subtle difference between this use of cardNames and the last one. When you are giving the name of a variable, use a quote mark before the name. MAKE is creating a variable, so it needs the name of the variable; we used a quote mark for that command. When you want the stuff inside a variable, which we call the variable's value, use a colon before the name of the variable. We wanted to print the contents of the variable, not the name of the variable, so we used a colon before the variable name for the PRINT command.
What happens if you goof? Try
Print "cardNames
The command works, but you get the name of the variable, not the contents.
Note This section uses a variable created in the last section. If you skipped the section entitled "MAKE and Variables," use this command to get ready for this section:Make "cardNames [Antarctica Africa Asia Australia Europe North\ America South\ America]
We need a way to pick the name of one card out of the stack, as well as a way to make sure that name is never picked again. FIRST takes a list as a parameter and returns the first element of the list. To see how this works, try this command from a HyperLogo text window:
Print First :cardNames
The first item in our cardNames list is Antarctica, so that's the name that is printed. Once we've finished with this card, though, we don't want to visit the same card a second time. The easy way to prevent a second visit is to yank the card name out of the list. We do that with BUTFIRST, which returns everything BUT the FIRST item in a list. You can see this with the line
Print ButFirst :cardNames
Of course, that just printed what was left of the list; the list inside cardNames is not changed. We need to use the MAKE command to change the original value. Try this sequence of commands to see how the value of cardNames changes.
Print :cardNames Make "cardNames ButFirst :cardNames Print :cardNames
FIRST, BUTFIRST and MAKE give us the tools we need to pick a card name from a list of card names, then remove the card name so it isn't returned twice.
Note This section uses a variable created in a previous section. If you skipped the section entitled "MAKE and Variables," use this command to get ready for this section:Make "cardNames [Antarctica Africa Asia Australia Europe North\ America South\ America]If you followed along in the last section, execute this command again to restore the list to it's original state.
If you've been following along, you can see by now how the Random Cards stack will work. We'll enter all of the names of the cards in a list, storing the list in a global variable called cardNames. To visit a card, we'll peel off the first card name using FIRST and move to the card using MOVETOCARD. We'll use MAKE and BUTFIRST to remove the name of the card from the list of cards so we don't visit the same card twice. The only major task left is to scramble the list so the card names appear in a random order. That's what the RANDOMIZE command does. It takes a list as input, and returns the same list in random order as an output.
Try this command from a HyperLogo text window. Place the cursor back at the end of the line and press return to execute it a second time. Do this several times and examine the list that is printed each time.
Print Randomize :cardNames
As you can see, Randomize does exactly what we need. You can use MAKE to stuff the randomized list back into the variable cardNames, and that's exactly what we'll do in the stack.
Note This section uses a variable created in a previous section. If you skipped the section entitled "MAKE and Variables," use this command to get ready for this section:Make "cardNames [Antarctica Africa Asia Australia Europe North\ America South\ America]If you have followed along in previous sections and changed the contents of cardNames, execute this statement again to initialize the .
There is one last issue we'll need to deal with in the project. What happens when there are no more cards to visit? You could do several things, from moving to a new stack to grading a test to quitting HyperStudio entirely. We'll just move back to the first card, which is named Title. You know how to do that already; what we have not learned to do is decide whether there are more cards left and act on that decision.
We use IF to make decisions in HyperLogo. It works pretty much like English: If some condition is met, we do something. In this case we want to check to see if there is anything left in a list of cards. EMPTYP does this for us, returning TRUE if the list is empty and FALSE if the list is not empty. If the list is empty, we use MOVETOCARD to move back to the first card. The actual statement uses square brackets around the commands to execute when the condition is TRUE. It looks like this:
If EmptyP :cardNames [MoveToCard "Title]
Open the HyperLogo Run Box. Start with this command to create an empty list:
Make "empty []
Next, move to some card other than the title card. Here's a command that will do it.
MoveToCard First Randomize :cardNames
This command uses pieces that you have seen before, but puts them together in a new way. If you aren't sure what the line does, stop and spend some time with it until you figure it out.
You're ready to try the IF command now. Start by typing the model line you looked at a moment ago, namely
If EmptyP :cardNames [MoveToCard "Title]
This command should not do anything, since cardNames still contains all seven continents. Now try replacing cardNames with empty, the name of the variable we created a moment ago that doesn't have anything in the list. The changed command is
If EmptyP :empty [MoveToCard "Title]
This time EMPTYP returns TRUE, so IF executes the statement inside the brackets, and you jump to the card named Title.
There are two copies of the Random Cards stack. Open Random Cards (or Random.stk on Windows). This stack has all of the visual elements you need so you don't have to spend time creating the cards, adding pictures of continents, and so forth. We'll add buttons and scripts to this stack to finish the project.
The stack itself has 8 cards. Flip through the cards; as you can see, the cards consist of the initial title card and seven cards with a picture of a continent. When it is complete, your stack will visit each continent in a random order, then return to the first card.
One key point is that every card has a name. HyperLogo can't work on cards or objects unless they have a name. You can see the name of the card by pulling down Objects and selecting About this Card Use the same dialog to add a name to a card if you are creating a stack from scratch.
So far, there are no buttons on the cards with pictures of continents. It's actually easier to add them yourself than to add a script to buttons that are already there. The first card has two buttons. We'll ignore the home button, which takes you back to the Home stack. There's no scripting involved. The yellow arrow is where the action will take place. This button has a HyperLogo script attached, but the script consists of a single space. This makes it easy to edit the script by holding the command key down (Alt on Windows) and clicking on the button.
Organizing your scripts is more important that you might think. One of the biggest problems you will face in a large, complex scripting project is figuring out where all of the pieces are, and who does what work. One of the simplest, most effective ways to organize the scripts in your stack is to create a set of procedures that do all of the work. In the rest of the stack, you'll use simple one line scripts, or perhaps just a couple of lines. These scripts call procedures that do all of the work.
There are several advantages to organizing the scripts this way. One advantage is that, you know where the procedures are. When it comes time to make a change, you jump to the spot where you saved all of the procedures and make the changes there. Another advantage is the simplicity of the scripts in the rest of the stack. As you'll see from this project, you can create easy copy-and-paste buttons that you can quickly drop in throughout the stack or on new cards. And if a change does become necessary, you don't have to change the scripts on every card. By changing the procedure these buttons call, in effect, you update all of the buttons in the stack with a single step.
There are two tasks we need to accomplish to make our stack work. The first is to create a list of all of the cards we need to visit. The list needs to be in random order. You already know how to use the individual commands to create such a list; here's a nicely packaged procedure that does all of the work.
To RandomizeCards ; Create a list of the card names in random order. Make "cardNames [Antarctica Africa Asia Australia Europe North\ America South\ America] Make "cardNames Randomize :cardNames END
Looking back at the commands covered earlier, the only new ideas are the TO-END lines that create the procedure itself and the line starting with the ; character.
TO and END mark the start and end of a procedure. TO is followed by the name you're giving the procedure. After this series of lines executes, there is a new command in HyperLogo called RANDOMIZECARDS. This command creates a variable named cardNames and fills it with a randomized list of cards. The line starting with ; is a comment. HyperLogo doesn't care if the comment is there or not. Good scripters add comments like this one to remind themselves and other people who read the script what the script is doing.
The second task our stack needs to accomplish is to move to the next random card. Of course, if there are no cards left to visit, we need to detect that fact and jump back to the card named Title. Here's a procedure that handles this for us.
To MoveToRandomCard ; Move to the next card in the randomized list, removing the card name from ; the list so we won't visit the same card twice. If all cards have been ; visited, move back to the title card. if EmptyP :cardNames [MoveToCard "Title Stop] MoveToCard First :cardNames Make "cardNames ButFirst :cardNames END
There is one new command in this procedure. STOP leaves a procedure early. It's used at the end of the IF statement. Once the IF statement detects an empty list, it executes all of the commands between the brackets. The first command is one you've seen before; it jumps back to the card named Title. After jumping back to that card, STOP leaves the procedure so it doesn't try to execute the commands that are left.
Open the empty script attached to the yellow arrow. Enter these two procedures in the script window, then add these lines:
; Randomize the card names. RandomizeCards ; Move to the first random card. MoveToRandomCard
The call to RANDOMIZECARDS sets up our initial random list of cards; calling MOVETORANDOMCARD moves to the first of these randomly selected cards.
Give the button a try. If you have typed everything correctly, clicking on the yellow arrow will take you to a random card in the stack. You can move back to the title card with Command-1 and try it again. Each time you should jump to a random card.
The next step is to add navigation buttons to each of the cards that show a continent. This button will take you to the next continent card, or back to the title card if you've already visited each continent. Of course, that's exactly what the MOVETORANDOMCARD procedure does, so all we have to do in these navigation buttons is call the MOVETORANDOMCARD procedure.
Follow these steps to create the first navigation button.
1. Move back to the first card in the stack.2. Select the arrow tool from the tool palette.
3. Select the yellow arrow button.
4. Copy the button.
5. Move to the next card, which shows a picture of Africa.
6. Paste the button.
7. Switch back to the browser tool (the finger tool).
8. Hold down the Command key and click on the yellow arrow button to edit the HyperLogo script.
9. Delete all of the lines except MoveToRandomCard. Add a comment so your script looks like this:
; Move to the next random card. MoveToRandomCard10. Close the script window.
You now have a button that will jump to the next random card. Be sure and test it to make sure it works. Here's one way to test the new button:
1. Move to the first card in the stack and click on the yellow arrow. This creates a list of random cards and takes you to the first card.2. You have a one in seven chance of landing on Africa, which means you're probably looking at the wrong card. Use Command-1 to jump back to the first card, then use Command-> to move to the Africa card.
3. Click on the yellow button. This should carry you to a randomly selected card. Of course, there is a one in six chance that the random card is Africa, so if it looks like nothing happened, don't panic. Click the button a second time. If you're still looking at the Africa card it's time to panic&emdash;or at least, it's time to start looking for a mistake.
The last change is to move the navigation button created in Step 3 to the other six continent cards.
1. Move to the Africa Card.2. Select the yellow arrow button and copy it.
3. Move to each of the other continent buttons in turn and paste the navigation button on the card.
Your stack should be complete now, but the only way to make sure is to try it. That's really what testing is all about.
Move to the first card and start clicking on the yellow navigation button. You should cycle through all seven continents, then move back to the title card. Try this several times. Make sure the order you visit the cards changes, and that each cycle visits seven cards.
While we did something very specific with this project, you can use the same ideas to create lots of different effects. This section explores a couple of simple changes that turns the stack into an automated slide show that changes the order of the pictures each time it runs.
The basic idea is to trigger the navigation button automatically using a timer rather than waiting on the user to click on the yellow button. Since the button is automatic there is no reason for it to be visible, so we'll also hide the button.
1. Delete all of the navigation buttons on the last six cards, leaving the buttons on the Africa card and title card untouched.2. Move to the Africa card.
3. Choose the arrow tool. Double click on the yellow arrow button to edit it.
4. Click on Show Icon, turning it off so the button is invisible.
5. Click on Actions, then on Automatic Timer to get to the Automatic Timer dialog.
6. Select "Do these actions after card is shown" and enter a time of one second.
7. Click OK and Done to complete the changes.
8. Copy this button and paste it onto the remaining continent cards.
Your stack is now a slide show! Click on the navigation button from the title card and the stack takes you on a world tour. Try it again and you visit the world in a different order.
This project showed how to create a stack that will visit any number of cards in a random order, visiting each card one time.
You learned one way to organize scripts in a stack, namely by encapsulating all of the ideas into procedures, which are collected on the first card of the stack to make changes easier. Any buttons in the rest of the stack simply call one of the procedures created on the first card.
This project used several common HyperLogo commands to accomplish these tasks. The commands used were:
Takes a list as input and returns a list with everything but the first element. We used BUTFIRST to remove the name of a card once the card had been visited so no card was visited twice.
Checks to see if a list has any elements. We used this command to see if we had visited all of the continent cards.
Takes a list as input and returns the first item from the list. We used FIRST to pick out the first card name from the cardNames list, passing the result to MOVETOCARD to move to the card.
Checks a condition, executing a list of statements if the condition is true. We used IF to check the cardNames variable, looking to see if it was empty. If so, we moved back to the first card in the stack.
Creates a variable if it doesn't exist, the places a new value in the variable. We used MAKE to create the cardNames variable, fill it with the names of the cards, and later to store the modified lists returned by BUTFIRST.
Moves to a card. We used MOVETOCARD to move to a specific card in the stack.
Takes a list as input and returns the same list with the elements randomized. We used RANDOMIZE to scramble the order of the cards in the cardNames variable.
Stops a procedure. We used STOP to leave the MOVETORANDOMCARD procedure early.
Declares a procedure. We used these commands to create two procedures that did all of the work in our stack.