11{-|
22Module : Yaifl.Object.Kind
3- Copyright : (c) Avery 2023-2024
3+ Copyright : (c) Avery 2023-2026
44License : MIT
55Maintainer : ppkfs@outlook.com
66
7- A game object (a thing or a room).
7+ Game objects represent the fundamental building blocks of the game world,
8+ encompassing both things (portable objects) and rooms (environmental locations).
9+
10+ This module defines the core `Object` data structure and its supporting components:
11+
12+ - `Object`: The primary data structure combining identification, naming, and kind-specific behaviour
13+ - `ObjectKind`: Classification system for object kinds (distinct from Haskell types)
14+ - `Timestamp`: Creation and modification tracking for objects
15+ - `Name*` types: Linguistic properties controlling article usage and pluralisation
16+ - `IsObject`: Typeclass for thing/room classification
817-}
918
1019module Yaifl.Object.Kind (
11- -- * Pointed sets
12- Pointed (.. )
1320 -- * Objects
1421 -- ** Components
1522 , NamePlurality (.. )
@@ -28,28 +35,50 @@ import Yaifl.Prelude
2835import Yaifl.Entity
2936import Yaifl.WorldModel (WMText )
3037
31- -- | If the object has a pluralised name.
38+ -- | Whether the object's name changes when pluralised.
39+ -- `SingularNamed` objects like "key" become "keys" when plural.
40+ -- `PluralNamed` objects like "sheep" remain "sheep" when plural.
3241data NamePlurality = SingularNamed | PluralNamed
3342 deriving stock (Show , Eq , Ord , Bounded , Enum , Generic , Read )
3443
35- -- | If the object should have an indefinite article or not.
44+ -- | Whether the object's name is a proper noun or common noun.
45+ -- `Proper` names (e.g., "John", "London") don't use articles.
46+ -- `Improper` names (e.g., "key", "door") may use indefinite articles.
3647data NameProperness = Improper | Proper
3748 deriving stock (Show , Eq , Ord , Bounded , Enum , Generic , Read )
3849
39- -- | If the object should have an indefinite article or not.
50+ -- | Whether the object's name is accessible to the command parser.
51+ -- `PrivatelyNamed` objects cannot be referred to by their given name in commands.
52+ -- They can only be referenced via their `understandAs` properties.
53+ -- `PubliclyNamed` objects can be referred to directly by their name in commands.
4054data NamePrivacy = PrivatelyNamed | PubliclyNamed
4155 deriving stock (Show , Eq , Ord , Bounded , Enum , Generic , Read )
4256
43- -- | See also `Yaifl.Metadata.typeDAG`. An object type is just a string that has some relations to other types.
44- -- there is no data or polymorphism connected to a type, so it's very possible to call something a supporter without
45- -- having some supporter properties.
57+ -- | A classification type for game objects, representing their role or category in the game world.
58+ -- ObjectKinds form a directed acyclic graph (see `Yaifl.Metadata.typeDAG`) where relationships
59+ -- between types are explicitly defined rather than implied through inheritance or polymorphism.
60+ --
61+ -- This design allows flexible classification: an object can be classified as a "supporter" without
62+ -- requiring any specific data structure or behavioural implementation. The type system is purely
63+ -- descriptive, enabling runtime type checking and hierarchical organisation without code coupling.
64+ --
65+ -- Examples of object kinds include: "container", "supporter", "door", "person", "scenery".
66+ --
67+ -- The `ObjectKind` is a simple wrapper around `Text` for type safety and to enable specific
68+ -- instances and operations related to the type system.
4669newtype ObjectKind = ObjectKind
4770 { unObjectKind :: Text
4871 } deriving stock (Eq , Show )
4972 deriving newtype (Read , Ord , IsString , Monoid , Semigroup )
5073
51- -- | A `Timestamp` is used to date events that modify, add, or remove objects.
52- -- Currently these aren't...used for anything.
74+ -- | A `Timestamp` tracks when objects are created or modified.
75+ -- Timestamps do not necessarily correspond to game turns, but rather to state update ticks.
76+ -- If an object's timestamp is older than the current game state, it indicates the object
77+ -- may be out of date and should be refreshed.
78+ --
79+ -- Currently implemented but not actively used in game logic, this field provides
80+ -- infrastructure for potential future features such as object aging, undo functionality,
81+ -- or temporal queries.
5382newtype Timestamp = Timestamp
5483 { unTimestamp :: Int
5584 } deriving stock (Show , Read , Generic )
@@ -69,7 +98,7 @@ data Object wm objData objSpecifics = Object
6998 , objectType :: ObjectKind
7099 , creationTime :: Timestamp
71100 , modifiedTime :: Timestamp
72- , specifics :: objSpecifics -- ^ A @vanilla@ object has no specific additional information; this is a @Pointed@ constraint.
101+ , specifics :: objSpecifics -- ^ Kind- specific data (e.g., door mechanics, container contents)
73102 , objectData :: objData -- ^ `ThingData`, `RoomData`, or `Either ThingData RoomData`.
74103 } deriving stock (Generic )
75104
@@ -91,7 +120,7 @@ objectEquals = (. getEntity) . (==) . getEntity
91120instance Eq (Object wm d s ) where
92121 (==) = objectEquals
93122
94- -- | Maybe I'll need this instance for something or other?
123+ -- | Order objects by creation time for chronological sorting.
95124instance Ord (Object wm d s ) where
96125 compare = (. creationTime) . compare . creationTime
97126
@@ -113,7 +142,13 @@ instance Bitraversable (Object wm) where
113142 s' = g (specifics o)
114143 in (\ d s -> o & # objectData .~ d & # specifics .~ s) <$> d' <*> s'
115144
116- -- | If something is a thing or a room.
145+ -- | Typeclass for determining whether an object is a thing or a room.
146+ -- This provides a uniform interface for thing/room classification across
147+ -- different object representations.
148+ --
149+ -- The classification follows the convention established in `Yaifl.Entity`:
150+ -- positive entity IDs represent `Yaifl.Thing.Kind.Thing`s, while negative
151+ -- entity IDs represent `Yaifl.Room.Kind.Room`s.
117152class IsObject o where
118153 isThing :: o -> Bool
119154
0 commit comments