diff options
| author | Freya Murphy <freya@freyacat.org> | 2025-10-07 11:01:19 -0400 |
|---|---|---|
| committer | Freya Murphy <freya@freyacat.org> | 2025-10-08 19:37:15 -0400 |
| commit | b11f074ceba10af62b35b414ecaa51a8f13c6550 (patch) | |
| tree | d12979f7eeb384f94b145ea763a97dcde353745b | |
| parent | Initial commit (diff) | |
| download | DungeonCrawl-b11f074ceba10af62b35b414ecaa51a8f13c6550.tar.gz DungeonCrawl-b11f074ceba10af62b35b414ecaa51a8f13c6550.tar.bz2 DungeonCrawl-b11f074ceba10af62b35b414ecaa51a8f13c6550.zip | |
initial baseline
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Cargo.lock | 432 | ||||
| -rw-r--r-- | Cargo.toml | 33 | ||||
| -rw-r--r-- | dungeon/Cargo.lock | 157 | ||||
| -rw-r--r-- | dungeon/Cargo.toml | 10 | ||||
| -rw-r--r-- | dungeon/src/lib.rs | 58 | ||||
| -rw-r--r-- | dungeon/src/map.rs | 189 | ||||
| -rw-r--r-- | dungeon/src/pos.rs | 122 | ||||
| -rw-r--r-- | flake.lock | 61 | ||||
| -rw-r--r-- | flake.nix | 54 | ||||
| -rw-r--r-- | game/Cargo.toml | 11 | ||||
| -rw-r--r-- | game/src/main.rs | 10 | ||||
| -rw-r--r-- | graphics/Cargo.toml | 15 | ||||
| -rw-r--r-- | graphics/src/lib.rs | 31 | ||||
| -rw-r--r-- | rustfmt.toml | 5 |
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 |