diff --git a/README.md b/README.md index 81c5126..f806b1e 100644 --- a/README.md +++ b/README.md @@ -14,3 +14,5 @@ This doesn't work and isn't ever likely to fully work: it's way too ambitious fo Copyright (c) 2019 Simon Brooke; licenced under the [GNU General Public Licence](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html), either version 2 or, at your option, any later version. +Some assets from [jMonkeyEngine](https://jmonkeyengine.org/) examples are currently included in this repository; they are under [a BSD-style licence](https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/LICENSE.md). + diff --git a/doc/Game-engine-integration.md b/doc/Game-engine-integration.md deleted file mode 100644 index e6f8fa4..0000000 --- a/doc/Game-engine-integration.md +++ /dev/null @@ -1,7 +0,0 @@ -# Game-engine integration (unfinished) - -To build a game using these ideas we need a lot of things that are well understood and already implemented: rendering a world, moving models of characters in a world, and so on. This collection of technologies which allow us to realise an interactive realisation of a world is typically called a game engine. - -It's my intention that the bits that I add to the mix should be open source in the hard sense of that phrase, fully free software released under GPL. They cannot therfore be directly linked to a proprietary game engine. - -But the current state of play is that the best and easiest to work with game engines are not open source; and while I could build a demo game using, for example, the [Godot engine](https://godotengine.org/) or [jMonkeyEngine](https://jmonkeyengine.org/) the result wouldn't be as compelling and *I believe* the effort would be more considerable than if I use [Unreal Engine](https://www.unrealengine.com/en-US), which is my current plan. \ No newline at end of file diff --git a/doc/Pseudo-object-inheritance.md b/doc/Pseudo-object-inheritance.md new file mode 100644 index 0000000..b0f03dc --- /dev/null +++ b/doc/Pseudo-object-inheritance.md @@ -0,0 +1,5 @@ +# Pseudo object inheritance + +This is simply to document how I'm doing type inheritance for game objects, since Clojure does not provide type inheritance for records and I'm currently building game objects on Clojure records. + +It's possible that I should instead build game objects on Java beans, which do have type (class) inheritance, and would work transparently; however, that isn't my current approach. \ No newline at end of file diff --git a/doc/Tree-library-evaluation.md b/doc/Tree-library-evaluation.md new file mode 100644 index 0000000..5244c33 --- /dev/null +++ b/doc/Tree-library-evaluation.md @@ -0,0 +1,78 @@ +# Tree library evaluation + +This is a comparative evaluation of open source tree libraries that I have found that I could make use of. It's entirely personal and subjective! + +## [SimArboreal](https://github.com/Simsilica/SimArboreal) + +### Overview + +Library by Paul Speed, who's a senior and prolific developer in the jMonkeyEngine community; designed to work with jMonkeyEngine, and consequently integrates well with it. + +### Licence + +[BSD-style licence](https://github.com/Simsilica/SimArboreal/blob/master/src/main/resources/license.txt). + +### Assessment + +Produces trees which are quite realistic but only for a limited range of broad-leaved species. The trees do have modelled roots, which is relatively unusual. The trees sway in virtual winds, although to my eye trunks sway too much and thinner twigs too little. A limited number of textures are supplied, but new textures can easily be added so this isn't an issue. Handles Level of Detail automatically within the context of the jME3 libraries, which is a real bonus. + +Does not provide the range of species, or of stages of growth, I want. To add convincing coniferous trees, or trees with more than one primary branching point on the main trunk, would require extra coding. The way leaves are handled is crude, but looks surprisingly persuasive. The codebase is reasonably well written and understandable, but there is virtually no documentation. If I have to build on someone else's library, this wouldn't be a bad choice. The one to beat. + +## [Tree3D](https://github.com/SnailBones/Tree3D) + +### Overview + +Looks like a student project, or something done fairly quickly as an exercise. + +### Licence + +None specified, not even 'public domain'. So might be a bit sketchy to copy from. + +### Assessment + +This is definitely not as complete or ready to use as SimArboreal; although it does build, the user interface doesn't work with modern Java. Whether it ever worked I don't know, but I wouldn't be confident. Code is reasonably well written, but almost completely undocumented. There is no rendering of bark or of leaves; although the branching structure is excellent and the variety of morphologies available is good, boughs do not bend. + +However, algorithmically, this has a much better understanding of how trees grow, and of tree morphology, than SimArboreal. A hybrid taking growth algorithms from this and texture, wind, level of detail and jME3 integration from SimArboreal might be relatively to do. + +## [Proctree.js](https://gltf-trees.donmccurdy.com/) + +Very polished demo project by Paul Brunt, author of a key JavaScript WebGL 3D library; but in JavaScript, so not directly usable. + +### Licence + +None specified, not even 'public domain'. So might be a bit sketchy to copy from. + +### Assessment + +Very beautiful, algorithmically elegant, excellent variety of morphology. But + +1. No textures; +2. No wind sway; +3. No roots; +4. No level of detail handler; +5. No leaves; +6. No modelling of bough curvature; +7. Wrong language; +8. Relatively poorly structured code; +8. No documentation. + +This would be great to steal inspiration from for a new library of my own, and could possibly be used to inspire a significant extension to SimArboreal, but in its current state it isn't usable. + +## What none of the candidates offer + +None of the candidates have + +1. Seasonal change; +2. Species prototypes; +3. Broken boughs; +4. Leaning or nonstraight primary trunks; + +These are all features I want. The same cherry tree encountered in spring should be bedecked with blossom; in summer, green leaved; in autumn, red leaved and heavy with berries; in winter, bare. As seasons change as the player explores the game world, the trees need to change with them. + +Cherries need to have green leaves tapering to a point at both ends, pink flowers in late spring, large red berries (and flocks of birds) in autumn. They need to have moderately tall trunks with upward pointing, quite stiff boughs. Pines need to have the same dark green needles all the way through the year, and, typically, tall straight trunks with a few irregular coronets of living branches near the top and occasional dead and probcably broken boughs lower down. And so on. I need the same procedural code to be able to generate thousands to millions of recognisably distinct individual trees of a biome-appropriate variety of recognisable species across the map. + +They need to be individual and distinct at least partly because users are likely to recognise some of them as landmarks. And they need to be reproducably generatable from mininal seeds, because there's no way you can store that many models at anything like the level of detail I need. + +## Conclusion + +At this point it's a choice between rolling my own, or using Paul Speed's SimArboreal and enhancing it (hopefully with his approval and co-operation). In the short term, if I finalise the engine decision on jME3 (and I think I'm fairly close to doing that), SimArboreal will do as a placeholder. However, I will continue to look for other possibilities, because I have so many other things to build, and although I do want good quality forests I don't have that much time to invest in them just now. \ No newline at end of file diff --git a/project.clj b/project.clj index 2486514..b562bc9 100644 --- a/project.clj +++ b/project.clj @@ -3,9 +3,9 @@ :codecov? true :emma-xml? true} :codox {:froboz.cloverage {:output "docs/cloverage" - :codecov? true - :html? true - :debug? true} + :codecov? true + :html? true + :debug? true} :metadata {:doc "**TODO**: write docs" :doc/format :markdown} :output-path "docs/codox" @@ -13,9 +13,9 @@ :cucumber-feature-paths ["test/features/"] :dependencies [[com.taoensso/timbre "6.5.0"] [environ "1.2.0"] - [hiccup "2.0.0-RC3"] + [hiccup "2.0.0-RC3"] [jme-clj "0.1.13"] -;; [jme3-core "3.4.0-stable"] + [org.jmonkeyengine/jme3-core "3.6.1-stable"] [journeyman-cc/walkmap "0.1.0-SNAPSHOT"] [me.raynes/fs "1.4.6"] [mw-engine "0.3.0-SNAPSHOT"] @@ -24,18 +24,22 @@ [org.clojure/algo.generic "1.0.0"] [org.clojure/clojure "1.11.2"] [org.clojure/math.numeric-tower "0.1.0"] + [org.clojure/tools.cli "1.1.230"] [org.clojure/tools.namespace "1.5.0"] [org.clojure/tools.reader "1.4.1"] [wherefore-art-thou "0.1.0-SNAPSHOT"]] :description "Prototype code towards the great game I've been writing about for ten years, and know I will never finish." :license {:name "GNU General Public License,version 2.0 or (at your option) any later version" :url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"} + :main cc.journeyman.the-great-game.launcher :plugins [[lein-adl "0.1.7"] [lein-cloverage "1.2.2"] [lein-codox "0.10.8"] ;;[lein-codox "0.10.7-cloverage"] [lein-cucumber "1.0.2"] - [org.clojars.benfb/lein-gorilla "0.7.0"] - ] + [org.clojars.benfb/lein-gorilla "0.7.0"]] + ;; TODO TODO: Ahead-of-time compilation is *definitely* needed before I put + ;; even an alpha release out, but it's breaking too much just now. + ;; :profiles {:uberjar {:aot :all}} ;; NOTE WELL: `lein release` won't work until we have a release repository ;; set, which we don't! @@ -49,5 +53,6 @@ ["uberjar"] ["change" "version" "leiningen.release/bump-version"] ["vcs" "commit"]] - + :source-paths ["src/clj"] + :java-source-paths ["src/java"] :url "https://github.com/simon-brooke/the-great-game") diff --git a/resources/images/splash.jpg b/resources/images/splash.jpg new file mode 100644 index 0000000..0a593b5 Binary files /dev/null and b/resources/images/splash.jpg differ diff --git a/resources/images/splash.png b/resources/images/splash.png new file mode 100644 index 0000000..83f8beb Binary files /dev/null and b/resources/images/splash.png differ diff --git a/resources/textures/terrain/brickwall/BrickWall.dds b/resources/textures/terrain/brickwall/BrickWall.dds new file mode 100644 index 0000000..2ac3b8b Binary files /dev/null and b/resources/textures/terrain/brickwall/BrickWall.dds differ diff --git a/resources/textures/terrain/brickwall/BrickWall.j3m b/resources/textures/terrain/brickwall/BrickWall.j3m new file mode 100644 index 0000000..0013c15 --- /dev/null +++ b/resources/textures/terrain/brickwall/BrickWall.j3m @@ -0,0 +1,8 @@ +Material Pong Rock : Common/MatDefs/Light/Lighting.j3md { + MaterialParameters { + Shininess : 2.0 + DiffuseMap : Repeat Textures/Terrain/BrickWall/BrickWall.dds + NormalMap : Repeat Textures/Terrain/BrickWall/BrickWall_normal_parallax.dds + PackedNormalParallax : true + } +} \ No newline at end of file diff --git a/resources/textures/terrain/brickwall/BrickWall.jpg b/resources/textures/terrain/brickwall/BrickWall.jpg new file mode 100644 index 0000000..c386a0d Binary files /dev/null and b/resources/textures/terrain/brickwall/BrickWall.jpg differ diff --git a/resources/textures/terrain/brickwall/BrickWallPBR.j3m b/resources/textures/terrain/brickwall/BrickWallPBR.j3m new file mode 100644 index 0000000..4d28048 --- /dev/null +++ b/resources/textures/terrain/brickwall/BrickWallPBR.j3m @@ -0,0 +1,9 @@ +Material Pong Rock PBR : Common/MatDefs/Light/PBRLighting.j3md { + MaterialParameters { + Roughness : 1.0 + Metallic : 0.0 + BaseColorMap : Repeat Textures/Terrain/BrickWall/BrickWall.jpg + NormalMap : Repeat Textures/Terrain/BrickWall/BrickWall_normal_parallax.dds + PackedNormalParallax: true + } +} \ No newline at end of file diff --git a/resources/textures/terrain/brickwall/BrickWallPBR2.j3m b/resources/textures/terrain/brickwall/BrickWallPBR2.j3m new file mode 100644 index 0000000..38ca15f --- /dev/null +++ b/resources/textures/terrain/brickwall/BrickWallPBR2.j3m @@ -0,0 +1,8 @@ +Material Pong Rock PBR : Common/MatDefs/Light/PBRLighting.j3md { + MaterialParameters { + Roughness : 1.0 + Metallic : 0.0 + BaseColorMap : Repeat Textures/Terrain/BrickWall/BrickWall.jpg + ParallaxMap : Repeat Textures/Terrain/BrickWall/BrickWall_height.jpg + } +} \ No newline at end of file diff --git a/resources/textures/terrain/brickwall/BrickWall_dxt5.dds b/resources/textures/terrain/brickwall/BrickWall_dxt5.dds new file mode 100644 index 0000000..7efe789 Binary files /dev/null and b/resources/textures/terrain/brickwall/BrickWall_dxt5.dds differ diff --git a/resources/textures/terrain/brickwall/BrickWall_height.jpg b/resources/textures/terrain/brickwall/BrickWall_height.jpg new file mode 100644 index 0000000..3486674 Binary files /dev/null and b/resources/textures/terrain/brickwall/BrickWall_height.jpg differ diff --git a/resources/textures/terrain/brickwall/BrickWall_normal.jpg b/resources/textures/terrain/brickwall/BrickWall_normal.jpg new file mode 100644 index 0000000..249d553 Binary files /dev/null and b/resources/textures/terrain/brickwall/BrickWall_normal.jpg differ diff --git a/resources/textures/terrain/brickwall/BrickWall_normal_parallax.dds b/resources/textures/terrain/brickwall/BrickWall_normal_parallax.dds new file mode 100644 index 0000000..df93b19 Binary files /dev/null and b/resources/textures/terrain/brickwall/BrickWall_normal_parallax.dds differ diff --git a/resources/textures/terrain/pond/Pond.dds b/resources/textures/terrain/pond/Pond.dds new file mode 100644 index 0000000..7470ead Binary files /dev/null and b/resources/textures/terrain/pond/Pond.dds differ diff --git a/resources/textures/terrain/pond/Pond.j3m b/resources/textures/terrain/pond/Pond.j3m new file mode 100644 index 0000000..92bc6a1 --- /dev/null +++ b/resources/textures/terrain/pond/Pond.j3m @@ -0,0 +1,11 @@ +Material Pong Rock : Common/MatDefs/Light/Lighting.j3md { + MaterialParameters { + DiffuseMap: Repeat Textures/Terrain/Pond/Pond.jpg + NormalMap: Repeat Textures/Terrain/Pond/Pond_normal.png + UseMaterialColors : true + Shininess: 32.0 + Ambient : 0.2 0.2 0.2 1.0 + Diffuse : 0.8 0.8 0.8 1.0 + Specular : 0.3 0.3 0.3 1.0 + } +} diff --git a/resources/textures/terrain/pond/Pond.jpg b/resources/textures/terrain/pond/Pond.jpg new file mode 100644 index 0000000..177881c Binary files /dev/null and b/resources/textures/terrain/pond/Pond.jpg differ diff --git a/resources/textures/terrain/pond/Pond_dxt5.dds b/resources/textures/terrain/pond/Pond_dxt5.dds new file mode 100644 index 0000000..309f2c7 Binary files /dev/null and b/resources/textures/terrain/pond/Pond_dxt5.dds differ diff --git a/resources/textures/terrain/pond/Pond_normal.png b/resources/textures/terrain/pond/Pond_normal.png new file mode 100644 index 0000000..8e566ed Binary files /dev/null and b/resources/textures/terrain/pond/Pond_normal.png differ diff --git a/resources/textures/terrain/rock/Rock.PNG b/resources/textures/terrain/rock/Rock.PNG new file mode 100644 index 0000000..4b5b190 Binary files /dev/null and b/resources/textures/terrain/rock/Rock.PNG differ diff --git a/resources/textures/terrain/rock/Rock.j3m b/resources/textures/terrain/rock/Rock.j3m new file mode 100644 index 0000000..b2e8256 --- /dev/null +++ b/resources/textures/terrain/rock/Rock.j3m @@ -0,0 +1,7 @@ +Material Rock : Common/MatDefs/Light/Lighting.j3md { + MaterialParameters { + Shininess: 16.0 + DiffuseMap : Textures/Terrain/Rock/Rock.PNG + NormalMap : Textures/Terrain/Rock/Rock_normal.png + } +} \ No newline at end of file diff --git a/resources/textures/terrain/rock/Rock_normal.png b/resources/textures/terrain/rock/Rock_normal.png new file mode 100644 index 0000000..48221c0 Binary files /dev/null and b/resources/textures/terrain/rock/Rock_normal.png differ diff --git a/resources/textures/terrain/splat/alpha1.png b/resources/textures/terrain/splat/alpha1.png new file mode 100644 index 0000000..bb7742f Binary files /dev/null and b/resources/textures/terrain/splat/alpha1.png differ diff --git a/resources/textures/terrain/splat/alpha2.png b/resources/textures/terrain/splat/alpha2.png new file mode 100644 index 0000000..28e48c6 Binary files /dev/null and b/resources/textures/terrain/splat/alpha2.png differ diff --git a/resources/textures/terrain/splat/alphamap.png b/resources/textures/terrain/splat/alphamap.png new file mode 100644 index 0000000..14f0a9b Binary files /dev/null and b/resources/textures/terrain/splat/alphamap.png differ diff --git a/resources/textures/terrain/splat/alphamap2.png b/resources/textures/terrain/splat/alphamap2.png new file mode 100644 index 0000000..9367ef6 Binary files /dev/null and b/resources/textures/terrain/splat/alphamap2.png differ diff --git a/resources/textures/terrain/splat/dirt.jpg b/resources/textures/terrain/splat/dirt.jpg new file mode 100644 index 0000000..4742068 Binary files /dev/null and b/resources/textures/terrain/splat/dirt.jpg differ diff --git a/resources/textures/terrain/splat/dirt_normal.png b/resources/textures/terrain/splat/dirt_normal.png new file mode 100644 index 0000000..2eb57f4 Binary files /dev/null and b/resources/textures/terrain/splat/dirt_normal.png differ diff --git a/resources/textures/terrain/splat/fortress512.png b/resources/textures/terrain/splat/fortress512.png new file mode 100644 index 0000000..b6b4ed1 Binary files /dev/null and b/resources/textures/terrain/splat/fortress512.png differ diff --git a/resources/textures/terrain/splat/grass.jpg b/resources/textures/terrain/splat/grass.jpg new file mode 100644 index 0000000..8d5b97d Binary files /dev/null and b/resources/textures/terrain/splat/grass.jpg differ diff --git a/resources/textures/terrain/splat/grass_normal.jpg b/resources/textures/terrain/splat/grass_normal.jpg new file mode 100644 index 0000000..12de380 Binary files /dev/null and b/resources/textures/terrain/splat/grass_normal.jpg differ diff --git a/resources/textures/terrain/splat/mountains1024.jpg b/resources/textures/terrain/splat/mountains1024.jpg new file mode 100644 index 0000000..37d6475 Binary files /dev/null and b/resources/textures/terrain/splat/mountains1024.jpg differ diff --git a/resources/textures/terrain/splat/mountains128.png b/resources/textures/terrain/splat/mountains128.png new file mode 100644 index 0000000..4a4dc7c Binary files /dev/null and b/resources/textures/terrain/splat/mountains128.png differ diff --git a/resources/textures/terrain/splat/mountains512.png b/resources/textures/terrain/splat/mountains512.png new file mode 100644 index 0000000..13cb4d1 Binary files /dev/null and b/resources/textures/terrain/splat/mountains512.png differ diff --git a/resources/textures/terrain/splat/pools.png b/resources/textures/terrain/splat/pools.png new file mode 100644 index 0000000..22e8b83 Binary files /dev/null and b/resources/textures/terrain/splat/pools.png differ diff --git a/resources/textures/terrain/splat/road.jpg b/resources/textures/terrain/splat/road.jpg new file mode 100644 index 0000000..21195e6 Binary files /dev/null and b/resources/textures/terrain/splat/road.jpg differ diff --git a/resources/textures/terrain/splat/road_normal.png b/resources/textures/terrain/splat/road_normal.png new file mode 100644 index 0000000..ae56480 Binary files /dev/null and b/resources/textures/terrain/splat/road_normal.png differ diff --git a/src/cc/journeyman/the_great_game/character/character.clj b/src/cc/journeyman/the_great_game/character/character.clj deleted file mode 100644 index ce174f4..0000000 --- a/src/cc/journeyman/the_great_game/character/character.clj +++ /dev/null @@ -1,9 +0,0 @@ -(ns cc.journeyman.the-great-game.character.character - "A character that can talk; either human or dragon (although very probably - we won't do talking dragons until really well into this process). All - characters have the news-passing abilities of a gossip, but we use `gossip` - to mean a special character who is part of the news-passing network." - (:require [cc.journeyman.the-great-game.gossip.gossip :refer [dialogue]] - [cc.journeyman.the-great-game.agent.agent :refer [Agent]])) - - diff --git a/src/cc/journeyman/architecture.md b/src/clj/cc/journeyman/architecture.md similarity index 100% rename from src/cc/journeyman/architecture.md rename to src/clj/cc/journeyman/architecture.md diff --git a/src/cc/journeyman/the_great_game/agent/agent.clj b/src/clj/cc/journeyman/the_great_game/agent/agent.clj similarity index 56% rename from src/cc/journeyman/the_great_game/agent/agent.clj rename to src/clj/cc/journeyman/the_great_game/agent/agent.clj index a6f99a8..282f13e 100644 --- a/src/cc/journeyman/the_great_game/agent/agent.clj +++ b/src/clj/cc/journeyman/the_great_game/agent/agent.clj @@ -69,61 +69,63 @@ (defrecord Agent ;; "A default agent." [name craft home culture] - ProtoObject - ProtoContainer + ;; ProtoObject + ;; ProtoContainer - (contents - "The `contents` of an actor are the contents of their pack(s) (if any), where - a pack may be any sort of bag or container which the actor could reasonably - be carrying." - [actor] - (flatten - (map contents (filter #(satisfies? ProtoContainer %) - (:burden actor))))) + ;; (contents + ;; "The `contents` of an actor are the contents of their pack(s) (if any), where + ;; a pack may be any sort of bag or container which the actor could reasonably + ;; be carrying." + ;; [actor] + ;; (flatten + ;; (map contents (filter #(satisfies? ProtoContainer %) + ;; (:burden actor))))) - (is-empty? - [actor] - (empty? (:burden actor))) + ;; (is-empty? + ;; [actor] + ;; (empty? (:burden actor))) - ProtoAgent + ;; ProtoAgent - (act - “Return a map in which :world is bound to a world like this `world `except that this `actor `has acted in it; and `:actor` is bound to an - actor like this `actor `except modified by the consequences of the action. - ‘Circle’ indicates which activation circle the actor is in. + ;; (act + ;; “Return a map in which :world is bound to a world like this `world `except that this `actor `has acted in it; and `:actor` is bound to an + ;; actor like this `actor `except modified by the consequences of the action. + ;; ‘Circle’ indicates which activation circle the actor is in. - Note that this implies that a `plan `is a function of three arguments, an - actor, a world. and a circle, and returns exactly the sort of map this - function returns.” - [actor world circle] - (let [urgent (case circle - :other (cond - (pending-scheduled-action? actor world circle) - (plan-scheduled-action actor world circle)) - :background (cond - (threatened? actor world circle) - (plan-fight-or-flight actor world circle) - (pending-scheduled-action? actor world circle) - (plan-scheduled-action actor world circle)) - ;; else - (cond - (threatened? actor world circle) - (plan-fight-or-flight actor world circle) - (hungry? actor world circle) - (plan-find-food actor world circle) - (tired? actor world circle) - (plan-find-rest actor world circle) - (pending-scheduled-action? actor world circle) - (plan-scheduled-action actor world circle))) - next-action (cond urgent urgent - (empty? (:plans actor)) - (plan-goal actor world circle) - :else (first (:plans actor))) - consequences (apply next-action (list actor world circle))] - ;; we return consequences of the action, except that, if the action - ;; was on the plans of the actor, we remove it. - (if-not (= next-action (first (:plans actor))) - consequences - (assoc consequences :actor - (assoc (:actor consequences) :plans - (rest (-> consequences :actor :plans)))))))) + ;; Note that this implies that a `plan `is a function of three arguments, an + ;; actor, a world. and a circle, and returns exactly the sort of map this + ;; function returns.” + ;; [actor world circle] + ;; (let [urgent (case circle + ;; :other (cond + ;; (pending-scheduled-action? actor world circle) + ;; (plan-scheduled-action actor world circle)) + ;; :background (cond + ;; (threatened? actor world circle) + ;; (plan-fight-or-flight actor world circle) + ;; (pending-scheduled-action? actor world circle) + ;; (plan-scheduled-action actor world circle)) + ;; ;; else + ;; (cond + ;; (threatened? actor world circle) + ;; (plan-fight-or-flight actor world circle) + ;; (hungry? actor world circle) + ;; (plan-find-food actor world circle) + ;; (tired? actor world circle) + ;; (plan-find-rest actor world circle) + ;; (pending-scheduled-action? actor world circle) + ;; (plan-scheduled-action actor world circle))) + ;; next-action (cond urgent urgent + ;; (empty? (:plans actor)) + ;; (plan-goal actor world circle) + ;; :else (first (:plans actor))) + ;; consequences (apply next-action (list actor world circle))] + ;; ;; we return consequences of the action, except that, if the action + ;; ;; was on the plans of the actor, we remove it. + ;; (if-not (= next-action (first (:plans actor))) + ;; consequences + ;; (assoc consequences :actor + ;; (assoc (:actor consequences) :plans + ;; (rest (-> consequences :actor :plans))))))) + + ) diff --git a/src/cc/journeyman/the_great_game/agent/schedule.clj b/src/clj/cc/journeyman/the_great_game/agent/schedule.clj similarity index 100% rename from src/cc/journeyman/the_great_game/agent/schedule.clj rename to src/clj/cc/journeyman/the_great_game/agent/schedule.clj diff --git a/src/cc/journeyman/the_great_game/buildings/module.clj b/src/clj/cc/journeyman/the_great_game/buildings/module.clj similarity index 100% rename from src/cc/journeyman/the_great_game/buildings/module.clj rename to src/clj/cc/journeyman/the_great_game/buildings/module.clj diff --git a/src/cc/journeyman/the_great_game/buildings/rectangular.clj b/src/clj/cc/journeyman/the_great_game/buildings/rectangular.clj similarity index 100% rename from src/cc/journeyman/the_great_game/buildings/rectangular.clj rename to src/clj/cc/journeyman/the_great_game/buildings/rectangular.clj diff --git a/src/clj/cc/journeyman/the_great_game/character/character.clj b/src/clj/cc/journeyman/the_great_game/character/character.clj new file mode 100644 index 0000000..d571739 --- /dev/null +++ b/src/clj/cc/journeyman/the_great_game/character/character.clj @@ -0,0 +1,114 @@ +(ns cc.journeyman.the-great-game.character.character + "A character that can talk; either human or dragon (although very probably + we won't do talking dragons until really well into this process). All + characters have the news-passing abilities of a gossip, but we use `gossip` + to mean a special character who is part of the news-passing network." + (:require [cc.journeyman.the-great-game.gossip.gossip :refer [dialogue]] + [cc.journeyman.the-great-game.agent.agent :refer [ProtoAgent]] + [cc.journeyman.the-great-game.character.container :refer [ProtoContainer]] + [clojure.string :as cs :only [join]]) + (:import [clojure.lang IPersistentMap])) + +(defn honorific + "Placeholder. If a character is a teir one craftsman, they get called 'Master'; + if a teir two ariston, they get called 'Ariston' and if a teir one ariston, + 'Tyrranos'. But the logic of this is about occupations, which probably isn't + this namespace." + [_character] + nil) + +(defn place-name + "Placeholder. We're going to have to have names of villages, towns, regions + and so on, and we're going to have to be able to retrieve those efficiently, + but I don't yet know how this is going to work. Definitely doesn't belong + in this namespace." + [_cell] + nil) + +(defn match-on? + "Placeholder, utility function. Do all these `objects` have the same values for + these `keys`?" + [keys & objects] + (reduce = (map #(select-keys % keys) objects))) + +(defprotocol ProtoCharacter + (full-name [character] + "Return the full name of this `character`, constructed according + to the default construction sequence") + (relative-name [character other] + "Return the name that `other` would naturally use in an + informal context to describe `character`") + (personal-name [character] + "Return the personal name of this `character`.")) + +(defrecord Character [object + agent + family-name + personal-name + occupation + rank + epithet + knowledge + wallet] + ;; A character; obviously, normally, a non-player character, although the + ;; player character is one of these. Essentially, an Agent which can speak, + ;; which has knowledge, which has a set of affective relationships with other + ;; characters. + ;; ProtoContainer + ProtoAgent + ProtoCharacter + + (personal-name [character] (:personal-name character)) + (full-name [character] + (let [e (:epithet character) + h (honorific character) + f (:family-name character) + p (:personal-name character) + o (:occupation character) + l (place-name (:cell character))] + (cs/join " " + (remove nil? + (flatten + [e + h + f + p + (when o ["the" o]) + (when l ["of" l])]))))) + (relative-name [character other] + (let [e (:epithet character) + h (honorific character) + f (:family-name character) + p (:personal-name character) + o (:occupation character) + h (place-name (:cell character)) + same-family? (= f (:family-name other))] + (cs/join " " + (remove nil? + (flatten + [(when-not (match-on? + [:family-name :cell] character other) + + e) + (when-not same-family? h) + (when-not same-family? h) + p + (when (and o (not (match-on? :occupation))) ["the" o]) + (when (and h + (not (match-on? [:cell] character other))) ["of" h])])))))) + + +(defn make-character + "Construct a Character record from this `seed` map" + [^IPersistentMap seed] + (let [object (make-object seed) + agent (make-actor seed)] + (apply Character. + (list (map seed [:agent + :family-name + :personal-name + :occupation + :rank + :epithet + :knowledge + :wallet]))))) \ No newline at end of file diff --git a/src/clj/cc/journeyman/the_great_game/character/sex.clj b/src/clj/cc/journeyman/the_great_game/character/sex.clj new file mode 100644 index 0000000..639d102 --- /dev/null +++ b/src/clj/cc/journeyman/the_great_game/character/sex.clj @@ -0,0 +1 @@ +(ns cc.journeyman.the-great-game.character.sex) diff --git a/src/cc/journeyman/the_great_game/gossip/gossip.clj b/src/clj/cc/journeyman/the_great_game/gossip/gossip.clj similarity index 100% rename from src/cc/journeyman/the_great_game/gossip/gossip.clj rename to src/clj/cc/journeyman/the_great_game/gossip/gossip.clj diff --git a/src/cc/journeyman/the_great_game/gossip/news_items.clj b/src/clj/cc/journeyman/the_great_game/gossip/news_items.clj similarity index 100% rename from src/cc/journeyman/the_great_game/gossip/news_items.clj rename to src/clj/cc/journeyman/the_great_game/gossip/news_items.clj diff --git a/src/cc/journeyman/the_great_game/holdings/holding.clj b/src/clj/cc/journeyman/the_great_game/holdings/holding.clj similarity index 100% rename from src/cc/journeyman/the_great_game/holdings/holding.clj rename to src/clj/cc/journeyman/the_great_game/holdings/holding.clj diff --git a/src/clj/cc/journeyman/the_great_game/launcher.clj b/src/clj/cc/journeyman/the_great_game/launcher.clj new file mode 100644 index 0000000..30fd510 --- /dev/null +++ b/src/clj/cc/journeyman/the_great_game/launcher.clj @@ -0,0 +1,87 @@ +(ns cc.journeyman.the-great-game.launcher + "Launcher for the game" + (:require [clojure.tools.cli :refer [parse-opts]] + [jme-clj.core :refer [add-control add-to-root app-settings cam + defsimpleapp fly-cam get-height-map image + image-based-height-map load-height-map + load-texture material set* start + terrain-lod-control terrain-quad]]) + (:import (com.jme3.texture Texture$WrapMode)) + (:gen-class)) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; +;;;; Launcher: parses any command line options, and launches the game. +;;;; +;;;; This program is free software; you can redistribute it and/or +;;;; modify it under the terms of the GNU General Public License +;;;; as published by the Free Software Foundation; either version 2 +;;;; of the License, or (at your option) any later version. +;;;; +;;;; This program is distributed in the hope that it will be useful, +;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;;; GNU General Public License for more details. +;;;; +;;;; You should have received a copy of the GNU General Public License +;;;; along with this program; if not, write to the Free Software +;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +;;;; USA. +;;;; +;;;; Copyright (C) 2024 Simon Brooke +;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(def cli-options + ;; An option with a required argument + [["-p" "--port PORT" "Port number" + :default 80 + :parse-fn #(Integer/parseInt %) + :validate [#(< 0 % 0x10000) "Must be a number between 0 and 65536"]] + ;; A non-idempotent option (:default is applied first) + ["-v" nil "Verbosity level" + :id :verbosity + :default 0 + :update-fn inc] ; Prior to 0.4.1, you would have to use: + ;; :assoc-fn (fn [m k _] (update-in m [k] inc)) + ;; A boolean option defaulting to nil + ["-h" "--help"]]) + +(defn init [] + (set* (fly-cam) :move-speed 50) + (let [grass (set* (load-texture "textures/terrain/splat/grass.jpg") :wrap Texture$WrapMode/Repeat) + dirt (set* (load-texture "textures/terrain/splat/dirt.jpg") :wrap Texture$WrapMode/Repeat) + rock (set* (load-texture "textures/terrain/splat/road.jpg") :wrap Texture$WrapMode/Repeat) + mat (material "Common/MatDefs/Terrain/Terrain.j3md") + height-map-tex (load-texture "textures/terrain/splat/mountains512.png") + height-map (->> height-map-tex image image-based-height-map load-height-map) + patch-size 65 + terrain (terrain-quad "my terrain" patch-size 513 (get-height-map height-map))] + (-> mat + (set* :texture "Alpha" (load-texture "textures/terrain/splat/alphamap.png")) + (set* :texture "Tex1" grass) + (set* :float "Tex1Scale" (float 64)) + (set* :texture "Tex2" dirt) + (set* :float "Tex2Scale" (float 32)) + (set* :texture "Tex3" rock) + (set* :float "Tex3Scale" (float 128))) + (-> terrain + (set* :material mat) + (set* :local-translation 0 -100 0) + (set* :local-scale 2 1 2) + (add-to-root) + (add-control (terrain-lod-control terrain (cam)))))) + +(defsimpleapp app :init init) + +(defn -main + "Launch the game." + [& args] + (parse-opts args cli-options) + + ;; this isn't working, not sure why not. + ;; (.setSettings app (app-settings false :dialog-image "images/splash.png")) + + (start app)) + \ No newline at end of file diff --git a/src/cc/journeyman/the_great_game/location/location.clj b/src/clj/cc/journeyman/the_great_game/location/location.clj similarity index 100% rename from src/cc/journeyman/the_great_game/location/location.clj rename to src/clj/cc/journeyman/the_great_game/location/location.clj diff --git a/src/cc/journeyman/the_great_game/lore/digester.clj b/src/clj/cc/journeyman/the_great_game/lore/digester.clj similarity index 100% rename from src/cc/journeyman/the_great_game/lore/digester.clj rename to src/clj/cc/journeyman/the_great_game/lore/digester.clj diff --git a/src/cc/journeyman/the_great_game/merchants/markets.clj b/src/clj/cc/journeyman/the_great_game/merchants/markets.clj similarity index 100% rename from src/cc/journeyman/the_great_game/merchants/markets.clj rename to src/clj/cc/journeyman/the_great_game/merchants/markets.clj diff --git a/src/cc/journeyman/the_great_game/merchants/merchant_utils.clj b/src/clj/cc/journeyman/the_great_game/merchants/merchant_utils.clj similarity index 100% rename from src/cc/journeyman/the_great_game/merchants/merchant_utils.clj rename to src/clj/cc/journeyman/the_great_game/merchants/merchant_utils.clj diff --git a/src/cc/journeyman/the_great_game/merchants/merchants.clj b/src/clj/cc/journeyman/the_great_game/merchants/merchants.clj similarity index 100% rename from src/cc/journeyman/the_great_game/merchants/merchants.clj rename to src/clj/cc/journeyman/the_great_game/merchants/merchants.clj diff --git a/src/cc/journeyman/the_great_game/merchants/planning.clj b/src/clj/cc/journeyman/the_great_game/merchants/planning.clj similarity index 100% rename from src/cc/journeyman/the_great_game/merchants/planning.clj rename to src/clj/cc/journeyman/the_great_game/merchants/planning.clj diff --git a/src/cc/journeyman/the_great_game/merchants/strategies/simple.clj b/src/clj/cc/journeyman/the_great_game/merchants/strategies/simple.clj similarity index 100% rename from src/cc/journeyman/the_great_game/merchants/strategies/simple.clj rename to src/clj/cc/journeyman/the_great_game/merchants/strategies/simple.clj diff --git a/src/cc/journeyman/the_great_game/objects/character.clj b/src/clj/cc/journeyman/the_great_game/objects/character.clj similarity index 100% rename from src/cc/journeyman/the_great_game/objects/character.clj rename to src/clj/cc/journeyman/the_great_game/objects/character.clj diff --git a/src/cc/journeyman/the_great_game/objects/container.clj b/src/clj/cc/journeyman/the_great_game/objects/container.clj similarity index 100% rename from src/cc/journeyman/the_great_game/objects/container.clj rename to src/clj/cc/journeyman/the_great_game/objects/container.clj diff --git a/src/cc/journeyman/the_great_game/objects/game_object.clj b/src/clj/cc/journeyman/the_great_game/objects/game_object.clj similarity index 100% rename from src/cc/journeyman/the_great_game/objects/game_object.clj rename to src/clj/cc/journeyman/the_great_game/objects/game_object.clj diff --git a/src/cc/journeyman/the_great_game/playroom.clj b/src/clj/cc/journeyman/the_great_game/playroom.clj similarity index 100% rename from src/cc/journeyman/the_great_game/playroom.clj rename to src/clj/cc/journeyman/the_great_game/playroom.clj diff --git a/src/cc/journeyman/the_great_game/proving/core.clj b/src/clj/cc/journeyman/the_great_game/proving/core.clj similarity index 93% rename from src/cc/journeyman/the_great_game/proving/core.clj rename to src/clj/cc/journeyman/the_great_game/proving/core.clj index 759a84c..ce3fe76 100644 --- a/src/cc/journeyman/the_great_game/proving/core.clj +++ b/src/clj/cc/journeyman/the_great_game/proving/core.clj @@ -26,7 +26,7 @@ microworld style world tagged with vegetation, etc, data). " ([height-map] (let [drained-world (get-drainage-map height-map)] - (run-world drained-world (compile (slurp "resources/baking/biome-rules.txt")) (count drained-world)))) + (run-world drained-world (compile (slurp "resources/data/baking/biome-rules.txt")) (count drained-world)))) ([height-map _rainfall-map] (get-biome-map height-map))) @@ -70,6 +70,7 @@ :camp (populate-npcs {:world world :cell cell :occupation :nomad}) :house (populate-npcs {:world world :cell cell :occupation :peasant}) :inn (populate-npcs {:world world :cell cell :occupation :innkeeper}) + :market (populate-npcs {:world world :cell cell :occupation :merchant}) ;; else nil)] (if npcs (assoc cell :npcs npcs) @@ -80,7 +81,7 @@ (probably some form of database) and return a structure which allows that database o be interrogated." [biome-map] - (let [world (run-world biome-map (compile (slurp "resources/baking/settlement-rules.txt")) (count biome-map)) + (let [world (run-world biome-map (compile (slurp "resources/data/baking/settlement-rules.txt")) (count biome-map)) with-npcs (map-world world (vary-meta (fn [w c] (populate-cell w c)) assoc :rule-type :ad-hoc))] ;; right, with that settled world, I'm going to put one herdsman with ;; five animals (either all sheep, all cattle, all goats, all horses or @@ -101,7 +102,7 @@ :roadmap []})) (defn get-road-map - [populated-world]) + [_populated-world]) (defn prove "Given this `height-map` (a monochrome raster) and optionally this diff --git a/src/cc/journeyman/the_great_game/proving/sketches.clj b/src/clj/cc/journeyman/the_great_game/proving/sketches.clj similarity index 100% rename from src/cc/journeyman/the_great_game/proving/sketches.clj rename to src/clj/cc/journeyman/the_great_game/proving/sketches.clj diff --git a/src/cc/journeyman/the_great_game/time.clj b/src/clj/cc/journeyman/the_great_game/time.clj similarity index 100% rename from src/cc/journeyman/the_great_game/time.clj rename to src/clj/cc/journeyman/the_great_game/time.clj diff --git a/src/cc/journeyman/the_great_game/utils.clj b/src/clj/cc/journeyman/the_great_game/utils.clj similarity index 100% rename from src/cc/journeyman/the_great_game/utils.clj rename to src/clj/cc/journeyman/the_great_game/utils.clj diff --git a/src/cc/journeyman/the_great_game/world/heightmap.clj b/src/clj/cc/journeyman/the_great_game/world/heightmap.clj similarity index 100% rename from src/cc/journeyman/the_great_game/world/heightmap.clj rename to src/clj/cc/journeyman/the_great_game/world/heightmap.clj diff --git a/src/cc/journeyman/the_great_game/world/location.clj b/src/clj/cc/journeyman/the_great_game/world/location.clj similarity index 100% rename from src/cc/journeyman/the_great_game/world/location.clj rename to src/clj/cc/journeyman/the_great_game/world/location.clj diff --git a/src/cc/journeyman/the_great_game/world/mw.clj b/src/clj/cc/journeyman/the_great_game/world/mw.clj similarity index 100% rename from src/cc/journeyman/the_great_game/world/mw.clj rename to src/clj/cc/journeyman/the_great_game/world/mw.clj diff --git a/src/cc/journeyman/the_great_game/world/routes.clj b/src/clj/cc/journeyman/the_great_game/world/routes.clj similarity index 100% rename from src/cc/journeyman/the_great_game/world/routes.clj rename to src/clj/cc/journeyman/the_great_game/world/routes.clj diff --git a/src/cc/journeyman/the_great_game/world/run.clj b/src/clj/cc/journeyman/the_great_game/world/run.clj similarity index 100% rename from src/cc/journeyman/the_great_game/world/run.clj rename to src/clj/cc/journeyman/the_great_game/world/run.clj diff --git a/src/cc/journeyman/the_great_game/world/world.clj b/src/clj/cc/journeyman/the_great_game/world/world.clj similarity index 100% rename from src/cc/journeyman/the_great_game/world/world.clj rename to src/clj/cc/journeyman/the_great_game/world/world.clj diff --git a/src/java/cc/journeyman/the_great_game/game_objects/JContainer.java b/src/java/cc/journeyman/the_great_game/game_objects/JContainer.java new file mode 100644 index 0000000..3ba09f7 --- /dev/null +++ b/src/java/cc/journeyman/the_great_game/game_objects/JContainer.java @@ -0,0 +1,40 @@ +package java.cc.journeyman.the_great_game.game_objects; + +import java.util.Collection; +import java.util.LinkedList; + +/** Java implementation of a game object which is a container. */ + +public class JContainer extends JObject { + /** The contents of this container. */ + private LinkedList contents = new LinkedList(); + + /** Get the contents of this container. */ + public LinkedList getContents() { + return this.contents; + } + + /** + * Add this single item to this container. + * + * @param item + */ + public void addItem(JObject item) { + } + + public void addItem(Object item) { + if (item instanceof JObject) { + this.addItem((JObject)item); + } else { + throw new IllegalArgumentException("All items added to a container must be game objects"); + } + } + + public void addItems(Collection items) { + for (Object item : items) { + + this.contents.add((JObject) item); + + } + } +} diff --git a/src/java/cc/journeyman/the_great_game/game_objects/JObject.java b/src/java/cc/journeyman/the_great_game/game_objects/JObject.java new file mode 100644 index 0000000..3a30ce4 --- /dev/null +++ b/src/java/cc/journeyman/the_great_game/game_objects/JObject.java @@ -0,0 +1,95 @@ +package java.cc.journeyman.the_great_game.game_objects; + +import com.jme3.bounding.BoundingBox; +import com.jme3.bounding.BoundingSphere; +import com.jme3.bounding.BoundingVolume; +import com.jme3.scene.Spatial; +import com.jme3.scene.Node; +import java.lang.Math; +import java.security.SecureRandom; + +/** + * Highly experimental! Using Java beans instead of Clojure records + * for underlying game objects, to allow type inheritance. It has the + * additional advantage that Java objects are inherently mutable. This is the + * root of the hierarchy, a basic object. + * + * See [JavaBeans Spec] + * (http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html). + * + * If this works(!), it is likely that object persistence and (re-loading) will + * happen in the Java layer rather than in the Clojure layer. + * + * A game object model in jMonkeyEngine is loaded as a 'Spatial' which + * is a subclass of 'Node', which has a 'BoundingVolume' i.v. which is + * instantiated as either a 'BoundingSphere' or a 'BoundingBox'. We + * can't directly extract length/width/height data from these... but we + * ought not to tolerate majow inconsistency between the size we report + * and the volume reported by the model. + */ +public class JObject { + private static SecureRandom idSeed = new SecureRandom(); + + /** + * When we have an actual database we'll probably get the id from + * the database... + */ + private long id = idSeed.nextLong(); + + private int weight = 0; + + private int length = 0; + + private int width = 0; + + private int height = 0; + + private Node model; + + private BoundingVolume getBoundingVolume() { + BoundingVolume result = null; + // if (model instanceof Spatial) { + // result = (Spatial) model.getWorldBound(); + // } + + return result; + } + + private double getMaxExtent() { + BoundingVolume v = this.getBoundingVolume(); + double result = -1; + + if (v instanceof BoundingBox) { + BoundingBox vb = (BoundingBox) v; + result = Math.max( Math.max( vb.getXExtent(), vb.getYExtent()), + vb.getZExtent()); + } else if (v instanceof BoundingSphere ) { + result = 2 * ((BoundingSphere) v).getRadius(); + } + + return result; + } + + /** */ + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + /** Return the id of this instance, obviously. */ + public long getId() { + return id; + } +} diff --git a/workspace.code-workspace b/workspace.code-workspace index 1a324a2..8113fcd 100644 --- a/workspace.code-workspace +++ b/workspace.code-workspace @@ -26,6 +26,9 @@ }, { "path": "../MicroWorld/mw-parser" + }, + { + "path": "../../Documents/fiction/merchants-war-game" } ], "settings": {