{"id":18812875,"url":"https://github.com/facundoolano/advenjure","last_synced_at":"2025-10-05T03:26:23.822Z","repository":{"id":57713044,"uuid":"52990233","full_name":"facundoolano/advenjure","owner":"facundoolano","description":"Text adventure engine written in Clojure and ClojureScript","archived":false,"fork":false,"pushed_at":"2017-10-28T22:33:33.000Z","size":615,"stargazers_count":311,"open_issues_count":37,"forks_count":18,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-04-14T06:47:18.914Z","etag":null,"topics":["adventure-game","adventure-game-engine","clojure","game-development","interactive-fiction","text-adventure"],"latest_commit_sha":null,"homepage":"https://facundoolano.github.io/advenjure/","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/facundoolano.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-02T19:31:24.000Z","updated_at":"2024-02-23T20:05:18.000Z","dependencies_parsed_at":"2022-09-05T22:50:47.508Z","dependency_job_id":null,"html_url":"https://github.com/facundoolano/advenjure","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facundoolano%2Fadvenjure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facundoolano%2Fadvenjure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facundoolano%2Fadvenjure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/facundoolano%2Fadvenjure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/facundoolano","download_url":"https://codeload.github.com/facundoolano/advenjure/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247332612,"owners_count":20921853,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adventure-game","adventure-game-engine","clojure","game-development","interactive-fiction","text-adventure"],"created_at":"2024-11-07T23:35:27.295Z","updated_at":"2025-10-05T03:26:18.210Z","avatar_url":"https://github.com/facundoolano.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# advenjure [![Build Status](https://secure.travis-ci.org/facundoolano/advenjure.png)](http://travis-ci.org/facundoolano/advenjure)\n\n![Example game](example.gif)\n\nAdvenjure is a text adventure (or interactive fiction) game engine. I wrote it as an excuse to learn Clojure.\nSome of its distinctive features are:\n\n  * Target the terminal and the browser with the same codebase.\n  * Unix-like prompt with smart tab completion and command history\n  * Customizable verbs and plugins.\n  * LucasArts inspired dialog trees.\n\n## Example game\n\nYou can see the code for a working example in the [advenjure-example](https://github.com/facundoolano/advenjure-example) repository and play it online [here](https://facundoolano.github.io/advenjure).\n\nFor a fully fledged game see [House Taken Over](https://github.com/facundoolano/house-taken-over).\n\n## Installation\n\nAdd the following to your project map as a dependency:\n\n```clojure\n[advenjure \"0.9.0\"]\n```\n\n## Basic Usage\n\n### Creating items\n\nText adventures consist mainly of moving around rooms and interacting with items\nthrough verb commands such as GO, LOOK, TAKE, etc.\n\nItems are represented by maps in advenjure. the `advenjure.items/make`\nfunction takes a name, a description and a set of key-value pairs to customize behavior.\nFor example:\n\n```clojure\n(require '[advenjure.items :as items])\n\n(def magazine (items/make \"magazine\"\n                          \"The cover read 'Sports Almanac 1950-2000'\"\n                          :take true\n                          :read \"Oh là là? Oh là là!?\"))\n```\n\nThat will define a magazine item that can be taken (put in the player's inventory)\nand can be read (which differs from looking at it).\n\nYou can provide a vector of names so the player can refer to it by one of its synonyms;\nthe first name in the vector will be considered its canonical name:\n\n```clojure\n(def magazine (items/make [\"magazine\" \"sports magazine\" \"newspaper\"]\n                          \"The cover read 'Sports Almanac 1950-2000'\"\n                          :take true\n                          :read \"Oh là là? Oh là là!?\"))\n```\n\nLike `:take` and `:read` there are keywords for the other actions\n(`:look-at`, `:open`, `:close`, `:unlock`, etc.).\n\nA special kind of items are those that can contain other items:\n\n```clojure\n(def magazine (items/make \"bag\" :items #{magazine} :closed true))\n```\n\nThe bag contains the magazine, but since it's `:closed` the player needs to open it\nbefore being able to look inside it and take its contents. Note that marking an\nobject as `:closed` also implies that OPEN and CLOSE verbs can be applied to it\n(i.e. it means `:open true, :close true`).\n\n### Creating rooms\n\nOnce you've created a bunch of items, you'll need to put them in a room (if not directly\ninto the player's inventory). Rooms are also maps and also have an\n`advenjure.rooms/make` function to build them:\n\n```clojure\n(require '[advenjure.rooms :as rooms])\n\n(def bedroom (rooms/make \"Bedroom\"\n                         \"A smelling bedroom.\"\n                         :initial-description \"I woke up in a smelling little bedroom, without windows.\"))\n```\n\nNote that rooms can have only one name. `:initial-description` is an optional attribute\nto define how the player will describe a room the first time he visits it,\nusually with a more verbose description. If `:initial-description` is not defined,\nand whenever the LOOK AROUND command is entered, the regular description will be used.\n\nTo add items to a room use `advenjure.rooms/add-item`:\n\n```clojure\n(def bedroom (-\u003e (rooms/make \"Bedroom\"\n                             \"A smelling bedroom.\"\n                             :initial-description \"I woke up in a smelling little bedroom, without windows.\")\n                 (rooms/add-item (items/make \"bed\" \"It was the bed I slept in.\"))\n                 (rooms/add-item magazine \"On the floor was a sports magazine.\")))\n```\n\nThe second parameter is an optional room-specific description of the item. It will be used\nto mention the item while describing the room (as opposed of the default `a \u003citem\u003e is here.`).\n\n### Building a room map\n\nOnce you have some rooms, you need to connect them to build a room map, which is\nnothing but a plain clojure hash map. First map the room to some id keyword,\nthen connect the rooms using the `advenjure.rooms/connect` function:\n\n```clojure\n(def room-map (-\u003e {:bedroom bedroom\n                   :living living\n                   :outside outside}\n                  (rooms/connect :bedroom :north :living)\n                  (rooms/connect :living :east :outside)))\n```\n\nAn alternative function, `advenjure.rooms/one-way-connect`, allows connecting the\nrooms just in one direction.\n\n### Building and running a game\n\nThe next building block is the game map itself, which contains the room map,\nthe player's inventory and a pointer to the current room. `advenjure.game/make`\nhelps to build it:\n\n```clojure\n(require '[advenjure.game :as game])\n\n(game/make room-map :bedroom)\n```\n\nThe room keyword defines what room the player will be in when the game starts.\nIf you want to start off the game with some items in the player's inventory,\njust pass them in a set as the third argument.\n\nLastly, the `advenjure.game/run` takes a game state map, a boolean function\nto tell if the game has finished and an optional string to print before it starts.\nPutting it all together in a `-main` function:\n\n```clojure\n(defn -main\n  \"Build and run the game.\"\n  [\u0026 args]\n  (let [game-state (game/make room-map :bedroom)\n        finished? #(= (:current-room %) :outside)]\n    (game/run game-state finished? :start-message \"Welcome to the advenjure!\")))\n```\n\nThe game flows by taking the initial game state map, prompting the user for a command,\napplying the command to produce a new game state and repeat the process until the\n`finished?` condition is met, which, in the example above means entering the\n`:outside` room.\n\n## Advanced Usage\n\nThere is a number of advanced features available in the engine:\n\n  * Overriding messages: use custom messages for a given action on a room or item.\n  * Pre conditions: function hook to define whether an action can be performed.\n  * Post conditions: function hook to customize how the game state is modified after an action is performed.\n  * Dialogs: interactive dialogs with 'character' items, in the style of the LucasArts graphic adventures.\n  * Text customization and internationalization.\n  * Custom verbs/commands.\n  * Plugin hooks to customize behavior without modifying the library.\n\nI'm waiting for the APIs to stabilize (and get a lot of free time) before fully documenting all those features,\nbut I'd be happy to write something up if you need help with something specific, just file an issue!\n\n## Run on the browser\n\nThe codebase is prepared to run both in the terminal with Clojure and the browser with ClojureScript.\nAn example configuration, using lein-cljsbuild would be:\n\n```clojure\n:cljsbuild\n    {:builds\n     {:main {:source-paths [\"src\"]\n             :compiler {:output-to \"main.js\"\n                        :main example.core\n                        :optimizations :simple\n                        :pretty-print false\n                        :optimize-constants true\n                        :static-fns true}}}\n```\n\nThen the command `lein cljsbuild once` will output a `main.js` file that can be included in any web page to run the game.\nThe HTML should have a `#terminal` div and include the [jQuery Terminal CSS](https://github.com/facundoolano/advenjure-example/blob/master/resources/jquery.terminal-0.11.7.css) to properly render the terminal.\n\nThe current limitations of the ClojureScript version of the library are:\n* No internationalization support (since clojure-gettext does not support ClojureScript).\n* Can use up to `:simple` optimizations (not `:advanced`), since [ClojureScript self-hosting](https://github.com/clojure/clojurescript/wiki/Optional-Self-hosting) is required for some of the advanced features.\n\nSee the [advenjure-example](https://github.com/facundoolano/advenjure-example) for a game that targets both the terminal and the browser.\n\n## Roadmap\n\n[Check the milestones](https://github.com/facundoolano/advenjure/milestones).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacundoolano%2Fadvenjure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffacundoolano%2Fadvenjure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffacundoolano%2Fadvenjure/lists"}