;;;; model.lisp -- bknr.datastore class definitions for dnd (in-package :dnd) (deftype title () `(member :noob)) (deftype character-class () `(member :hero)) (deftype priority () `(member :low :medium :high)) (defun hero-class (h) "barGaryan") ; TODO: real implementation (defun hero-title (h) "Scouse Chef") ; TODO: real implementation (defun renown (hero) (experience hero)) ; TODO: real implementaiton ;;; PERSISTENT MIXINS (defclass has-uid () ((nuid :reader uid :initform (nuid) :index-type idx:string-unique-index :index-reader object-with-uid)) (:metaclass db:persistent-class)) (defclass can-equip () ((equipment-table :initform nil :type list :documentation "A PLIST mapping 'equipment slots' to instances of LOOT. Equipment slots are things like :head, :torso, :left-ring, etc") (equipment-slot-names :initform +standard-humanoid-equipment+ :initarg :slot-names :type (list keyword) :documentation "The list of slots available to this entity.")) (:metaclass db:persistent-class)) (defclass has-bag () ((bag :reader bag :initform nil :type list :documentation "A list of items that this entity is carrying.")) (:metaclass db:persistent-class)) (defclass has-chronicle () ((chronicle :accessor chronicle :initform nil)) (:metaclass db:persistent-class) (:documentation "A chronicle is a general purpose log of events.")) (defparameter +standard-humanoid-equipment+ '(:head :neck :torso :waist :legs :feet :arms :left-fingers :right-fingers :left-holding :right-holding :cloak) "The equipment slots for standard humanoids") ;;; ABSTRACT CLASSES (defclass game-object (db:store-object has-uid has-chronicle) () (:metaclass db:persistent-class)) ;;; SYSTEM CLASSES (defclass player (db:store-object has-uid) ((nick :reader nickname :initarg :nickname :initform (error "Players must have a nick") :type string :index-type idx:string-unique-index :index-reader player-with-nick) (pwhash :accessor pwhash :type string :initarg :pwhash :documentation "A hash of the password, hashed with the value of the pwsalt slot.") (pwsalt :reader pwsalt :initform (nuid) :type string :documentation "Salt for this hero's password hash.")) (:metaclass db:persistent-class)) ;; TODO expiration? (defclass session (db:store-object) ((player :reader session-player :initarg :player) (id :reader session-id :initform (nuid) :index-type idx:string-unique-index :index-reader session-with-id)) (:metaclass db:persistent-class)) ;;; GAME CLASSES (defclass hero (game-object has-bag can-equip) ((name :accessor name :initarg :name :initform (error "Heroes must be named") :type string :index-type idx:string-unique-index :index-reader hero-known-as) (player :reader player :initarg :player :type player :index-type idx:hash-index :index-reader player-heroes) (quest :accessor quest :initarg :quest :initform nil :type (or nil quest) :documentation "The quest that this hero is on. A hero may be on only one quest at a time.")) (:metaclass db:persistent-class)) (defmethod adventure ((hero hero)) (a:when-let (quest (quest hero)) (adventure quest))) (defclass adventure (game-object) ((creator :reader creator :initarg :creator :initform (error "adventures must have a creator") :type player :documentation "The player instance of the user who made this adventure.") (seers :accessor seers :initarg :seers :initform nil :type (or nil (cons player)) :documentation "Seers are the people who peer out into their instruments of divination that heroes may go on quests.") (title :accessor title :initarg :title :initform (error "A adventure needs a title") :type string) (description :accessor description :initarg :description :initform "" :type string) (rumors :accessor rumors :initform nil :type (or nil (cons rumor)) :documentation "Beasts, Monsters, and Hazards rumored to be lurking about.")) (:metaclass db:persistent-class) (:documentation "A adventure is a container of quests. Adventures are expected to be engaged with on a particular schedule, and are run by particular people.")) (defclass rumor (game-object) ((reporter :reader reporter :initarg :reporter :type player :documentation "The player who hast reported the vile rumor.") (reported :accessor reported :initform (error "A rumor must contain some reported matter") :initarg :reported :type string :documentation "A description of the supposed peril that awaits heroes in a particular adventure.")) (:metaclass db:persistent-class) (:documentation "Transcript of a rumor reported by some player related to a Adventure.")) (defclass quest (game-object) ((adventure :reader adventure :initarg :adventure :initform (error "No quest can fall outside the scope of a adventure.") :type adventure :index-type idx:hash-index :index-reader quests-in-adventure :documentation "The adventure to which this quest belongs") (name :accessor name :initarg :name :type string :initform (format nil "~a" (gensym "QUEST"))) (horizon-of-hope :accessor horizon-of-hope :initarg :deadline :type integer :initform nil :documentation "When all hope becomes lost.") (inception :accessor quest-inception :initform nil :type (or nil integer) :documentation "Time at which the quest began.")) (:metaclass db:persistent-class) (:documentation "A collection of hazards with a deadline and start date which heroes will attack.")) (defclass hazard (game-object) ((quest :accessor quest-of :index-type idx:hash-index :index-reader hazards-in-quest :documentation "The quest to which this hazard belongs. Initially it is unbound. It becomes boudn when the hazard is added to a quest.") (description :accessor description :initarg :description :initform "" :type string :documentation "") (overcomep :accessor is-overcome :initform nil :documentation "indicates whether or not this hazard has been overcome.") (imminence :accessor imminence-of :type priority :documentation "") (menace ;; difficulty :accessor menace-of :type integer :documentation "How dangerous the hazard is." )) (:metaclass db:persistent-class) (:documentation "Hazard is a superclass for all hazards encountered in a quest. It's chronicle includes data about which heroes fought and which overcame."))