commit ef85bb4e4ba7f99c85295eafd9c4fc694468fde8 Author: Guillem George Date: Fri Feb 27 20:31:35 2026 +0100 given diff --git a/libzork/client/client.tar b/libzork/client/client.tar new file mode 100644 index 0000000..751b62b Binary files /dev/null and b/libzork/client/client.tar differ diff --git a/libzork/client/flake.lock b/libzork/client/flake.lock new file mode 100644 index 0000000..c21ffb6 --- /dev/null +++ b/libzork/client/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1751984180, + "narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/libzork/client/flake.nix b/libzork/client/flake.nix new file mode 100644 index 0000000..b6eb844 --- /dev/null +++ b/libzork/client/flake.nix @@ -0,0 +1,23 @@ +{ + description = "Flake for libzork"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = { self, nixpkgs }: { + devShells.x86_64-linux.default = with nixpkgs.legacyPackages.x86_64-linux; mkShell { + buildInputs = [ + gcc + cmake + yaml-cpp + curl + nlohmann_json + openssl + cmake + pkg-config + ]; + + }; + }; +} diff --git a/libzork/libzork/include/libzork/exceptions.hh b/libzork/libzork/include/libzork/exceptions.hh new file mode 100644 index 0000000..e0f58f6 --- /dev/null +++ b/libzork/libzork/include/libzork/exceptions.hh @@ -0,0 +1,23 @@ +#pragma once + +#include + +namespace libzork +{ + + class RunnerQuit : public std::exception + { + public: + RunnerQuit() = default; + ~RunnerQuit() override = default; + }; + + class RunnerInterrupt : public std::runtime_error + { + public: + using super_type = std::runtime_error; + using super_type::super_type; + ~RunnerInterrupt() override = default; + }; + +} // namespace libzork diff --git a/libzork/libzork/include/libzork/runner/choice.hh b/libzork/libzork/include/libzork/runner/choice.hh new file mode 100644 index 0000000..8b5bd62 --- /dev/null +++ b/libzork/libzork/include/libzork/runner/choice.hh @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace libzork::runner +{ + + class ChoiceRunner : public InteractiveRunner + { + public: + using InteractiveRunner::InteractiveRunner; + + ~ChoiceRunner() override = default; + }; + + std::unique_ptr + make_choice_runner(std::unique_ptr story, + std::istream& is = std::cin, + std::ostream& os = std::cout); + +} // namespace libzork::runner diff --git a/libzork/libzork/include/libzork/runner/html.hh b/libzork/libzork/include/libzork/runner/html.hh new file mode 100644 index 0000000..a56b0ba --- /dev/null +++ b/libzork/libzork/include/libzork/runner/html.hh @@ -0,0 +1,20 @@ +#pragma once + +#include + +namespace libzork::runner +{ + + class HTMLRunner : public Runner + { + public: + using Runner::Runner; + + ~HTMLRunner() override = default; + }; + + std::unique_ptr + make_html_runner(std::unique_ptr story, + const fs::path& output_dir); + +} // namespace libzork::runner diff --git a/libzork/libzork/include/libzork/runner/interactive.hh b/libzork/libzork/include/libzork/runner/interactive.hh new file mode 100644 index 0000000..6f45935 --- /dev/null +++ b/libzork/libzork/include/libzork/runner/interactive.hh @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +namespace libzork::runner +{ + + class InteractiveRunner : public Runner + { + public: + using Runner::Runner; + + InteractiveRunner(std::unique_ptr story, + std::istream& is = std::cin, + std::ostream& os = std::cout); + + ~InteractiveRunner() override = default; + + void run() override; + + virtual void print_script() const; + virtual void process_input() = 0; + + protected: + std::istream& is_; + std::ostream& os_; + }; + +} // namespace libzork::runner diff --git a/libzork/libzork/include/libzork/runner/runner.hh b/libzork/libzork/include/libzork/runner/runner.hh new file mode 100644 index 0000000..e51808e --- /dev/null +++ b/libzork/libzork/include/libzork/runner/runner.hh @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace libzork::runner +{ + + class Runner + { + public: + Runner(std::unique_ptr story); + + virtual ~Runner() = default; + + virtual void run() = 0; + + protected: + std::unique_ptr story_; + }; + +} // namespace libzork::runner diff --git a/libzork/libzork/include/libzork/runner/smart.hh b/libzork/libzork/include/libzork/runner/smart.hh new file mode 100644 index 0000000..c712156 --- /dev/null +++ b/libzork/libzork/include/libzork/runner/smart.hh @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +namespace libzork::runner +{ + + class SmartRunner : public InteractiveRunner + { + public: + using InteractiveRunner::InteractiveRunner; + + ~SmartRunner() override = default; + + virtual std::unordered_set + tokenize(const std::string& str) const = 0; + virtual bool has_unmatched_token( + const std::unordered_set& user_tokens, + const std::unordered_set& choice_tokens) const = 0; + }; + + std::unique_ptr make_smart_runner( + std::unique_ptr story, const fs::path& synonyms_path, + std::istream& is = std::cin, std::ostream& os = std::cout); + +} // namespace libzork::runner diff --git a/libzork/libzork/include/libzork/store/store.hh b/libzork/libzork/include/libzork/store/store.hh new file mode 100644 index 0000000..b58047e --- /dev/null +++ b/libzork/libzork/include/libzork/store/store.hh @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include + +namespace libzork::story +{ + + // Forward declaration because of the recursive dependencies + // store.hh -> node.hh -> (action|condition).hh -> store.hh + class Node; + class Story; + +} // namespace libzork::story + +namespace libzork::store +{ + + class Store + { + public: + virtual ~Store() = default; + + virtual const story::Node* get_active_node() const = 0; + virtual void set_active_node(const story::Node* node) = 0; + + virtual bool has_variable(const std::string& name) const = 0; + virtual int get_variable(const std::string& name) const = 0; + virtual void set_variable(const std::string& name, int value) = 0; + virtual std::map get_inventory() const = 0; + }; + + std::unique_ptr make_store(); + + class UndoStore + { + public: + virtual ~UndoStore() = default; + + virtual void new_state() = 0; + virtual bool undo() = 0; + virtual bool redo() = 0; + }; + + class SaveStore + { + public: + virtual ~SaveStore() = default; + + virtual void save(std::ostream& os) const = 0; + virtual void restore(std::istream& is, const story::Story& story) = 0; + }; + +} // namespace libzork::store diff --git a/libzork/libzork/include/libzork/story/node.hh b/libzork/libzork/include/libzork/story/node.hh new file mode 100644 index 0000000..d370eb3 --- /dev/null +++ b/libzork/libzork/include/libzork/story/node.hh @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; + +namespace libzork::story +{ + + class Node + { + public: + virtual ~Node() = default; + + virtual const std::string& get_name() const = 0; + virtual const std::string& get_text() const = 0; + + virtual const Node* get_choice(std::size_t index, + bool check_conditions = true) const = 0; + virtual std::vector + list_choices(bool check_conditions = true) const = 0; + virtual void add_choice( + const Node* other, const std::string& text, + std::vector> conditions = {}, + std::vector> actions = {}) = 0; + }; + + std::unique_ptr make_node(const std::string& name, + const fs::path& script_path); + +} // namespace libzork::story diff --git a/libzork/libzork/include/libzork/story/story.hh b/libzork/libzork/include/libzork/story/story.hh new file mode 100644 index 0000000..c0dcced --- /dev/null +++ b/libzork/libzork/include/libzork/story/story.hh @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +namespace fs = std::filesystem; + +namespace libzork::story +{ + + class Story + { + public: + virtual ~Story() = default; + + virtual const std::string& get_title() const = 0; + virtual const Node* get_current() const = 0; + virtual void set_current(const Node* node) = 0; + virtual const store::Store* get_store() const = 0; + virtual std::ostream& display(std::ostream& os) const = 0; + }; + + std::unique_ptr make_story(const fs::path& path); + +} // namespace libzork::story diff --git a/libzork/libzork/include/libzork/vars/action.hh b/libzork/libzork/include/libzork/vars/action.hh new file mode 100644 index 0000000..f06c1f1 --- /dev/null +++ b/libzork/libzork/include/libzork/vars/action.hh @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +namespace libzork::vars +{ + + class Action + { + public: + virtual ~Action() = default; + + virtual void apply() const = 0; + }; + + std::unique_ptr make_action(store::Store& store, + const std::string& variable, + const std::string& action, int value); + +} // namespace libzork::vars diff --git a/libzork/libzork/include/libzork/vars/condition.hh b/libzork/libzork/include/libzork/vars/condition.hh new file mode 100644 index 0000000..4f84f6b --- /dev/null +++ b/libzork/libzork/include/libzork/vars/condition.hh @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include + +namespace libzork::vars +{ + + class Condition + { + public: + virtual bool apply() const = 0; + + virtual ~Condition() = default; + }; + + std::unique_ptr make_condition(const store::Store& store, + const std::string& variable, + const std::string& comparison, + int value); + +} // namespace libzork::vars diff --git a/libzork/libzork/src/exceptions.cc b/libzork/libzork/src/exceptions.cc new file mode 100644 index 0000000..f24eb9b --- /dev/null +++ b/libzork/libzork/src/exceptions.cc @@ -0,0 +1,6 @@ +#include "exceptions.hh" + +#include + +namespace libzork +{} // namespace libzork diff --git a/libzork/libzork/src/exceptions.hh b/libzork/libzork/src/exceptions.hh new file mode 100644 index 0000000..5e196ef --- /dev/null +++ b/libzork/libzork/src/exceptions.hh @@ -0,0 +1,19 @@ +#ifndef EXCEPTIONS_HH +#define EXCEPTIONS_HH + +#include + +namespace libzork +{ + class NotImplemented : public std::runtime_error + { + public: + NotImplemented(const char* file = __builtin_FILE(), + int line = __builtin_LINE()) + : std::runtime_error(std::string{ "Unimplemented function: " } + + file + ":" + std::to_string(line)) + {} + }; + +} // namespace libzork +#endif // !EXCEPTIONS_HH diff --git a/libzork/libzork/src/runner/choice.cc b/libzork/libzork/src/runner/choice.cc new file mode 100644 index 0000000..d3057a3 --- /dev/null +++ b/libzork/libzork/src/runner/choice.cc @@ -0,0 +1,19 @@ +#include + +#include "exceptions.hh" +#include "runner/choice_impl.hh" + +namespace libzork::runner +{ + + std::unique_ptr + make_choice_runner(std::unique_ptr story, std::istream& is, + std::ostream& os) + { + (void)story; + (void)is; + (void)os; + throw NotImplemented(); + } + +} // namespace libzork::runner diff --git a/libzork/libzork/src/runner/choice_impl.cc b/libzork/libzork/src/runner/choice_impl.cc new file mode 100644 index 0000000..b78d070 --- /dev/null +++ b/libzork/libzork/src/runner/choice_impl.cc @@ -0,0 +1,21 @@ +#include "runner/choice_impl.hh" + +#include +#include + +#include "exceptions.hh" + +namespace libzork::runner +{ + + void ChoiceRunnerImpl::print_script() const + { + throw NotImplemented(); + } + + void ChoiceRunnerImpl::process_input() + { + throw NotImplemented(); + } + +} // namespace libzork::runner diff --git a/libzork/libzork/src/runner/choice_impl.hh b/libzork/libzork/src/runner/choice_impl.hh new file mode 100644 index 0000000..9ba5876 --- /dev/null +++ b/libzork/libzork/src/runner/choice_impl.hh @@ -0,0 +1,19 @@ +#ifndef CHOICE_IMPL_HH +#define CHOICE_IMPL_HH + +#include + +namespace libzork::runner +{ + + class ChoiceRunnerImpl : public ChoiceRunner + { + public: + ~ChoiceRunnerImpl() override = default; + + void print_script() const override; + void process_input() override; + }; + +} // namespace libzork::runner +#endif // !CHOICE_IMPL_HH diff --git a/libzork/libzork/src/runner/html.cc b/libzork/libzork/src/runner/html.cc new file mode 100644 index 0000000..ec67f43 --- /dev/null +++ b/libzork/libzork/src/runner/html.cc @@ -0,0 +1,18 @@ +#include + +#include "exceptions.hh" +#include "runner/html_impl.hh" + +namespace libzork::runner +{ + + std::unique_ptr + make_html_runner(std::unique_ptr story, + const fs::path& output_dir) + { + (void)story; + (void)output_dir; + throw NotImplemented(); + } + +} // namespace libzork::runner diff --git a/libzork/libzork/src/runner/html_impl.cc b/libzork/libzork/src/runner/html_impl.cc new file mode 100644 index 0000000..e7b982b --- /dev/null +++ b/libzork/libzork/src/runner/html_impl.cc @@ -0,0 +1,13 @@ +#include "runner/html_impl.hh" + +#include "exceptions.hh" + +namespace libzork::runner +{ + + void HTMLRunnerImpl::run() + { + throw NotImplemented(); + } + +} // namespace libzork::runner diff --git a/libzork/libzork/src/runner/html_impl.hh b/libzork/libzork/src/runner/html_impl.hh new file mode 100644 index 0000000..2c474bd --- /dev/null +++ b/libzork/libzork/src/runner/html_impl.hh @@ -0,0 +1,18 @@ +#ifndef HTML_IMPL_HH +#define HTML_IMPL_HH + +#include + +namespace libzork::runner +{ + + class HTMLRunnerImpl : public HTMLRunner + { + public: + ~HTMLRunnerImpl() override = default; + + void run() override; + }; + +} // namespace libzork::runner +#endif // !HTML_IMPL_HH diff --git a/libzork/libzork/src/runner/interactive.cc b/libzork/libzork/src/runner/interactive.cc new file mode 100644 index 0000000..517c272 --- /dev/null +++ b/libzork/libzork/src/runner/interactive.cc @@ -0,0 +1,26 @@ +#include +#include + +#include "exceptions.hh" + +namespace libzork::runner +{ + + InteractiveRunner::InteractiveRunner(std::unique_ptr story, + std::istream& is, std::ostream& os) + : Runner(std::move(story)) + , is_(is) + , os_(os) + {} + + void InteractiveRunner::print_script() const + { + throw NotImplemented(); + } + + void InteractiveRunner::run() + { + throw NotImplemented(); + } + +} // namespace libzork::runner diff --git a/libzork/libzork/src/runner/runner.cc b/libzork/libzork/src/runner/runner.cc new file mode 100644 index 0000000..63fd259 --- /dev/null +++ b/libzork/libzork/src/runner/runner.cc @@ -0,0 +1,14 @@ +#include + +#include "exceptions.hh" + +namespace libzork::runner +{ + + Runner::Runner(std::unique_ptr story) + { + (void)story; + throw NotImplemented(); + } + +} // namespace libzork::runner diff --git a/libzork/libzork/src/runner/smart.cc b/libzork/libzork/src/runner/smart.cc new file mode 100644 index 0000000..e99dd90 --- /dev/null +++ b/libzork/libzork/src/runner/smart.cc @@ -0,0 +1,21 @@ +#include + +#include "exceptions.hh" +#include "runner/smart_impl.hh" + +namespace libzork::runner +{ + + std::unique_ptr + make_smart_runner(std::unique_ptr story, + const fs::path& synonyms_path, std::istream& is, + std::ostream& os) + { + (void)story; + (void)synonyms_path; + (void)is; + (void)os; + throw NotImplemented(); + } + +} // namespace libzork::runner diff --git a/libzork/libzork/src/runner/smart_impl.cc b/libzork/libzork/src/runner/smart_impl.cc new file mode 100644 index 0000000..022f07a --- /dev/null +++ b/libzork/libzork/src/runner/smart_impl.cc @@ -0,0 +1,29 @@ +#include "runner/smart_impl.hh" + +#include "exceptions.hh" + +namespace libzork::runner +{ + + void SmartRunnerImpl::process_input() + { + throw NotImplemented(); + } + + std::unordered_set + SmartRunnerImpl::tokenize(const std::string& str) const + { + (void)str; + throw NotImplemented(); + } + + bool SmartRunnerImpl::has_unmatched_token( + const std::unordered_set& user_tokens, + const std::unordered_set& choice_tokens) const + { + (void)user_tokens; + (void)choice_tokens; + throw NotImplemented(); + } + +} // namespace libzork::runner diff --git a/libzork/libzork/src/runner/smart_impl.hh b/libzork/libzork/src/runner/smart_impl.hh new file mode 100644 index 0000000..f56d756 --- /dev/null +++ b/libzork/libzork/src/runner/smart_impl.hh @@ -0,0 +1,22 @@ +#ifndef SMART_IMPL_HH +#define SMART_IMPL_HH + +#include + +namespace libzork::runner +{ + + class SmartRunnerImpl : public SmartRunner + { + public: + void process_input() override; + virtual std::unordered_set + tokenize(const std::string& str) const override; + virtual bool + has_unmatched_token(const std::unordered_set& user_tokens, + const std::unordered_set& + choice_tokens) const override; + }; + +} // namespace libzork::runner +#endif // !SMART_IMPL_HH diff --git a/libzork/libzork/src/store/store.cc b/libzork/libzork/src/store/store.cc new file mode 100644 index 0000000..2f4adbb --- /dev/null +++ b/libzork/libzork/src/store/store.cc @@ -0,0 +1,14 @@ +#include + +#include "exceptions.hh" +#include "store/store_impl.hh" + +namespace libzork::store +{ + + std::unique_ptr make_store() + { + throw NotImplemented(); + } + +} // namespace libzork::store diff --git a/libzork/libzork/src/store/store_impl.cc b/libzork/libzork/src/store/store_impl.cc new file mode 100644 index 0000000..6b8f5ab --- /dev/null +++ b/libzork/libzork/src/store/store_impl.cc @@ -0,0 +1,43 @@ +#include "store/store_impl.hh" + +#include "exceptions.hh" + +namespace libzork::store +{ + + const story::Node* StoreImpl::get_active_node() const + { + throw NotImplemented(); + } + + void StoreImpl::set_active_node(const story::Node* node) + { + (void)node; + throw NotImplemented(); + } + + bool StoreImpl::has_variable(const std::string& name) const + { + (void)name; + throw NotImplemented(); + } + + int StoreImpl::get_variable(const std::string& name) const + { + (void)name; + throw NotImplemented(); + } + + void StoreImpl::set_variable(const std::string& name, int value) + { + (void)name; + (void)value; + throw NotImplemented(); + } + + std::map StoreImpl::get_inventory() const + { + throw NotImplemented(); + } + +} // namespace libzork::store diff --git a/libzork/libzork/src/store/store_impl.hh b/libzork/libzork/src/store/store_impl.hh new file mode 100644 index 0000000..b3cffa1 --- /dev/null +++ b/libzork/libzork/src/store/store_impl.hh @@ -0,0 +1,24 @@ +#ifndef STORE_IMPL_HH +#define STORE_IMPL_HH + +#include + +namespace libzork::store +{ + + class StoreImpl : public Store + { + public: + ~StoreImpl() override = default; + + const story::Node* get_active_node() const override; + void set_active_node(const story::Node* node) override; + + bool has_variable(const std::string& name) const override; + int get_variable(const std::string& name) const override; + void set_variable(const std::string& name, int value) override; + std::map get_inventory() const override; + }; + +} // namespace libzork::store +#endif // !STORE_IMPL_HH diff --git a/libzork/libzork/src/story/choice.cc b/libzork/libzork/src/story/choice.cc new file mode 100644 index 0000000..766e9d3 --- /dev/null +++ b/libzork/libzork/src/story/choice.cc @@ -0,0 +1,4 @@ +#include "story/choice.hh" + +namespace libzork::story +{} // namespace libzork::story diff --git a/libzork/libzork/src/story/choice.hh b/libzork/libzork/src/story/choice.hh new file mode 100644 index 0000000..5bf502d --- /dev/null +++ b/libzork/libzork/src/story/choice.hh @@ -0,0 +1,11 @@ +#ifndef CHOICE_HH +#define CHOICE_HH + +namespace libzork::story +{ + + class Choice + {}; + +} // namespace libzork::story +#endif // !CHOICE_HH diff --git a/libzork/libzork/src/story/node.cc b/libzork/libzork/src/story/node.cc new file mode 100644 index 0000000..343834a --- /dev/null +++ b/libzork/libzork/src/story/node.cc @@ -0,0 +1,17 @@ +#include + +#include "exceptions.hh" +#include "story/node_impl.hh" + +namespace libzork::story +{ + + std::unique_ptr make_node(const std::string& name, + const fs::path& script_path) + { + (void)name; + (void)script_path; + throw NotImplemented(); + } + +} // namespace libzork::story diff --git a/libzork/libzork/src/story/node_impl.cc b/libzork/libzork/src/story/node_impl.cc new file mode 100644 index 0000000..11b8041 --- /dev/null +++ b/libzork/libzork/src/story/node_impl.cc @@ -0,0 +1,56 @@ +#include "story/node_impl.hh" + +#include + +#include "exceptions.hh" + +namespace libzork::story +{ + const std::string& NodeImpl::get_name() const + { + throw NotImplemented(); + } + + const std::string& NodeImpl::get_text() const + { + throw NotImplemented(); + } + + const Node* NodeImpl::get_choice(size_t index, bool check_conditions) const + { + (void)check_conditions; + (void)index; + throw NotImplemented(); + } + + std::vector NodeImpl::list_choices(bool check_conditions) const + { + (void)check_conditions; + throw NotImplemented(); + } + + void NodeImpl::add_choice( + const Node* other, const std::string& text, + std::vector> conditions, + std::vector> actions) + { + (void)other; + (void)text; + (void)conditions; + (void)actions; + throw NotImplemented(); + } + + const NodeImpl& to_impl(const Node& node) + { + (void)node; + throw NotImplemented(); + } + + NodeImpl& to_impl(Node& node) + { + (void)node; + throw NotImplemented(); + } + +} // namespace libzork::story diff --git a/libzork/libzork/src/story/node_impl.hh b/libzork/libzork/src/story/node_impl.hh new file mode 100644 index 0000000..6c58eb7 --- /dev/null +++ b/libzork/libzork/src/story/node_impl.hh @@ -0,0 +1,31 @@ +#ifndef NODE_IMPL_HH +#define NODE_IMPL_HH + +#include + +namespace libzork::story +{ + + class NodeImpl : public Node + { + public: + ~NodeImpl() override = default; + + const std::string& get_name() const override; + const std::string& get_text() const override; + + const Node* get_choice(std::size_t index, + bool check_conditions = true) const override; + std::vector + list_choices(bool check_conditions = true) const override; + void add_choice( + const Node* other, const std::string& text, + std::vector> conditions = {}, + std::vector> actions = {}) override; + }; + + const NodeImpl& to_impl(const Node& node); + NodeImpl& to_impl(Node& node); + +} // namespace libzork::story +#endif // !NODE_IMPL_HH diff --git a/libzork/libzork/src/story/story.cc b/libzork/libzork/src/story/story.cc new file mode 100644 index 0000000..33b30b4 --- /dev/null +++ b/libzork/libzork/src/story/story.cc @@ -0,0 +1,15 @@ +#include + +#include "exceptions.hh" +#include "story/story_impl.hh" + +namespace libzork::story +{ + + std::unique_ptr make_story(const fs::path& path) + { + (void)path; + throw NotImplemented(); + } + +} // namespace libzork::story diff --git a/libzork/libzork/src/story/story_impl.cc b/libzork/libzork/src/story/story_impl.cc new file mode 100644 index 0000000..d991c20 --- /dev/null +++ b/libzork/libzork/src/story/story_impl.cc @@ -0,0 +1,35 @@ +#include "story/story_impl.hh" + +#include "exceptions.hh" + +namespace libzork::story +{ + + const std::string& StoryImpl::get_title() const + { + throw NotImplemented(); + } + + const Node* StoryImpl::get_current() const + { + throw NotImplemented(); + } + + void StoryImpl::set_current(const Node* node) + { + (void)node; + throw NotImplemented(); + } + + const store::Store* StoryImpl::get_store() const + { + throw NotImplemented(); + } + + std::ostream& StoryImpl::display(std::ostream& os) const + { + (void)os; + throw NotImplemented(); + } + +} // namespace libzork::story diff --git a/libzork/libzork/src/story/story_impl.hh b/libzork/libzork/src/story/story_impl.hh new file mode 100644 index 0000000..9107452 --- /dev/null +++ b/libzork/libzork/src/story/story_impl.hh @@ -0,0 +1,25 @@ +#ifndef STORY_IMPL_HH +#define STORY_IMPL_HH + +#include + +namespace libzork::story +{ + + class StoryImpl : public Story + { + public: + ~StoryImpl() override = default; + + const std::string& get_title() const override; + const Node* get_current() const override; + void set_current(const Node* node) override; + const store::Store* get_store() const override; + std::ostream& display(std::ostream& os) const override; + }; + + const StoryImpl& to_impl(const Story& story); + StoryImpl& to_impl(Story& story); + +} // namespace libzork::story +#endif // !STORY_IMPL_HH diff --git a/libzork/libzork/src/vars/action.cc b/libzork/libzork/src/vars/action.cc new file mode 100644 index 0000000..83d8c8e --- /dev/null +++ b/libzork/libzork/src/vars/action.cc @@ -0,0 +1,20 @@ +#include + +#include "exceptions.hh" +#include "vars/action_impl.hh" + +namespace libzork::vars +{ + + std::unique_ptr make_action(store::Store& store, + const std::string& variable, + const std::string& action, int value) + { + (void)store; + (void)variable; + (void)action; + (void)value; + throw NotImplemented(); + } + +} // namespace libzork::vars diff --git a/libzork/libzork/src/vars/action_impl.cc b/libzork/libzork/src/vars/action_impl.cc new file mode 100644 index 0000000..d0abcf7 --- /dev/null +++ b/libzork/libzork/src/vars/action_impl.cc @@ -0,0 +1,13 @@ +#include "vars/action_impl.hh" + +#include "exceptions.hh" + +namespace libzork::vars +{ + + void ActionImpl::apply() const + { + throw NotImplemented(); + } + +} // namespace libzork::vars diff --git a/libzork/libzork/src/vars/action_impl.hh b/libzork/libzork/src/vars/action_impl.hh new file mode 100644 index 0000000..35aed48 --- /dev/null +++ b/libzork/libzork/src/vars/action_impl.hh @@ -0,0 +1,18 @@ +#ifndef ACTION_IMPL_HH +#define ACTION_IMPL_HH + +#include + +namespace libzork::vars +{ + + class ActionImpl : public Action + { + public: + ~ActionImpl() override = default; + + void apply() const override; + }; + +} // namespace libzork::vars +#endif // !ACTION_IMPL_HH diff --git a/libzork/libzork/src/vars/condition.cc b/libzork/libzork/src/vars/condition.cc new file mode 100644 index 0000000..d0fb648 --- /dev/null +++ b/libzork/libzork/src/vars/condition.cc @@ -0,0 +1,21 @@ +#include +#include + +#include "exceptions.hh" + +namespace libzork::vars +{ + + std::unique_ptr make_condition(const store::Store& store, + const std::string& variable, + const std::string& comparison, + int value) + { + (void)store; + (void)variable; + (void)comparison; + (void)value; + throw NotImplemented(); + } + +} // namespace libzork::vars diff --git a/libzork/libzork/src/vars/condition_impl.cc b/libzork/libzork/src/vars/condition_impl.cc new file mode 100644 index 0000000..7d11fdc --- /dev/null +++ b/libzork/libzork/src/vars/condition_impl.cc @@ -0,0 +1,16 @@ +#include "vars/condition_impl.hh" + +#include +#include + +#include "exceptions.hh" + +namespace libzork::vars +{ + + bool ConditionImpl::apply() const + { + throw NotImplemented(); + } + +} // namespace libzork::vars diff --git a/libzork/libzork/src/vars/condition_impl.hh b/libzork/libzork/src/vars/condition_impl.hh new file mode 100644 index 0000000..738f1b0 --- /dev/null +++ b/libzork/libzork/src/vars/condition_impl.hh @@ -0,0 +1,18 @@ +#ifndef CONDITION_IMPL_HH +#define CONDITION_IMPL_HH + +#include + +namespace libzork::vars +{ + + class ConditionImpl : public Condition + { + public: + ~ConditionImpl() override = default; + + bool apply() const override; + }; + +} // namespace libzork::vars +#endif // !CONDITION_IMPL_HH diff --git a/libzork/src/main.cc b/libzork/src/main.cc new file mode 100644 index 0000000..1cd4d62 --- /dev/null +++ b/libzork/src/main.cc @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +#include "options.hh" + +std::unique_ptr get_story(const Config& config) +{ + return libzork::story::make_story(config.story_path); +} + +std::unique_ptr +get_runner(const Config& config, std::unique_ptr story) +{ + switch (config.story_type) + { + case StoryType::Choice: + return libzork::runner::make_choice_runner(std::move(story)); + case StoryType::Smart: + return libzork::runner::make_smart_runner(std::move(story), + config.story_arg); + case StoryType::HTML: + return libzork::runner::make_html_runner(std::move(story), + config.story_arg); + default: + return nullptr; + } +} + +int main(int argc, char** argv) +{ + Config config; + try + { + config = parse_options(argc, argv); + } + catch (const std::invalid_argument& exc) + { + std::cerr << "invalid options: " << exc.what() << "\n"; + return 1; + } + + std::unique_ptr runner; + + auto story = get_story(config); + story->display(std::cout); + // runner = get_runner(config, std::move(story)); + // + // try + // { + // runner->run(); + // } + // catch (const libzork::RunnerQuit&) + // {} + + return 0; +} diff --git a/libzork/src/options.cc b/libzork/src/options.cc new file mode 100644 index 0000000..e97a7ea --- /dev/null +++ b/libzork/src/options.cc @@ -0,0 +1,57 @@ +#include "options.hh" + +#include +#include + +namespace +{ + constexpr option options[] = { + { "story", required_argument, nullptr, 's' }, + { "smart", required_argument, nullptr, 'm' }, + { "html", required_argument, nullptr, 'h' }, + }; + + std::string usage(const std::string& name) + { + return "usage: " + name + + " (--story )" + " [--smart | --html ]"; + }; +} // namespace + +Config parse_options(int argc, char** argv) +{ + Config config; + int opt; + while ((opt = getopt_long(argc, argv, "s:m:h:t:u:o:n:r:", options, nullptr)) + != -1) + { + switch (opt) + { + case 's': // --story + config.story_path = optarg; + break; + case 'm': // --smart + if (config.story_type == StoryType::HTML) + throw std::invalid_argument( + "incompatble options: `--smart` and `--html`"); + config.story_type = StoryType::Smart; + config.story_arg = optarg; + break; + case 'h': // --html + if (config.story_type == StoryType::Smart) + throw std::invalid_argument( + "incompatible options: `--smart` and `--html`"); + config.story_type = StoryType::HTML; + config.story_arg = optarg; + break; + default: + throw std::invalid_argument(usage(argv[0])); + } + }; + + if (config.story_path.empty()) + throw std::invalid_argument("option '--story' is mandatory"); + + return config; +} diff --git a/libzork/src/options.hh b/libzork/src/options.hh new file mode 100644 index 0000000..d3f919d --- /dev/null +++ b/libzork/src/options.hh @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +namespace fs = std::filesystem; + +enum class StoryType +{ + Choice, + Smart, + HTML, +}; + +struct Config +{ + std::filesystem::path story_path; + StoryType story_type = StoryType::Choice; + fs::path story_arg; /** Undefined if story_type is StoryType::BASIC */ +}; + +Config parse_options(int argc, char** argv); diff --git a/libzork/tests/scripts/little_quest/castle.txt b/libzork/tests/scripts/little_quest/castle.txt new file mode 100644 index 0000000..23bef37 --- /dev/null +++ b/libzork/tests/scripts/little_quest/castle.txt @@ -0,0 +1,3 @@ +You enter the castle. +A large dragon blocks your path, preventing you from proceeding further. +A sword is on your left. diff --git a/libzork/tests/scripts/little_quest/castle_weapon.txt b/libzork/tests/scripts/little_quest/castle_weapon.txt new file mode 100644 index 0000000..7e1d77f --- /dev/null +++ b/libzork/tests/scripts/little_quest/castle_weapon.txt @@ -0,0 +1,3 @@ +You enter the castle. +A large dragon blocks your path, preventing you from proceeding further. +To your right, there is a forge. Perhaps there are weapons there ? diff --git a/libzork/tests/scripts/little_quest/forest.txt b/libzork/tests/scripts/little_quest/forest.txt new file mode 100644 index 0000000..e37ad98 --- /dev/null +++ b/libzork/tests/scripts/little_quest/forest.txt @@ -0,0 +1,4 @@ +You find yourself in a vast, lush forest. +In the distance, you spot a prince perched atop a tower of a castle. +He appears to be in desperate need of assistance. +To your right lies a house. diff --git a/libzork/tests/scripts/little_quest/house.txt b/libzork/tests/scripts/little_quest/house.txt new file mode 100644 index 0000000..c285e6a --- /dev/null +++ b/libzork/tests/scripts/little_quest/house.txt @@ -0,0 +1,2 @@ +There is a bed, worn out from fatigue, you collapse onto it and take a nap. +The end. diff --git a/libzork/tests/scripts/little_quest/tower.txt b/libzork/tests/scripts/little_quest/tower.txt new file mode 100644 index 0000000..2e61000 --- /dev/null +++ b/libzork/tests/scripts/little_quest/tower.txt @@ -0,0 +1,2 @@ +You slay the dragon, climb the tower, and find the prince safe and sound. +The end. diff --git a/libzork/tests/scripts/short_static/cave.txt b/libzork/tests/scripts/short_static/cave.txt new file mode 100644 index 0000000..f77f4bf --- /dev/null +++ b/libzork/tests/scripts/short_static/cave.txt @@ -0,0 +1 @@ +This is a dark cave diff --git a/libzork/tests/scripts/short_static/forest.txt b/libzork/tests/scripts/short_static/forest.txt new file mode 100644 index 0000000..ac917ab --- /dev/null +++ b/libzork/tests/scripts/short_static/forest.txt @@ -0,0 +1 @@ +This is a large forest diff --git a/libzork/tests/scripts/short_static/welcome.txt b/libzork/tests/scripts/short_static/welcome.txt new file mode 100644 index 0000000..af5626b --- /dev/null +++ b/libzork/tests/scripts/short_static/welcome.txt @@ -0,0 +1 @@ +Hello, world! diff --git a/libzork/tests/stories/dynamic/story.yml b/libzork/tests/stories/dynamic/story.yml new file mode 100644 index 0000000..7d75431 --- /dev/null +++ b/libzork/tests/stories/dynamic/story.yml @@ -0,0 +1,51 @@ +title: A dynamic story +scripts-path: ../../scripts/little_quest +variables: + - name: health + value: 10 + - name: sword_taken + value: 0 +story: + - name: forest + script: forest.txt + choices: + - text: Enter the house + target: house + - text: Enter the castle + target: castle + - text: Eat a fruit + target: forest + actions: + - name: health + operation: add + value: 10 + - name: house + script: house.txt + choices: [] + - name: castle + script: castle_weapon.txt + choices: + - text: Flee + target: forest + - text: Take the sword + target: castle + conditions: + - name: sword_taken + comparison: equal + value: 0 + actions: + - name: sword_taken + operation: add + value: 1 + - text: Kill the dragon + target: tower + conditions: + - name: sword_taken + comparison: equal + value: 1 + - name: health + comparison: greater + value: 10 + - name: tower + script: tower.txt + choices: [] diff --git a/libzork/tests/stories/long_static/story.yml b/libzork/tests/stories/long_static/story.yml new file mode 100644 index 0000000..152fad8 --- /dev/null +++ b/libzork/tests/stories/long_static/story.yml @@ -0,0 +1,25 @@ +title: A long static story +scripts-path: ../../scripts/little_quest +story: + - name: forest + script: forest.txt + choices: + - text: Enter the house + target: house + - text: Enter the castle + target: castle + - text: Eat a fruit + target: forest + - name: house + script: house.txt + choices: [] + - name: castle + script: castle.txt + choices: + - text: Flee + target: forest + - text: Kill the dragon + target: tower + - name: tower + script: tower.txt + choices: [] diff --git a/libzork/tests/stories/short_static/story.yml b/libzork/tests/stories/short_static/story.yml new file mode 100644 index 0000000..701a954 --- /dev/null +++ b/libzork/tests/stories/short_static/story.yml @@ -0,0 +1,16 @@ +title: A short static story +scripts-path: ../../scripts/short_static +story: + - name: welcome + script: welcome.txt + choices: + - text: Explore the cave + target: cave + - text: Go in the forest + target: forest + - name: cave + script: cave.txt + choices: [] + - name: forest + script: forest.txt + choices: []