Skip to content

Basic Arcweave tutorial | Part 15: Polish the project ​

Polish this tutorial's project: delete unused boards, merge elements, and make better use of the morale score system.

Video tutorial ​

Watch this tutorial as a video:

⚠️ This video does not reflect the latest updates to Arcweave's UI.

✅ You can play the finished version of the Tutorial Project here and explore its diagrams and structure here.


Clean up the project ​

To clean up the project, you can:

  • Delete any "dummy" elements or boards used purely for demonstration.
  • Delete any empty boards.
  • Remove unused formatting.
  • Delete unused variables. For example, the roll_result variable we used earlier to deduct from the player's morale is no longer needed once we change how morale is calculated (see below).

Initial morale ​

If you followed Part 13, your starting element already rolls the player's initial morale. This section puts that setup together. If your project still assigns a fixed value instead, replace it with a dice roll.

Roll for initial morale ​

In the element where morale is first set, replace the fixed value with a dice roll:

arcscript
player_morale = roll(6,3)

This rolls three six-sided dice and assigns the result to player_morale.

Show initial morale ​

Next, let's render the result to the player. In the element's text, show the value and add some text that introduces it:

arcscript
You start with a morale of
show(player_morale, ".")

Morale commentary ​

We can let the game comment on the player's initial morale, by adding some conditional text:

arcscript
if player_morale < 12
    It's not that great, to be honest, but you have to work with what you've got.
elseif player_morale >= 12 and player_morale <18
    It's a pretty good morale score to start with.
else
    Perfect morale score! You feel super elevated!
endif

Put it all together ​

Putting all of the above together, the starting element looks like this:

arcscript
You rub your eyes. You are on the floor. Your office. It's midday. And you have work to do.

You start with a morale of
player_morale = roll(6,3)
show(player_morale, ".")
if player_morale < 12
    It's not that great, to be honest, but you have to work with what you've got.
elseif player_morale >= 12 and player_morale <18
    It's a pretty good morale score to start with.
else
    Perfect morale score! You feel super elevated!
endif

✅ Test this in Play Mode. Due to the initial value being randomized, you'll see different outcomes each time you restart the story.

Add morale check ​

There's not much point in having a stat like morale if it never affects anything.

Let's add a morale check at a key moment in the story: when Horace opens the door and comments on the player being late (or dirty).

Add a penalty ​

First, let's add a penalty for not having showered. Inside the element where Horace opens the door, type:

arcscript
Horace Linetti opens the door and lets you in.

if shower_taken
    "You're late!" he says.
else
    "Good Lord! You smell as if you've spent the night on an office floor," he says, fanning the air with his hand.
    player_morale = player_morale - 2
endif

Roll the check ​

Next, we add the actual check: we'll roll a 20-sided die and compare it against the player's morale. As an extra rule, if the player has maximum morale (18), the check is considered a success.

Add the following to the element content:

arcscript
if player_morale >= roll(20) or player_morale == 18
    You enter the apartment. As you marvel at the design of the living room, he disappears towards the bedrooms. "Let me know if you find my grandmother's ring," he hollers.
else
    You freeze with shame. Without a word, you turn around and leave.
endif

Store the result ​

Right now, the outcome of the check only affects the text shown inside that one element; it does not affect the options or the rest of the story. To fix this, we need to store the result in a variable so we can evaluate it anywhere else needed.

  1. Create a new Boolean variable called morale_check_success, with initial value set to false.
  2. Inside the element content, plant accordingly the assignment of the morale_check_success variable:
arcscript
if player_morale >= roll(20) or player_morale == 18
    morale_check_success = true
    You enter the apartment. As you marvel at the design of the living room, he disappears towards the bedrooms. "Let me know if you find my grandmother's ring," he hollers.
else
    morale_check_success = false
    You freeze with shame. Without a word, you turn around and leave.
endif

✅ For safety, explicitly set the variable to false in the else branch, even if false is also its initial value.


Complete element content ​

So, the complete element content is now:

arcscript
Horace Linetti opens the door and lets you in.

if shower_taken
    "You're late!" he says.
else
    "Good Lord! You smell as if you've spent the night on an office floor," he says, fanning the air with his hand.
    player_morale = player_morale - 2
endif
if player_morale >= roll(20) or player_morale == 18
    morale_check_success = true
    You enter the apartment. As you marvel at the design of the living room, he disappears towards the bedrooms. "Let me know if you find my grandmother's ring," he hollers.
else
    morale_check_success = false
    You freeze with shame. Without a word, you turn around and leave.
endif

Branch the outputs ​

After this element, add a branch that evaluates the morale_check_success variable and diverts the flow accordingly:

  • If true → You continue to the living room.
  • If false → You walk away.

✅ Test it in Play Mode with Debug mode turned on so you can watch the variables update in real time. Try it both with and without showering to confirm both outcomes work as expected.

Reset variables on restart ​

If your project has restart jumpers (see Add restart jumpers in Part 9), be careful: once your project has several variables, jumping straight back to the start without resetting them can cause the story to behave incorrectly. (The Restart button in Play Mode's menu already resets all variables and visits.)

Not every variable should be reset, though. For example, a variable that counts how many times the player has died should usually persist across restarts, since that's the entire point of tracking it. In this project, however, we want a clean slate every time, so in the story's starting element we reset:

  • morale_check_success: No need to reset; it gets recalculated before it's used.
  • player_morale: No need to reset; it gets recalculated before it's used.
  • shower_taken: Reset to false
  • ring_state: Reset to 0
  • has_key: Reset to false

Since resetting the first two variables does no harm, you can reset all of them at once: add ${ resetAll() } at the top of the starting element's content. resetAll() resets every global, board, and component variable to its initial value; to keep some of them unchanged, pass them as arguments, e.g. resetAll(player_morale). It does not reset element visits; use resetVisits() for that.

Simplify unnecessary branches ​

Branches are useful when they affect the flow of the story or the player's available actions. They're overkill, however, when their only job is to change which text gets rendered; that's a job for code inside an element instead.

In the bathroom, for example, there is a branch diverting to two nearly identical elements. Their only difference is the displayed text depending on whether the player has picked up the key. We can simplify this by merging the two elements into one and using Arcscript in the element's content to create conditional text:

arcscript
Two identical mirrors over two identical sinks. You wonder whether the siblings have to do everything simultaneously.
if !has_key

Hey, wait a second. These two mirrors are not positioned fully flat on the wall. They actually... When you stand at the centre of the room, they both reflect the same corner: the top part of the door.
endif

Afterwards, we need to fix the option of examining the door, so it doesn't happen again and again. Add a new branch after the above element that checks whether the player already has the key:

  • if not has_key → Go to the element where the key is found.

✅ The branch only has an if statement. If the player already has the key, there is no other option than to go back.

Play through this section again to confirm that examining the mirrors behaves correctly whether or not the player has already found the key.

Adding a project cover ​

As a final polishing touch, let's give the project a cover image:

  1. Exit the project by clicking the Workspace icon at the top left of your window.
  2. Find your project thumbnail in the list, click the three dots •••, and select Upload cover.
  3. Select an image from your drive and upload it.

Your project now has a cover, which will be shown in your project list and when sharing the project with others.

What's next ​

This project is now finished! The following pages and their videos demonstrate more features, the next one being importing & exporting projects in a Pro or Team workspace.