diff --git a/SConstruct b/SConstruct
old mode 100644
new mode 100755
index 27e219b..57e9f0b
--- a/SConstruct
+++ b/SConstruct
@@ -37,6 +37,9 @@ godot_headers_path = "godot-cpp/godot-headers/"
cpp_bindings_path = "godot-cpp/"
cpp_library = "libgodot-cpp"
+obelisk_bindings_path = "obelisk/"
+obelisk_library = "libobelisk"
+
# Updates the environment with the option variables.
opts.Update(env)
@@ -112,9 +115,9 @@ else:
cpp_library += '.' + str(env['bits'])
# make sure our binding library is properly includes
-env.Append(CPPPATH=['.', godot_headers_path, cpp_bindings_path + 'include/', cpp_bindings_path + 'include/core/', cpp_bindings_path + 'include/gen/'])
-env.Append(LIBPATH=[cpp_bindings_path + 'bin/'])
-env.Append(LIBS=[cpp_library])
+env.Append(CPPPATH=['.', obelisk_bindings_path + 'include/', godot_headers_path, cpp_bindings_path + 'include/', cpp_bindings_path + 'include/core/', cpp_bindings_path + 'include/gen/'])
+env.Append(LIBPATH=[cpp_bindings_path + 'bin/', obelisk_bindings_path + 'bin/'])
+env.Append(LIBS=[cpp_library, obelisk_library])
# tweak this if you want to use different folders, or more folders, to store your source code in.
env.Append(CPPPATH=['src/'])
diff --git a/godot/Main.tscn b/godot/Main.tscn
index 1324688..2cc9a1b 100644
--- a/godot/Main.tscn
+++ b/godot/Main.tscn
@@ -1,14 +1,14 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://Main.gdns" type="Script" id=1]
-[ext_resource path="res://levels/PrototypeR.tscn" type="PackedScene" id=2]
+[ext_resource path="res://levels/TestLevel.tscn" type="PackedScene" id=2]
[ext_resource path="res://gui/GameOver.tscn" type="PackedScene" id=3]
[ext_resource path="res://gui/GameWon.tscn" type="PackedScene" id=4]
[node name="Main" type="Node"]
pause_mode = 2
script = ExtResource( 1 )
-game_version = "1.1.0"
+game_version = "1.0.0"
level = ExtResource( 2 )
[node name="Level" type="Node" parent="."]
diff --git a/godot/alai.kb b/godot/alai.kb
new file mode 100644
index 0000000..c9d78ac
Binary files /dev/null and b/godot/alai.kb differ
diff --git a/godot/characters/enemies/WalkingEnemy.gd b/godot/characters/enemies/WalkingEnemy.gd
index 15707dc..f3b424f 100644
--- a/godot/characters/enemies/WalkingEnemy.gd
+++ b/godot/characters/enemies/WalkingEnemy.gd
@@ -9,35 +9,36 @@ export var gravity = 9.8
func _ready() -> void:
- if direction == 1:
- $AnimatedSprite.flip_h = true
- $FloorChecker.position.x = $CollisionShape2D.shape.get_extents().x * direction
- $FloorChecker.enabled = detect_edges
- Event.connect("level_loaded", self, "_on_level_loaded")
+ if direction == 1:
+ $AnimatedSprite.flip_h = true
+ $FloorChecker.position.x = $CollisionShape2D.shape.get_extents().x * direction
+ $FloorChecker.enabled = detect_edges
+ Event.connect("level_loaded", self, "_on_level_loaded")
func _physics_process(_delta: float) -> void:
- if is_on_wall() or not $FloorChecker.is_colliding() and is_on_floor() and $FloorChecker.enabled:
- direction *= -1
- $AnimatedSprite.flip_h = not $AnimatedSprite.flip_h
- $FloorChecker.position.x = $CollisionShape2D.shape.get_extents().x * direction
+ if is_on_wall() or not $FloorChecker.is_colliding() and is_on_floor() and $FloorChecker.enabled:
+ direction *= -1
+ $AnimatedSprite.flip_h = not $AnimatedSprite.flip_h
+ $FloorChecker.position.x = $CollisionShape2D.shape.get_extents().x * direction
- velocity.y += gravity
- velocity.x = speed * direction
- velocity = move_and_slide(velocity, Vector2.UP)
+ velocity.y += gravity
+ velocity.x = speed * direction
+ velocity = move_and_slide(velocity, Vector2.UP)
- for i in get_slide_count():
- var collision = get_slide_collision(i)
- if collision.collider.name == "Player":
- Event.emit_signal("player_touched", 3)
+ for i in get_slide_count():
+ var collision = get_slide_collision(i)
+ if collision.collider.name == "Player":
+ Event.emit_signal("player_touched", 3)
- Event.emit_signal("object_updated", self.get_name(), "Walking", global_position, velocity)
+ Event.emit_signal("object_updated", self.get_name(), "Walking", global_position, velocity)
+ Event.emit_signal("report_object", self.get_name(), "Walking", global_position, velocity)
func squash() -> void:
- Event.emit_signal("object_removed", self.get_name())
- queue_free()
+ Event.emit_signal("object_removed", self.get_name())
+ queue_free()
func _on_level_loaded() -> void:
- Event.emit_signal("object_created", self.get_name(), "Walking", global_position, Vector2(0, 0))
+ Event.emit_signal("object_created", self.get_name(), "Walking", global_position, Vector2(0, 0))
diff --git a/godot/characters/player/AI.gdns b/godot/characters/player/AI.gdns
new file mode 100644
index 0000000..9ac28b0
--- /dev/null
+++ b/godot/characters/player/AI.gdns
@@ -0,0 +1,8 @@
+[gd_resource type="NativeScript" load_steps=2 format=2]
+
+[ext_resource path="res://gdnative/alai.tres" type="GDNativeLibrary" id=1]
+
+[resource]
+resource_name = "AI"
+class_name = "AI"
+library = ExtResource( 1 )
diff --git a/godot/characters/player/Player.tscn b/godot/characters/player/Player.tscn
index 5ac8d15..471d986 100644
--- a/godot/characters/player/Player.tscn
+++ b/godot/characters/player/Player.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=10 format=2]
+[gd_scene load_steps=11 format=2]
[ext_resource path="res://characters/player/sprites/green.tres" type="SpriteFrames" id=1]
[ext_resource path="res://characters/player/states/Idle.gdns" type="Script" id=2]
@@ -8,6 +8,7 @@
[ext_resource path="res://characters/player/states/Jump.gdns" type="Script" id=6]
[ext_resource path="res://characters/player/states/Fall.gdns" type="Script" id=7]
[ext_resource path="res://assets/sounds/jump.wav" type="AudioStream" id=8]
+[ext_resource path="res://characters/player/AI.gdns" type="Script" id=9]
[sub_resource type="RectangleShape2D" id=1]
extents = Vector2( 7, 12 )
@@ -16,6 +17,9 @@ extents = Vector2( 7, 12 )
collision_mask = 10
script = ExtResource( 5 )
+[node name="AI" type="Node" parent="."]
+script = ExtResource( 9 )
+
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
frames = ExtResource( 1 )
animation = "idle"
diff --git a/godot/collectables/coin/Coin.gd b/godot/collectables/coin/Coin.gd
new file mode 100644
index 0000000..7ab13fe
--- /dev/null
+++ b/godot/collectables/coin/Coin.gd
@@ -0,0 +1,5 @@
+extends Area2D
+
+
+func _process(_delta: float) -> void:
+ Event.emit_signal("report_object", self.get_name(), "not collected", global_position, Vector2())
diff --git a/godot/collectables/coin/Coin.tscn b/godot/collectables/coin/Coin.tscn
index 1c40bc1..7dd7f88 100644
--- a/godot/collectables/coin/Coin.tscn
+++ b/godot/collectables/coin/Coin.tscn
@@ -1,10 +1,11 @@
-[gd_scene load_steps=11 format=2]
+[gd_scene load_steps=12 format=2]
[ext_resource path="res://assets/coin.png" type="Texture" id=1]
[ext_resource path="res://state_machine/StateMachine.gdns" type="Script" id=2]
[ext_resource path="res://collectables/coin/states/CoinNotCollected.gdns" type="Script" id=3]
[ext_resource path="res://collectables/coin/states/CoinCollected.gdns" type="Script" id=4]
[ext_resource path="res://assets/sounds/coin.wav" type="AudioStream" id=5]
+[ext_resource path="res://collectables/coin/Coin.gd" type="Script" id=6]
[sub_resource type="CircleShape2D" id=1]
radius = 6.0
@@ -43,6 +44,7 @@ tracks/0/keys = {
[node name="Coin" type="Area2D"]
collision_layer = 4
+script = ExtResource( 6 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2( 9, 9 )
@@ -51,7 +53,6 @@ shape = SubResource( 1 )
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
frames = SubResource( 4 )
animation = "spin"
-frame = 1
playing = true
centered = false
diff --git a/godot/goal/Goal.gd b/godot/goal/Goal.gd
new file mode 100644
index 0000000..f9aa6db
--- /dev/null
+++ b/godot/goal/Goal.gd
@@ -0,0 +1,5 @@
+extends Area2D
+
+
+func _process(_delta: float) -> void:
+ Event.emit_signal("report_object", self.get_name(), "not touched", global_position, Vector2())
diff --git a/godot/goal/Goal.tscn b/godot/goal/Goal.tscn
index ee70903..e2b005a 100644
--- a/godot/goal/Goal.tscn
+++ b/godot/goal/Goal.tscn
@@ -1,9 +1,10 @@
-[gd_scene load_steps=9 format=2]
+[gd_scene load_steps=10 format=2]
[ext_resource path="res://assets/flag.png" type="Texture" id=1]
[ext_resource path="res://goal/GoalNotReached.gdns" type="Script" id=2]
[ext_resource path="res://goal/GoalReached.gdns" type="Script" id=3]
[ext_resource path="res://state_machine/StateMachine.gdns" type="Script" id=4]
+[ext_resource path="res://goal/Goal.gd" type="Script" id=5]
[sub_resource type="RectangleShape2D" id=5]
extents = Vector2( 10, 18 )
@@ -25,15 +26,13 @@ animations = [ {
} ]
[node name="Goal" type="Area2D"]
-position = Vector2( 324, 378 )
collision_layer = 32
+script = ExtResource( 5 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
-position = Vector2( 18, 18 )
shape = SubResource( 5 )
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
-position = Vector2( 18, 18 )
frames = SubResource( 8 )
animation = "flagmove"
playing = true
diff --git a/godot/levels/TestLevel.tmx b/godot/levels/TestLevel.tmx
new file mode 100644
index 0000000..c15493b
--- /dev/null
+++ b/godot/levels/TestLevel.tmx
@@ -0,0 +1,112 @@
+
+
diff --git a/godot/levels/TestLevel.tmx.import b/godot/levels/TestLevel.tmx.import
new file mode 100644
index 0000000..83771b2
--- /dev/null
+++ b/godot/levels/TestLevel.tmx.import
@@ -0,0 +1,24 @@
+[remap]
+
+importer="vnen.tiled_importer"
+type="PackedScene"
+path="res://.import/TestLevel.tmx-6c18e110a6e6432fa76e1b0b7b8bc560.scn"
+
+[deps]
+
+source_file="res://levels/TestLevel.tmx"
+dest_files=[ "res://.import/TestLevel.tmx-6c18e110a6e6432fa76e1b0b7b8bc560.scn" ]
+
+[params]
+
+custom_properties=true
+tile_metadata=false
+uv_clip=true
+y_sort=true
+image_flags=7
+collision_layer=2
+collision_mask=0
+embed_internal_images=false
+save_tiled_properties=false
+add_background=true
+post_import_script=""
diff --git a/godot/levels/TestLevel.tscn b/godot/levels/TestLevel.tscn
new file mode 100644
index 0000000..3503d69
--- /dev/null
+++ b/godot/levels/TestLevel.tscn
@@ -0,0 +1,83 @@
+[gd_scene load_steps=10 format=2]
+
+[ext_resource path="res://characters/enemies/shelly/Shelly.tscn" type="PackedScene" id=1]
+[ext_resource path="res://collectables/coin/Coin.tscn" type="PackedScene" id=2]
+[ext_resource path="res://goal/Goal.tscn" type="PackedScene" id=3]
+[ext_resource path="res://hud/CoinHUD.tscn" type="PackedScene" id=4]
+[ext_resource path="res://characters/player/Player.tscn" type="PackedScene" id=5]
+[ext_resource path="res://assets/music/prototype_r.ogg" type="AudioStream" id=6]
+[ext_resource path="res://assets/backgrounds/hills.png" type="Texture" id=7]
+[ext_resource path="res://levels/TestLevel.tmx" type="PackedScene" id=8]
+[ext_resource path="res://CameraLimit.gdns" type="Script" id=9]
+
+[node name="TestLevel" type="Node2D"]
+
+[node name="Player" parent="." instance=ExtResource( 5 )]
+position = Vector2( 36, 498 )
+collision_layer = 5
+
+[node name="Camera2D" type="Camera2D" parent="Player"]
+current = true
+limit_left = 0
+limit_top = 0
+limit_right = 512
+limit_bottom = 288
+drag_margin_h_enabled = true
+drag_margin_v_enabled = true
+__meta__ = {
+"_edit_bone_": true
+}
+
+[node name="VisibilityNotifier2D" type="VisibilityNotifier2D" parent="Player/Camera2D"]
+rect = Rect2( 0, 0, 24, 24 )
+
+[node name="ParallaxBackground" type="ParallaxBackground" parent="."]
+
+[node name="ParallaxLayer" type="ParallaxLayer" parent="ParallaxBackground"]
+motion_scale = Vector2( 0.2, 0.1 )
+motion_offset = Vector2( 0, -288 )
+motion_mirroring = Vector2( 528, 0 )
+
+[node name="Sprite" type="Sprite" parent="ParallaxBackground/ParallaxLayer"]
+texture = ExtResource( 7 )
+centered = false
+
+[node name="Map" type="Node2D" parent="."]
+
+[node name="TestLevel" parent="Map" instance=ExtResource( 8 )]
+script = ExtResource( 9 )
+
+[node name="CoinHUD" parent="." instance=ExtResource( 4 )]
+
+[node name="Coins" type="Node" parent="."]
+
+[node name="Coin" parent="Coins" instance=ExtResource( 2 )]
+position = Vector2( 144, 504 )
+
+[node name="Coin5" parent="Coins" instance=ExtResource( 2 )]
+position = Vector2( 270, 468 )
+
+[node name="Coin7" parent="Coins" instance=ExtResource( 2 )]
+position = Vector2( 216, 504 )
+
+[node name="Coin8" parent="Coins" instance=ExtResource( 2 )]
+position = Vector2( 459, 468 )
+
+[node name="Coin9" parent="Coins" instance=ExtResource( 2 )]
+position = Vector2( 560, 468 )
+
+[node name="BGM" type="AudioStreamPlayer" parent="."]
+stream = ExtResource( 6 )
+volume_db = -25.0
+autoplay = true
+
+[node name="Goal" parent="." instance=ExtResource( 3 )]
+position = Vector2( 656, 504 )
+
+[node name="Enemies" type="Node" parent="."]
+
+[node name="Shelly" parent="Enemies" instance=ExtResource( 1 )]
+position = Vector2( 379, 510 )
+
+[node name="Shelly2" parent="Enemies" instance=ExtResource( 1 )]
+position = Vector2( 628, 510 )
diff --git a/obelisk/include/knowledge_base.h b/obelisk/include/knowledge_base.h
new file mode 100644
index 0000000..4930033
--- /dev/null
+++ b/obelisk/include/knowledge_base.h
@@ -0,0 +1,292 @@
+#ifndef OBELISK_KNOWLEDGE_BASE_H
+#define OBELISK_KNOWLEDGE_BASE_H
+
+#include "models/action.h"
+#include "models/entity.h"
+#include "models/fact.h"
+#include "models/rule.h"
+#include "models/suggest_action.h"
+#include "models/verb.h"
+
+#include
+
+#include
+#include
+#include
+#include
+
+namespace obelisk
+{
+ /**
+ * @brief The KnowledgeBase class represents a collection of facts, rules,
+ * actions, and related language connectors.
+ *
+ */
+ class KnowledgeBase
+ {
+ private:
+ /**
+ * @brief The filename of the opened KnowledgeBase.
+ *
+ */
+ const char* filename_;
+
+ /**
+ * @brief The SQLite connection handle.
+ *
+ */
+ sqlite3* dbConnection_ = nullptr;
+
+ /**
+ * @brief The user passed flags to use when opening the database.
+ *
+ */
+ int flags_;
+
+ /**
+ * @brief Enable foreign key functionality in the open database.
+ *
+ * This must always be done when the connection is opened or it will
+ * not enforce the foreign key constraints.
+ */
+ void enableForeignKeys();
+
+ /**
+ * @brief Create the tables in the database.
+ *
+ * @param[in] function This function is called to create the table.
+ */
+ void createTable(std::function function);
+
+ public:
+ /**
+ * @brief Construct a new KnowledgeBase object.
+ *
+ * @param[in] filename The name of the file to save the knowledge
+ * base as.
+ * @param[in] flags The flags to open the KnowledgeBase with.
+ */
+ KnowledgeBase(const char* filename, int flags);
+
+ /**
+ * @brief Construct a new KnowledgeBase object.
+ *
+ * @param[in] filename The name of the file to save the knowledge
+ * base as.
+ */
+ KnowledgeBase(const char* filename) :
+ KnowledgeBase(filename,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)
+ {
+ }
+
+ /**
+ * @brief Destroy the KnowledgeBase object.
+ *
+ * This will close the opened KnowledgeBase before destroying it.
+ */
+ ~KnowledgeBase();
+
+ /**
+ * @brief Add entities to the KnowledgeBase.
+ *
+ * @param[in,out] entities The entities to add. If the insert is
+ * successful it will have a row ID, if not the ID will be 0.
+ */
+ void addEntities(std::vector& entities);
+
+ /**
+ * @brief Add verbs to the KnowledgeBase.
+ *
+ * @param[in,out] verbs The verbs to add. If the insert is
+ * successful it will have a row ID, if not the ID will be 0.
+ */
+ void addVerbs(std::vector& verbs);
+
+ /**
+ * @brief Add actions to the KnowledgeBase.
+ *
+ * @param[in,out] actions The actions to add. If the insert is
+ * successful it will have a row ID, if nto the ID will be 0.
+ */
+ void addActions(std::vector& actions);
+
+ /**
+ * @brief Add facts to the KnowledgeBase.
+ *
+ * @param[in,out] facts The facts to add. If the insert is
+ * successful it will have a row ID, if not the ID will be 0.
+ */
+ void addFacts(std::vector& facts);
+
+ /**
+ * @brief Add suggested actions to the KnowledgeBase.
+ *
+ * @param[in,out] suggestActions The suggested actions to add. If
+ * the insert is successful it will have a row ID, if not the ID
+ * will be 0.
+ */
+ void addSuggestActions(
+ std::vector& suggestActions);
+
+ /**
+ * @brief Add rules to the KnowledgeBase.
+ *
+ * @param[in,out] rules The rules to add. If the insert is
+ * successful it will have a row ID, if not the ID will be 0.
+ */
+ void addRules(std::vector& rules);
+
+ /**
+ * @brief Get an Entity object based on the ID it contains.
+ *
+ * @param[in,out] entity The Entity object should contain just the
+ * ID and the rest will be filled in.
+ */
+ void getEntity(obelisk::Entity& entity);
+
+ /**
+ * @brief Get a Verb object based on the ID it contains.
+ *
+ * @param[in,out] verb The Verb object should contain just the ID
+ * and the rest will be filled in.
+ */
+ void getVerb(obelisk::Verb& verb);
+
+ /**
+ * @brief Get an Action based on the ID it contains.
+ *
+ * @param[in] action The Action object should contain just the ID
+ * and the rest will be filled in.
+ */
+ void getAction(obelisk::Action& action);
+
+ /**
+ * @brief Get a Fact object based on the ID it contains.
+ *
+ * @param[in,out] fact The Fact object should contain just the ID
+ * and the rest will be filled in.
+ */
+ void getFact(obelisk::Fact& fact);
+
+ /**
+ * @brief Get a SuggestAction based on the ID it contains.
+ *
+ * @param[in,out] suggestAction The SuggestAction object should
+ * contain just the ID and the rest will be filled in.
+ */
+ void getSuggestAction(obelisk::SuggestAction& suggestAction);
+
+ /**
+ * @brief Get a Rule based on the ID it contains.
+ *
+ * @param[in,out] rule The Rule object should contain just the ID
+ * and the rest will be filled in.
+ */
+ void getRule(obelisk::Rule& rule);
+
+ /**
+ * @brief Check if a rule looks for this Fact, if so update its
+ * truth.
+ *
+ * @param[in,out] fact The Fact to check for existing rules.
+ */
+ void checkRule(obelisk::Fact& fact);
+
+ /**
+ * @brief Update the is true field in the KnowledgeBase.
+ *
+ * @param[in,out] fact The fact to update.
+ */
+ void updateIsTrue(obelisk::Fact& fact);
+
+ /**
+ * @brief Query the KnowledgeBase to see if a Fact is true or false.
+ *
+ * @param[in] fact The Fact to check.
+ */
+ void queryFact(obelisk::Fact& fact);
+
+ /**
+ * @brief Query the KnowledgeBase to get a suggested action based
+ * on a Fact.
+ * If a SuggestAction doesn't exist, it will return an empty Action.
+ *
+ * @param[in] fact The Fact to search for.
+ * @param[out] action The Action that is suggested to take.
+ */
+ void querySuggestAction(obelisk::Fact& fact,
+ obelisk::Action& action);
+
+ /**
+ * @brief Take a float and divide it into 2 floats.
+ *
+ * This is useful to store doubles in SQLite since SQLite doesn't
+ * have a double type. Instead just store the 2 floats in the
+ * database. Then after selecting them combine them.
+ *
+ * @param[out] result1 The first float generated from the double.
+ * @param[out] result2 The second float generated from the double.
+ * @param[in] var The double to split into the 2 floats.
+ */
+ void getFloat(float& result1, float& result2, double var);
+
+ /**
+ * @brief Combines 2 separated floats back into a double.
+ *
+ * This will recombine the separated floats from the getFloat
+ * method.
+ *
+ * @param[out] result The double generated from the combined floats.
+ * @param[in] var1 The first float to combine.
+ * @param[in] var2 The second float to combine.
+ */
+ void getDouble(double& result, float var1, float var2);
+ };
+
+ /**
+ * @brief Exception thrown by the KnowledgeBase.
+ *
+ */
+ class KnowledgeBaseException : public std::exception
+ {
+ private:
+ /**
+ * @brief The error message given.
+ *
+ */
+ const std::string errorMessage_;
+
+ public:
+ /**
+ * @brief Construct a new KnowledgeBaseException object.
+ *
+ */
+ KnowledgeBaseException() :
+ errorMessage_("an unknown error ocurred")
+ {
+ }
+
+ /**
+ * @brief Construct a new KnowledgeBaseException object.
+ *
+ * @param[in] errorMessage The error message given when thrown.
+ */
+ KnowledgeBaseException(const std::string& errorMessage) :
+ errorMessage_(errorMessage)
+ {
+ }
+
+ /**
+ * @brief Get the error message that occurred.
+ *
+ * @return const char* Returns the error message.
+ */
+ const char* what() const noexcept
+ {
+ return errorMessage_.c_str();
+ }
+ };
+} // namespace obelisk
+
+#endif
diff --git a/obelisk/include/models/action.h b/obelisk/include/models/action.h
new file mode 100644
index 0000000..2d06c03
--- /dev/null
+++ b/obelisk/include/models/action.h
@@ -0,0 +1,128 @@
+#ifndef OBELISK_MODELS_ACTION_H
+#define OBELISK_MODELS_ACTION_H
+
+#include
+
+#include
+
+namespace obelisk
+{
+ /**
+ * @brief The Action model represents an action to take when a fact is true
+ * or false.
+ *
+ */
+ class Action
+ {
+ private:
+ /**
+ * @brief The ID of the Action in the KnowledgeBase.
+ *
+ */
+ int id_;
+
+ /**
+ * @brief The name of the Action.
+ *
+ */
+ std::string name_;
+
+ public:
+ /**
+ * @brief Construct a new Action object.
+ *
+ */
+ Action() :
+ id_(0),
+ name_("")
+ {
+ }
+
+ /**
+ * @brief Construct a new Action object.
+ *
+ * @param[in] id The ID of the Action.
+ */
+ Action(int id) :
+ id_(id),
+ name_("")
+ {
+ }
+
+ /**
+ * @brief Construct a new Action object.
+ *
+ * @param[in] name The name of the Action.
+ */
+ Action(std::string name) :
+ id_(0),
+ name_(name)
+ {
+ }
+
+ /**
+ * @brief Construct a new Action object.
+ *
+ * @param[in] id The ID of the Action.
+ * @param[in] name The name of the Action.
+ */
+ Action(int id, std::string name) :
+ id_(id),
+ name_(name)
+ {
+ }
+
+ /**
+ * @brief Create the Action table in the KnowledgeBase.
+ *
+ * @return const char* Returns the query used to create the table.
+ */
+ static const char* createTable();
+
+ /**
+ * @brief Get the ID of the Action.
+ *
+ * @return int& Returns the ID.
+ */
+ int& getId();
+
+ /**
+ * @brief Set the ID of the Action.
+ *
+ * @param[in] id Set the ID of the Action.
+ */
+ void setId(int id);
+
+ /**
+ * @brief Get the name of the Action.
+ *
+ * @return std::string& The Action name.
+ */
+ std::string& getName();
+
+ /**
+ * @brief Set the name of the Action.
+ *
+ * @param[in] name The name of the Action.
+ */
+ void setName(std::string name);
+
+ /**
+ * @brief Select an Action from the datbase based on the object
+ * name.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void selectByName(sqlite3* dbConnection);
+
+ /**
+ * @brief Insert an Action into the KnowledgeBase based on the
+ * object's fields.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void insert(sqlite3* dbConnection);
+ };
+} // namespace obelisk
+
+#endif
diff --git a/obelisk/include/models/entity.h b/obelisk/include/models/entity.h
new file mode 100644
index 0000000..0241575
--- /dev/null
+++ b/obelisk/include/models/entity.h
@@ -0,0 +1,128 @@
+#ifndef OBELISK_MODELS_ENTITY_H
+#define OBELISK_MODELS_ENTITY_H
+
+#include
+
+#include
+
+namespace obelisk
+{
+ /**
+ * @brief The Entity model represents either a left or right side entity,
+ * typically used in facts and rules.
+ *
+ */
+ class Entity
+ {
+ private:
+ /**
+ * @brief The ID of the Entity in the KnowledgeBase.
+ *
+ */
+ int id_;
+
+ /**
+ * @brief The name of the Entity.
+ *
+ */
+ std::string name_;
+
+ public:
+ /**
+ * @brief Construct a new Entity object.
+ *
+ */
+ Entity() :
+ id_(0),
+ name_("")
+ {
+ }
+
+ /**
+ * @brief Construct a new Entity object.
+ *
+ * @param[in] id The ID of the Entity.
+ */
+ Entity(int id) :
+ id_(id),
+ name_("")
+ {
+ }
+
+ /**
+ * @brief Construct a new Entity object.
+ *
+ * @param[in] name The name of the Entity.
+ */
+ Entity(std::string name) :
+ id_(0),
+ name_(name)
+ {
+ }
+
+ /**
+ * @brief Construct a new Entity object.
+ *
+ * @param[in] id The ID of the Entity.
+ * @param[in] name The name of the Entity.
+ */
+ Entity(int id, std::string name) :
+ id_(id),
+ name_(name)
+ {
+ }
+
+ /**
+ * @brief Create the table in the KnowledgeBase.
+ *
+ * @return const char* Returns the query used to create the table.
+ */
+ static const char* createTable();
+
+ /**
+ * @brief Get the ID of the Entity.
+ *
+ * @return int& Returns the ID.
+ */
+ int& getId();
+
+ /**
+ * @brief Set the ID of the Entity.
+ *
+ * @param[in] id The ID of the Entity.
+ */
+ void setId(int id);
+
+ /**
+ * @brief Get the name of the Entity.
+ *
+ * @return std::string& The name of the Entity.
+ */
+ std::string& getName();
+
+ /**
+ * @brief Set the name of the Entity.
+ *
+ * @param[in] name The name of the Entity.
+ */
+ void setName(std::string name);
+
+ /**
+ * @brief Select an Entity from the KnowledgeBase based on the
+ * object's name.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void selectByName(sqlite3* dbConnection);
+
+ /**
+ * @brief Insert an Entity into the KnowledgeBase based on the
+ * object's fields.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void insert(sqlite3* dbConnection);
+ };
+} // namespace obelisk
+
+#endif
diff --git a/obelisk/include/models/fact.h b/obelisk/include/models/fact.h
new file mode 100644
index 0000000..21810b2
--- /dev/null
+++ b/obelisk/include/models/fact.h
@@ -0,0 +1,247 @@
+#ifndef OBELISK_MODELS_FACT_H
+#define OBELISK_MODELS_FACT_H
+
+#include "models/action.h"
+#include "models/entity.h"
+#include "models/fact.h"
+#include "models/verb.h"
+
+#include
+
+namespace obelisk
+{
+ /**
+ * @brief The Fact model represents truth in the releationship between two
+ * entities separated by a verb.
+ *
+ */
+ class Fact
+ {
+ private:
+ /**
+ * @brief The ID of the Fact in the KnowledgeBase.
+ *
+ */
+ int id_;
+
+ /**
+ * @brief The Entity from the left side of the expression.
+ *
+ */
+ obelisk::Entity leftEntity_;
+
+ /**
+ * @brief The Entity from the right side of the expression.
+ *
+ */
+ obelisk::Entity rightEntity_;
+
+ /**
+ * @brief The Verb that represents the relationship in the
+ * expression.
+ *
+ */
+ obelisk::Verb verb_;
+
+ /**
+ * @brief Whether or not the fact is considered true or not.
+ *
+ */
+ double isTrue_;
+
+ public:
+ /**
+ * @brief Construct a new Fact object.
+ *
+ */
+ Fact() :
+ id_(0),
+ leftEntity_(),
+ rightEntity_(),
+ verb_(),
+ isTrue_(0)
+ {
+ }
+
+ /**
+ * @brief Construct a new Fact object.
+ *
+ * @param[in] id The ID of the Fact in the KnowledgeBase.
+ */
+ Fact(int id) :
+ id_(id),
+ leftEntity_(),
+ rightEntity_(),
+ verb_(),
+ isTrue_(0)
+ {
+ }
+
+ /**
+ * @brief Construct a new Fact object.
+ *
+ * @param[in] leftEntity The Entity on the left side of the
+ * expression.
+ * @param[in] rightEntity The Entity on the right side of the
+ * expression.
+ * @param[in] verb The Verb separating the entities.
+ * @param[in] isTrue Whether or not the fact is true.
+ */
+ Fact(obelisk::Entity leftEntity,
+ obelisk::Entity rightEntity,
+ obelisk::Verb verb,
+ double isTrue = 0) :
+ id_(0),
+ leftEntity_(leftEntity),
+ rightEntity_(rightEntity),
+ verb_(verb),
+ isTrue_(isTrue)
+ {
+ }
+
+ /**
+ * @brief Construct a new Fact object.
+ *
+ * @param[in] id The ID of the Fact in the KnowledgeBase.
+ * @param[in] leftEntity The Entity on the left side of the
+ * expression.
+ * @param[in] rightEntity The Entity on the right side of the
+ * expression.
+ * @param[in] verb The Verb separating the entities.
+ * @param[in] isTrue Whether or not the fact is true.
+ */
+ Fact(int id,
+ obelisk::Entity leftEntity,
+ obelisk::Entity rightEntity,
+ obelisk::Verb verb,
+ double isTrue = 0) :
+ id_(id),
+ leftEntity_(leftEntity),
+ rightEntity_(rightEntity),
+ verb_(verb),
+ isTrue_(isTrue)
+ {
+ }
+
+ /**
+ * @brief Create the Fact table in the KnowledgeBase.
+ *
+ * @return const char* Returns the query used to create the table.
+ */
+ static const char* createTable();
+
+ /**
+ * @brief Get the ID of the Fact
+ *
+ * @return int& Returns the ID.
+ */
+ int& getId();
+
+ /**
+ * @brief Set the ID of the Fact.
+ *
+ * @param[in] id Set the ID of the Fact.
+ */
+ void setId(int id);
+
+ /**
+ * @brief Get the left Entity object.
+ *
+ * @return Entity& The left Entity.
+ */
+ Entity& getLeftEntity();
+
+ /**
+ * @brief Set the left Entity object.
+ *
+ * @param[in] leftEntity The left Entity to set.
+ */
+ void setLeftEntity(obelisk::Entity leftEntity);
+
+ /**
+ * @brief Get the right Entity object.
+ *
+ * @return Entity& The right Entity.
+ */
+ Entity& getRightEntity();
+
+ /**
+ * @brief Set the right Entity object.
+ *
+ * @param[in] rightEntity The right Entity to set.
+ */
+ void setRightEntity(obelisk::Entity rightEntity);
+
+ /**
+ * @brief Get the Verb object.
+ *
+ * @return Verb& The Verb.
+ */
+ Verb& getVerb();
+
+ /**
+ * @brief Set the Verb object.
+ *
+ * @param[in] verb The Verb.
+ */
+ void setVerb(obelisk::Verb verb);
+
+ /**
+ * @brief Gets the isTrue value.
+ *
+ * @return true If the Fact is considered true.
+ * @return false If the Fact is considered false.
+ */
+ double& getIsTrue();
+
+ /**
+ * @brief Set the Fact as true or false.
+ *
+ * @param[in] isTrue Whether or not the Fact is true.
+ */
+ void setIsTrue(double isTrue);
+
+ /**
+ * @brief Select the Fact from the KnowledgeBase by IDs of the
+ * sub-objects.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void selectById(sqlite3* dbConnection);
+
+ /**
+ * @brief Select the Fact from the KnowledgeBase by the name's of
+ * the entities and verb.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void selectByName(sqlite3* dbConnection);
+
+ /**
+ * @brief Select an Action from the KnowledgeBase using the provided
+ * Fact.
+ *
+ * @param[in] dbConnection The database connection to use.
+ * @param[out] action The Action to take based on the provided fact.
+ */
+ void selectActionByFact(sqlite3* dbConnection,
+ obelisk::Action& action);
+
+ /**
+ * @brief Insert the Fact into the KnowledgeBase.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void insert(sqlite3* dbConnection);
+
+ /**
+ * @brief Update whether or not the fact is true in the
+ * KnowledgeBase.
+ *
+ * @param[in] dbConnection The database connection.
+ */
+ void updateIsTrue(sqlite3* dbConnection);
+ };
+} // namespace obelisk
+
+#endif
diff --git a/obelisk/include/models/rule.h b/obelisk/include/models/rule.h
new file mode 100644
index 0000000..efbdced
--- /dev/null
+++ b/obelisk/include/models/rule.h
@@ -0,0 +1,163 @@
+#ifndef OBELISK_MODELS_RULE_H
+#define OBELISK_MODELS_RULE_H
+
+#include "models/fact.h"
+
+#include
+#include
+
+namespace obelisk
+{
+ /**
+ * @brief The Rule model represents a truth relation between 2 Facts.
+ *
+ */
+ class Rule
+ {
+ private:
+ /**
+ * @brief The ID of the Rule in the KnowledgeBase.
+ *
+ */
+ int id_;
+
+ /**
+ * @brief The Fact that depends on the Fact reason being true.
+ *
+ */
+ obelisk::Fact fact_;
+
+ /**
+ * @brief The Fact that makes the other Fact true or false.
+ *
+ */
+ obelisk::Fact reason_;
+
+ public:
+ /**
+ * @brief Construct a new Rule object.
+ *
+ */
+ Rule() :
+ id_(0),
+ fact_(),
+ reason_()
+ {
+ }
+
+ /**
+ * @brief Construct a new Rule object.
+ *
+ * @param[in] id The ID of the Rule in the KnowledgeBase.
+ */
+ Rule(int id) :
+ id_(id),
+ fact_(),
+ reason_()
+ {
+ }
+
+ /**
+ * @brief Construct a new Rule object.
+ *
+ * @param[in] fact The Fact.
+ * @param[in] reason The reason Fact.
+ */
+ Rule(obelisk::Fact fact, obelisk::Fact reason) :
+ id_(0),
+ fact_(fact),
+ reason_(reason)
+ {
+ }
+
+ /**
+ * @brief Construct a new Rule object.
+ *
+ * @param[in] id The ID of the Rule.
+ * @param[in] fact The Fact.
+ * @param[in] reason The reason Fact.
+ */
+ Rule(int id, obelisk::Fact fact, obelisk::Fact reason) :
+ id_(id),
+ fact_(fact),
+ reason_(reason)
+ {
+ }
+
+ /**
+ * @brief Create the Rule table in the KnowledgeBase.
+ *
+ * @return const char* Returns the query used to create the table.
+ */
+ static const char* createTable();
+
+ /**
+ * @brief Get the ID of the Rule.
+ *
+ * @return int& The ID.
+ */
+ int& getId();
+
+ /**
+ * @brief Set the ID of the Rule.
+ *
+ * @param[in] id The ID.
+ */
+ void setId(int id);
+
+ /**
+ * @brief Get the Fact object.
+ *
+ * @return obelisk::Fact& The Fact.
+ */
+ obelisk::Fact& getFact();
+
+ /**
+ * @brief Set the Fact object.
+ *
+ * @param[in] fact The Fact.
+ */
+ void setFact(obelisk::Fact fact);
+
+ /**
+ * @brief Get the reason Fact object.
+ *
+ * @return obelisk::Fact& The reason Fact.
+ */
+ obelisk::Fact& getReason();
+
+ /**
+ * @brief Set the reason Fact object.
+ *
+ * @param[in] reason The reason Fact.
+ */
+ void setReason(obelisk::Fact reason);
+
+ /**
+ * @brief Select the Rule from the KnowledgeBase by IDs of the
+ * sub-objects.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void selectById(sqlite3* dbConnection);
+
+ /**
+ * @brief Get the rules that match the reason.
+ *
+ * @param[in] dbConnection The database connection to use.
+ * @param[out] rules The rules to fill in from the database.
+ */
+ static void selectByReason(sqlite3* dbConnection,
+ int reasonId,
+ std::vector& rules);
+
+ /**
+ * @brief Insert the Rule into the KnowledgeBase.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void insert(sqlite3* dbConnection);
+ };
+} // namespace obelisk
+
+#endif
diff --git a/obelisk/include/models/suggest_action.h b/obelisk/include/models/suggest_action.h
new file mode 100644
index 0000000..16d123e
--- /dev/null
+++ b/obelisk/include/models/suggest_action.h
@@ -0,0 +1,185 @@
+#ifndef OBELISK_MODELS_SUGGEST_ACTION_H
+#define OBELISK_MODELS_SUGGEST_ACTION_H
+
+#include "models/action.h"
+#include "models/fact.h"
+
+#include
+
+namespace obelisk
+{
+ /**
+ * @brief The SuggestAction model representas the actions to take depending
+ * on if the Fact is true or false.
+ *
+ */
+ class SuggestAction
+ {
+ private:
+ /**
+ * @brief The ID of the SuggestAction.
+ *
+ */
+ int id_;
+
+ /**
+ * @brief The Fact to check the truth of.
+ *
+ */
+ obelisk::Fact fact_;
+
+ /**
+ * @brief The Action to take if the Fact is true.
+ *
+ */
+ obelisk::Action trueAction_;
+
+ /**
+ * @brief The Action to take if the Fact is false.
+ *
+ */
+ obelisk::Action falseAction_;
+
+ public:
+ /**
+ * @brief Construct a new SuggestAction object.
+ *
+ */
+ SuggestAction() :
+ id_(0),
+ fact_(),
+ trueAction_(),
+ falseAction_()
+ {
+ }
+
+ /**
+ * @brief Construct a new SuggestAction object.
+ *
+ * @param[in] id The ID of the SuggestAction in the KnowledgeBase.
+ */
+ SuggestAction(int id) :
+ id_(id),
+ fact_(),
+ trueAction_(),
+ falseAction_()
+ {
+ }
+
+ /**
+ * @brief Construct a new SuggestAction object.
+ *
+ * @param[in] fact The Fact.
+ * @param[in] trueAction The true Action.
+ * @param[in] falseAction The false Action.
+ */
+ SuggestAction(obelisk::Fact fact,
+ obelisk::Action trueAction,
+ obelisk::Action falseAction) :
+ id_(0),
+ fact_(fact),
+ trueAction_(trueAction),
+ falseAction_(falseAction)
+ {
+ }
+
+ /**
+ * @brief Construct a new SuggestAction object.
+ *
+ * @param[in] id The ID of the SuggestAction in the KnowledgeBase.
+ * @param[in] fact The Fact.
+ * @param[in] trueAction The true Action.
+ * @param[in] falseAction The false Action.
+ */
+ SuggestAction(int id,
+ obelisk::Fact fact,
+ obelisk::Action trueAction,
+ obelisk::Action falseAction) :
+ id_(id),
+ fact_(fact),
+ trueAction_(trueAction),
+ falseAction_(falseAction)
+ {
+ }
+
+ /**
+ * @brief Create the SuggestAction table in the database.
+ *
+ * @return const char* Returns the query used to create the table.
+ */
+ static const char* createTable();
+
+ /**
+ * @brief Get the ID of the SuggestAction.
+ *
+ * @return int& Returns the ID.
+ */
+ int& getId();
+
+ /**
+ * @brief Set the ID of the SuggestAction.
+ *
+ * @param[in] id The new ID.
+ */
+ void setId(int id);
+
+ /**
+ * @brief Get the Fact object.
+ *
+ * @return obelisk::Fact& Returns the Fact.
+ */
+ obelisk::Fact& getFact();
+
+ /**
+ * @brief Set the Fact object.
+ *
+ * @param[in] fact The new Fact.
+ */
+ void setFact(obelisk::Fact fact);
+
+ /**
+ * @brief Get the true Action object.
+ *
+ * @return obelisk::Action& Returns the true Action.
+ */
+ obelisk::Action& getTrueAction();
+
+ /**
+ * @brief Set the true Action object.
+ *
+ * @param[in] trueAction The new true Action.
+ */
+ void setTrueAction(obelisk::Action trueAction);
+
+ /**
+ * @brief Get the false Action object.
+ *
+ * @return obelisk::Action& Returns the false Action.
+ */
+ obelisk::Action& getFalseAction();
+
+ /**
+ * @brief Set the false Action object.
+ *
+ * @param[in] falseAction The new false Action.
+ */
+ void setFalseAction(obelisk::Action falseAction);
+
+ /**
+ * @brief Select the SuggestAction from the KnowledgeBase by IDs of
+ * the sub-objects.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void selectById(sqlite3* dbConnection);
+
+ /**
+ * @brief Insert the SuggestAction into the KnowledgeBase.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void insert(sqlite3* dbConnection);
+ };
+} // namespace obelisk
+
+#endif
diff --git a/obelisk/include/models/verb.h b/obelisk/include/models/verb.h
new file mode 100644
index 0000000..150e86f
--- /dev/null
+++ b/obelisk/include/models/verb.h
@@ -0,0 +1,126 @@
+#ifndef OBELISK_MODELS_VERB_H
+#define OBELISK_MODELS_VERB_H
+
+#include
+
+#include
+
+namespace obelisk
+{
+ /**
+ * @brief The Verb model represents a verb which is used to connnect
+ * entities.
+ *
+ */
+ class Verb
+ {
+ private:
+ /**
+ * @brief The ID of the Verb in the KnowledgeBase.
+ *
+ */
+ int id_;
+
+ /**
+ * @brief The name of the Verb.
+ *
+ */
+ std::string name_;
+
+ public:
+ /**
+ * @brief Construct a new Verb object.
+ *
+ */
+ Verb() :
+ id_(0),
+ name_("")
+ {
+ }
+
+ /**
+ * @brief Construct a new Verb object.
+ *
+ * @param[in] id The ID of the Verb.
+ */
+ Verb(int id) :
+ id_(id),
+ name_("")
+ {
+ }
+
+ /**
+ * @brief Construct a new Verb object.
+ *
+ * @param[in] name The name of the Verb.
+ */
+ Verb(std::string name) :
+ id_(0),
+ name_(name)
+ {
+ }
+
+ /**
+ * @brief Construct a new Verb object.
+ *
+ * @param[in] id The ID of the Verb.
+ * @param[in] name The name of the Verb.
+ */
+ Verb(int id, std::string name) :
+ id_(id),
+ name_(name)
+ {
+ }
+
+ /**
+ * @brief Create the Verb table in the KnowledgeBase.
+ *
+ * @return const char* Returns the query used to create the table.
+ */
+ static const char* createTable();
+
+ /**
+ * @brief Get the ID of the Verb.
+ *
+ * @return int& Returns the ID.
+ */
+ int& getId();
+
+ /**
+ * @brief Set the ID of the Verb.
+ *
+ * @param[in] id Set the ID of the Verb.
+ */
+ void setId(int id);
+
+ /**
+ * @brief Get the name of the Verb.
+ *
+ * @return std::string& The Verb name.
+ */
+ std::string& getName();
+
+ /**
+ * @brief Set the name of the Verb.
+ *
+ * @param[in] name The Verb name.
+ */
+ void setName(std::string name);
+
+ /**
+ * @brief Select a verb by name from the KnowledgeBase.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void selectByName(sqlite3* dbConnection);
+
+ /**
+ * @brief Insert a new verb into the KnowledgeBase.
+ *
+ * @param[in] dbConnection The database connection to use.
+ */
+ void insert(sqlite3* dbConnection);
+ };
+} // namespace obelisk
+
+#endif
diff --git a/obelisk/include/obelisk.h b/obelisk/include/obelisk.h
new file mode 100644
index 0000000..1e434bc
--- /dev/null
+++ b/obelisk/include/obelisk.h
@@ -0,0 +1,82 @@
+#ifndef OBELISK_INCLUDE_OBELISK_H
+#define OBELISK_INCLUDE_OBELISK_H
+
+#include "knowledge_base.h"
+
+#include
+#include
+
+/**
+ * @brief The obelisk namespace contains everything needed to compile obelisk
+ * code.
+ *
+ */
+namespace obelisk
+{
+ /**
+ * @brief The obelisk library provides everything needed to consult the
+ * KnowledgeBase.
+ *
+ */
+ class Obelisk
+ {
+ private:
+ std::unique_ptr kb_;
+
+ public:
+ /**
+ * @brief Construct a new Obelisk object.
+ *
+ */
+ Obelisk(std::string filename);
+
+ /**
+ * @brief Destroy the Obelisk object.
+ *
+ */
+ ~Obelisk() = default;
+
+ /**
+ * @brief Get the obelisk version.
+ *
+ * @return std::string The version.
+ */
+ std::string getVersion();
+
+ /**
+ * @brief Get the obelisk library so version.
+ *
+ * @return int The version.
+ */
+ int getLibVersion();
+
+ /**
+ * @brief Query the obelisk KnowledgeBase to see if a Fact is true
+ * or not.
+ *
+ * @param[in] p_obelisk The obelisk object pointer.
+ * @param[in] left_entity The left entity.
+ * @param[in] verb The verb.
+ * @param[in] right_entity The right entity.
+ * @return double Returns whether or not the Fact is true.
+ */
+ double query(const std::string& leftEntity,
+ const std::string& verb,
+ const std::string& rightEntity);
+
+ /**
+ * @brief Query the Obelisk KnowledgeBase and return the suggested
+ * action to take.
+ *
+ * @param[in] leftEntity The left entity.
+ * @param[in] verb The verb.
+ * @param[in] rightEntity The right entity.
+ * @return std::string Returns the suggested action.
+ */
+ std::string queryAction(const std::string& leftEntity,
+ const std::string& verb,
+ const std::string& rightEntity);
+ };
+} // namespace obelisk
+
+#endif
diff --git a/src/Event.cpp b/src/Event.cpp
index cd762b0..26b0efc 100644
--- a/src/Event.cpp
+++ b/src/Event.cpp
@@ -12,6 +12,7 @@ void alai::Event::_register_methods()
godot::register_signal("player_died");
godot::register_signal("player_won");
godot::register_signal("player_touched", "damage", GODOT_VARIANT_TYPE_INT);
+ godot::register_signal("report_object", "name", GODOT_VARIANT_TYPE_STRING, "state", GODOT_VARIANT_TYPE_STRING, "position", GODOT_VARIANT_TYPE_VECTOR2, "velocity", GODOT_VARIANT_TYPE_VECTOR2);
}
alai::Event::Event()
diff --git a/src/Main.cpp b/src/Main.cpp
index f6f1341..0059a96 100644
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -1,5 +1,6 @@
#include "Event.h"
#include "Main.h"
+#include "obelisk.h"
#include
@@ -39,6 +40,10 @@ void alai::Main::_init()
void alai::Main::_ready()
{
+ auto obelisk = std::unique_ptr {new obelisk::Obelisk("alai.kb")};
+ godot::Godot::print("Obelisk version: " + godot::String(obelisk->getVersion().c_str()));
+ godot::Godot::print("Obelisk library version: " + godot::String(std::to_string(obelisk->getLibVersion()).c_str()));
+
auto success = _project_settings->load_resource_pack("monitor.pck");
if (success)
{
diff --git a/src/godot.cpp b/src/godot.cpp
index d0835f3..8e07724 100644
--- a/src/godot.cpp
+++ b/src/godot.cpp
@@ -8,6 +8,7 @@
#include "goal/GoalReached.h"
#include "gui/game_over/GameOverScreen.h"
#include "gui/game_won/GameWonScreen.h"
+#include "player/AI.h"
#include "player/Player.h"
#include "player/states/PlayerFall.h"
#include "player/states/PlayerIdle.h"
@@ -20,7 +21,7 @@
/**
* @brief This function connects the gdnative init function.
- *
+ *
*/
extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o)
{
@@ -29,7 +30,7 @@ extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o)
/**
* @brief This function connects the gdnative terminate function.
- *
+ *
*/
extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o)
{
@@ -41,7 +42,7 @@ extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_opt
/**
* @brief This function connects the init methods in the classes to godot's gdnative.
- *
+ *
*/
extern "C" void GDN_EXPORT godot_nativescript_init(void *handle)
{
@@ -53,6 +54,7 @@ extern "C" void GDN_EXPORT godot_nativescript_init(void *handle)
godot::register_class();
godot::register_class();
godot::register_class();
+ godot::register_class();
godot::register_class();
godot::register_class();
godot::register_class();
diff --git a/src/gui/game_over/GameOverScreen.cpp b/src/gui/game_over/GameOverScreen.cpp
index 667bb2c..92499f9 100644
--- a/src/gui/game_over/GameOverScreen.cpp
+++ b/src/gui/game_over/GameOverScreen.cpp
@@ -38,9 +38,9 @@ void alai::GameOverScreen::_ready()
void alai::GameOverScreen::_on_restart_button_pressed()
{
- if (_resource_loader->exists("res://levels/PrototypeR.tscn"))
+ if (_resource_loader->exists("res://levels/TestLevel.tscn"))
{
- godot::Ref level_scene = _resource_loader->load("res://levels/PrototypeR.tscn");
+ godot::Ref level_scene = _resource_loader->load("res://levels/TestLevel.tscn");
auto level = level_scene->instance();
auto level_node = get_tree()->get_root()->get_node("Main")->find_node("Level");
diff --git a/src/player/AI.cpp b/src/player/AI.cpp
new file mode 100644
index 0000000..d667bf0
--- /dev/null
+++ b/src/player/AI.cpp
@@ -0,0 +1,104 @@
+#include "player/AI.h"
+
+void alai::player::AI::_register_methods()
+{
+ godot::register_method("_ready", &AI::_ready);
+ godot::register_method("_physics_process", &AI::_physics_process);
+ godot::register_method("_on_object_report", &AI::_on_object_report);
+}
+
+alai::player::AI::AI()
+{
+}
+
+alai::player::AI::~AI()
+{
+}
+
+void alai::player::AI::_init()
+{
+ _input = godot::Input::get_singleton();
+ obelisk = std::unique_ptr {new obelisk::Obelisk("alai.kb")};
+}
+
+void alai::player::AI::_ready()
+{
+ parent = Object::cast_to(get_parent());
+
+ event = get_node("/root/Event");
+ event->connect("report_object", this, "_on_object_report");
+}
+
+void alai::player::AI::_physics_process(float delta)
+{
+ while (!entities.empty())
+ {
+ const auto& entity = entities.front();
+
+ if (obelisk->query(entity.name.utf8().get_data(), "is", "touchable") > 0)
+ {
+ auto player_position = parent->get_global_position();
+ if (entity.position.x > player_position.x)
+ {
+ _input->action_press("right");
+ }
+ else
+ {
+ _input->action_press("left");
+ }
+ }
+
+ if (obelisk->query(entity.name.utf8().get_data(), "is", "bouncable") > 0)
+ {
+ auto player_position = parent->get_global_position();
+ auto distance = sqrt(pow(player_position.x - entity.position.x, 2) + pow(player_position.y - entity.position.y, 2));
+ int jump_distance = 0;
+
+ auto player_direction = parent->get_velocity();
+
+ auto action = obelisk->queryAction(entity.name.utf8().get_data(), "is", "bouncable");
+ if (action == "jump on")
+ {
+ jump_distance = 100;
+ }
+ else if (action == "jump over")
+ {
+ jump_distance = 50;
+ }
+
+ if (distance < jump_distance)
+ {
+ if (_input->is_action_pressed("right") && player_position.x < entity.position.x)
+ {
+ _input->action_press("jump");
+ }
+ else if (_input->is_action_pressed("left") && player_position.x > entity.position.x)
+ {
+ _input->action_press("jump");
+ }
+ }
+ }
+
+ if (obelisk->query(entity.name.utf8().get_data(), "is", "gold") > 0 && obelisk->query(std::string("gold ") + entity.name.utf8().get_data(), "is", "collectable") > 0)
+ {
+ auto player_position = parent->get_global_position();
+ float distance = player_position.x - entity.position.x;
+ if (distance > -10 && distance < 10 && player_position.y - entity.position.y > 20)
+ {
+ _input->action_press("jump");
+ }
+ }
+
+ entities.pop();
+ }
+}
+
+void alai::player::AI::_on_object_report(godot::String name, godot::String state, godot::Vector2 position, godot::Vector2 velocity)
+{
+ auto entity = Entity();
+ entity.name = name.to_lower().rstrip("0123456789");
+ entity.state = state;
+ entity.position = position;
+ entity.velocity = velocity;
+ entities.push(entity);
+}
diff --git a/src/player/AI.h b/src/player/AI.h
new file mode 100644
index 0000000..e3ae57d
--- /dev/null
+++ b/src/player/AI.h
@@ -0,0 +1,88 @@
+#ifndef ALAI_PLAYER_AI_H
+#define ALAI_PLAYER_AI_H
+
+#include "Event.h"
+#include "obelisk.h"
+#include "player/Player.h"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace alai
+{
+ namespace player
+ {
+ class Entity
+ {
+ public:
+ godot::String name;
+ godot::String state;
+ godot::Vector2 position;
+ godot::Vector2 velocity;
+ };
+
+ class AI : public godot::Node
+ {
+ GODOT_CLASS(AI, godot::Node)
+
+ private:
+ /**
+ * @brief Input singleton.
+ *
+ */
+ godot::Input* _input;
+
+ /**
+ * @brief The obelisk object.
+ *
+ */
+ std::unique_ptr obelisk;
+
+ alai::Event* event;
+
+ std::queue entities;
+
+ alai::player::Player* parent;
+
+ public:
+ /**
+ * @brief This method registers classes with Godot.
+ *
+ * @details This method registers methods, properties, and signals with the Godot engine.
+ */
+ static void
+ _register_methods();
+
+ AI();
+ ~AI();
+
+ /**
+ * @brief Initialize the class from Godot.
+ *
+ * @details This method is called just once when the Godot engine connects to the instance of the class.
+ */
+ void _init();
+
+ /**
+ * @brief Code to be run when ready.
+ *
+ * @details This method is run when all the children of this node are ready.
+ */
+ void _ready();
+
+ /**
+ * @brief The physics processed every delta time.
+ *
+ * @param[in] delta The time since the method was last run.
+ */
+ void _physics_process(float delta);
+
+ void _on_object_report(godot::String name, godot::String state, godot::Vector2 position, godot::Vector2 velocity);
+ };
+ } // namespace player
+} // namespace alai
+
+#endif