Wikipedia: Scripting language
Tengo is well suited for NPC behaviour, ability definitions, and quest logic in a game engine. The Go host loads and evaluates the script each tick, providing game state through a custom game module. Scripts can be hot-reloaded and modders can write them without touching Go.
fmt := import("fmt")
player := {health: 45, position: {x: 20, y: 15}, weapon: "sword"}
npc := {
name: "Guard",
health: 80,
position: {x: 10, y: 10},
state: "idle",
alert_range: 8,
attack_range: 2,
}
within := func(a, b, r) {
dx := a.x - b.x
dy := a.y - b.y
return dx*dx + dy*dy <= r*r
}
tick := func(npc, player) {
if npc.state == "idle" {
if within(player.position, npc.position, npc.alert_range) {
npc.state = "alerted"
return {action: "say", text: "Halt! Who goes there?"}
}
return {action: "patrol"}
}
if npc.state == "alerted" {
if within(player.position, npc.position, npc.attack_range) {
npc.state = "fighting"
} else {
return {action: "move_towards", target: player.position}
}
}
if npc.state == "fighting" {
if npc.health < 20 {
npc.state = "fleeing"
return {action: "say", text: "Mercy!"}
}
dmg := 12
if player.weapon != "" { dmg = 8 }
return {action: "attack", damage: dmg}
}
if npc.state == "fleeing" {
return {action: "run"}
}
return {action: "idle"}
}
print_tick := func(npc, result) {
fmt.printf("%-10s → %s", npc.state, result["action"])
if !is_undefined(result["text"]) {
fmt.printf(": %q", result["text"])
}
if !is_undefined(result["target"]) {
t := result["target"]
fmt.printf(" (%d,%d)", t.x, t.y)
}
if !is_undefined(result["damage"]) {
fmt.printf(" (dmg %d)", result["damage"])
}
fmt.println("")
}
positions := [
{x: 20, y: 15}, // out of range → patrol
{x: 14, y: 12}, // alert range → alerted, say
{x: 12, y: 11}, // closing in → move_towards
{x: 10, y: 10}, // attack range → fighting, attack
]
for _, pos in positions {
player.position = pos
result := tick(npc, player)
print_tick(npc, result)
}
fmt.println("--- NPC takes heavy damage ---")
npc.health = 15
result := tick(npc, player)
print_tick(npc, result)
try it
idle → patrol alerted → say: "Halt! Who goes there?" alerted → move_towards (12,11) fighting → attack (dmg 8) --- NPC takes heavy damage --- fleeing → say: "Mercy!"