What It Does
Legend tells of a technomancy adept so devoutly reverent of the Spirit that he acquired (or was gifted) an uncanny precognitive ability. Upon his death (which he was ironically unable to escape), his fellows arranged to have his head cybernetically preserved, melding his mind with machine. Sophisticated though the machine was, it could not adapt to the subtle varieties and various subtleties of the adept’s soul, and while the hybrid retained his miraculous power to see into the future, his responses became constrained by the computer’s binary logic. There are, however, occasionally hints that the oracle still dreams of things beautiful and wondrous…
Oraskul simulates a computer-terminal connection to the oracle so that he may be queried and consulted about future events. Magically, it is inspired by oracular heads throughout history. Æsthetically, it is inspired by the servo-skulls of Warhammer 40,000. Effectively, it is a glorified Magic 8-Ball, and like the 8-Ball, Oraskul can reply only to yes-no questions.
When you start Oraskul a series of initialization messages prints (that do nothing more than create the illusion that something more is happening), then you are prompted to input your query. When you submit your query, Oraskul “thinks” for a moment and then replies with his answer in text and voice.
Due to its deterministic pseudorandomness, Oraskul‘s value as a genuine oracle is limited. The project is intended primarily to demonstrate creativity. The narrative of the Tech-Adept shrouds the oracle’s functionality in myth and mystery, but it could be any narrative. Oraskul‘s responses are copied from the Magic 8-Ball’s, but they could be any responses (not only yes/maybe/no), and there could be any number of them. Oraskul‘s audio samples lend the oracle a voice, but they could be any audio samples. Indeed, you could make an oracle that responds only in sounds (or to sounds, instead of keyboard input), and not only spoken words but any sounds you may infer divinatory meanings from.
How It Works
Oraskul has only one sprite, but it has nine scripts, 70 costumes, and 21 sounds. The scripts are all event-driven to make them modular; each can be called as needed from other scripts. The image of the robotic skull belongs to the stage as its only backdrop; the stage has no scripts or sounds.
Several of the scripts have to do with printing text to the screen. There are several ways to do that in Scratch. Say you want to display the word, “ABRACADABRA”…
- You could make a costume of the word “ABRACADABRA” and show it. This is how text is displayed in, e.g., the Thebanet project. You can either draw the text in Scratch’s paint editor using the text tool, but there you are limited to Scratch’s built-in fonts; or you draw it outside of Scratch and then import it. The biggest shortcoming of this method is that you need a costume for every unique set of text you want to display. Let us say you want to use Scratch’s username block to print the user’s name on the screen; you would need to make a costume for every possible username! Clearly, that will not do.
- You can print variable text to the screen using Scratch’s say () or think () block, e.g., say (username) or think (
ABRACADABRA). The problem with these methods is they look cartoonish and you have little control over how they appear.
- You can save the text in a variable or list and then show the variable or list on screen, like viewing your score in the ZenerTest project. As with the say () and think () blocks, you have little control over how variables and lists appear on screen; they are always orange boxes with blocky, white text.
- Use one of the Scratch modifications that includes blocks for printing text to the screen, e.g., Scribble.
- Make your own text printing system. You would need a costume for each character you might want to print, and then draw each letter on the screen individually. E.g., to print the word, “ABRACADABRA,” you would need one costume each of ‘A’, ‘B’, ‘C’, ‘D’, and ‘R’, then for each letter in the word, you would switch to the costume matching that letter, stamp it, and then move however many steps are needed to print the next character. This requires a considerable amount of work at the beginning because you need to make a costume for each letter, number, and punctuation mark you might print, and if you want to use uppercase and lowercase letters then you need to make two costumes for every letter. This method works better with monospaced fonts because the characters widths are always the same, so the number of pixels to move between one character and the next remains constant.
Although Oraskul only has 20 unique responses and so I could have just made a costume for each response, I chose the last method so I could emulate an old computer terminal printing text one character at a time. I made a complete alphabet of ASCII characters in a monospaced font—70 costumes in toto including a cursor block.
When you click the green flag to start Oraskul, the first script initializes several variables related to printing text; then broadcasts the message
clearText and waits for the script for that event to finish; then broadcasts
playintro and waits for that event’s script to finish; and then goes into a forever loop of broadcasting the message
askForQuery and waiting for its script to finish before broadcasting the same message again.
Before I explain more about the scripts, let me explain some of the variables.
START_Y are technically variables in Scratch, but I treat them as constants (so I typed them in ALL_CAPS instead of
startY), which just means that once they are set, they do not change while the project is running. They hold the starting x and y coordinates of the cursor for any printing to the screen. By making these variables, if I want to change where on the screen printing begins, I do not need to search through all of the scripts for every place where the sprite moves to that position; I can simply change it in one place in the when green flag clicked script. Ditto for
SPACING_V, which hold the the number of pixels between horizontal and vertical lines of text, respectively.
newLineY (which actually behaves as a true variable) specifies the new y coordinate every time a new line of text is added.
printing is a Boolean variable that is set to 1 when text is being printed to the screen, and 0 when that is not happening; it allows me to prevent certain things from occurring while text is being printed.
phrase holds the string of text to be printed on the current line.
divinationNum is randomly generated every time a new query is asked; it corresponds to the various possible divination messages kept in the list named
divinations, as well as to the names of the corresponding sound files (e.g., when
divinationNum = 5, Oraskul displays the fifth item from the
divinations list, and plays the corresponding sound file that is named
div5—both the text and the sound file say, “You may rely on it”). The
k variables are indices for various loops.
clearText script calls the clear block to erase any text that has been drawn to the screen before switching the sprite’s costume to
cursor and moving the sprite to the starting x and y positions for printing text.
playIntro script prints out every line from the list named
introText. It calls both the
newLine scripts. The
printText script prints whatever text string is recorded in the variable
phrase, which it does by looping through each character in the string, changing from the costume
cursor to the costume named for the current character (e.g., the costume for the character ‘A’ is named
A, and the costume for character ‘.’ — period — is named
.), stamping the costume on the screen, then changing back to costume
cursor and moving to the right by the number of steps recorded in
SPACING_H. After printing all the characters in
printText script calls the
blinkCursor script, which switches between the
cursor costume and the costume for the space character (‘ ‘), thus creating the appearance of a blinking cursor at the end of the line. The
newLine script subtracts the value in
newLineY (we use subtraction here because the sprite is moving down the screen as new lines are added, so the y coordinate value decreases, or increases in a negative direction) and stores the difference in the
newLineY variable, then moves the sprite to the position at
START_X (the starting x position of every line) and
newlineY (the new y position).
playIntro finishes, Oraskul resumes the when green flag clicked script, with the forever block around broadcast (
askForQuery) and wait. The
askForQuery script prints the text, ‘WHAT IS YOUR QUERY?’, and plays the corresponding sound file (named
query), then prompts you to type in your question. If your response (which is stored in a special Scratch variable named answer) equals anything other than the word ‘butterfly’ (which I will explain in a moment), Oraskul calls the
divineFuture script, which is the main feature of this project. Oraskul randomly selects a reply to your question by generating a random number between 1 and the length of the
divinations list (so, if the list contains 20 possible messages, the random number is between 1 and 20), then printing the message text and playing the corresponding sound file. The reason for using the join () () block within the play sound () block is to demonstrate a way of indexing sounds or costume files that is different from how we indexed files in earlier projects. Recall that in ZenerTest, costume 1 was also named
1, costume 2 was named
2, &c. In Oraskul, the first sound file is named
1, so play sound (
1) would actually play the file
query instead of the file corresponding to the first divination message, which is the second sound file, i.e., sound 2. By naming sound 2
div1, and then joining the string ‘div’ with the randomly generated divination number, the play sound () block plays the file named
div3, &c.) instead of playing the file numbered 1 (or 2, 3, &c.). This would be especially useful if, say, in addition to giving random divinations, Oraskul could sing random songs: you could name the sound files for the songs
song2, &c., and then play a random song with play sound (join (
someRandomNumber)). You would not need to care about the order of the sound files on the Sounds tab in Scratch.
If you input ‘butterfly’ when prompted for your query, you will see a glimpse of Oraskul‘s dream. Oraskul calls the
drawArt script instead of
divineFuture, which prints the contents of the
asciiArt list. (I am explaining this to you so you understand how the project works, but this sort of thing would do well as a surprise or Easter egg.)
Make It Better
- It is very easy to change the things that Oraskul says, by editing the lists
asciiArt. Remember that if you change
divinations, the corresponding audio file(s) will no longer correspond, so you would need to change those too, or…
- Use the Scratch Text-to-Speech experimental extension to speak Oraskul’s replies.
- Try programming more complex dialogue interactions using techniques featured in text adventure games or ELIZA.
- Notice how similar the
drawArtscripts are. Can you make one script that does everything that is redundant across those three?
- The project must be stopped manually by clicking the red stop sign. Add something that allows you to communicate your intention to leave, e.g., a script that responds to you typing ‘goodbye’ at the ‘What is your query?’ prompt. Include an appropriate response from Oraskul before calling the stop (all) block. Additionally or alternatively, program Oraskul to randomly “hang up” on you.
- Add a way to mute or change the audio volume from within the project while it is running.
The backdrop image is “Skull of a human size robot” by svedoliver.
The ASCII butterfly was designed by Jonathon R. Oglesbee a.k.a. JRO.