# HG changeset patch # User Steve Losh # Date 1342582869 14400 # Node ID 88091919d482d5777114ecdb70953a37ef589050 # Parent 811f328099c66446b8e6a14bf1878dd9b71e1601 Messages! diff -r 811f328099c6 -r 88091919d482 brain-dump.markdown --- a/brain-dump.markdown Tue Jul 17 23:22:14 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -Ideas -===== - -Remove the distinction between items and creatures. ALL THING ARE ENTITY. - - (defprocotol Entity - (tick [this game]) - (get-location [this game?]) - (get-id [this])) - - (def Entity - (with-meta Entity :default-fns - {:tick (fn [this game] game) - :get-location (fn [this game] (:location this)) - :get-id (fn [this] (:id this))})) - - -Individual things will implement the protocol: - - (defrecord Pixie [id location]) - - (extend-entity Pixie - (tick [this game] - (do-stuff game))) - - (extend Pixie Entity - (merge {:tick (fn [this game] game) - :get-location (fn [this game] (:location this)) - :get-id (fn [this] (:id this))} - {:tick (fn [this game] - (do-stuff game))})) - - (defmacro extend-entity [cls & fns] - (let [fnmap (into {} - (for [[fn-name & fn-tail] fns] - [(keyword fn-name) fn-tail]))] - `(extend ~cls Entity - (merge default-entity-fns - ~fnmap)))) - -The Entity protocol should be very sparse. Most functionality will come from -other protocols that can be "added in" on a case-by-case basis. Like mixins, -but without the monkeypatching clusterfuck. - -Sample Entities ---------------- - -A Fungus might look like: - - (extend' Fungus Destructible ...) - (extend' Fungus Metabolizer ...) - -Funguses don't do much. They do draw nutrition from the soil though, so their -nutritional value should grow over time until they split. - -Goblins: - - (extend' Goblin Mobile ...) - (extend' Goblin Destructible ...) - (extend' Goblin Attacker ...) - (extend' Goblin AI ...) - (extend' Goblin Container ...) - (extend' Goblin Wearer ...) - (extend' Goblin Wielder ...) - (extend' Goblin Eater ...) - (extend' Goblin Metabolizer ...) - -Goblines are mobs that can walk around, be killed, kill things, have an -inventory, wear armor and wield weapons, eat food, and burn their eaten food. - -Pixies: - - (extend' Pixie Mobile ...) - (extend' Pixie Destructible ...) - (extend' Pixie Attacker ...) - (extend' Pixie AI ...) - - (extend' Pixie Item ...) - (extend' Pixie Applicable ...) - (extend' Pixie Edible ...) - -Here Pixies are entities that move around, can be destroyed (i.e. killed), can -attack other entities, have an AI to decide actions (put this in tick?). Sounds -like a normal monster, but they can also function as an item if you pick them -up. They can then be applied or eaten. - -Ideas for Entity Protocols --------------------------- - -### Entity - -Base protocol. All entities must implement this. - -Basically it's implementation-related stuff that's not gameplay-related. - -Exception: materials? - -### Mobile - -Can move autonomously. - -### Item - -Can be placed in a container. - -### Armor - -Can be worn as armor by wearers. - -### Weapon - -Can be used as a weapon by wielders. - -### Container - -Can hold things that implement Item. Creatures can be Containers -- this -effectively means they have an inventory. - -### Food - -Can be eaten by Eaters (maybe). - -### Quaffable - -Can be drunk by drinkers. - -### Eater - -Can eat Food (maybe). - -### Drinker - -Can drink Quaffables (maybe). - -### Metabolizer - -Has a notion of "energy" that either decreases over time (hunger) or increases -over time (photosynthesis). - -### Destructible - -Can be destroyed by physical (or magical) trauma. Usually handled through HP -counts. - -### Decaying - -Can transform to something else (or nothing) over a period of time. - -### Attacker - -Can physically attack other creatures. - -### Wielder - -Can use other entities as weapons if they implement Weapon. - -### Wearer - -Can use other entities as armor if they implement Armor. - -### Sentient - -Has an alignment. Not sure about this one. diff -r 811f328099c6 -r 88091919d482 src/caves/core.clj --- a/src/caves/core.clj Tue Jul 17 23:22:14 2012 -0400 +++ b/src/caves/core.clj Tue Jul 17 23:41:09 2012 -0400 @@ -16,12 +16,17 @@ (defn tick-all [world] (reduce tick-entity world (vals (:entities world)))) +(defn clear-messages [game] + (assoc-in game [:world :entities :player :messages] nil)) + + (defn run-game [game screen] (loop [{:keys [input uis] :as game} game] (when (seq uis) (if (nil? input) - (let [game (update-in game [:world] tick-all)] - (draw-game game screen) + (let [game (update-in game [:world] tick-all) + _ (draw-game game screen) + game (clear-messages game)] (recur (get-input game screen))) (recur (process-input (dissoc game :input) input)))))) diff -r 811f328099c6 -r 88091919d482 src/caves/entities/aspects/attacker.clj --- a/src/caves/entities/aspects/attacker.clj Tue Jul 17 23:22:14 2012 -0400 +++ b/src/caves/entities/aspects/attacker.clj Tue Jul 17 23:41:09 2012 -0400 @@ -1,5 +1,6 @@ (ns caves.entities.aspects.attacker - (:use [caves.entities.aspects.destructible :only [Destructible take-damage + (:use [caves.entities.aspects.receiver :only [send-message]] + [caves.entities.aspects.destructible :only [Destructible take-damage defense-value]] [caves.entities.core :only [defaspect]])) @@ -9,7 +10,13 @@ (defaspect Attacker (attack [this target world] {:pre [(satisfies? Destructible target)]} - (take-damage target (get-damage this target world) world)) + (let [damage (get-damage this target world)] + (->> world + (take-damage target damage) + (send-message this "You strike the %s for %d damage!" + [(:glyph target) damage]) + (send-message target "The %s strikes you for %d damage!" + [(:glyph target) damage])))) (attack-value [this world] (get this :attack 1))) diff -r 811f328099c6 -r 88091919d482 src/caves/entities/aspects/receiver.clj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/caves/entities/aspects/receiver.clj Tue Jul 17 23:41:09 2012 -0400 @@ -0,0 +1,14 @@ +(ns caves.entities.aspects.receiver + (:use [caves.entities.core :only [defaspect]])) + + +(defaspect Receiver + (receive-message [this message world] + (update-in world [:entities (:id this) :messages] conj message))) + + +(defn send-message [entity message args world] + (if (satisfies? Receiver entity) + (receive-message entity (apply format message args) world) + world)) + diff -r 811f328099c6 -r 88091919d482 src/caves/entities/player.clj --- a/src/caves/entities/player.clj Tue Jul 17 23:22:14 2012 -0400 +++ b/src/caves/entities/player.clj Tue Jul 17 23:41:09 2012 -0400 @@ -1,5 +1,6 @@ (ns caves.entities.player (:use [caves.entities.core :only [Entity add-aspect]] + [caves.entities.aspects.receiver :only [Receiver]] [caves.entities.aspects.mobile :only [Mobile move can-move?]] [caves.entities.aspects.digger :only [Digger dig can-dig?]] [caves.entities.aspects.attacker :only [Attacker attack]] @@ -18,6 +19,7 @@ (add-aspect Player Digger) (add-aspect Player Attacker) (add-aspect Player Destructible) +(add-aspect Player Receiver) (defn make-player [location] (map->Player {:id :player diff -r 811f328099c6 -r 88091919d482 src/caves/ui/drawing.clj --- a/src/caves/ui/drawing.clj Tue Jul 17 23:22:14 2012 -0400 +++ b/src/caves/ui/drawing.clj Tue Jul 17 23:41:09 2012 -0400 @@ -107,6 +107,11 @@ (s/move-cursor screen x y))) +(defn draw-messages [screen messages] + (when (seq messages) + (s/put-sheet screen 0 0 messages))) + + (defmethod draw-ui :play [ui game screen] (let [world (:world game) {:keys [tiles entities]} world @@ -119,6 +124,7 @@ (doseq [entity (vals entities)] (draw-entity screen origin entity)) (draw-hud screen game) + (draw-messages screen (:messages player)) (highlight-player screen origin player)))