summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrant Shoshin Shangreaux <shoshin@cicadas.surf>2023-03-05 11:33:08 -0600
committerGrant Shoshin Shangreaux <shoshin@cicadas.surf>2023-03-05 11:33:08 -0600
commit89d0d687992b41f7f0f9b0d3da19d9d587f06010 (patch)
tree8d1dabc9cf9c79358b16c23959681fc299219e57
parent04df19a88a381e6bdc60d7f566e02e99b40c0087 (diff)
Add: page-render-mode, model cleanup, tavern view wip
-rw-r--r--DEV.org15
-rw-r--r--endpoints.lisp12
-rw-r--r--model.lisp48
-rw-r--r--pages.lisp40
4 files changed, 93 insertions, 22 deletions
diff --git a/DEV.org b/DEV.org
index f123a54..66f3c53 100644
--- a/DEV.org
+++ b/DEV.org
@@ -8,6 +8,21 @@
- [X] handle post (set a cookie/header)
- [X] make a tavern page
** TODO Make Campaigns
+ - creator
+ - seers
+ - title
+ - rumors
+
+As a player, I can "petition the Emperor" to submit a request for a campaign
+against the darkness. I give this campaign a title it shall be known by.
+I will become the CREATOR of the campaign, and one of its SEERS. I can
+appoint fellow players as additional SEERS.
+
+Once a campaign exists, any player may submit a RUMOR related to said
+campaign. Rumors are viewable by all, but SEERS may act upon those rumors
+to lay out a plan of attack, create a QUEST which is filled with HAZARDS
+informed by those rumors.
+
** TODO Make Monsters (in campaigns)
** TODO Attack Monsters (assign heroes / change status)
diff --git a/endpoints.lisp b/endpoints.lisp
index 4cd9aef..96e3876 100644
--- a/endpoints.lisp
+++ b/endpoints.lisp
@@ -53,6 +53,13 @@ I.e. It should be called within the scope of a request handler."
"Returns T if user agent string matches on a list of known text browsers."
(some (lambda (s) (search s user-agent)) '("Emacs" "Lynx" "w3m")))
+(defun page-render-mode (user-agent)
+ "Given the USER-AGENT string from request headers, returns a symbol which
+indicates which render mode to use. For example if Emacs is the user-agent,
+return :text-12mode."
+ (cond ((text-browser-p user-agent) :text-page)
+ (t :page)))
+
(defmacro with-session ((player &key session (redirect "/tavern-door")) &body body)
(let ((session (or session (gensym "SESSION"))))
`(a:if-let (,session (current-session))
@@ -129,9 +136,8 @@ functions in url parameters in endpoint definitions."
(defendpoint* :get "/tavern" () ()
(with-session (me)
- (if (text-browser-p (lzb:request-header :user-agent))
- (tavern-text me)
- (tavern me))))
+ (render (page-render-mode (lzb:request-header :user-agent))
+ (make-instance 'tavern :player me))))
(defendpoint* :get "/godess-shrine" () ()
(with-session (player)
diff --git a/model.lisp b/model.lisp
index 0598cf7..fef01da 100644
--- a/model.lisp
+++ b/model.lisp
@@ -103,7 +103,7 @@
:initarg :campaign
:initform nil
:type campaign
- :documentation "A hero may be in at mostk one campaign at a time."))
+ :documentation "A hero may be in at most one campaign at a time."))
(:metaclass db:persistent-class))
@@ -123,51 +123,75 @@
:reader campaign-creator
:initarg :creator
:initform (error "campaigns must have a creator")
- :documentation "The hero instance of the user who made this campaign.")
+ :type player
+ :documentation "The player instance of the user who made this campaign.")
(seers
:accessor campaign-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 campaign-title
+ :accessor title
:initarg :title
- :initform (error "A campaign needs a title"))
+ :initform (error "A campaign needs a title")
+ :type string)
(rumors
:accessor campaign-rumors
- :initarg nil
+ :initform nil
+ :type (or nil (cons rumor))
:documentation "Beasts, Monsters, and Hazards rumored to be lurking about."))
(:metaclass db:persistent-class)
(:documentation "A campaign is a container of quests. Campaigns are expected to be engaged with on a particular schedule, and are run by particular people."))
+(defclass rumor (db:store-object)
+ ((reporter
+ :reader rumor-reporter
+ :initarg :reporter
+ :type player
+ :documentation "The player who hast reported the vile rumor.")
+ (content
+ :accessor rumor-content
+ :initform (error "A rumor must have content")
+ :initarg :content
+ :type string
+ :documentation "A description of the supposed peril that awaits heroes in a particular campaign."))
+ (:metaclass db:persistent-class)
+ (:documentation "Transcript of a rumor reported by some player related to a Campaign."))
+
(defclass quest (game-object)
((campaign
:reader quest-campaign
:initarg :campaign
:initform (error "No quest can fall outside the scope of a campaign.")
+ :type campaign
:index-type idx:hash-index
:index-reader quests-in-campaign
:documentation "The campaign to which this quest belongs")
(name
:accessor quest-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.")
(heroes
:accessor heroes-on-quest
:initarg :heroes
:initform nil
+ :type (or nil (cons hero))
:documentation "A list of heroes in this quest. Join and flight dates are logged in the chronicle.")
- (startedp
- :accessor quest-startedp
+ (inception
+ :accessor quest-inception
:initform nil
- :documentation "Indication of whether the quest is active or not - i.e. whether heroes are on this quest."))
+ :type (or nil integer)
+ :documentation "Time at which the quest began."))
(:metaclass db:persistent-class)
- (:documentation "A collection of hazards"))
+ (:documentation "A collection of hazards with a deadline and start date which heroes will attack."))
(defclass hazard (game-object)
((quest
@@ -175,6 +199,12 @@
: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
diff --git a/pages.lisp b/pages.lisp
index 9701334..378156a 100644
--- a/pages.lisp
+++ b/pages.lisp
@@ -32,6 +32,14 @@ must specialize :left :milsddle :right on your desired data type."
(:div :class "middle-column" (render :middle data))
(:div :class "right-column" (render :right data)))))
+;;; Object-Endpoint Helpers
+
+(defgeneric url-path-to (obj)
+ (:documentation "Return a string that is the absolute url path to OBJ."))
+
+(defmethod url-path-to ((obj campaign))
+ (format nil "/campaign/~a" (urlify (title obj))))
+
;;; PAGES
(defmacro with-page ((&key title) &body body)
@@ -95,19 +103,31 @@ must specialize :left :milsddle :right on your desired data type."
(with-page (:title "A Bustling Tavern")
(render :three-column-layout tavern)))
-(defun tavern-text (player)
- (with-page (:title "A Bustling Tavern")
- (render :page-text (make-instance 'tavern :player player))))
-
-(defrender :page-text ((tavern tavern))
+(defrender :text-page ((tavern tavern))
(let ((player (player tavern)))
(with-html
(render :details player)
- (:table
- (:tr (:td (:h4 "Your Heroes"))
- (:td (:h4 "Your Campaigns")))
- (:tr (:td (:h4 "Gossip & Gab"))
- (:td (:h4 "Comrades in Arms")))))))
+ (render :list (player-heroes player))
+ (:a :href "/spymaster" "Report a Roguish Rumour...")
+ ;; (:table
+ ;; (:tr (:td (:h4 "Your Heroes"))
+ ;; (:td (:h4 "Your Campaigns")))
+ ;; (:tr (:td (:h4 "Gossip & Gab"))
+ ;; (:td (:h4 "Comrades in Arms"))))
+
+ )))
+
+(defrender :list-item ((hero hero))
+ (with-html
+ (with-slots ((name campaign) hero)
+ (:p name "the" (hero-class hero) (hero-title hero)
+ (when campaign
+ (:span "who is off in the campaign")
+ (:span (render :inline campaign)))))))
+
+(defrender :inline ((campaign campaign))
+ (with-html
+ (:a :href (url-path-to campaign) (title campaign))))
(defrender :left ((tavern tavern))
(let ((player (player tavern)))