feat: author emergent situations and dialogue

This commit is contained in:
Rijad Zuzo
2026-08-12 21:58:12 +02:00
parent 14120115d4
commit d12e9515fb
29 changed files with 856 additions and 143 deletions
@@ -3,12 +3,15 @@ extends Resource
@export var intent_id: StringName
@export var response_intent_ids: Array[StringName] = []
@export var template_catalog_id: StringName
func validate() -> Array[String]:
var errors: Array[String] = []
if not ConversationSemantic.is_valid_id(intent_id):
errors.append("intent_id is invalid")
if template_catalog_id.is_empty():
errors.append("template_catalog_id is empty for '%s'" % intent_id)
var seen: Dictionary = {}
for response_intent_id in response_intent_ids:
if not ConversationSemantic.is_valid_id(response_intent_id):
@@ -20,3 +23,11 @@ func validate() -> Array[String]:
else:
seen[response_intent_id] = true
return errors
func duplicate_definition() -> ConversationIntentDefinition:
var copy := ConversationIntentDefinition.new()
copy.intent_id = intent_id
copy.response_intent_ids = response_intent_ids.duplicate()
copy.template_catalog_id = template_catalog_id
return copy
@@ -1,12 +1,15 @@
class_name ConversationTemplateCatalog
extends Resource
@export var catalog_id: StringName
@export var line_templates: Dictionary = {}
@export var option_templates: Dictionary = {}
func validate(intent_ids: Array[StringName] = ConversationIntentIds.ALL) -> Array[String]:
var errors: Array[String] = []
if catalog_id.is_empty():
errors.append("catalog_id is empty")
_validate_templates(line_templates, "line", intent_ids, errors)
_validate_templates(option_templates, "option", intent_ids, errors)
errors.sort()
@@ -21,6 +24,14 @@ func get_option_templates(intent_id: StringName) -> Array[String]:
return _get_templates(option_templates, intent_id)
func get_line_template_ids() -> Array[StringName]:
return _template_ids(line_templates)
func get_option_template_ids() -> Array[StringName]:
return _template_ids(option_templates)
func _get_templates(source: Dictionary, intent_id: StringName) -> Array[String]:
var result: Array[String] = []
var values: Variant = source.get(String(intent_id), [])
@@ -34,6 +45,23 @@ func _get_templates(source: Dictionary, intent_id: StringName) -> Array[String]:
func _validate_templates(
source: Dictionary, kind: String, intent_ids: Array[StringName], errors: Array[String]
) -> void:
var allowed_ids := {}
for intent_id in intent_ids:
allowed_ids[intent_id] = true
for raw_intent_id in source:
if not raw_intent_id is String and not raw_intent_id is StringName:
errors.append("Non-string %s template intent ID" % kind)
continue
var source_intent_id := StringName(raw_intent_id)
if not allowed_ids.has(source_intent_id):
errors.append("Unknown %s template intent '%s'" % [kind, source_intent_id])
var raw_templates: Variant = source[raw_intent_id]
if not raw_templates is Array and not raw_templates is PackedStringArray:
errors.append("Invalid %s templates for '%s'" % [kind, source_intent_id])
continue
for raw_template in raw_templates:
if not raw_template is String:
errors.append("Non-string %s template for '%s'" % [kind, source_intent_id])
for intent_id in intent_ids:
var templates := _get_templates(source, intent_id)
if templates.is_empty():
@@ -42,3 +70,14 @@ func _validate_templates(
for template in templates:
if template.strip_edges().is_empty():
errors.append("Empty %s template for '%s'" % [kind, intent_id])
func _template_ids(source: Dictionary) -> Array[StringName]:
var result: Array[StringName] = []
for raw_id in source:
if raw_id is String or raw_id is StringName:
result.append(StringName(raw_id))
result.sort_custom(
func(left: StringName, right: StringName) -> bool: return String(left) < String(right)
)
return result
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"accept"
response_intent_ids = Array[StringName]([&"thank", &"report_progress", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"acknowledge_supersession"
response_intent_ids = Array[StringName]([&"thank", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"ask_wellbeing"
response_intent_ids = Array[StringName]([&"describe_need", &"share_fact", &"offer_help", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"ask_what_happened"
response_intent_ids = Array[StringName]([&"share_fact", &"ask_who_else", &"offer_help", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"ask_who_else"
response_intent_ids = Array[StringName]([&"share_fact", &"offer_help", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"ask_work"
response_intent_ids = Array[StringName]([&"describe_need", &"report_progress", &"share_fact", &"ask_who_else", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"decline"
response_intent_ids = Array[StringName]([&"reproach", &"renegotiate", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"describe_need"
response_intent_ids = Array[StringName]([&"offer_help", &"decline", &"ask_who_else", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,8 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"goodbye"
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"greet"
response_intent_ids = Array[StringName]([&"ask_work", &"ask_wellbeing", &"ask_what_happened", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"offer_help"
response_intent_ids = Array[StringName]([&"accept", &"decline", &"renegotiate"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"renegotiate"
response_intent_ids = Array[StringName]([&"accept", &"decline", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"report_progress"
response_intent_ids = Array[StringName]([&"thank", &"renegotiate", &"acknowledge_supersession", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"reproach"
response_intent_ids = Array[StringName]([&"acknowledge_supersession", &"renegotiate", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"share_fact"
response_intent_ids = Array[StringName]([&"ask_what_happened", &"ask_who_else", &"acknowledge_supersession", &"thank", &"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="ConversationIntentDefinition" load_steps=2 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="1"]
[resource]
script = ExtResource("1")
intent_id = &"thank"
response_intent_ids = Array[StringName]([&"goodbye"])
template_catalog_id = &"jajce_conversation_templates"
@@ -1,87 +1,23 @@
[gd_resource type="Resource" script_class="ConversationIntentCatalog" load_steps=18 format=3]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentCatalog.gd" id="1_catalog"]
[ext_resource type="Script" path="res://simulation/dialogue/ConversationIntentDefinition.gd" id="2_intent"]
[sub_resource type="Resource" id="Intent_greet"]
script = ExtResource("2_intent")
intent_id = &"greet"
response_intent_ids = Array[StringName]([&"ask_work", &"ask_wellbeing", &"ask_what_happened", &"goodbye"])
[sub_resource type="Resource" id="Intent_ask_work"]
script = ExtResource("2_intent")
intent_id = &"ask_work"
response_intent_ids = Array[StringName]([&"describe_need", &"report_progress", &"share_fact", &"ask_who_else", &"goodbye"])
[sub_resource type="Resource" id="Intent_ask_wellbeing"]
script = ExtResource("2_intent")
intent_id = &"ask_wellbeing"
response_intent_ids = Array[StringName]([&"describe_need", &"share_fact", &"offer_help", &"goodbye"])
[sub_resource type="Resource" id="Intent_ask_what_happened"]
script = ExtResource("2_intent")
intent_id = &"ask_what_happened"
response_intent_ids = Array[StringName]([&"share_fact", &"ask_who_else", &"offer_help", &"goodbye"])
[sub_resource type="Resource" id="Intent_share_fact"]
script = ExtResource("2_intent")
intent_id = &"share_fact"
response_intent_ids = Array[StringName]([&"ask_what_happened", &"ask_who_else", &"acknowledge_supersession", &"thank", &"goodbye"])
[sub_resource type="Resource" id="Intent_describe_need"]
script = ExtResource("2_intent")
intent_id = &"describe_need"
response_intent_ids = Array[StringName]([&"offer_help", &"decline", &"ask_who_else", &"goodbye"])
[sub_resource type="Resource" id="Intent_ask_who_else"]
script = ExtResource("2_intent")
intent_id = &"ask_who_else"
response_intent_ids = Array[StringName]([&"share_fact", &"offer_help", &"goodbye"])
[sub_resource type="Resource" id="Intent_offer_help"]
script = ExtResource("2_intent")
intent_id = &"offer_help"
response_intent_ids = Array[StringName]([&"accept", &"decline", &"renegotiate"])
[sub_resource type="Resource" id="Intent_accept"]
script = ExtResource("2_intent")
intent_id = &"accept"
response_intent_ids = Array[StringName]([&"thank", &"report_progress", &"goodbye"])
[sub_resource type="Resource" id="Intent_decline"]
script = ExtResource("2_intent")
intent_id = &"decline"
response_intent_ids = Array[StringName]([&"reproach", &"renegotiate", &"goodbye"])
[sub_resource type="Resource" id="Intent_report_progress"]
script = ExtResource("2_intent")
intent_id = &"report_progress"
response_intent_ids = Array[StringName]([&"thank", &"renegotiate", &"acknowledge_supersession", &"goodbye"])
[sub_resource type="Resource" id="Intent_renegotiate"]
script = ExtResource("2_intent")
intent_id = &"renegotiate"
response_intent_ids = Array[StringName]([&"accept", &"decline", &"goodbye"])
[sub_resource type="Resource" id="Intent_thank"]
script = ExtResource("2_intent")
intent_id = &"thank"
response_intent_ids = Array[StringName]([&"goodbye"])
[sub_resource type="Resource" id="Intent_reproach"]
script = ExtResource("2_intent")
intent_id = &"reproach"
response_intent_ids = Array[StringName]([&"acknowledge_supersession", &"renegotiate", &"goodbye"])
[sub_resource type="Resource" id="Intent_acknowledge_supersession"]
script = ExtResource("2_intent")
intent_id = &"acknowledge_supersession"
response_intent_ids = Array[StringName]([&"thank", &"goodbye"])
[sub_resource type="Resource" id="Intent_goodbye"]
script = ExtResource("2_intent")
intent_id = &"goodbye"
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/accept.tres" id="2_accept"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/acknowledge_supersession.tres" id="3_acknowledge"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/ask_wellbeing.tres" id="4_wellbeing"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/ask_what_happened.tres" id="5_happened"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/ask_who_else.tres" id="6_who"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/ask_work.tres" id="7_work"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/decline.tres" id="8_decline"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/describe_need.tres" id="9_need"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/goodbye.tres" id="10_goodbye"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/greet.tres" id="11_greet"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/offer_help.tres" id="12_offer"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/renegotiate.tres" id="13_renegotiate"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/report_progress.tres" id="14_progress"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/reproach.tres" id="15_reproach"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/share_fact.tres" id="16_share"]
[ext_resource type="Resource" path="res://simulation/dialogue/resources/intents/thank.tres" id="17_thank"]
[resource]
script = ExtResource("1_catalog")
intents = Array[ExtResource("2_intent")]([SubResource("Intent_greet"), SubResource("Intent_ask_work"), SubResource("Intent_ask_wellbeing"), SubResource("Intent_ask_what_happened"), SubResource("Intent_share_fact"), SubResource("Intent_describe_need"), SubResource("Intent_ask_who_else"), SubResource("Intent_offer_help"), SubResource("Intent_accept"), SubResource("Intent_decline"), SubResource("Intent_report_progress"), SubResource("Intent_renegotiate"), SubResource("Intent_thank"), SubResource("Intent_reproach"), SubResource("Intent_acknowledge_supersession"), SubResource("Intent_goodbye")])
intents = [ExtResource("11_greet"), ExtResource("7_work"), ExtResource("4_wellbeing"), ExtResource("5_happened"), ExtResource("16_share"), ExtResource("9_need"), ExtResource("6_who"), ExtResource("12_offer"), ExtResource("2_accept"), ExtResource("8_decline"), ExtResource("14_progress"), ExtResource("13_renegotiate"), ExtResource("17_thank"), ExtResource("15_reproach"), ExtResource("3_acknowledge"), ExtResource("10_goodbye")]
@@ -4,6 +4,7 @@
[resource]
script = ExtResource("1_catalog")
catalog_id = &"jajce_conversation_templates"
line_templates = {
"accept": ["That works for me.", "Yes, let us do that."],
"acknowledge_supersession": ["Things have changed since then; I understand.", "That news has overtaken our earlier plan."],