Libregamejam version of the game

This commit is contained in:
Jaidyn Ann 2023-07-15 05:04:17 -05:00
parent 72c49e3c89
commit 8d4fcb2295
12 changed files with 174 additions and 56 deletions

View File

@ -199,6 +199,7 @@ Returns the state for use with STATE-LOOP, pay attention!"
(list :parameters (list :dialogue (cdr dialogue-list) :map map))
(progn
(:hide-cursor)
(clear-input)
(list :drop (1+ (or (getf dialogue :drop) 0))
:function (getf dialogue :function)
:parameters (if (member :parameters dialogue)

View File

@ -13,7 +13,7 @@
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;;; FLORA-SEARCH-AURORA.DISPLAY
;;;; FLORA-SEARCH-AURORA.DISPLAY
;;;; All display-related curses go here.
(in-package :flora-search-aurora.display)

View File

@ -13,7 +13,7 @@
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;;; FLORA-SEARCH-AURORA.ENGINE
;;;; FLORA-SEARCH-AURORA.ENGINE
;;;; The core of the games engine, the loop. Not much to see here other
;;;; than a loop. Honest!
@ -39,7 +39,7 @@ overheat, or something ¯\_(ツ)_/¯"
(let ((state-result
(apply (car states) (cons matrix state-params)))) ;; Run the last-added state-loop.
(:print-screen-matrix (:matrix-delta last-matrix matrix)) ;; Print its results.
;; (format *error-output* "~S~%" state-result)
;; (format *error-output* "S::~S~%D::~S~%" states state-result)
(force-output)
(state-loop
(cond ((listp state-result)

View File

@ -446,9 +446,38 @@ run the :USE function of the nearest entity, if it has any."
:en "... You're pretentious, as per usual.")))
(defun childhood-friend-dialogue-lavendula (sasha)
(start-dialogue
(say sasha :eo "Ee... dankon?"
:en "Uh... thanks?")
(say sasha :eo "Kion vi eĉ alcelas per ĉi tio? Je dio."
:en "What're you even getting at? Jesus.")
(say 'player :eo "Saŝa, mi pensas ke lavendo perfekte akordas vin."
:en "Sasha, I think lavender fits you perfectly.")
(say 'player :eo "Vi malfidas ĉiun, eĉ tiujn kiuj plej fidas je vi."
:en "You distrust and alienate everyone, even those who are most loyal to you.")
(say 'player :eo "Mi eble ne diris rekte ĝis nun, do jen:"
:en "Maybe I haven't said it directly before, so I'll go ahead now:")
(face sasha ";w:" ":w:")
(say 'player :eo "Mi zorgas pri vi multe, vi ĉiam estis mia plej kara amiko."
:en "I care about you a lot, Sasha, and you've always been my dearest friend.")
(say 'player :eo "Malgraŭ via mistraktado, mi neniam foriris, ĉu ne?"
:en "Despite your pushing me away -- violently -- I never did leave, right?")
(say 'player :eo "Mi konscias ke vi \"testadis\" nian amikecon, sed vi ne devas tion fari plu."
:en "I know you try to \"test\" our friendship, but you don't have to do that anymore.")
(say sasha :en "...")
(say sasha :eo "... ĉu vere bonas?"
:en "... is it really alright?")
(say 'player :eo "Jes. Friends?"
:en "Yea. Friends?")
(face sasha "<w<" "^o^")
(say sasha :eo "Amikoj."
:en "Friends.")))
(defun childhood-friend-dialogue-bracelet (map sasha)
(append (childhood-friend-dialogue-bracelet-intro sasha)
(if (getf-act map :sasha-flourish)
(if (getf-act map :encourage-friendship)
(childhood-friend-dialogue-bracelet-good-end sasha)
(childhood-friend-dialogue-bracelet-bad-end sasha))))
@ -456,11 +485,17 @@ run the :USE function of the nearest entity, if it has any."
(defun childhood-friend-use (map item-plist &optional entity-id)
(let ((item-id (:string->symbol (getf item-plist :id))))
(cond ((eq item-id 'bracelet)
(if (getf-act map :encourage-friendship)
(setf (getf-act map :perfect-friendship) 't))
(make-dialogue-state
map (childhood-friend-dialogue-bracelet map entity-id)))
((eq item-id 'neĝfloro)
(remove-item map entity-id)
(make-dialogue-state map (childhood-friend-dialogue-edelweiss entity-id)))
((eq item-id 'lavendula)
(setf (getf-act map :encourage-friendship) 't)
(remove-item map entity-id)
(make-dialogue-state map (childhood-friend-dialogue-lavendula entity-id)))
('t
(refusal-use map item-plist entity-id)))))
@ -569,15 +604,11 @@ avoid triggering this."
(defun flashback-childhood-friend-use (map item-plist &optional entity-id)
(let ((item-id (:string->symbol (getf item-plist :id))))
(cond ((eq item-id 'bracelet))
(cond ((eq item-id 'bracelet)
;; If player gives her the special bracelet, skip the dialogue intro
(make-dialogue-state
map (flashback-childhood-friend-dialogue-bracelet map entity-id))
((eq item-id 'neĝfloro)
(make-dialogue-state map (childhood-friend-dialogue-edelweiss entity-id)))
('t
;; Otherwise, have her politely refuse. =w=
(refusal-use map item-plist entity-id)))))
(make-dialogue-state
map (flashback-childhood-friend-dialogue-bracelet map entity-id)))
('t (childhood-friend-use map item-plist entity-id)))))
@ -1284,9 +1315,8 @@ Initializes the current instance of the game, and such."
(defparameter *flashback-casino-map* (🌍:plist->map (metacopy:copy-thing *flashback-casino-map-plist*)))
(defparameter *flashback-school-map* (🌍:plist->map (metacopy:copy-thing *flashback-school-map-plist*)))
(defparameter *outdoors-map* (🌍:plist->map (metacopy:copy-thing *outdoors-map-plist*)))
(take-item *base-map* 'neĝfloro)
;; (make-flashback-state (alexandria:random-elt (flashbacks)))))
(make-overworld-state *base-map*)))
(take-item *base-map* 'lavendula)
(make-flashback-state (alexandria:random-elt (flashbacks)))))
(defun main-menu ()

View File

@ -94,3 +94,11 @@ Part of INVENTORY-STATE."
(lambda (matrix &key (title title) (subtitle subtitle) (side-text side-text) (return return) (progress 0))
(funcall #'intermission-state
matrix :title title :subtitle subtitle :side-text side-text :progress progress :return return)))
(defun make-intermission-state (title subtitle side-text return)
"Return a state-plist for intermission, for use with STATE-LOOP."
(list :parameters nil
:function
(make-intermission-function title subtitle side-text return)))

View File

@ -13,7 +13,7 @@
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;;; FLORA-SEARCH-AURORA.INVENTORY
;;;; FLORA-SEARCH-AURORA.INVENTORY 🎒
;;;; The menu for inventory selection/management.
(in-package :flora-search-aurora.inventory)
@ -95,7 +95,7 @@ Part of INVENTORY-STATE."
(list :parameters (list :map map :inventory inventory-menu)))
;; Return the menu itself, if non-nil.
(menu-return
menu-return)
't)
;; If menu-return was non-nil, the user left the menu. Lets leave inventory!
('t
(list :drop 1 :parameters (list :map map))))))
@ -108,15 +108,15 @@ Part of INVENTORY-STATE."
(defun render-selected-item (matrix items)
"Draw the title, avatar, and description of the currently-selected item to
the bottom of the screen."
(let* ((item (menu:selected-menu-item items))
(let* ((item (📋:selected-menu-item items))
(name (list :en (or (getf item :name-en) (getf item :inv-name-en) (getf item :id))
:eo (or (getf item :name-eo) (getf item :inv-name-eo))))
(desc (list :en (getf item :desc-en)
:eo (getf item :desc-eo))))
(display:render-string-verbatim matrix (str:concat ":" (:getf-lang name) ": "
(getf item :avatar))
(:render-string-verbatim matrix (str:concat ":" (:getf-lang name) ": "
(getf item :avatar))
'(:x 1 :y 17))
(display:render-string matrix (:getf-lang desc)
(:render-string matrix (:getf-lang desc)
'(:x 1 :y 18) :width 70)))
@ -140,7 +140,7 @@ Part of INVENTORY-STATE."
(inventory-state-update map inventory submenu))
(defun make-inventory-state (map)
(defun make-inventory-function (map)
"Return a state-function for inventory-listing, for use with STATE-LOOP."
(lambda (matrix &key (map map) (submenu nil) (inventory (items->menu-plist (gethash :items map))))
(apply #'🎒:inventory-state

View File

@ -32,13 +32,6 @@ rectangle as defined by its TOP-LEFT-CORNER & BOTTOM-RIGHT-CORNER."
(>= (getf point :y) (getf top-left-corner :y))))
(defmacro remove-from-alistf (key alist)
"Remove the given item from an associative list destructively."
`(alexandria:removef
,alist ,key
:test (lambda (key item) (eq key (car item)))))
;;; ———————————————————————————————————
;;; Accessors
@ -61,7 +54,7 @@ rectangle as defined by its TOP-LEFT-CORNER & BOTTOM-RIGHT-CORNER."
Literally kill them, show no mercy, dig your sharp nails into their fleshy
stomache and PULL HARD, show NO REMORSE. RAAAAAA 🗡🩸"
(mapcar (lambda (chunk-alist)
(overworld::remove-from-alistf entity-id (cdr chunk-alist)))
(:remove-from-alistf entity-id (cdr chunk-alist)))
(gethash :entities map)))
@ -168,8 +161,10 @@ Used primarily in moving between different maps in an overworld state."
(defun overworld-state-update (map Δt)
"Do nothing, lol. Core part of OVERWORLD-STATE.
Returns parameters to be used in the next invocation of OVERWORLD-STATE."
(process-overworld-time map Δt)
(process-overworld-input map))
(let ((time-result (process-overworld-time map Δt)))
(if time-result
time-result
(process-overworld-input map))))
(defun seconds->game-datetime (seconds &key (game-day-length 240))
@ -186,15 +181,42 @@ Returns a plist of properties :DAY, :HOUR, and :MINUTE, all numbers."
:minute (floor (* 60 minutes-fraction))))))
(defun end-game-string (map)
(str:concat
(if (getf-act map :encourage-scientist)
(:getf-lang '(:en "The cities of Etteburg and Bigborough live in peace. Doctor Klara Tim reached new heights in her professional career."
:eo "La urboj de Etburgo kaj Egburo apudvivas pace. Doktoro Klara Tim atingis altojn en sia kariero, plimemfide."))
(:getf-lang '(:en "The city of Etteburg was nearly completely destroyed by the neighboring city Bigborough's police force, which claimed the city as its own.")))
" "
(if (getf-act map :perfect-friendship)
(:getf-lang '(:en "Friendship with Sasha blossoms, and the two are closer than ever before. She no longer broods by the cliffside, but has reintegrated into society. What an impactful flower, huh?"))
(if (getf-act map :encourage-friendship)
(:getf-lang '(:en "Friendship with Sasha is better than ever before, yet still somewhat distant. Often, Sasha returns to the cliffside."))
(:getf-lang '(:en "To this day, Sasha broods by the cliffside alone."))))))
(defun end-game (map)
(setf flora-search-aurora:*knows* (gethash :knows map))
(🎭:make-intermission-state
'(:eo "LUDO FINITA" :en "GAME OVER")
'(:en "Where are they now?")
(list :en (end-game-string map))
(list :drop 1)))
(defun process-overworld-time (map Δt)
"Do nothing, lol. Core part of OVERWORLD-STATE.
Returns parameters to be used in the next invocation of OVERWORLD-STATE."
(let* ((time (:incf-0 (gethash :seconds map) Δt))
(game-datetime (seconds->game-datetime time)))
;; Go through the day-update procedures!
(when (not (eq (getf game-datetime :day)
(gethash :day map)))
(setf (gethash :day map) (getf game-datetime :day)))))
(if (eq (gethash :day map) 3)
(end-game map)
(progn
;; Go through the day-update procedures!
(when (not (eq (getf game-datetime :day)
(gethash :day map)))
(setf (gethash :day map) (getf game-datetime :day)))
nil))))
(defun process-overworld-input (map)

View File

@ -22,6 +22,7 @@
#:plist=
#:incf-0
#:at-least #:at-most
#:remove-from-alistf
#:string->symbol
#:system-language #:langcode->keysym #:getf-lang
:*language*))
@ -111,8 +112,9 @@
(defpackage :flora-search-aurora
(:nicknames :fsa :)
(:export #:main
:player)
:player :*knows*)
(:use :cl
:flora-search-aurora.input :flora-search-aurora.display
:flora-search-aurora.overworld :flora-search-aurora.dialogue
:flora-search-aurora.menu))

View File

@ -430,7 +430,7 @@ Fojfoje mi ja ŝatas mian fakon, mdr.</property>
</properties>
<point/>
</object>
<object id="10" name="Ring" type="Entity" x="346.347" y="606.126">
<object id="10" name="Ring" type="Entity" x="26.347" y="657.459">
<properties>
<property name="adjective-en" value="pretty"/>
<property name="adjective-eo" value="bele"/>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="left-down" width="72" height="41" tilewidth="17" tileheight="17" infinite="0" nextlayerid="5" nextobjectid="29">
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="left-down" width="72" height="41" tilewidth="17" tileheight="17" infinite="0" nextlayerid="7" nextobjectid="35">
<tileset firstgid="1" source="font.tsx"/>
<layer id="1" name="Foreground" width="72" height="41">
<properties>
@ -128,7 +128,35 @@
<property name="Δy" type="int" value="-1"/>
</properties>
</object>
<object id="26" name="Cat" x="1114" y="367.5">
</objectgroup>
<objectgroup id="2" name="People">
<object id="11" name="Player" type="Person" x="606.727" y="675.464">
<properties>
<property name="facing-right" type="bool" value="false"/>
<property name="id" value="✿:player"/>
</properties>
<point/>
</object>
</objectgroup>
<objectgroup id="5" name="Items">
<object id="30" name="Leontopodium nivale" type="Item" x="606" y="28">
<properties>
<property name="adjective-en" value="invigorating"/>
<property name="adjective-eo" value="kuraĝige"/>
<property name="avatar" value="&lt;*&gt;"/>
<property name="desc-en" value="Leontopodium nivale: Courage, daring."/>
<property name="desc-eo" value="Leontopodium nivale: Kuraĝo, bravemo.r"/>
<property name="id" value="✿:neĝfloro"/>
<property name="interact" value="✿:TAKE-ITEM-INTERACT"/>
<property name="name-en" value="Edelweiss"/>
<property name="name-eo" value="Neĝfloro"/>
<property name="use" value="✿:to-person-use"/>
</properties>
<point/>
</object>
</objectgroup>
<objectgroup id="6" name="Descriptions">
<object id="31" name="Cat" x="1117" y="370.5">
<properties>
<property name="avatar" value="f"/>
<property name="desc-en">(It's a kitty! How cute!)
@ -142,7 +170,7 @@
</properties>
<point/>
</object>
<object id="27" name="Dog" x="162.5" y="301.5">
<object id="32" name="Dog" x="165.5" y="304.5">
<properties>
<property name="avatar" value="d"/>
<property name="desc-en">(Bark bark! It's a dog!)
@ -156,9 +184,7 @@
</properties>
<point/>
</object>
</objectgroup>
<objectgroup id="2" name="People">
<object id="10" name="Exit window" type="Trigger" x="606.329" y="676.813">
<object id="33" name="Exit window" type="Trigger" x="609" y="679.5">
<properties>
<property name="desc-en">(Jesus, this place is a nightmare.)
(No wonder they went out of business!)
@ -174,15 +200,5 @@ r</property>
</properties>
<point/>
</object>
<object id="11" name="Player" type="Person" x="603.102" y="675.464">
<properties>
<property name="facing-right" type="bool" value="false"/>
<property name="id" value="✿:player"/>
</properties>
<point/>
</object>
<object id="28" x="603" y="25">
<point/>
</object>
</objectgroup>
</map>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="left-down" width="288" height="100" tilewidth="12" tileheight="17" infinite="0" nextlayerid="20" nextobjectid="130">
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="left-down" width="288" height="100" tilewidth="12" tileheight="17" infinite="0" nextlayerid="21" nextobjectid="133">
<tileset firstgid="1" source="font.tsx"/>
<layer id="1" name="Background" width="288" height="100">
<properties>
@ -1875,8 +1875,40 @@ DANĜERA LOKO - VENENA MATERIO
<point/>
</object>
</objectgroup>
<objectgroup id="20" name="Items">
<object id="131" name="Leontopodium nivale" type="Item" x="3270.67" y="104">
<properties>
<property name="adjective-en" value="invigorating"/>
<property name="adjective-eo" value="kuraĝige"/>
<property name="avatar" value="&lt;*&gt;"/>
<property name="desc-en" value="Leontopodium nivale: Courage, daring."/>
<property name="desc-eo" value="Leontopodium nivale: Kuraĝo, bravemo.r"/>
<property name="id" value="✿:neĝfloro"/>
<property name="interact" value="✿:TAKE-ITEM-INTERACT"/>
<property name="name-en" value="Edelweiss"/>
<property name="name-eo" value="Neĝfloro"/>
<property name="use" value="✿:to-person-use"/>
</properties>
<point/>
</object>
<object id="132" name="Lavendula" type="Item" x="1109" y="1660">
<properties>
<property name="adjective-en" value="offputting"/>
<property name="adjective-eo" value="malkomfortige"/>
<property name="avatar" value="&lt;@&gt;"/>
<property name="desc-en" value="Lavendula: Distrust, facade."/>
<property name="desc-eo" value="Lavendula: Malfido, ŝajnigo."/>
<property name="id" value="✿:lavendula"/>
<property name="interact" value="✿:TAKE-ITEM-INTERACT"/>
<property name="name-en" value="Lavender"/>
<property name="name-eo" value="Lavendo"/>
<property name="use" value="✿:to-person-use"/>
</properties>
<point/>
</object>
</objectgroup>
<objectgroup id="7" name="People">
<object id="2" name="Player" type="Person" x="2806.33" y="491.34">
<object id="2" name="Player" type="Person" x="484.997" y="216.673">
<properties>
<property name="facing-right" type="bool" value="true"/>
<property name="id" value="✿:player"/>

View File

@ -125,6 +125,13 @@ minimum returns your more pitiful of moments."
;;; ———————————————————————————————————
;;; Linguistic & symbolic affirs
;;; ———————————————————————————————————
(defmacro remove-from-alistf (key alist &key (test 'eql))
"Remove the given item from an associative list destructively."
`(alexandria:removef
,alist ,key
:test (lambda (key item) (,test key (car item)))))
(defun string->symbol (string)
"Given a STRING with an optionally defined package (e.g., package:symbol),
return it as an appopriate symbol."