summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-10-07 11:01:19 -0400
committerFreya Murphy <freya@freyacat.org>2025-10-08 19:37:15 -0400
commitb11f074ceba10af62b35b414ecaa51a8f13c6550 (patch)
treed12979f7eeb384f94b145ea763a97dcde353745b
parentInitial commit (diff)
downloadDungeonCrawl-b11f074ceba10af62b35b414ecaa51a8f13c6550.tar.gz
DungeonCrawl-b11f074ceba10af62b35b414ecaa51a8f13c6550.tar.bz2
DungeonCrawl-b11f074ceba10af62b35b414ecaa51a8f13c6550.zip
initial baseline
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock432
-rw-r--r--Cargo.toml33
-rw-r--r--dungeon/Cargo.lock157
-rw-r--r--dungeon/Cargo.toml10
-rw-r--r--dungeon/src/lib.rs58
-rw-r--r--dungeon/src/map.rs189
-rw-r--r--dungeon/src/pos.rs122
-rw-r--r--flake.lock61
-rw-r--r--flake.nix54
-rw-r--r--game/Cargo.toml11
-rw-r--r--game/src/main.rs10
-rw-r--r--graphics/Cargo.toml15
-rw-r--r--graphics/src/lib.rs31
-rw-r--r--rustfmt.toml5
15 files changed, 1189 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..e581bad
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,432 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
+
+[[package]]
+name = "bindgen"
+version = "0.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f"
+dependencies = [
+ "bitflags",
+ "cexpr",
+ "clang-sys",
+ "itertools",
+ "log",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash",
+ "shlex",
+ "syn",
+]
+
+[[package]]
+name = "bitflags"
+version = "2.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
+
+[[package]]
+name = "cc"
+version = "1.2.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1d05d92f4b1fd76aad469d46cdd858ca761576082cd37df81416691e50199fb"
+dependencies = [
+ "find-msvc-tools",
+ "shlex",
+]
+
+[[package]]
+name = "cexpr"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
+
+[[package]]
+name = "clang-sys"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
+dependencies = [
+ "glob",
+ "libc",
+ "libloading",
+]
+
+[[package]]
+name = "cmake"
+version = "0.1.54"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "dungeon"
+version = "0.1.0"
+dependencies = [
+ "rand",
+]
+
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3"
+
+[[package]]
+name = "game"
+version = "0.1.0"
+dependencies = [
+ "dungeon",
+ "graphics",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasi",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
+
+[[package]]
+name = "graphics"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "dungeon",
+ "raylib",
+]
+
+[[package]]
+name = "itertools"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.176"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
+
+[[package]]
+name = "libloading"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
+dependencies = [
+ "cfg-if",
+ "windows-link",
+]
+
+[[package]]
+name = "log"
+version = "0.4.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
+
+[[package]]
+name = "memchr"
+version = "2.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "prettyplease"
+version = "0.2.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
+dependencies = [
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.101"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "rand"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
+dependencies = [
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "raylib"
+version = "5.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5c54335590d1b6e6fbdbccee09dafdfd76a1111fc3c709eca949e71e81f7a8a"
+dependencies = [
+ "cfg-if",
+ "paste",
+ "raylib-sys",
+ "seq-macro",
+ "thiserror",
+]
+
+[[package]]
+name = "raylib-sys"
+version = "5.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ce5adc950b042db67f1f78f24f7e76563652ce24db032afe9ca9e534d8b7a13"
+dependencies = [
+ "bindgen",
+ "cc",
+ "cmake",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "seq-macro"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc"
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "syn"
+version = "2.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
+
+[[package]]
+name = "wasi"
+version = "0.14.7+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
+dependencies = [
+ "wasip2",
+]
+
+[[package]]
+name = "wasip2"
+version = "1.0.1+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
+
+[[package]]
+name = "wit-bindgen"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
+
+[[package]]
+name = "zerocopy"
+version = "0.8.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..c553f8e
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,33 @@
+[workspace]
+members = ["dungeon", "game", "graphics"]
+resolver = "2"
+
+[workspace.lints.clippy]
+# nursery
+branches_sharing_code = "warn"
+collection_is_never_read = "warn"
+derive_partial_eq_without_eq = "warn"
+return_self_not_must_use = "warn"
+use_self = "warn"
+
+# pedantic
+cast_possible_wrap = "warn"
+cast_possible_truncation = "warn"
+inconsistent_struct_constructor = "warn"
+manual_assert = "warn"
+map_unwrap_or = "warn"
+needless_pass_by_value = "warn"
+redundant_closure_for_method_calls = "warn"
+redundant_else = "warn"
+semicolon_if_nothing_returned = "warn"
+single_match_else = "warn"
+uninlined_format_args = "warn"
+unused_self = "warn"
+unnested_or_patterns = "warn"
+used_underscore_binding = "warn"
+
+# restriction
+allow_attributes = "warn"
+expect_used = "deny"
+shadow_reuse = "warn"
+unwrap_used = "deny"
diff --git a/dungeon/Cargo.lock b/dungeon/Cargo.lock
new file mode 100644
index 0000000..b9a6727
--- /dev/null
+++ b/dungeon/Cargo.lock
@@ -0,0 +1,157 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "cfg-if"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
+
+[[package]]
+name = "dungeon"
+version = "0.1.0"
+dependencies = [
+ "rand",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasi",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.176"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.101"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
+[[package]]
+name = "rand"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
+dependencies = [
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
+
+[[package]]
+name = "wasi"
+version = "0.14.7+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
+dependencies = [
+ "wasip2",
+]
+
+[[package]]
+name = "wasip2"
+version = "1.0.1+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
+dependencies = [
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wit-bindgen"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
+
+[[package]]
+name = "zerocopy"
+version = "0.8.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/dungeon/Cargo.toml b/dungeon/Cargo.toml
new file mode 100644
index 0000000..5548248
--- /dev/null
+++ b/dungeon/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "dungeon"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+rand = "0.9"
+
+[lints]
+workspace = true
diff --git a/dungeon/src/lib.rs b/dungeon/src/lib.rs
new file mode 100644
index 0000000..66faec3
--- /dev/null
+++ b/dungeon/src/lib.rs
@@ -0,0 +1,58 @@
+//! The `dungon` crate contains the core functionality for
+//! interacting with a `Dungeon` and its components.
+
+mod map;
+mod pos;
+
+pub use map::*;
+pub use pos::*;
+
+/// The `Dungeon` type represents the game state of the
+/// dungeon crawler.
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct Dungeon {
+ player: Entity,
+ floor: Floor,
+}
+impl Dungeon {
+ /// Creates a new `Dungeon`.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use dungeon::Dungeon;
+ ///
+ /// let dungeon = Dungeon::new();
+ /// ```
+ #[must_use]
+ pub fn new() -> Self {
+ let floor = Floor::generate();
+ let player = Entity::player(floor.player_start());
+
+ Self { player, floor }
+ }
+
+ /// Creates a new `Dungeon` with a provided seed.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use dungeon::Dungeon;
+ ///
+ /// let seed = 234690523482u64;
+ /// let dungeon = Dungeon::new_seeded(seed);
+ /// ```
+ #[must_use]
+ pub fn new_seeded(seed: u64) -> Self {
+ let floor = Floor::generate_seeded(seed);
+ let player = Entity::player(floor.player_start());
+
+ Self { player, floor }
+ }
+}
+
+impl Default for Dungeon {
+ fn default() -> Self {
+ Self::new()
+ }
+}
diff --git a/dungeon/src/map.rs b/dungeon/src/map.rs
new file mode 100644
index 0000000..8c4328c
--- /dev/null
+++ b/dungeon/src/map.rs
@@ -0,0 +1,189 @@
+//! The `map` module contains structures of the dungeon game map
+//! including the current `Floor`, map `Tile`, and `Entity`.
+
+use crate::pos::{Direction, Pos};
+
+/// `MAP_SIZE` is the size of the size of the dungeon grid.
+pub const MAP_SIZE: u16 = 100;
+
+/// The number of tiles in the dungeon grid
+pub const TILE_COUNT: usize = MAP_SIZE as usize * MAP_SIZE as usize;
+
+/// The `EntityKind` represents what kind of entity this is.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum EntityKind {
+ Player,
+}
+
+/// The `Entity` kind represents the main player, or any other
+/// ai autonomous character that can move freely across the
+/// dungeon.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct Entity {
+ pos: Pos,
+ dir: Direction,
+ kind: EntityKind,
+}
+impl Entity {
+ /// Creates a new `Entity` at a given `Pos`, `Direction`, and `EntityKind`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use dungeon::{Pos, Direction, Entity, EntityKind};
+ ///
+ /// let pos = Pos::new(0, 0).unwrap();
+ /// let dir = Direction::North;
+ /// let kind = EntityKind::Player;
+ /// let entity = Entity::new(pos, dir, kind);
+ /// ```
+ #[must_use]
+ pub const fn new(pos: Pos, dir: Direction, kind: EntityKind) -> Self {
+ Self { pos, dir, kind }
+ }
+
+ /// Creates the Player version of the `Entity`
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use dungeon::{Pos, Entity};
+ ///
+ /// let pos = Pos::new(0, 0).unwrap();
+ /// let player = Entity::player(pos);
+ /// ```
+ #[must_use]
+ pub const fn player(pos: Pos) -> Self {
+ let dir = Direction::East;
+ let kind = EntityKind::Player;
+ Self::new(pos, dir, kind)
+ }
+
+ /// Returns the `Pos` of the entity
+ #[must_use]
+ pub const fn pos(&self) -> Pos {
+ self.pos
+ }
+
+ /// Returns a mutable referense to the `Pos` of the entity
+ #[must_use]
+ pub const fn pos_mut(&mut self) -> &mut Pos {
+ &mut self.pos
+ }
+
+ /// Returns the `Direction` of the entity
+ #[must_use]
+ pub const fn dir(&self) -> Direction {
+ self.dir
+ }
+
+ /// Returns a mutable referense to the `Direction` of the entity
+ #[must_use]
+ pub const fn dir_mut(&mut self) -> &mut Direction {
+ &mut self.dir
+ }
+
+ /// Returns the `EntityKind` of this entity
+ #[must_use]
+ pub const fn kind(&self) -> EntityKind {
+ self.kind
+ }
+}
+
+/// The `Tile` enum represents what is (or is not) at
+/// any given spot in the dungeon grid.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum Tile {
+ /// `Wall` represents an impassible wall
+ Wall,
+ /// `Air` represents empty walkable space
+ Air,
+}
+
+/// The `Floor` type represents the current playing
+/// grid of the dungeon. It contains the tiles of the
+/// grid, and the starting position of the player.
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct Floor {
+ /// The dungeon grid
+ tiles: Box<[Tile; TILE_COUNT]>,
+ /// The position the player starts at
+ player_start: Pos,
+ /// The seed used when generating the dungeon grid
+ seed: u64,
+}
+impl Floor {
+ /// Generates a dungeon `Floor` using wave function collapse.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use dungeon::Floor;
+ ///
+ /// let floor = Floor::generate();
+ /// ```
+ #[must_use]
+ pub fn generate() -> Self {
+ let seed = rand::random();
+ Self::generate_seeded(seed)
+ }
+
+ /// Genreates a dungeon `Floor` using wave function collapse provided with a seed.
+ ///
+ /// The provided seed is used for randomness in the wave function
+ /// collapse algorithm.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use dungeon::Floor;
+ ///
+ /// /// here is our very seedy seed
+ /// let seed = 2893249402u64;
+ /// let floor = Floor::generate_seeded(seed);
+ /// ```
+ #[must_use]
+ pub fn generate_seeded(_seed: u64) -> Self {
+ unimplemented!()
+ }
+
+ /// Returns the start position of the player
+ #[must_use]
+ pub const fn player_start(&self) -> Pos {
+ self.player_start
+ }
+
+ /// Returns the seed used to generate the map
+ #[must_use]
+ pub const fn seed(&self) -> u64 {
+ self.seed
+ }
+
+ /// Returns a `Tile` on the dungeon grid at `Pos`.
+ #[must_use]
+ pub const fn get(&self, pos: Pos) -> Tile {
+ let idx = pos.idx();
+ self.tiles[idx]
+ }
+
+ /// Returns a multable reference to a `Tile` on the dungeon grid at `Pos`.
+ #[must_use]
+ pub const fn get_mut(&mut self, pos: Pos) -> &mut Tile {
+ let idx = pos.idx();
+ &mut self.tiles[idx]
+ }
+
+ /// Returns a reference to all tiles in the `Floor`.
+ /// The size of this lise will always be `TILE_COUNT` long.
+ #[must_use]
+ pub const fn tiles(&self) -> &[Tile] {
+ &*self.tiles
+ }
+
+ /// Returns a mutable reference to all tiles in the `Floor`.
+ /// The size of this lise will always be `TILE_COUNT` long.
+ #[must_use]
+ pub const fn tiles_mut(&mut self) -> &mut [Tile] {
+ &mut *self.tiles
+ }
+}
diff --git a/dungeon/src/pos.rs b/dungeon/src/pos.rs
new file mode 100644
index 0000000..bfd994f
--- /dev/null
+++ b/dungeon/src/pos.rs
@@ -0,0 +1,122 @@
+//! The `pos` module contains structures for representation an
+//! entity or objects position and facing direction inside the
+//! dungeon grid.
+
+use crate::map::MAP_SIZE;
+
+/// The `Direction` type represents a direction an entity
+/// or any position object is facing inside the dungeon map.
+/// Since the dungeon lives on a grid, there are only four
+/// possible directions.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum Direction {
+ North,
+ South,
+ East,
+ West,
+}
+
+/// The `Pos` type represents a 2D position inside the dungeon grid.
+///
+/// The max size for the dungeon map is set by the `MAP_SIZE` constant
+/// and therefore the x and y positions can be between 0 and `MAP_SIZE - 1`.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct Pos(u16, u16);
+impl Pos {
+ /// Creates a new position from a given x and y position.
+ ///
+ /// Returns `None` if the position goes out of the map.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use dungeon::Pos;
+ ///
+ /// let pos = Pos::new(0,0);
+ /// assert!(pos.is_some());
+ /// ```
+ ///
+ /// ```
+ /// use dungeon::{Pos, MAP_SIZE};
+ ///
+ /// let pos = Pos::new(MAP_SIZE, MAP_SIZE);
+ /// assert!(pos.is_none())
+ /// ```
+ #[must_use]
+ pub const fn new(x: u16, y: u16) -> Option<Self> {
+ if x >= MAP_SIZE || y >= MAP_SIZE {
+ None
+ } else {
+ Some(Self(x, y))
+ }
+ }
+
+ /// Returns the x and y positions of `Pos`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use dungeon::Pos;
+ ///
+ /// let pos = Pos::new(5,7).unwrap();
+ /// let (x,y) = pos.xy();
+ /// assert_eq!(x, 5);
+ /// assert_eq!(y, 7);
+ /// ```
+ #[must_use]
+ pub const fn xy(self) -> (u16, u16) {
+ (self.0, self.1)
+ }
+
+ /// Converts the x and y positions into an index of a continous list.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use dungeon::{Pos, MAP_SIZE};
+ ///
+ /// let pos = Pos::new(1,2).unwrap();
+ /// let idx = pos.idx();
+ /// assert_eq!(idx, 1 + 2 * MAP_SIZE as usize);
+ /// ```
+ #[must_use]
+ pub const fn idx(self) -> usize {
+ let (x, y) = self.xy();
+ let idx = x + y * MAP_SIZE;
+ idx as usize
+ }
+
+ /// Steps `Pos` one space in the `Direction` `dir`.
+ ///
+ /// Returns `None` if the position goes out of the map.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use dungeon::{Direction, Pos};
+ ///
+ /// let pos = Pos::new(0, 1).unwrap();
+ /// let new_pos = pos.step(Direction::North);
+ /// assert_eq!(new_pos, Pos::new(0, 0));
+ /// ```
+ ///
+ /// ```
+ /// use dungeon::{Direction, Pos};
+ ///
+ /// let pos = Pos::new(0, 1).unwrap();
+ /// let new_pos = pos.step(Direction::West);
+ /// assert!(new_pos.is_none());
+ /// ```
+ #[must_use]
+ pub const fn step(self, dir: Direction) -> Option<Self> {
+ use Direction as D;
+ let (x, y) = self.xy();
+ match dir {
+ D::North if y > 0 => Self::new(x, y - 1),
+ D::South => Self::new(x, y + 1),
+ D::East => Self::new(x + 1, y),
+ D::West if x > 0 => Self::new(x - 1, y),
+ _ => None,
+ }
+ }
+}
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..664ccda
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,61 @@
+{
+ "nodes": {
+ "flake-utils": {
+ "inputs": {
+ "systems": "systems"
+ },
+ "locked": {
+ "lastModified": 1731533236,
+ "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1759381078,
+ "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "flake-utils": "flake-utils",
+ "nixpkgs": "nixpkgs"
+ }
+ },
+ "systems": {
+ "locked": {
+ "lastModified": 1681028828,
+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+ "owner": "nix-systems",
+ "repo": "default",
+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-systems",
+ "repo": "default",
+ "type": "github"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..f39a7c1
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,54 @@
+{
+ description = "unnamed game";
+
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+ flake-utils.url = "github:numtide/flake-utils";
+ };
+
+ outputs = {
+ nixpkgs,
+ flake-utils,
+ ...
+ }: let
+ supportedSystems = let
+ inherit (flake-utils.lib) system;
+ in [
+ system.aarch64-linux
+ system.x86_64-linux
+ ];
+ in
+ flake-utils.lib.eachSystem supportedSystems (system: let
+ pkgs = import nixpkgs {inherit system;};
+ libs = with pkgs; [
+ libGL
+ wayland
+ xorg.libXrandr
+ xorg.libXinerama
+ xorg.libXcursor
+ xorg.libXi
+ ];
+ in {
+ devShell =
+ pkgs.mkShell
+ {
+ packages = with pkgs; [
+ # rust
+ rustc
+ rustfmt
+ rust-analyzer
+ cargo
+ clippy
+ # raylib
+ cmake
+ clang
+ glfw
+ pkg-config
+ ] ++ libs;
+ LD_LIBRARY_PATH = libs;
+ LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
+ };
+
+ formatter = pkgs.alejandra;
+ });
+}
diff --git a/game/Cargo.toml b/game/Cargo.toml
new file mode 100644
index 0000000..01a8ec9
--- /dev/null
+++ b/game/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "game"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+dungeon = { path = "../dungeon" }
+graphics = { path = "../graphics" }
+
+[lints]
+workspace = true
diff --git a/game/src/main.rs b/game/src/main.rs
new file mode 100644
index 0000000..252830a
--- /dev/null
+++ b/game/src/main.rs
@@ -0,0 +1,10 @@
+use dungeon::*;
+use graphics::*;
+
+fn main() {
+ let mut window = Window::new(720, 480, "game");
+ let dungeon = Dungeon::new();
+ while window.is_open() {
+ window.draw(&dungeon);
+ }
+}
diff --git a/graphics/Cargo.toml b/graphics/Cargo.toml
new file mode 100644
index 0000000..0842f90
--- /dev/null
+++ b/graphics/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "graphics"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+anyhow = "1"
+dungeon = { path = "../dungeon" }
+raylib = "5.5"
+
+[target.'cfg(target_os = "linux")'.dependencies]
+raylib = { version = "5.5", features = ["wayland"] }
+
+[lints]
+workspace = true
diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs
new file mode 100644
index 0000000..c0b0019
--- /dev/null
+++ b/graphics/src/lib.rs
@@ -0,0 +1,31 @@
+use dungeon::Dungeon;
+use raylib::prelude::*;
+
+pub struct Window {
+ handle: RaylibHandle,
+ thread: RaylibThread,
+}
+impl Window {
+ /// Instantiates a new window provided with the default
+ /// window `width`, `height`, and `title`.
+ pub fn new(width: i32, height: i32, title: &str) -> Self {
+ let (handle, thread) = raylib::init()
+ .size(width, height)
+ .title(title)
+ .resizable()
+ .log_level(TraceLogLevel::LOG_WARNING)
+ .build();
+ Self { handle, thread }
+ }
+
+ /// Returns if the window should be closed.
+ /// This usually means the 'x' button has been pressed.
+ pub fn is_open(&self) -> bool {
+ !self.handle.window_should_close()
+ }
+
+ /// Draws a frame provided with the game state `Dungeon`
+ pub fn draw(&mut self, _dungeon: &Dungeon) {
+ let _draw = self.handle.begin_drawing(&self.thread);
+ }
+}
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..2c29b8d
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1,5 @@
+hard_tabs = true
+tab_spaces = 4
+max_width = 92
+
+use_field_init_shorthand = true