{"id":17182098,"url":"https://github.com/jmtd/liquorice","last_synced_at":"2025-07-22T22:05:00.121Z","repository":{"id":66799088,"uuid":"138318625","full_name":"jmtd/liquorice","owner":"jmtd","description":"Haskell embedded domain-specific language (eDSL) for the algorithmic construction of maps for the computer game \"Doom\"","archived":false,"fork":false,"pushed_at":"2021-01-26T11:51:15.000Z","size":478,"stargazers_count":13,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-13T17:58:16.393Z","etag":null,"topics":["doom","edsl","fractal","game","haskell","logo","procedural-generation"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jmtd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-06-22T15:26:27.000Z","updated_at":"2024-03-09T19:29:29.000Z","dependencies_parsed_at":null,"dependency_job_id":"b86bcca8-52c0-48c6-9107-0788befc404c","html_url":"https://github.com/jmtd/liquorice","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/jmtd/liquorice","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmtd%2Fliquorice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmtd%2Fliquorice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmtd%2Fliquorice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmtd%2Fliquorice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jmtd","download_url":"https://codeload.github.com/jmtd/liquorice/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmtd%2Fliquorice/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266580319,"owners_count":23951198,"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","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["doom","edsl","fractal","game","haskell","logo","procedural-generation"],"created_at":"2024-10-15T00:35:59.704Z","updated_at":"2025-07-22T22:05:00.105Z","avatar_url":"https://github.com/jmtd.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Liquorice\n\n![](logo.png \"Liquorice Logo\")\n\n*Liquorice* is a system for constructing maps for the [computer game Doom](https://doomwiki.org/wiki/Doom) by writing algorithms to describe the geometry. A *Liquorice* program is a series of instructions to move a virtual \"turtle\" or \"pen\", which define the walls, floors, rooms and monsters as it goes.\n\nMore specifically, *Liquorice* is an embedded domain-specific language (eDSL) within the pure functional programming language [Haskell](https://www.haskell.org/).\n\n## Quick example\n\n    -- simple example, triangle (for orientation); unique texture per line\n    import Liquorice.Monad\n    import Liquorice.Render\n\n    main = buildWad \"example1.wad\" $ runWadL $ do\n        mid \"ZZWOLF1\"\n        draw 128 0\n        mid \"ZZWOLF2\"\n        draw 0 128\n        turnaround\n        mid \"ZZWOLF3\"\n        draw 128 128\n        rightsector 0 128 160\n        turnaround\n        step 64 32\n        thing\n\n## More detailed example\n\nSee [examples/birds.hs](examples/birds.hs), for an example program\nthat generates a complete playable map. The map targets Doom 1 / The\nUltimate Doom (map slot E2M8), and requires a doom engine with raised\nengine limits, such as [Crispy Doom](https://www.chocolate-doom.org/wiki/Crispy_Doom).\n\nThe generated PWAD, with nodes, ready to play: [birds.zip](https://redmars.org/liquorice/birds.zip)\n\n*birds.hs* is a re-implementation/transformation of [\"Bird Cage\"\nfor WadC](https://redmars.org/wadc/examples/#_birds_wl).\n\n## Getting Started\n\n### For Doom novices\n\nDoom's engine source code was open-sourced in 1996, but you need a copy of\nthe game's data files to use them. You can buy [The Ultimate Doom](https://www.gog.com/game/the_ultimate_doom) and [Doom II](https://www.gog.com/game/doom_ii_final_doom) at [Gog](http://www.gog.com/), amongst other places. Failing that, you could try [FreeDoom](https://freedoom.github.io/), a free-content game for Doom engines.\n\nExamples of powerful open source engines include [Crispy Doom](https://www.chocolate-doom.org/wiki/index.php/Crispy_Doom), [Eternity Engine](http://eternity.youfailit.net/wiki/Main_Page) and [GZDoom](https://zdoom.org/index).\n\n### For Haskell novices\n\n…\n\n## Evaluation\n\nThe commands that a typical *Liquorice* program will use are predominantly\nmonadic, and so make use of Haskell's \"do-notation\" for ordering. Internally,\nthe majority of these monadic functions are wrappers around pure equivalents\nwhich transform an input `Context` type into an output, e.g.:\n\n    xoff :: Int -\u003e Context -\u003e Context\n    xoff x c = c { paletteXoff = x }\n\n    place :: Int -\u003e Int -\u003e (Context -\u003e Context) -\u003e Context -\u003e Context\n    place x y fn c = c \u0026 step x y\n                       \u0026 fn\n                       \u0026 step (-1 * x) (-1 * y)\n\nThe pure functions can be combined using the infix operator `\u0026` (from\n`Data.Function`), or the more usual composition operator (which reads\nback-to-front). However, the monadic versions are probably more user-\nfriendly, and so the separate pure implementations might go away or\nstop being explicitly exported at some point. We also probably need to\nuse the monadic versions if we want to introduce randomness or debug IO\nin the middle of a program.\n\nA series of monadic Liquorice statements are converted into a final `Context`\nvia `runWadL`. A `Context` is written to an output PWAD file via\n\n    buildWad :: FilePath -\u003e Context -\u003e IO ()\n\nInternally, `buildWad` first converts a `Context` into an intermediate data\nstructure `WadMap`, which closely resembles the binary structure of a PWAD.\n(`WadMap` itself is a specialisation of `Wad`, imposing the presence of map\n specific lumps)\n\n\n## Pros/Cons\n\nPros:\n\n* Unlike WadC, you have full access to the Context at any point in your\n  program, which you can inspect or transform as you wish.\n* You also have the full power of the Haskell programming language.\n* In particular simply infix numeric operators are hugely useful.\n\nCons:\n\n* There's no GUI.\n* The Pure-versus-Monadic functions are a bit awkward and I might get rid of the\npure versions altogether in the future\n* There are some slow parts (line splitting in particular)\n* If you don't know Haskell, this will be very hard to use and most error messages\nwill make little sense.\n* You need a Haskell development environment installed to use *Liquorice*.\n\n## Code overview\n\nThe following three source files are the ones that you will want to import\nas modules to your Liquorice program:\n\n * `Liquorice.hs` — The main `Context` definition and most basic pure operations\n * `Liquorice/Monad.hs` — monadic wrappers around the above, + some more\n * `Liquorice/Render.hs` — exports `buildWad` for exporting a PWAD\n\nThese are back-end implementation details:\n\n * `Liquorice/Pure.hs` — most of the \"standard library\", in pure functions\n * `Liquorice/Line.hs` — `Line` type, line splitting and tests\n * `Liquorice/Wad.hs` — Wad and WadMap definitions and binary serialisation\n * `TestMain.hs` — HTF test harness\n\n## Author\n\n*Liquorice* was created by [Jonathan Dowland](https://jmtd.net/) and is\ndistributed under the terms of the GNU Public License, version 3 (see\n[COPYING](COPYING)).\n\nThe design of *Liquorice* is heavily\ninfluenced by [Wad Language (WadC)](https://jmtd.net/wadc/), which in turn owes\na debt to [LOGO](http://el.media.mit.edu/logo-foundation/what_is_logo/logo_programming.html).\n\n## See also\n\n * [Jonathan Dowland's homepage](https://jmtd.net/)\n * [WadC](https://jmtd.net/wadc/)\n * [The Doom Wiki](https://doomwiki.org/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmtd%2Fliquorice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjmtd%2Fliquorice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmtd%2Fliquorice/lists"}