diff --git a/game/project.godot b/game/project.godot
index 727e7a3..5689903 100644
--- a/game/project.godot
+++ b/game/project.godot
@@ -10,7 +10,8 @@ config_version=5
[application]
-config/name="Langjam Game"
+config/name="Gamma cooked"
+run/main_scene="uid://ce1jmpre2oxkg"
config/features=PackedStringArray("4.5", "GL Compatibility")
config/icon="res://icon.svg"
diff --git a/game/rule_entity_parent.gd b/game/rule_entity_parent.gd
new file mode 100644
index 0000000..eb4bd6f
--- /dev/null
+++ b/game/rule_entity_parent.gd
@@ -0,0 +1,87 @@
+extends Node
+
+var initializing = true
+
+# Set a property on an entity
+func set_entity_property(obj: Object, property_name: StringName, value: Variant):
+ obj.set(property_name, value)
+ obj.set_meta(property_name, value)
+
+func set_entity_property_deferred(obj: Object, property_name: StringName, value: Variant):
+ obj.set_deferred(property_name, value)
+ obj.call_deferred("set_meta", property_name, value)
+
+func get_entity_property(obj: Object, property_name: StringName) -> Variant:
+ var v = obj.get(property_name)
+ if v != null:
+ return v
+ if property_name in obj.get_meta_list():
+ return obj.get_meta(property_name)
+ return null
+
+# Called when the node enters the scene tree for the first time.
+func _ready() -> void:
+ pass
+ #for c in get_children():
+ #var e = SimEntity.new(c)
+ #entities.push_back(e)
+
+# Called every frame. 'delta' is the elapsed time since the previous frame.
+func _process(_delta: float) -> void:
+ pass
+
+var sad_texture: Texture2D = load("res://textures/sad1.svg")
+
+# Perform a deferred update using a recording object.
+# fn must:
+# * Be pure
+# * Only use state it captured when it was created (not new global state)
+# * Be commutative and associated with all other updates on the property.
+# If these conditions are met, the order of updates should not be observable, so the order of
+# rule execution should not be observable.
+func deferred_update(record: Dictionary, obj: Object, property_name: StringName, fn):
+ var key = [obj, property_name]
+ var v = record.get(key)
+ if v == null:
+ v = get_entity_property(obj, property_name)
+ v = fn.call(v)
+ record[key] = v
+
+func _physics_process(_delta: float) -> void:
+ var recorded: Dictionary = {}
+ for a in get_children():
+ if initializing:
+ deferred_update(recorded, a, StringName("friend"), func(_v): return "None")
+ for b in get_children():
+ if a == b:
+ continue
+ #if get_entity_property(b, StringName("moving")):
+ var a_offset: Vector2 = get_entity_property(a, StringName("position"))
+ var b_offset: Vector2 = get_entity_property(b, StringName("position"))
+ if a_offset.distance_to(b_offset) < 20:
+ deferred_update(recorded, a, StringName("friend"), func(_v): return b.name)
+ if a_offset.distance_to(b_offset) < 100:
+ var vel = (a_offset - b_offset) / 100
+ deferred_update(recorded, a, StringName("position"), func (v): return v - vel)
+
+ if get_entity_property(a, StringName("emotional")):
+ for b in get_children():
+ if a == b:
+ continue
+ var a_offset: Vector2 = get_entity_property(a, StringName("position"))
+ var b_offset = get_entity_property(b, StringName("position"))
+ if a_offset.distance_to(b_offset) < 10:
+ deferred_update(recorded, a, StringName("texture"), func (_v): return sad_texture)
+
+ if get_entity_property(a, StringName("moving")):
+ var offset = get_entity_property(a, StringName("position"))
+ if offset != null:
+ deferred_update(recorded, a, StringName("position"), func (v):
+ v.x += 1
+ return v
+ )
+
+ for k in recorded.keys():
+ set_entity_property(k[0], k[1], recorded[k])
+
+ initializing = false
diff --git a/game/rule_entity_parent.gd.uid b/game/rule_entity_parent.gd.uid
new file mode 100644
index 0000000..a9c514b
--- /dev/null
+++ b/game/rule_entity_parent.gd.uid
@@ -0,0 +1 @@
+uid://b4s1n6b74hrj0
diff --git a/game/test_scene.tscn b/game/test_scene.tscn
index 9ae6d05..738333e 100644
--- a/game/test_scene.tscn
+++ b/game/test_scene.tscn
@@ -1,9 +1,22 @@
-[gd_scene load_steps=2 format=3 uid="uid://ce1jmpre2oxkg"]
+[gd_scene load_steps=4 format=3 uid="uid://ce1jmpre2oxkg"]
-[ext_resource type="Texture2D" uid="uid://cy64oitmrt583" path="res://icon.svg" id="1_uhqqe"]
+[ext_resource type="Script" uid="uid://b4s1n6b74hrj0" path="res://rule_entity_parent.gd" id="1_uhqqe"]
+[ext_resource type="Texture2D" uid="uid://ecg3llvsdms" path="res://textures/wink.svg" id="2_ia1lp"]
+[ext_resource type="Texture2D" uid="uid://cy64oitmrt583" path="res://icon.svg" id="3_sasra"]
[node name="Node2D" type="Node2D"]
+script = ExtResource("1_uhqqe")
+
+[node name="Line2D" type="Line2D" parent="."]
+position = Vector2(-5, 36)
+points = PackedVector2Array(0, 0, 30, 50)
+
+[node name="Sprite2D2" type="Sprite2D" parent="."]
+position = Vector2(801, 177)
+texture = ExtResource("3_sasra")
[node name="Sprite2D" type="Sprite2D" parent="."]
-position = Vector2(414, 299)
-texture = ExtResource("1_uhqqe")
+position = Vector2(399, 173)
+texture = ExtResource("2_ia1lp")
+metadata/moving = true
+metadata/emotional = true
diff --git a/game/textures/happy.svg b/game/textures/happy.svg
new file mode 100644
index 0000000..81867a8
--- /dev/null
+++ b/game/textures/happy.svg
@@ -0,0 +1,40 @@
+
+
+
+
diff --git a/game/textures/happy.svg.import b/game/textures/happy.svg.import
new file mode 100644
index 0000000..f8a6ef4
--- /dev/null
+++ b/game/textures/happy.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://502oh1bix4id"
+path="res://.godot/imported/happy.svg-fd33a7aeedbdafea8797b06b9dd0664e.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://textures/happy.svg"
+dest_files=["res://.godot/imported/happy.svg-fd33a7aeedbdafea8797b06b9dd0664e.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/game/textures/sad1.svg b/game/textures/sad1.svg
new file mode 100644
index 0000000..6d51da7
--- /dev/null
+++ b/game/textures/sad1.svg
@@ -0,0 +1,58 @@
+
+
+
+
diff --git a/game/textures/sad1.svg.import b/game/textures/sad1.svg.import
new file mode 100644
index 0000000..141eae0
--- /dev/null
+++ b/game/textures/sad1.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://c6njtxqwr03s2"
+path="res://.godot/imported/sad1.svg-ff4ee8724c479ec02c56521325058822.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://textures/sad1.svg"
+dest_files=["res://.godot/imported/sad1.svg-ff4ee8724c479ec02c56521325058822.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/game/textures/sad2.svg b/game/textures/sad2.svg
new file mode 100644
index 0000000..32bb4b2
--- /dev/null
+++ b/game/textures/sad2.svg
@@ -0,0 +1,58 @@
+
+
+
+
diff --git a/game/textures/sad2.svg.import b/game/textures/sad2.svg.import
new file mode 100644
index 0000000..2f41417
--- /dev/null
+++ b/game/textures/sad2.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://delx0kt0sdbta"
+path="res://.godot/imported/sad2.svg-4a4a94f5c4f85b61eb6518ab6153b182.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://textures/sad2.svg"
+dest_files=["res://.godot/imported/sad2.svg-4a4a94f5c4f85b61eb6518ab6153b182.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/game/textures/wink.svg b/game/textures/wink.svg
new file mode 100644
index 0000000..62872af
--- /dev/null
+++ b/game/textures/wink.svg
@@ -0,0 +1,58 @@
+
+
+
+
diff --git a/game/textures/wink.svg.import b/game/textures/wink.svg.import
new file mode 100644
index 0000000..7c9a7cb
--- /dev/null
+++ b/game/textures/wink.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://ecg3llvsdms"
+path="res://.godot/imported/wink.svg-cabb34892182fcb85ac461ed45c7cc16.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://textures/wink.svg"
+dest_files=["res://.godot/imported/wink.svg-cabb34892182fcb85ac461ed45c7cc16.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false