The following paper is a curriculum for learning basic computer science concepts using World of Warcraft and the scripting language Lua. I wrote the paper with two other MIT students while taking Eric Klopfer's course "Computer Games and Simulations for Education and Exploration" (11.127/CMS.590) in March, 2011. It was originally published on my MIT site. I am archiving it here for anyone who is interested in learning how video games can be used for education. See "A curriculum for learning computer programming in WoW" for background on this project.
Curriculum: Teaching Computer Science through WoW Scripts
Andrew Hsiao, Ian Lamont, Michele Pratusevich
CMS.590: Professor Klopfer
1 March 2011
For decades, games have introduced young people to computer programming. Early exposure to programming games has been a stepping stone to careers in computer science and technology-related entrepreneurship. There are many well-known examples. Long before he built Facebook, Mark Zuckerberg reveled in creating computer games with his friends, and Salesforce.com cofounder Marc Benioff got his start in the computer industry as a teenage designer of games for Atari home computers.
But even among young people who don't become programmers or found startups, there is a widespread awareness of the role in programming in creating games. There comes a point in the life of a typical primary school student that he or she will wonder how handheld, console, or web-based games are made, and the answer will come back that someone - or a group of people - entered a series of instructions into a computer to make it display images, play sounds, and perform functions that make up the gameplay. Some of the more dedicated gamers or curious tinkerers may be compelled to take things a step further by designing their own games, or modifying existing games ("modding") to extend the gameplay in some fashion. In doing so, these youths learn many elementary programming concepts, including computer languages, software tools, and fundamental computer science building blocks such as variables and functions.
Many others, however, will never take that next step. They will be aware of the role of programming in creating games and other software, but will never learn specific concepts or the practical aspects of computer programming.
Teaching Computer Science through WoW Scripts is designed to help non-programmers bridge the gap. The following series of four exercises is designed to be the beginning of a course in teaching high-school students basic computer science concepts, as well as critical thinking skills, using the online role-playing game World of Warcraft and the scripting language Lua. The curriculum is aimed at teenagers who have never been exposed to computer programming or played the game, although those with some experience may be able to develop more advanced scripts to use in the game. Students will learn how computer languages work, including core concepts such as if statements, loops, and variables.
With these foundations, students can then learn more complicated programming concepts such as functions to develop their own complex customizations of WoW. In a more comprehensive computer science curriculum, the concept of saving scripts that can be run much more easily using macros would be explained. For an advanced curriculum, the creation of add-ons would provide a practical purpose to programming and scripting. However, because add-on creation is involved and complicated, it is not one of the exercises described here.
World of Warcraft (WoW) is a sword-and-sorcery fantasy world that lets anyone with a PC or laptop and an Internet connection battle monsters, find virtual treasure, and play with other people who are online at the same time. The world is not unlike J.R.R. Tolkien's Lord of the Rings, or the fantasy game Dungeons & Dragons. It was launched by Blizzard in 2004, and is one of the top online role-playing games, with millions of users in the United States, China, and elsewhere.
Lua is a powerful, lightweight programming language that is known as a "scripting language." Scripting languages enable control of an application (in this case, World of Warcraft) but Lua has also been used for other games, industrial applications, and consumer hardware platforms.
"Scripts" are small computer programs that perform a very specific function. Typically, they are a very precise set of instructions that the software environment (i.e., WoW or some other program) can understand. Sometimes they are as short as a few sentences of text. In a game like WoW, a script might display extra information about a monster that is attacking a player, or help a player find a new route to a certain destination. Many first curricula in computer science use scripting languages to teach fundamental computer science concepts because they have more gradual learning curves than other kinds of programming languages. Scripts do not require installing compilers and interpreters that come with more complex programming languages. After learning basic programming concepts in a scripting language, more complicated programs can be written using multiple scripts.
Specific computer science topics, exercises, and outcomes in the WoW programming curriculum are listed below.
Instructors may wonder why a gaming environment is being used to learn programming concepts, as opposed to textbooks and traditional classroom lectures. Besides the obvious interest that games hold for young people (according to a recent survey, 80% of American teens aged 12-17 own a game console ), the practice of experimenting in a game world reinforces what James Paul Gee refers to as the Probe, Hypothesis, Reprobe, Rethink Cycle. As noted by Gee in What Video Games Have To Teach Us About Learning And Literacy, this cycle is required to learn complex and fast-moving video games in immersive 3D environments, like the one found in WoW. The four-stage cycle works as follows:
- The player must probe the virtual world, which involves looking around the current environment, clocking on something, or engaging in a certain action.
- Based on reflection during and after probing, the player must form a hypothesis about what something (a text, object, artifact, event, or action) might mean in a usefully situated way.
- The player reprobes the world with that hypothesis in mind, seeing what effect he or she gets.
- The player treats this effect as feedback from the world and accepts or rethinks his or her own original hypothesis.
But the process is not limited to learning how to survive an attack by a monster or find a certain treasure in a video game. The Probe, Hypothesis, Reprobe, Rethink Cycle can be applied to a variety of extracurricular learning situations. It is part of humans' innate ability to recognize patterns, self-reflect on outcomes based on success/failure feedback cycles, and derive powerful learning experiences. "It's how children learn," Gee writes, "when they are not learning in school."
For the WoW programming curriculum, the Probe, Hypothesis, Reprobe, Rethink Cycle will take place on two levels. Learning to program requires cycles of experimentation and testing on the code, in order to make sure it works and improve the functionality. There is also the effect of the scripts on the gameplay itself, which students can also probe and test in a shared environment with their classmates. Some students may want to share their "mods" with each other, or cooperatively work on more complex tasks (for instance, dividing up coding and testing responsibilities). Such behavior adds to the learning experience and encourages critical thinking and teamwork in a shared environment of peers.
Tools you will need
Students will need to have World of Warcraft installed on the laptop or PC they are using for class. They should register their game, create a player, and experiment with the world before starting the exercises. We recommend that each player spend at least three hours in WoW and reach at least level 3 before starting the first exercise. Before attempting an exercise, students' characters should be in a town or other place where they will not be attacked or disturbed.
The basic tool needed to create scripts in Lua is the WoW game itself. Very simple yet powerful scripts can be created right in the chat box of WoW. The first exercise describes in some detail how this is done. For creating more complex scripts, a basic text editor like Notepad (that comes standard with every PC) or TextEdit (included with every Mac) can be used to edit the scripts before pasting them into the WoW chat box. Students will not need to use external text editors (outside of the WoW chat box) to create scripts until they are at a level where they are using macros to hold their scripts.
Before starting on the exercises, students should be aware that there are a plethora of resources available online about writing Lua scripts, macros, and add-ons. World of Warcraft has built-in functions that are available through an "application programming interface" (shorted to API) that can be used in any script. An API is just a collection of functions and properties of the language that can be used by the programmer. Information about the WoW API can be found here.
Summary of class exercises
1. Beginning programming concepts and Hello World
Creating a simple program that displays the text "Hello World" is a long tradition in teaching new computing languages to students. In this exercise, students will use the Lua scripting language to display "Hello World" in the WoW chatbox.
In the first activity the student will learn how to accomplish one of the simplest tasks in programming: outputting a message. With this program, the student will be able to "print" statements. Explain to the student the meaning of "print" in programming jargon: being able to "print" refers to being able to output text to some sort of interface the programmer can see. When programming in Lua in World of Warcraft, that interface is the chat box. An important thing to note when printing to the chat box is that whatever is printed will not be broadcast to the world. Rather, it is only printed in the chat box of the user who is running the script. The student should be shown this script to print a message to the chat box:
/script print("Hello World!");
Take a look at the components of this program. First the statement "/script" is typed into the chat box to denote the start of a Lua script. All scripts you type into the chat box will start with this statement.
Next there is the statement "print". This function is provided by the World of Warcraft API to give the programmer the opportunity to print statements to the chat box. Built-in functions can be used in any program to accomplish tasks the programmer does not want to hard-code himself. Many of the built-in functions in any environment or programming language accomplish tasks that would be very difficult to code by the programmer.
When a function such as "print" is used by the programmer, it is referred to as a function call. The function calls using the built-in functions in WoW are straightforward - the function call "print("Hello World!")" takes the chat frame at the bottom left of the screen and adds the message "Hello World!" to it.
The ""Hello World!"" between parentheses immediately after the function is what is called the argument of the function. Arguments are parameters that are used by the function to accomplish a specific task and usually vary between function calls. In this particular case, the text can be changed to anything that the programmer wants to be output to the chat box.
The semicolon at the end of the statement denotes the end of a logical statement in the script. A semicolon is required at the end of every logical statement. This is a confusing concept to first-time programmers, but hopefully the examples provided in the exercises will give more insight about this. It is up to the discretion of the teacher how much they want to enforce and encourage the use of semicolons.
Note that the text must be put between quotation marks to be recognized as a valid text input. Each function requires its own special formatting for the arguments, but for outputting text to a chat box, the text must be enclosed in quotation marks. Notice how the text is printed on one line in the chat box. To print something that spans multiple lines, use the sequence of characters "\n" (it means "new line", back from the days of the first programming languages). When this sequence is inserted into a block of text, the text that comes after it will be on a new line. So the code:
/script print("Hello \n World!");
will print "Hello" and "World!" on different lines. Finally, the statement is closed with a semicolon. In Lua, a semicolon denotes the end of a line of code. When typing scripts into the chat box, the semicolon is necessary for the chat box to understand that it is finished running the script and can begin taking normal chat box input again.
Text is not the only thing that can be printed to the chat box. Text in the context of programming is referred to as a string. The reason that the text must be put between quotation marks in the print statement is that the script only recognizes strings when they are put between quotation marks.
Strings are only one type of input that the script recognizes. If a script sees a number, it treats it differently than a string. A whole number in the context of programming is referred to as an int (short for integer). Ints can be used in arguments of function calls, but they do not need to be surrounded by quotation marks. This idea of strings and ints brings up a more advanced concept in computer science that would be revisited in a more advanced exercise: the idea of types of input that the script sees. The students learning computer science through WoW Scripts do not need to understand the idea of types, but they should know that the script treats numbers and text differently.
Using print statements are useful in programming for a variety of reasons. When needing to test outputs of programs that are more complicated or wanting the user to see a certain message, print statements are a simple way of achieving this goal.
As an additional exercise, a student should modify the above code to print his or her name into the chat box. Modify the code to print numbers as well - keep in mind that numbers do not need to be surrounded by quotation marks.
2. Conditional statements
This section is intended to introduce students to basic control flow using if statements. Explain to students what control statements do: if statements take a conditional statement, and then execute a specific section of code depending on if the conditional statement is true or false. Present the following script to the students:
if (IsPartyLeader()) then
print("I am the leader of my party!");
print("I am not the leader of my party.");
In one line for in-game use the script would look like:
/script if (IsPartyLeader()) then print("I am the leader of my party!"); else print("I am not the leader of my party."); end;
"IsPartyLeader()" is a function like "print", except this function does not take any arguments because it does not need information from the user to perform its task. All the information it needs is automatically gathered from the game. In this case, it will be true if the player calling the function is the leader of a party, and false otherwise. The reason for the "()" at the end of the function call is that all function calls must contain these parentheses. However, not all function calls require arguments between the parentheses.
Have the students log on to WoW and pair up. Have one student in each pair create a party and invite the student they are paired with. Then have both students run the script and verify that the one that is the leader has the message "I am the leader of my party!" in their chat window and the other student has the message "I am not the leader of my party." Then have the second student invite the first student to a party and have them both run the script again, and verify that both students have the other message printed out to their chat window. After the students have had a chance to try it out themselves, walk them through the execution of this script, pointing out how the control flow differs for each case, and how the game decides which message to print.
Now have the students modify the script so that if they are outdoors, the script prints out "I am outdoors!" otherwise the script prints out "I am indoors." The relevant function you should have them use is the IsOutdoors() function. The end result should look similar to the following code:
if (IsOutdoors()) then
print("I am outdoors.");
print("I am indoors.");
To run the script in-game the following should be typed into the chat window:
/script if (IsOutdoors()) then print("I am outdoors."); else print("I am indoors."); end;
To have students test out their scripts, have them use their hearthstones to get to a town or city, and then stand outside the doorway to a building. Run the script while outside, then walk into the building and run the script again. The two messages should print out into their chat windows.
At the end of this module students should understand how if statements work.
This section details how to introduce students to variables, both in terms of what kinds of variables there are (types) and how to use them in scripts. The concepts of ints and strings were introduced in the first exercise but are given a more thorough (but not complete) examination here. Explain the concept of variables to students: variables are placeholders for other values, and are usually used to allow for easier manipulation of whatever data you are working with. Show the following code snippet to the students:
When showing how to translate the expanded code into the one liner for in-game usage, make sure to point out that since we are putting all of the code into one line, we have to include a semicolon between the statements as a delimiter for where one statement ends and the next begins. The in-game code would be the following:
/script local a=3; local b=4; print(a*b);
Have the students run the script on their own machines. Next explain the difference between local variables and global variables. Local variables only exist for the one single run of the script, while global variables persist even after the script has finished running. Local variables must be specifically declared as such; if there is no "local" keyword before the variable is defined, the game will assume you want the variable to be a global variable. To demonstrate, have the students enter the following:
/script print(a); print(b);
They should get "nil" as a result both times. "nil" means that there is nothing there, that the game thinks the variable is undefined. Now have them run the first script with the local keywords taken out:
/script a=3; b=4; print(a*b);
And then run:
/script print(a); print(b);
This time they should get "3" and "4" printed to their chat boxes instead of "nil".
Finally we want to teach the students that there are different types of variables. This is explaining with an example the difference between an int and string that was introduced in the first exercise. Show them the following script and ask them what they think will happen:
local d="Hello, World!";
After having them guess, have them run it in-game:
/script local c=2; local d="Hello, World!"; print(c*d);
They should have nothing print out at all. This is because "c" is representing a number while "d" is representing a string, and the game has no idea how to multiply a number to a word; it only knows how to multiply if it has two numbers. When something goes wrong in a "/script" command, the game will simply stop running the script, which is why nothing is being printed out.
At the end of this exercise students should understand that variables are placeholders for other concrete values, and that there are both local and global variables as well as different kinds of variables. As an exercise, have the students do some basic calculations with print statements based on the experience points and money awarded by a quest. An example of such an exercise would be printing the name of a quest and then the ratio of the number experience points to the number of money awarded by the quest.
Loop statements repeat a specific computing task. By the end of this activity, students will be able to create a loop that goes through their players' extensive inventories of weapons, armor, treasure, and other objects, and displays them in the chat box.
The outcome for this second activity is to teach students the basic programming control flow of for loops. A for loop is a control flow used in computer science to complete a repeated action. Automating this process instead of typing out the same line of code or executing the same action multiple times saves time and effort. A simple version of a for loop can be used to for example print 10 messages to the chat box:
/script for i = 1, 10 do print("Again!") end;
What is happening in this script is simple: the for loop syntax counts from 1 to 10 inside the loop, executing whatever statements are between the "do" and "end" tags. There can be more than one statement between the "do" and "end" tags, since any action can be executed inside of a loop.
The use of "i" in the for loop is called a counter. It is a variable (taught in the previous activity) that keeps track of the number of times the for loop has been executed. To change the number of times the for loop is executed, simply change the numbers after the variable "i". This variable can be used inside the statements of the for loop (between the "do" and "end" tags) to do any number of things - for example, you can print the variable itself inside the for loop:
/script for i = 5, 8 do print(i); print("\n"); end;
And the script will print the numbers 5, 6, 7, 8 in the chat box on separate lines. There are many things you can do with for loops in the context of the game. For example, try the following exercises:
- 6 times, if the player is the party leader, print "I am the party leader!"
- Challenge: using online resources and the World of Warcraft API to write a script that loops through all the items in your bags and prints out their names in the chat box.
Students should be level 3 or higher in World of Warcraft and have active accounts prior to starting the lessons. Explaining some of the basic definitions (Lua, script, chat box, etc.) and discussing the test environment (i.e., WoW) should take no more than 45 minutes. Each exercise should take one 45-minute class session to complete, although instructors may want to devote more time to certain lessons if students need more time to experiment with the scripts.
An important thing to note about learning programming is the self-help portion. To become proficient programmers knowledgeable about programming concepts and execution, students should spend time experimenting with writing their own scripts. The more time students spend on the exercises, the better of an understanding of computer science concepts they will have.
Once the lessons are complete, some students may be interested in progressing beyond the curriculum exercises. A good place to start is the WoW API, which will provide many interesting built-in functions to experiment with. To get started with macros, please visit http://www.wowwiki.com/Making_a_macro .
The simple exercises that follow will reinforce some of the basic concepts described above. Any subset of these exercises can be used as an assessment of concepts learned. The teacher can decide which exercises to use as an assessment and which can be used as additional practice assignments. Exercises are grouped by concepts. In all exercises, students should be encouraged to test the scripts they have written. For example, for the first conditional statement exercise below, students should be encouraged to run the script first when they are targeting another character and then later when they are not targeting another character.
- Ask the students to use print to display the first names of three of their classmates on three separate lines in the chat box
/script print("Andrew"); print("Ian"); print("Michele");
- Ask the students to use print as a calculator to calculate the amount of copper they have in their possession. The conversion rate is 1 silver piece equals 100 copper pieces. They should just manually open their bag to see how much silver and copper they have, converting and adding the numbers to calculate the total amount of copper they have.
/script print("I have ");print(3*100+52);print(" copper.");
- Using the WoW API, find the relevant functions to accomplish the following task: check to see whether you have a character targeted. If you do, print a statement saying so. If you don't print an alternate statement.
/script if(UnitHealth("playertarget")~=0) then print("TARGET ACQUIRED!!"); else print("I don't have a target..."); end;
- Using the WoW API, find the relevant functions to accomplish the following task: if you are swimming or not swimming, print a relevant statement.
/script if(IsSwimming()) then print("I am swimming."); else print("I am not swimming."); end;
- Design a simple script using variables and the built-in function GetMoney() to print the number of silver pieces in your possession. This is building on one of the additional exercises from the built-in functions - automating finding the amount of money you have in your possession instead of having to look in the bag yourself. Use print() to give context to the number displayed. GetMoney() returns the number of copper pieces in the player's possession. The conversion rate is 1 silver piece equals 100 copper pieces.
/script a=GetMoney(); b=100; print("You have "); print(a/b); print(" silver pieces");
- Design a script that prints out how much money you would make if you sold every item in your backpack. Use the following code snippet to get the sell price of an item:
local itemSellPrice=select(11, GetItemInfo(itemID));
Every time the previous line of code is run, the variable itemSellPrice will contain the sell price in copper of the item with the ID of itemID. The function GetContainerItemID will be useful here; read its documentation in the WoW API.
- Example solution:
/script local total=0; for i=1,9 do local itemSellPrice=select(11,GetItemInfo(GetContainerItemID(0,i))); total=total+itemSellPrice; end; print("My items are worth"); print(total); print("copper.");
Note that the ending index of the for loop must equal the number of items in the student's backpack, and that all the items must be packed as tightly towards the top of the backpack as possible (i.e. there can be no gaps).