Ref Values
Before this: Ref Parameters
Next steps: Per-Player State
A *int parameter points a mod at a variable when you write the call. A ref
can also be a value: kept in a variable, and pointed somewhere else while the
game runs. This lesson keeps three counters and a button that chooses which
one the other button adds to.
Contents
button1 Held -> chip next
button2 Held -> chip add
chip sign -> decal Text
Code
@left in next: exec
@left in add: exec
var a: int = 0
var b: int = 0
var c: int = 0
var picked: *int
var name: string = "none"
@right out sign = "A ${a.Value} B ${b.Value} C ${c.Value}<br>Picked: ${name.Value}"
on next {
if name == "A" {
picked = &b
name = "B"
} else if name == "B" {
picked = &c
name = "C"
} else {
picked = &a
name = "A"
}
}
on add {
*picked += 1
}
var picked: *intis a variable that holds a ref to anintvariable. It starts empty.&bisb’s ref, as a value.picked = &bstores it.*pickedis the variablepickedpoints at.*picked += 1adds one to whichever ofa,borcthat is.nextstepspickedfrom A to B to C and round again.namekeeps the letter for the sign.
The add handler never mentions a, b or c. Press next twice, then
add three times. Which counter goes up? What happens if you press add
before you have ever pressed next?
Run
- Compile the chip and paste it in-game. Place two Buttons and a brick with a Text Decal.
- Wire one Button’s Held to
next, the other’s Held toadd, andsignto the Text Decal’s Text. - Press
addfirst: nothing happens, since nothing is picked yet. Pressnext: A is picked. Pressadd: A goes up. Pressnextandadd: B goes up.
Under the Hood
Open the chip. picked is a Var like the others, but what it holds is a
ref to another Var. The three Set Variable gates that write picked each
take their Value from a different counter’s Var Ref output. That wire
is &a, &b or &c.
The add chain is two gates. A Get Variable reads picked, and its
Value output is wired into the Var Ref input of an Increment
Variable. In Ref Parameters the Var Ref input was wired
straight from one counter when you compiled. Here it comes from a variable,
so which counter it reaches is decided while the game runs.
A ref is not the number it points at. Leave out the * and the compiler
stops you:
@left in add: exec
var a: int = 0
var picked: *int
on add {
picked = &a
picked += 1
}
Error: [WS004] operator '+' cannot be applied to a reference (*int, int): refs and bricks only compare with `==` and `!=`
A ref can start out pointing somewhere. The = &a is baked into the save,
so picked already holds a’s ref when the program is pasted, with no gate
to set it:
var a: int = 0
var picked: *int = &a
The initializer has to name a var, array or map declared above it. A ref that
is only known while the game runs, such as one read from another var, is
still dropped with a WSP001 warning.
Modify
-
Add a third button that clears the picked counter:
*picked = 0. One handler clears whichever counter is picked. -
Keep the refs in a list instead of an
ifchain.(*int)[]is an array of refs, filled the first timenextruns:@left in next: exec @left in add: exec var a: int = 0 var b: int = 0 var c: int = 0 var lanes: (*int)[] var lane: int = -1 var picked: *int @right out sign = "A ${a.Value} B ${b.Value} C ${c.Value}<br>Picked: ${lane.Value + 1}" on next { if lanes.length() == 0 { lanes.push(&a) lanes.push(&b) lanes.push(&c) } lane = (lane + 1) % 3 picked = lanes[lane] } on add { *picked += 1 }Add a fourth counter
d. Only the list and the% 3change. -
A ref value can go to a
*intparameter. The mod then works on the variable the ref points at. Add this mod and call it withpicked:mod bump(count: *int, by: int) { count += by } on add { bump(picked, 5) }
Make
Make a switchboard. Three Point Lights are each driven by a bool
variable. One button picks the next light, and another flips the picked one
on or off (*sel = !*sel). A sign says which light is picked.
button1 Held -> chip next
button2 Held -> chip flip
chip lamp1 -> light1 Enabled
chip lamp2 -> light2 Enabled
chip lamp3 -> light3 Enabled
chip sign -> decal Text
Good to Know
- An empty ref stops the chain. Reading or writing through
pickedbefore anything was stored in it ends the handler at that line, with no message. - Refs compare only with refs.
picked == &aasks whetherpickedpoints ata. Comparing a ref with a number is an error (WS084), because the game treats1 == <ref>as true. - Shown as text, a ref prints as
Var, not as the value it points at. Read through it with*first. - Arrays and maps are already passed as themselves: an
int[]mod parameter needs no*, as in Ref Parameters.
See Reference values and Ref and Deref in the reference.
Next: Per-Player State.