diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:08:27 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:08:27 +0200 |
| commit | c9b6b9a5ca082fe7c1b6f58d7713f785a9eb6a5c (patch) | |
| tree | 3e4f42f93c7ae89a364e4d51fff6e5cec4e55fa9 /rushs/libzork | |
add: graphs et rushs
Diffstat (limited to 'rushs/libzork')
56 files changed, 1153 insertions, 0 deletions
diff --git a/rushs/libzork/libzork/CMakeLists.txt b/rushs/libzork/libzork/CMakeLists.txt new file mode 100644 index 0000000..f9fccbc --- /dev/null +++ b/rushs/libzork/libzork/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.21.2) +project(Zork) + +add_executable(zork_test) +target_compile_options(zork_test PRIVATE -Wall -Wextra -Werror -pedantic -std=c++20 -Wold-style-cast) +set_target_properties(zork_test PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF) +add_subdirectory(src) +add_subdirectory(zorkxplorer) + +target_link_libraries(zork_test PUBLIC libzork) +target_include_directories(zork_test PUBLIC + "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/include" + "${PROJECT_SOURCE_DIR}/src" +) +target_include_directories(libzork PUBLIC + "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/include" + "${PROJECT_SOURCE_DIR}/src" +)
\ No newline at end of file diff --git a/rushs/libzork/libzork/client/flake.nix b/rushs/libzork/libzork/client/flake.nix new file mode 100644 index 0000000..b6eb844 --- /dev/null +++ b/rushs/libzork/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/rushs/libzork/libzork/src/CMakeLists.txt b/rushs/libzork/libzork/src/CMakeLists.txt new file mode 100644 index 0000000..4f4224d --- /dev/null +++ b/rushs/libzork/libzork/src/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.21.2) +project(Zork) +add_library(libzork SHARED) + +target_compile_options(libzork PUBLIC -Wall -Wextra -Werror -pedantic -std=c++20 -Wold-style-cast) +set_target_properties(libzork PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" + OUTPUT_NAME "zork" ) +target_include_directories(libzork PRIVATE + "${PROJECT_SOURCE_DIR}/include" + "${PROJECT_SOURCE_DIR}/src" +) + +target_sources(libzork PRIVATE exceptions.cc) + +find_library(YAML-CPP NAMES yaml-cpp libyaml-cpp REQUIRED) +target_link_libraries(libzork PUBLIC yaml-cpp) + +add_subdirectory(runner) +add_subdirectory(store) +add_subdirectory(story) +add_subdirectory(vars)
\ No newline at end of file diff --git a/rushs/libzork/libzork/src/exceptions.cc b/rushs/libzork/libzork/src/exceptions.cc new file mode 100644 index 0000000..f24eb9b --- /dev/null +++ b/rushs/libzork/libzork/src/exceptions.cc @@ -0,0 +1,6 @@ +#include "exceptions.hh" + +#include <string> + +namespace libzork +{} // namespace libzork diff --git a/rushs/libzork/libzork/src/exceptions.hh b/rushs/libzork/libzork/src/exceptions.hh new file mode 100644 index 0000000..93c0a0b --- /dev/null +++ b/rushs/libzork/libzork/src/exceptions.hh @@ -0,0 +1,17 @@ +#pragma once + +#include <stdexcept> + +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 diff --git a/rushs/libzork/libzork/src/runner/CMakeLists.txt b/rushs/libzork/libzork/src/runner/CMakeLists.txt new file mode 100644 index 0000000..5e472d4 --- /dev/null +++ b/rushs/libzork/libzork/src/runner/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.21.2) +project(Zork) +target_sources(libzork PRIVATE choice.cc choice_impl.cc html.cc html_impl.cc interactive.cc runner.cc smart.cc smart_impl.cc) +set_target_properties(libzork PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF)
\ No newline at end of file diff --git a/rushs/libzork/libzork/src/runner/caca.caca b/rushs/libzork/libzork/src/runner/caca.caca new file mode 100644 index 0000000..2df4dd2 --- /dev/null +++ b/rushs/libzork/libzork/src/runner/caca.caca @@ -0,0 +1,13 @@ +#include <caca.h> + +void caca::caca(caca::Caca& caca, string caca) { + std::caca caca = caca.get_caca(); + for(auto caca : caca) { + if(!caca->caca.is_caca()) { + return caca; + } + caca = caca.caca; + } + caca.set_caca(caca.get_caca()); + return caca; +}
\ No newline at end of file diff --git a/rushs/libzork/libzork/src/runner/choice.cc b/rushs/libzork/libzork/src/runner/choice.cc new file mode 100644 index 0000000..1e677bb --- /dev/null +++ b/rushs/libzork/libzork/src/runner/choice.cc @@ -0,0 +1,17 @@ +#include <algorithm> +#include <libzork/runner/choice.hh> + +#include "exceptions.hh" +#include "runner/choice_impl.hh" + +namespace libzork::runner +{ + + std::unique_ptr<ChoiceRunner> + make_choice_runner(std::unique_ptr<story::Story> story, std::istream& is, + std::ostream& os) + { + return std::make_unique<ChoiceRunnerImpl>(std::move(story), is, os); + } + +} // namespace libzork::runner diff --git a/rushs/libzork/libzork/src/runner/choice_impl.cc b/rushs/libzork/libzork/src/runner/choice_impl.cc new file mode 100644 index 0000000..2572ef3 --- /dev/null +++ b/rushs/libzork/libzork/src/runner/choice_impl.cc @@ -0,0 +1,40 @@ +#include "runner/choice_impl.hh" + +#include <libzork/exceptions.hh> +#include <sstream> + +#include "exceptions.hh" + +namespace libzork::runner +{ + + void ChoiceRunnerImpl::print_script() const + { + InteractiveRunner::print_script(); + os_ << "\n"; + size_t i = 1; + for (auto choice : story_->get_current()->list_choices()) + { + os_ << i << ". " << choice << "\n"; + i++; + } + os_ << "\n"; + } + + void ChoiceRunnerImpl::process_input() + { + int input; + std::string s; + std::getline(is_, s); + if (!is_) + throw RunnerInterrupt{ "Bad input." }; + std::istringstream ss{ s }; + ss >> input; + const story::Node* choice; + if (ss.fail() || !ss.eof() + || !((choice = story_->get_current()->get_choice(input - 1)))) + throw RunnerInterrupt{ "Bad input." }; + story_->set_current(choice); + } + +} // namespace libzork::runner diff --git a/rushs/libzork/libzork/src/runner/choice_impl.hh b/rushs/libzork/libzork/src/runner/choice_impl.hh new file mode 100644 index 0000000..6818bab --- /dev/null +++ b/rushs/libzork/libzork/src/runner/choice_impl.hh @@ -0,0 +1,18 @@ +#pragma once + +#include <libzork/runner/choice.hh> + +namespace libzork::runner +{ + + class ChoiceRunnerImpl : public ChoiceRunner + { + public: + using ChoiceRunner::ChoiceRunner; + ~ChoiceRunnerImpl() override = default; + + void print_script() const override; + void process_input() override; + }; + +} // namespace libzork::runner diff --git a/rushs/libzork/libzork/src/runner/html.cc b/rushs/libzork/libzork/src/runner/html.cc new file mode 100644 index 0000000..ec67f43 --- /dev/null +++ b/rushs/libzork/libzork/src/runner/html.cc @@ -0,0 +1,18 @@ +#include <libzork/runner/html.hh> + +#include "exceptions.hh" +#include "runner/html_impl.hh" + +namespace libzork::runner +{ + + std::unique_ptr<HTMLRunner> + make_html_runner(std::unique_ptr<story::Story> story, + const fs::path& output_dir) + { + (void)story; + (void)output_dir; + throw NotImplemented(); + } + +} // namespace libzork::runner diff --git a/rushs/libzork/libzork/src/runner/html_impl.cc b/rushs/libzork/libzork/src/runner/html_impl.cc new file mode 100644 index 0000000..e7b982b --- /dev/null +++ b/rushs/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/rushs/libzork/libzork/src/runner/html_impl.hh b/rushs/libzork/libzork/src/runner/html_impl.hh new file mode 100644 index 0000000..3d47a3e --- /dev/null +++ b/rushs/libzork/libzork/src/runner/html_impl.hh @@ -0,0 +1,16 @@ +#pragma once + +#include <libzork/runner/html.hh> + +namespace libzork::runner +{ + + class HTMLRunnerImpl : public HTMLRunner + { + public: + ~HTMLRunnerImpl() override = default; + + void run() override; + }; + +} // namespace libzork::runner diff --git a/rushs/libzork/libzork/src/runner/interactive.cc b/rushs/libzork/libzork/src/runner/interactive.cc new file mode 100644 index 0000000..85a76a8 --- /dev/null +++ b/rushs/libzork/libzork/src/runner/interactive.cc @@ -0,0 +1,40 @@ +#include <libzork/exceptions.hh> +#include <libzork/runner/interactive.hh> + +#include "exceptions.hh" + +namespace libzork::runner +{ + + InteractiveRunner::InteractiveRunner(std::unique_ptr<story::Story> story, + std::istream& is, std::ostream& os) + : Runner(std::move(story)) + , is_(is) + , os_(os) + {} + + void InteractiveRunner::print_script() const + { + os_ << story_->get_current()->get_text(); + } + + void InteractiveRunner::run() + { + print_script(); + while (story_->get_current()->list_choices().size() != 0) + { + try + { + os_ << "> "; + process_input(); + } + catch (RunnerInterrupt& i) + { + os_ << i.what() << "\n"; + continue; + } + print_script(); + } + } + +} // namespace libzork::runner diff --git a/rushs/libzork/libzork/src/runner/runner.cc b/rushs/libzork/libzork/src/runner/runner.cc new file mode 100644 index 0000000..3968723 --- /dev/null +++ b/rushs/libzork/libzork/src/runner/runner.cc @@ -0,0 +1,12 @@ +#include <libzork/runner/runner.hh> + +#include "exceptions.hh" + +namespace libzork::runner +{ + + Runner::Runner(std::unique_ptr<story::Story> story) + : story_{ std::move(story) } + {} + +} // namespace libzork::runner diff --git a/rushs/libzork/libzork/src/runner/smart.cc b/rushs/libzork/libzork/src/runner/smart.cc new file mode 100644 index 0000000..e99dd90 --- /dev/null +++ b/rushs/libzork/libzork/src/runner/smart.cc @@ -0,0 +1,21 @@ +#include <libzork/runner/smart.hh> + +#include "exceptions.hh" +#include "runner/smart_impl.hh" + +namespace libzork::runner +{ + + std::unique_ptr<SmartRunner> + make_smart_runner(std::unique_ptr<story::Story> 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/rushs/libzork/libzork/src/runner/smart_impl.cc b/rushs/libzork/libzork/src/runner/smart_impl.cc new file mode 100644 index 0000000..022f07a --- /dev/null +++ b/rushs/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<std::string> + SmartRunnerImpl::tokenize(const std::string& str) const + { + (void)str; + throw NotImplemented(); + } + + bool SmartRunnerImpl::has_unmatched_token( + const std::unordered_set<std::string>& user_tokens, + const std::unordered_set<std::string>& choice_tokens) const + { + (void)user_tokens; + (void)choice_tokens; + throw NotImplemented(); + } + +} // namespace libzork::runner diff --git a/rushs/libzork/libzork/src/runner/smart_impl.hh b/rushs/libzork/libzork/src/runner/smart_impl.hh new file mode 100644 index 0000000..201237f --- /dev/null +++ b/rushs/libzork/libzork/src/runner/smart_impl.hh @@ -0,0 +1,20 @@ +#pragma once + +#include <libzork/runner/smart.hh> + +namespace libzork::runner +{ + + class SmartRunnerImpl : public SmartRunner + { + public: + void process_input() override; + virtual std::unordered_set<std::string> + tokenize(const std::string& str) const override; + virtual bool + has_unmatched_token(const std::unordered_set<std::string>& user_tokens, + const std::unordered_set<std::string>& + choice_tokens) const override; + }; + +} // namespace libzork::runner diff --git a/rushs/libzork/libzork/src/store/CMakeLists.txt b/rushs/libzork/libzork/src/store/CMakeLists.txt new file mode 100644 index 0000000..420356d --- /dev/null +++ b/rushs/libzork/libzork/src/store/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.21.2) +project(Zork) +target_sources(libzork PRIVATE store.cc store_impl.cc) +set_target_properties(libzork PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF)
\ No newline at end of file diff --git a/rushs/libzork/libzork/src/store/store.cc b/rushs/libzork/libzork/src/store/store.cc new file mode 100644 index 0000000..be91193 --- /dev/null +++ b/rushs/libzork/libzork/src/store/store.cc @@ -0,0 +1,14 @@ +#include <libzork/store/store.hh> + +#include "exceptions.hh" +#include "store/store_impl.hh" + +namespace libzork::store +{ + + std::unique_ptr<Store> make_store() + { + return std::make_unique<StoreImpl>(); + } + +} // namespace libzork::store diff --git a/rushs/libzork/libzork/src/store/store_impl.cc b/rushs/libzork/libzork/src/store/store_impl.cc new file mode 100644 index 0000000..3abcb55 --- /dev/null +++ b/rushs/libzork/libzork/src/store/store_impl.cc @@ -0,0 +1,42 @@ +#include "store/store_impl.hh" + +#include "exceptions.hh" + +namespace libzork::store +{ + + const story::Node* StoreImpl::get_active_node() const + { + return active_node_; + } + + void StoreImpl::set_active_node(const story::Node* node) + { + active_node_ = node; + } + + 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<std::string, int> StoreImpl::get_inventory() const + { + throw NotImplemented(); + } + +} // namespace libzork::store diff --git a/rushs/libzork/libzork/src/store/store_impl.hh b/rushs/libzork/libzork/src/store/store_impl.hh new file mode 100644 index 0000000..a978128 --- /dev/null +++ b/rushs/libzork/libzork/src/store/store_impl.hh @@ -0,0 +1,26 @@ +#pragma once + +#include <libzork/store/store.hh> + +namespace libzork::store +{ + + class StoreImpl : public Store + { + public: + StoreImpl() = default; + ~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<std::string, int> get_inventory() const override; + + private: + const story::Node* active_node_ = nullptr; + }; + +} // namespace libzork::store diff --git a/rushs/libzork/libzork/src/story/CMakeLists.txt b/rushs/libzork/libzork/src/story/CMakeLists.txt new file mode 100644 index 0000000..6549964 --- /dev/null +++ b/rushs/libzork/libzork/src/story/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.21.2) +project(Zork) +target_sources(libzork PRIVATE node.cc node_impl.cc story.cc story_impl.cc choice.cc) +set_target_properties(libzork PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF)
\ No newline at end of file diff --git a/rushs/libzork/libzork/src/story/choice.cc b/rushs/libzork/libzork/src/story/choice.cc new file mode 100644 index 0000000..4b01983 --- /dev/null +++ b/rushs/libzork/libzork/src/story/choice.cc @@ -0,0 +1,16 @@ +// +// Created by martial.simon on 2/28/25. +// + +#include <story/choice.hh> +namespace libzork::story +{ + std::string Choice::get_text() const + { + return text_; + } + const Node* Choice::get_choice() const + { + return choice_; + } +} // namespace libzork::story
\ No newline at end of file diff --git a/rushs/libzork/libzork/src/story/choice.hh b/rushs/libzork/libzork/src/story/choice.hh new file mode 100644 index 0000000..08bbd29 --- /dev/null +++ b/rushs/libzork/libzork/src/story/choice.hh @@ -0,0 +1,25 @@ +// +// Created by martial.simon on 2/28/25. +// + +#pragma once +#include <libzork/story/node.hh> +#include <string> + +namespace libzork::story +{ + class Choice + { + public: + Choice(const std::string& text, const Node* choice) + : text_(text) + , choice_(choice) + {} + std::string get_text() const; + const Node* get_choice() const; + + private: + std::string text_; + const Node* choice_; + }; +} // namespace libzork::story diff --git a/rushs/libzork/libzork/src/story/node.cc b/rushs/libzork/libzork/src/story/node.cc new file mode 100644 index 0000000..416b902 --- /dev/null +++ b/rushs/libzork/libzork/src/story/node.cc @@ -0,0 +1,21 @@ +#include <fstream> +#include <libzork/story/node.hh> + +#include "exceptions.hh" +#include "story/node_impl.hh" + +namespace libzork::story +{ + + std::unique_ptr<Node> make_node(const std::string& name, + const fs::path& script_path) + { + auto stream = std::ifstream(script_path.c_str()); + if (!stream.is_open()) + throw std::invalid_argument{ "Invalid file, unable to open." }; + std::ostringstream o; + o << stream.rdbuf(); + return std::make_unique<NodeImpl>(name, o.str()); + } + +} // namespace libzork::story diff --git a/rushs/libzork/libzork/src/story/node_impl.cc b/rushs/libzork/libzork/src/story/node_impl.cc new file mode 100644 index 0000000..c9877e8 --- /dev/null +++ b/rushs/libzork/libzork/src/story/node_impl.cc @@ -0,0 +1,73 @@ +#include "story/node_impl.hh" + +#include <fstream> + +#include "exceptions.hh" + +namespace libzork::story +{ + NodeImpl::NodeImpl(const std::string& name, const std::string& text) + : name_(name) + , text_(text) + {} + + const std::string& NodeImpl::get_name() const + { + return name_; + } + + const std::string& NodeImpl::get_text() const + { + return text_; + } + + const Node* NodeImpl::get_choice(size_t index, bool check_conditions) const + { + (void)check_conditions; + if (choices_.size() <= index) + return nullptr; + return choices_.at(index).get_choice(); + } + + std::vector<std::string> NodeImpl::list_choices(bool check_conditions) const + { + (void)check_conditions; + std::vector<std::string> texts; + for (auto choice : choices_) + { + texts.push_back(choice.get_text()); + } + return texts; + } + + void NodeImpl::add_choice( + const Node* other, const std::string& text, + std::vector<std::unique_ptr<vars::Condition>> conditions, + std::vector<std::unique_ptr<vars::Action>> actions) + { + (void)conditions; + (void)actions; + Choice c{ text, other }; + choices_.push_back(std::move(c)); + } + + const NodeImpl& to_impl(const Node& node) + { + const NodeImpl* cast = dynamic_cast<const NodeImpl*>(&node); + if (!cast) + throw std::runtime_error{ + "Invalid conversion from const Node* to const NodeImpl*" + }; + return *cast; + } + + NodeImpl& to_impl(Node& node) + { + NodeImpl* cast = dynamic_cast<NodeImpl*>(&node); + if (!cast) + throw std::runtime_error{ + "Invalid conversion from const Node* to const NodeImpl*" + }; + return *cast; + } +} // namespace libzork::story diff --git a/rushs/libzork/libzork/src/story/node_impl.hh b/rushs/libzork/libzork/src/story/node_impl.hh new file mode 100644 index 0000000..f55de7c --- /dev/null +++ b/rushs/libzork/libzork/src/story/node_impl.hh @@ -0,0 +1,38 @@ +#pragma once + +#include <libzork/story/node.hh> +#include <story/choice.hh> + +namespace libzork::story +{ + class NodeImpl : public Node + { + public: + NodeImpl(const std::string& name, const std::string& text); + ~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<std::string> + list_choices(bool check_conditions = true) const override; + + void add_choice( + const Node* other, const std::string& text, + std::vector<std::unique_ptr<vars::Condition>> conditions = {}, + std::vector<std::unique_ptr<vars::Action>> actions = {}) override; + + private: + const std::string name_; + const std::string text_; + std::vector<Choice> choices_; + }; + + const NodeImpl& to_impl(const Node& node); + + NodeImpl& to_impl(Node& node); +} // namespace libzork::story diff --git a/rushs/libzork/libzork/src/story/story.cc b/rushs/libzork/libzork/src/story/story.cc new file mode 100644 index 0000000..4b26eff --- /dev/null +++ b/rushs/libzork/libzork/src/story/story.cc @@ -0,0 +1,15 @@ +#include <libzork/story/story.hh> +#include <store/store_impl.hh> + +#include "exceptions.hh" +#include "story/story_impl.hh" + +namespace libzork::story +{ + + std::unique_ptr<Story> make_story(const fs::path& path) + { + return std::make_unique<StoryImpl>(path); + } + +} // namespace libzork::story diff --git a/rushs/libzork/libzork/src/story/story_impl.cc b/rushs/libzork/libzork/src/story/story_impl.cc new file mode 100644 index 0000000..ad39d09 --- /dev/null +++ b/rushs/libzork/libzork/src/story/story_impl.cc @@ -0,0 +1,118 @@ +#include "story/story_impl.hh" + +#include "exceptions.hh" +#include "node_impl.hh" + +namespace libzork::story +{ + + StoryImpl::StoryImpl(const fs::path& path) + { + YAML::Node config = YAML::LoadFile(path); + title_ = config["title"].as<std::string>(); + auto dir = config["scripts-path"].as<std::string>(); + auto story = config["story"]; + for (auto script : story) + { + auto name = script["name"].as<std::string>(); + auto script_path = script["script"].as<std::string>(); + nodes_.push_back( + make_node(name, path.parent_path() / dir / script_path)); + } + size_t i = 0; + for (auto script : story) + { + for (auto choice : script["choices"]) + { + auto text = choice["text"].as<std::string>(); + auto matches = std::ranges::find_if( + nodes_.begin(), nodes_.end(), + [choice](const std::unique_ptr<Node>& c) -> bool { + return c->get_name() + == choice["target"].as<std::string>(); + }); + nodes_.at(i)->add_choice(matches->get(), text); + } + i++; + } + if (nodes_.empty()) + store_ = nullptr; + else + { + store_ = store::make_store(); + store_->set_active_node(nodes_.at(0).get()); + } + } + const std::string& StoryImpl::get_title() const + { + return title_; + } + + const Node* StoryImpl::get_current() const + { + if (!store_) + return nullptr; + return store_->get_active_node(); + } + + void StoryImpl::set_current(const Node* node) + { + store_->set_active_node(node); + } + + const store::Store* StoryImpl::get_store() const + { + return store_.get(); + } + + std::ostream& StoryImpl::display(std::ostream& os) const + { + os << "digraph story {\n"; + for (auto node = nodes_.begin(); node != nodes_.end(); node++) + { + auto choices = node->get()->list_choices(); + if (choices.size() == 0) + continue; + os << "\t\"" << node->get()->get_name() << "\" -> "; + if (choices.size() > 1) + { + os << "{"; + os << "\"" << to_impl(*node->get()->get_choice(0)).get_name() + << "\""; + for (size_t i = 1; i < choices.size(); i++) + { + os << " " << "\"" + << to_impl(*node->get()->get_choice(i)).get_name() + << "\""; + } + os << "}"; + } + else + { + os << "\"" << to_impl(*node->get()->get_choice(0)).get_name() + << "\""; + } + os << ";\n"; + } + os << "}\n"; + return os; + } + const StoryImpl& to_impl(const Story& story) + { + const StoryImpl* cast = dynamic_cast<const StoryImpl*>(&story); + if (!cast) + throw std::runtime_error{ + "Invalid conversion from const Node* to const NodeImpl*" + }; + return *cast; + } + StoryImpl& to_impl(Story& story) + { + StoryImpl* cast = dynamic_cast<StoryImpl*>(&story); + if (!cast) + throw std::runtime_error{ + "Invalid conversion from const Node* to const NodeImpl*" + }; + return *cast; + } +} // namespace libzork::story diff --git a/rushs/libzork/libzork/src/story/story_impl.hh b/rushs/libzork/libzork/src/story/story_impl.hh new file mode 100644 index 0000000..6062d2f --- /dev/null +++ b/rushs/libzork/libzork/src/story/story_impl.hh @@ -0,0 +1,31 @@ +#pragma once + +#include <libzork/story/story.hh> +#include <store/store_impl.hh> +#include <yaml-cpp/yaml.h> + +namespace libzork::story +{ + + class StoryImpl : public Story + { + public: + StoryImpl(const fs::path& path); + ~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; + + private: + std::string title_; + std::vector<std::unique_ptr<Node>> nodes_; + std::unique_ptr<store::Store> store_; + }; + + const StoryImpl& to_impl(const Story& story); + StoryImpl& to_impl(Story& story); + +} // namespace libzork::story diff --git a/rushs/libzork/libzork/src/vars/CMakeLists.txt b/rushs/libzork/libzork/src/vars/CMakeLists.txt new file mode 100644 index 0000000..8e3e5d5 --- /dev/null +++ b/rushs/libzork/libzork/src/vars/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.21.2) + +target_sources(libzork PRIVATE action.cc action_impl.cc condition.cc condition_impl.cc) +set_target_properties(libzork PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF)
\ No newline at end of file diff --git a/rushs/libzork/libzork/src/vars/action.cc b/rushs/libzork/libzork/src/vars/action.cc new file mode 100644 index 0000000..83d8c8e --- /dev/null +++ b/rushs/libzork/libzork/src/vars/action.cc @@ -0,0 +1,20 @@ +#include <libzork/vars/action.hh> + +#include "exceptions.hh" +#include "vars/action_impl.hh" + +namespace libzork::vars +{ + + std::unique_ptr<Action> 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/rushs/libzork/libzork/src/vars/action_impl.cc b/rushs/libzork/libzork/src/vars/action_impl.cc new file mode 100644 index 0000000..d0abcf7 --- /dev/null +++ b/rushs/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/rushs/libzork/libzork/src/vars/action_impl.hh b/rushs/libzork/libzork/src/vars/action_impl.hh new file mode 100644 index 0000000..bc7f933 --- /dev/null +++ b/rushs/libzork/libzork/src/vars/action_impl.hh @@ -0,0 +1,16 @@ +#pragma once + +#include <libzork/vars/action.hh> + +namespace libzork::vars +{ + + class ActionImpl : public Action + { + public: + ~ActionImpl() override = default; + + void apply() const override; + }; + +} // namespace libzork::vars diff --git a/rushs/libzork/libzork/src/vars/condition.cc b/rushs/libzork/libzork/src/vars/condition.cc new file mode 100644 index 0000000..d0fb648 --- /dev/null +++ b/rushs/libzork/libzork/src/vars/condition.cc @@ -0,0 +1,21 @@ +#include <libzork/store/store.hh> +#include <libzork/vars/condition.hh> + +#include "exceptions.hh" + +namespace libzork::vars +{ + + std::unique_ptr<Condition> 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/rushs/libzork/libzork/src/vars/condition_impl.cc b/rushs/libzork/libzork/src/vars/condition_impl.cc new file mode 100644 index 0000000..7d11fdc --- /dev/null +++ b/rushs/libzork/libzork/src/vars/condition_impl.cc @@ -0,0 +1,16 @@ +#include "vars/condition_impl.hh" + +#include <algorithm> +#include <map> + +#include "exceptions.hh" + +namespace libzork::vars +{ + + bool ConditionImpl::apply() const + { + throw NotImplemented(); + } + +} // namespace libzork::vars diff --git a/rushs/libzork/libzork/src/vars/condition_impl.hh b/rushs/libzork/libzork/src/vars/condition_impl.hh new file mode 100644 index 0000000..c8b300c --- /dev/null +++ b/rushs/libzork/libzork/src/vars/condition_impl.hh @@ -0,0 +1,16 @@ +#pragma once + +#include <libzork/vars/condition.hh> + +namespace libzork::vars +{ + + class ConditionImpl : public Condition + { + public: + ~ConditionImpl() override = default; + + bool apply() const override; + }; + +} // namespace libzork::vars diff --git a/rushs/libzork/libzork/tests/scripts/little_quest/castle.txt b/rushs/libzork/libzork/tests/scripts/little_quest/castle.txt new file mode 100644 index 0000000..23bef37 --- /dev/null +++ b/rushs/libzork/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/rushs/libzork/libzork/tests/scripts/little_quest/castle_weapon.txt b/rushs/libzork/libzork/tests/scripts/little_quest/castle_weapon.txt new file mode 100644 index 0000000..7e1d77f --- /dev/null +++ b/rushs/libzork/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/rushs/libzork/libzork/tests/scripts/little_quest/forest.txt b/rushs/libzork/libzork/tests/scripts/little_quest/forest.txt new file mode 100644 index 0000000..e37ad98 --- /dev/null +++ b/rushs/libzork/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/rushs/libzork/libzork/tests/scripts/little_quest/house.txt b/rushs/libzork/libzork/tests/scripts/little_quest/house.txt new file mode 100644 index 0000000..c285e6a --- /dev/null +++ b/rushs/libzork/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/rushs/libzork/libzork/tests/scripts/little_quest/tower.txt b/rushs/libzork/libzork/tests/scripts/little_quest/tower.txt new file mode 100644 index 0000000..2e61000 --- /dev/null +++ b/rushs/libzork/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/rushs/libzork/libzork/tests/scripts/short_static/cave.txt b/rushs/libzork/libzork/tests/scripts/short_static/cave.txt new file mode 100644 index 0000000..f77f4bf --- /dev/null +++ b/rushs/libzork/libzork/tests/scripts/short_static/cave.txt @@ -0,0 +1 @@ +This is a dark cave diff --git a/rushs/libzork/libzork/tests/scripts/short_static/forest.txt b/rushs/libzork/libzork/tests/scripts/short_static/forest.txt new file mode 100644 index 0000000..ac917ab --- /dev/null +++ b/rushs/libzork/libzork/tests/scripts/short_static/forest.txt @@ -0,0 +1 @@ +This is a large forest diff --git a/rushs/libzork/libzork/tests/scripts/short_static/welcome.txt b/rushs/libzork/libzork/tests/scripts/short_static/welcome.txt new file mode 100644 index 0000000..af5626b --- /dev/null +++ b/rushs/libzork/libzork/tests/scripts/short_static/welcome.txt @@ -0,0 +1 @@ +Hello, world! diff --git a/rushs/libzork/libzork/tests/stories/dynamic/story.yml b/rushs/libzork/libzork/tests/stories/dynamic/story.yml new file mode 100644 index 0000000..7d75431 --- /dev/null +++ b/rushs/libzork/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/rushs/libzork/libzork/tests/stories/long_static/story.yml b/rushs/libzork/libzork/tests/stories/long_static/story.yml new file mode 100644 index 0000000..152fad8 --- /dev/null +++ b/rushs/libzork/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/rushs/libzork/libzork/tests/stories/short_static/story.yml b/rushs/libzork/libzork/tests/stories/short_static/story.yml new file mode 100644 index 0000000..701a954 --- /dev/null +++ b/rushs/libzork/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: [] diff --git a/rushs/libzork/libzork/zorkxplorer/CMakeLists.txt b/rushs/libzork/libzork/zorkxplorer/CMakeLists.txt new file mode 100644 index 0000000..9633f06 --- /dev/null +++ b/rushs/libzork/libzork/zorkxplorer/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.21.2) +project(Zork) +add_subdirectory(src)
\ No newline at end of file diff --git a/rushs/libzork/libzork/zorkxplorer/src/CMakeLists.txt b/rushs/libzork/libzork/zorkxplorer/src/CMakeLists.txt new file mode 100644 index 0000000..88a75d1 --- /dev/null +++ b/rushs/libzork/libzork/zorkxplorer/src/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.21.2) +project(Zork) +target_sources(zork_test PUBLIC main.cc options.cc)
\ No newline at end of file diff --git a/rushs/libzork/libzork/zorkxplorer/src/hello.txt b/rushs/libzork/libzork/zorkxplorer/src/hello.txt new file mode 100644 index 0000000..05a682b --- /dev/null +++ b/rushs/libzork/libzork/zorkxplorer/src/hello.txt @@ -0,0 +1 @@ +Hello!
\ No newline at end of file diff --git a/rushs/libzork/libzork/zorkxplorer/src/main.cc b/rushs/libzork/libzork/zorkxplorer/src/main.cc new file mode 100644 index 0000000..2494d62 --- /dev/null +++ b/rushs/libzork/libzork/zorkxplorer/src/main.cc @@ -0,0 +1,63 @@ +#include <fstream> +#include <iostream> +#include <libzork/exceptions.hh> +#include <libzork/runner/choice.hh> +#include <libzork/runner/html.hh> +#include <libzork/runner/smart.hh> + +#include "options.hh" + +std::unique_ptr<libzork::story::Story> get_story(const Config& config) +{ + return libzork::story::make_story(config.story_path); +} + +std::unique_ptr<libzork::runner::Runner> +get_runner(const Config& config, std::unique_ptr<libzork::story::Story> 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; + } + + auto story = get_story(config); + auto output = std::ofstream( + "/home/martial.simon/afs/ing/zork/libzork/tests/output/dot.out"); + story->display(output); + + std::unique_ptr<libzork::runner::Runner> runner = + libzork::runner::make_choice_runner(std::move(story), std::cin, + std::cout); + + try + { + runner->run(); + } + catch (const libzork::RunnerQuit&) + {} + + return 0; +} diff --git a/rushs/libzork/libzork/zorkxplorer/src/options.cc b/rushs/libzork/libzork/zorkxplorer/src/options.cc new file mode 100644 index 0000000..e97a7ea --- /dev/null +++ b/rushs/libzork/libzork/zorkxplorer/src/options.cc @@ -0,0 +1,57 @@ +#include "options.hh" + +#include <getopt.h> +#include <iostream> + +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 <story.yml>)" + " [--smart <synonyms.yml> | --html <directory/>]"; + }; +} // 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/rushs/libzork/libzork/zorkxplorer/src/options.hh b/rushs/libzork/libzork/zorkxplorer/src/options.hh new file mode 100644 index 0000000..d3f919d --- /dev/null +++ b/rushs/libzork/libzork/zorkxplorer/src/options.hh @@ -0,0 +1,22 @@ +#pragma once + +#include <filesystem> +#include <optional> + +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/rushs/libzork/libzork/zorkxplorer/src/world.txt b/rushs/libzork/libzork/zorkxplorer/src/world.txt new file mode 100644 index 0000000..5dd01c1 --- /dev/null +++ b/rushs/libzork/libzork/zorkxplorer/src/world.txt @@ -0,0 +1 @@ +Hello, world!
\ No newline at end of file |
