Character Scripts

Now for what games use coroutines for most: scripts for characters. Each character gets a coroutine that describes what it does, from start to end, one turn after another. The game runs in turns (on our farm, a turn is one day): every turn, it resumes each character's coroutine once, and each character does one step and yields.

Hugo the trader has a route with three stops. Bella the cow has the same routine every two days, so her script is a loop that never ends:

-- Who does what on Sunflower Farm
local function hugo()
    print("Hugo is at the market.")
    coroutine.yield()
    print("Hugo visits Sunflower Farm.")
    coroutine.yield()
    print("Hugo travels to the city.")
end

local function bella()
    while true do
        print("Bella grazes in the meadow.")
        coroutine.yield()
        print("Bella rests in the barn.")
        coroutine.yield()
    end
end

local characters = {coroutine.create(hugo), coroutine.create(bella)}

for day = 1, 4 do
    print("Day " .. day)
    for _, character in ipairs(characters) do
        if coroutine.status(character) ~= "dead" then
            coroutine.resume(character)
        end
    end
end

This prints:

Day 1
Hugo is at the market.
Bella grazes in the meadow.
Day 2
Hugo visits Sunflower Farm.
Bella rests in the barn.
Day 3
Hugo travels to the city.
Bella grazes in the meadow.
Day 4
Bella rests in the barn.

The coroutines are in a list, so the game loop doesn't care how many characters there are: it gives each of them a turn, in the order of the list. The characters take turns; they never run at the same time. Each one runs until its yield, and only then does the next one get its turn. On day 4, Hugo's script has already ended (dead), so the loop skips him.

Why coroutines? Without them, Hugo would need a variable that remembers his step, and every day an if step == 1 then … elseif step == 2 then …, and every character would need such variables of its own. A coroutine remembers where it stopped, and its local variables too, so each script reads from top to bottom like a story: first this, then wait, then that. Bella's script shows it: a loop with two steps, nothing more.

Instructions

Rex the dog brings Emma a stick every day, and he counts them. Write a function rex for his script: a local variable sticks that starts at 0, then a loop that runs forever. In the loop, Rex adds one stick, prints Rex brings stick number 1. (with the current number) and yields. Make a coroutine from rex and resume it every day, right after Hugo. The program prints:

Day 1
Hugo sells seeds at the market.
Rex brings stick number 1.
Day 2
Hugo buys eggs at Sunflower Farm.
Rex brings stick number 2.
Day 3
Hugo leaves for the city.
Rex brings stick number 3.

Grandpa Joe, the neighbor, comes for a chat every second day: on days 2, 4, 6, and so on. Write his script, grandpaJoe: in a loop that runs forever, he first lets a day go by (just coroutine.yield()), then prints Grandpa Joe comes for a chat. and yields again. Put the three coroutines in a list characters, in the order Hugo, Rex, Grandpa Joe, and in a loop with ipairs, resume every one that isn't dead. Make the game four days long. The program prints:

Day 1
Hugo sells seeds at the market.
Rex brings stick number 1.
Day 2
Hugo buys eggs at Sunflower Farm.
Rex brings stick number 2.
Grandpa Joe comes for a chat.
Day 3
Hugo leaves for the city.
Rex brings stick number 3.
Day 4
Rex brings stick number 4.
Grandpa Joe comes for a chat.

Start programming for free

By signing up, you agree to the Terms of Service and Privacy Policy.

Or sign up with:

4/6