diff --git a/flora-search-aurora.asd b/flora-search-aurora.asd
index 13eef1f..d400eeb 100644
--- a/flora-search-aurora.asd
+++ b/flora-search-aurora.asd
@@ -8,6 +8,7 @@
(:file "display")
(:file "input")
(:file "menu")
+ (:file "settings")
(:file "inventory")
(:file "intermission")
(:file "overworld.util")
diff --git a/flora-search-aurora.lisp b/flora-search-aurora.lisp
index 93743cc..0630611 100644
--- a/flora-search-aurora.lisp
+++ b/flora-search-aurora.lisp
@@ -13,7 +13,7 @@
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program. If not, see .
-;;;; FLORA-SEARCH-AURORA
+;;;; FLORA-SEARCH-AURORA ✿
;;;; A simple TUI-game made for the text-flavoured LibreJam of 2023-06!
;;;; See: https://jamgaroo.xyz/jams/2
@@ -561,7 +561,7 @@ avoid triggering this."
;;; ———————————————————————————————————
-;;; Military base!
+;;; Military-base!
;;; ———————————————————————————————————
(defun captain-snake-interact (map &optional entity-id)
(make-dialogue-state
@@ -962,30 +962,23 @@ avoid triggering this."
Initializes the current instance of the game, and such."
;; We’ve gotta make fresh copies of the maps, in case the user’s restarted the game.
;; metacopy, I love you <3 <3 <3
- (defparameter *base-map* (🌍:plist->map (metacopy:copy-thing *base-map-plist*)))
- (defparameter *casino-map* (🌍:plist->map (metacopy:copy-thing *casino-map-plist*)))
- (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*)))
-;; (make-flashback-function (alexandria:random-elt (flashbacks))))
- (make-overworld-function *base-map*))
-
-
-(defun submenu ()
- `((:en "IDK"
- :selection 100 :selected t)
- (:en "GO BACK"
- :drop 1)))
+ (lambda (matrix)
+ (defparameter *base-map* (🌍:plist->map (metacopy:copy-thing *base-map-plist*)))
+ (defparameter *casino-map* (🌍:plist->map (metacopy:copy-thing *casino-map-plist*)))
+ (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*)))
+ ;; (make-flashback-function (alexandria:random-elt (flashbacks))))
+ (make-overworld-state *casino-map*)))
(defun main-menu ()
- `((:en "PLAY" :eo "EKLUDI"
- :selection 100 :selected t
+ `((:en "Play" :eo "Ekludi"
+ :selection 50 :selected t
:function ,(start-game-function))
- (:en "SUBMENU" :eo "SUBMENUO" :row 1
- :function ,(📋:make-menu-function (submenu)))
- (:en "TERURE" :eo "BADLY" :row 1)
- (:en "QUIT" :eo "REZIGNI" :row 2
+ (:en "Settings" :eo "Agordoj" :row 1
+ :function ,(🔧:make-settings-menu-function))
+ (:en "Give in" :eo "Cedi" :row 2
:drop 1)))
diff --git a/input.lisp b/input.lisp
index bda93b1..05f7d2e 100644
--- a/input.lisp
+++ b/input.lisp
@@ -13,7 +13,7 @@
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program. If not, see .
-;;;; FLORA-SEARCH-AURORA.INPUT
+;;;; FLORA-SEARCH-AURORA.INPUT ⌨
;;;; All input-related voodoo goes here: Input reading, translating, parsing, etc.
(in-package :flora-search-aurora.input)
@@ -58,6 +58,10 @@
+numpad-game-layout+))
+(defparameter *keyboard* +qwerty-layout+)
+(defparameter *controls* +arrows-game-layout+)
+
+
(defun read-char-plist (&optional (stream *standard-input*))
"Reads a character directly from standard-input (sans buffering).
Simple terminal escape codes (like arrow-keys) are translated into
@@ -84,7 +88,7 @@ docstring of #'escape-code-to-character for more info."
(list :char the-char :modifier modifier :escaped escaped))))
-(defun normalize-char-plist (char-plist &optional (layout +qwerty-layout+))
+(defun normalize-char-plist (char-plist &optional (layout *keyboard*))
"Given a character input property list (as received from READ-CHAR-PLIST),
massage the output into parsable, deescaped, QWERTY-according format."
(let ((normalized (deescape-char-plist char-plist)))
@@ -102,7 +106,7 @@ Not at all comprehensive, but probably-mostly-just-good-enough. ¯\_ (ツ)_/¯"
(defun read-gamefied-char-plist
- (&optional (stream *standard-input*) (layout +qwerty-layout+) (game-layout +arrows-game-layout+))
+ (&optional (stream *standard-input*) (layout *keyboard*) (game-layout *controls*))
"Read a character directly from standard-input, then translating its character into the QWERTY
equivalent, then parsing that character into semantic meaning. Results in a plist like so:
(:char #\w :semantic ↑ :modifier nil :escaped nil)"
@@ -110,7 +114,7 @@ equivalent, then parsing that character into semantic meaning. Results in a plis
game-layout))
-(defun gameify-char-plist (char-plist &optional (game-layout +arrows-game-layout+))
+(defun gameify-char-plist (char-plist &optional (game-layout *keyboard*))
"Given a character input plist (as received by READ-CHAR-PLIST), return a
char plist containing a :FUNCTION property, which contains one of several
semantic symbols that match up for menus/gameplay: ↑, →, ←, ↓, 🆗, or ❎."
@@ -120,7 +124,6 @@ semantic symbols that match up for menus/gameplay: ↑, →, ←, ↓, 🆗, or
char-plist)))
-
(defun deescape-char-plist (char-plist)
"Translate escaped characters into somewhat-semantically-adjacent
characters, like left arrow-key (escaped D) into ← (“LEFTWARDS ARROW”)."
diff --git a/menu.lisp b/menu.lisp
index 5263150..b6e7fdd 100644
--- a/menu.lisp
+++ b/menu.lisp
@@ -13,7 +13,7 @@
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program. If not, see .
-;;;; FLORA-SEARCH-AURORA.UI
+;;;; FLORA-SEARCH-AURORA.MENU 📋
;;;; Generic menu-making, displaying, and management.
;;;; Let's get to it, we're on a deadline!
@@ -168,7 +168,7 @@ That is, 0 for non-selected items and 100 for selected items."
(select-right-menu-item menu-plist)
't))
('⌨:❎
- nil)
+ (list :drop 1))
('⌨:🆗
(if (getf selected-item :exec)
(apply (getf selected-item :exec) '())
diff --git a/overworld.lisp b/overworld.lisp
index 0b23935..986ae36 100644
--- a/overworld.lisp
+++ b/overworld.lisp
@@ -13,7 +13,7 @@
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program. If not, see .
-;;;; FLORA-SEARCH-AURORA.OVERWORLD
+;;;; FLORA-SEARCH-AURORA.OVERWORLD 🌍
;;;; All game-functions and data relating to the “overworld” (that is,
;;;; the primary gameplay, the RPG-ish-ish bits).
@@ -212,7 +212,17 @@ Returns parameters to be used in the next invocation of OVERWORLD-STATE."
(apply (…:string->symbol interaction) (list map interactee-id))
(list :parameters (list :map map)))))
('⌨:❎
- (list :function (🎒:make-inventory-state map)))
+ (list :function
+ (📋:make-menu-function
+ `((:en "Continue" :eo "Malpaŭzigi"
+ :drop 1 :selected t :selection 50)
+ (:en "Backpack" :eo "Sako"
+ :function ,(🎒:make-inventory-function map)
+ :drop 1)
+ (:en "Settings" :eo "Agordoj"
+ :function ,(🔧:make-settings-menu-function))
+ (:en "Give up" :eo "Rezigni"
+ :drop 3)))))
;; Simple up-down-left-right movements
('⌨:→
(move-player map :Δx 1))
@@ -401,7 +411,7 @@ plist containing a character (:CHAR) and :X & :Y coordinates."
;;; ———————————————————————————————————
(defun overworld-state
(matrix &key map (Δt .02))
- "Render the given map to the matrix and take user-input — for one frame.
+ "Render the given map to the MATRIX and take user-input — for one frame.
A state-function for use with STATE-LOOP."
(sleep Δt)
(overworld-state-draw matrix map)
@@ -409,7 +419,12 @@ A state-function for use with STATE-LOOP."
(defun make-overworld-function (map)
- "Return a state-function for a a map, for use with STATE-LOOP."
+ "Return a state-function for a a MAP, for use with STATE-LOOP."
(lambda (matrix &key (map map))
(apply #'🌍:overworld-state
(list matrix :map map))))
+
+
+(defun make-overworld-state (map)
+ "Return a state-plist for a a MAP, for use with STATE-LOOP."
+ (list :function (make-overworld-function map)))
diff --git a/packages.lisp b/packages.lisp
index 050a1d0..e9e78b8 100644
--- a/packages.lisp
+++ b/packages.lisp
@@ -23,8 +23,8 @@
#:incf-0
#:at-least #:at-most
#:string->symbol
- #:system-language #:langcode->keysym #:getf-lang))
-
+ #:system-language #:langcode->keysym #:getf-lang
+ :*language*))
(defpackage :flora-search-aurora.input
(:use :cl)
@@ -36,7 +36,8 @@
:control :meta :shift
+qwerty-layout+ +dvorak-layout+
+arrows-game-layout+ +wasd-game-layout+ +ijkl-game-layout+
- :↑ :← :→ :↓ :↰ :↱ :↲ :↳ :🆗 :❎))
+ :↑ :← :→ :↓ :↰ :↱ :↲ :↳ :🆗 :❎
+ :*keyboard* :*controls*))
(defpackage :flora-search-aurora.display
(:nicknames :fsa.dsp :display :✎)
@@ -53,6 +54,12 @@
#:selected-menu-item
:label :selection :selected))
+(defpackage :flora-search-aurora.settings
+ (:nicknames :fsa.set :settings :🔧)
+ (:use :cl)
+ (:export #:make-settings-menu-function #:settings-menu))
+
+
(defpackage :flora-search-aurora.dialogue
(:nicknames :fsa.dia :dialogue :💬)
(:use :cl)
@@ -63,7 +70,7 @@
(defpackage :flora-search-aurora.inventory
(:nicknames :fsa.inv :inventory :🎒)
(:use :cl)
- (:export #:inventory-state #:make-inventory-state))
+ (:export #:inventory-state #:make-inventory-function))
(defpackage :flora-search-aurora.intermission
(:nicknames :fsa.int :intermission :🎭)
@@ -72,19 +79,21 @@
:make-intermission-function))
(defpackage :flora-search-aurora.overworld.util
- (:nicknames :fsa.o.u :overworld.util :🌍.…)
+ (:nicknames :fsa.ovr.… :overworld.util :🌍.…)
(:use :cl)
(:export #:coords->symbol #:symbol->coords
#:world-coords->screen-coords
#:world-coords-chunk
#:map->plist #:plist->map
- #:save-map-to-file))
+ #:save-map-to-file
+ :*language*))
(defpackage :flora-search-aurora.overworld
- (:nicknames :fsa.o :overworld :🌍)
+ (:nicknames :fsa.ovr :overworld :🌍)
(:use :cl
:flora-search-aurora.overworld.util)
- (:export #:overworld-state #:overworld-state-draw #:make-overworld-function
+ (:export #:make-overworld-state #:make-overworld-function
+ #:overworld-state #:overworld-state-draw
#:merge-maps
#:world-coords->screen-coords
#:getf-entity #:getf-entity-data #:removef-entity
diff --git a/settings.lisp b/settings.lisp
new file mode 100644
index 0000000..2c69180
--- /dev/null
+++ b/settings.lisp
@@ -0,0 +1,92 @@
+;;;; Copyright © 2023, Jaidyn Ann
+;;;;
+;;;; This program is free software: you can redistribute it and/or
+;;;; modify it under the terms of the GNU General Public License as
+;;;; published by the Free Software Foundation, either version 3 of
+;;;; the License, or (at your option) any later version.
+;;;;
+;;;; This program is distributed in the hope that it will be useful,
+;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;;; GNU General Public License for more details.
+;;;;
+;;;; You should have received a copy of the GNU General Public License
+;;;; along with this program. If not, see .
+
+;;;; FLORA-SEARCH-AURORA.SETTINGS 🔧
+;;;; Guess whatttt? Settings, that’s what. =w=
+;;;; How riveting!
+
+(in-package :flora-search-aurora.settings)
+
+
+(defun make-controls-function (controls)
+ "Simple state-function (for use with STATE-LOOP's state plists) that sets the
+keyboard controls to the given CONTROLS."
+ (lambda (matrix)
+ (setq ⌨:*controls* controls)
+ (list :drop 1)))
+
+
+(defun make-keyboard-function (layout)
+ "Simple state-function (for use with STATE-LOOP's state plists) that sets the
+keyboard layout to the given LAYOUT."
+ (lambda (matrix)
+ (setq ⌨:*keyboard* layout)
+ (list :drop 1)))
+
+
+(defun make-language-function (language)
+ "Simple state-function (for use with STATE-LOOP's state plists) that sets the
+game language to the given LANGUAGE."
+ (lambda (matrix)
+ (setq …:*language* language)
+ (list :drop 1)))
+
+
+(defun keyboard-menu ()
+ `((:en "QWERTY"
+ :selection 50 :selected t
+ :function ,(make-keyboard-function ⌨:+qwerty-layout+)
+ :drop 1)
+ (:en "Dvorak"
+ :function ,(make-keyboard-function ⌨:+dvorak-layout+)
+ :drop 1)
+ (:en "Arrows" :eo "Sagoj"
+ :function ,(make-controls-function ⌨:+arrows-game-layout+)
+ :row 1 :drop 1)
+ (:en "WASD"
+ :function ,(make-controls-function ⌨:+wasd-game-layout+)
+ :row 1 :drop 1)
+ (:en "IJKL" :eo "IJKL"
+ :function ,(make-controls-function ⌨:+ijkl-game-layout+)
+ :row 1 :drop 1)))
+
+
+(defun language-menu ()
+ `((:en "Esperanto"
+ :selected t :selection 50
+ :function ,(make-language-function :eo)
+ :drop 1)
+ (:en "English"
+ :function ,(make-language-function :en)
+ :row 1 :drop 1)))
+
+
+(defun settings-menu ()
+ `((:en "Keyboard" :eo "Klavararanĝo"
+ :selection 50 :selected t
+ :function
+ ,(📋:make-menu-function (keyboard-menu))
+ :drop 1)
+ (:en "Language" :eo "Lingvo"
+ :function ,(📋:make-menu-function (language-menu))
+ :drop 1)
+ (:en "Back" :eo "Reiri"
+ :drop 1)))
+
+
+(defun make-settings-menu-function ()
+ "Create a menu state-function for use with STATE-LOOP, displaying settings
+and allowing the user to modify them. Pretty self-explanatory, tbh."
+ (📋:make-menu-function (settings-menu)))
diff --git a/util.lisp b/util.lisp
index 4cb5c65..b3005c4 100644
--- a/util.lisp
+++ b/util.lisp
@@ -153,8 +153,11 @@ if the language is among the supported. Otherwise, nil."
:en))
-(defun getf-lang (plist &optional (language (system-language)) (fallback-lang :en))
- "With a plist containing keys of language-codes, return the property either fitting the
+(defun getf-lang (plist &key language (fallback-lang :en))
+ "With a PLIST containing keys of language-codes, return the property either fitting the
preferred LANGUAGE, or the backup FALLBACK-LANG (if LANGUAGE’s is NIL)."
- (or (getf plist language)
+ (or (getf plist (or language (ignore-errors *language*) (system-language)))
(getf plist fallback-lang)))
+
+
+(defparameter *language* (…:system-language))