Download Project or Preview Online
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_X
and START_Y
are technically variables in Scratch, but I treat them as constants (so I typed them in ALL_CAPS instead of startX
and 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_H
and 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 i
, j
, and k
variables are indices for various loops.
The 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.
The playIntro
script prints out every line from the list named introText
. It calls both the printText
and 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 phrase
, the 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 SPACING_V
from 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).
When 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 query
, not 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 div1
(or div2
, 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 song1
, song2
, &c., and then play a random song with play sound (join (song
) (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
introText
,divinations
, orasciiArt
. Remember that if you changedivinations
, 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
playIntro
,divineFuture
, anddrawArt
scripts 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.
Credits
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.