X-Git-Url: https://jxself.org/git/?p=mudsync.git;a=blobdiff_plain;f=mudsync%2Fplayer.scm;h=63af65e77a8f84071f5780cfd486f6a5fb183717;hp=feb14f80a2375e9b67a4d6b4728ab558226c0c12;hb=8a2341e98f75a5df295f49c08485eb6339dda19e;hpb=a91cab366a655c3162fb516b7b1242d60f0e2d2a diff --git a/mudsync/player.scm b/mudsync/player.scm index feb14f8..63af65e 100644 --- a/mudsync/player.scm +++ b/mudsync/player.scm @@ -23,9 +23,12 @@ #:use-module (mudsync parser) #:use-module (8sync systems actors) #:use-module (8sync agenda) + #:use-module (ice-9 control) #:use-module (ice-9 format) + #:use-module (ice-9 match) #:use-module (oop goops) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-9) #:export ( player-self-commands)) @@ -41,6 +44,9 @@ (append player-actions gameobj-actions)) +(define player-dispatcher + (simple-dispatcher player-actions*)) + (define-class () (username #:init-keyword #:username #:accessor player-username) @@ -54,7 +60,7 @@ (message-handler #:init-value ;; @@: We're gonna need action inheritance real awful soon, huh? - (simple-dispatcher player-actions*))) + (wrap-apply player-dispatcher))) ;;; player message handlers @@ -75,11 +81,12 @@ (define winner (pk 'winner (find-command-winner command-candidates input-rest))) - (<- player (gameobj-gm player) 'write-home - #:text - (format #f "<~a>: ~s\n" - (player-username player) - input))) + (match winner + ((cmd-action winner-id message-args) + (apply send-message player (pk 'winner-id winner-id) (pk 'cmd-action cmd-action) (pk 'message-args message-args))) + (#f + (<- player (gameobj-gm player) 'write-home + #:text "Huh?\n")))) ;;; player methods @@ -99,4 +106,102 @@ (<- player (gameobj-gm player) 'write-home #:text message-text)) +;;; Command handling +;;; ================ + +;; @@: Hard to know whether this should be in player.scm or here... +;; @@: This could be more efficient as a stream...!? +(define (player-gather-command-handlers player verb) + (define player-loc + (let ((result (gameobj-loc player))) + (if result + result + (throw 'player-has-no-location + "Player ~a has no location! How'd that happen?\n" + #:player-id (actor-id player))))) + ;; Ask the room for its commands + (define room-commands + ;; TODO: Map room id and sort + (message-ref + (<-wait player player-loc + 'get-container-commands + #:verb verb) + 'commands)) + + ;; All the co-occupants of the room (not including ourself) + (define co-occupants + (remove + (lambda (x) (equal? x (actor-id player))) + (message-ref + (<-wait player player-loc 'get-occupants) + 'occupants))) + + ;; @@: There's a race condition here if someone leaves the room + ;; during this, heh... + ;; I'm not sure it can be solved, but "lag" on the race can be + ;; reduced maybe? + + ;; Get all the co-occupants' commands + (define co-occupant-commands + ;; TODO: Switch this to a fold. Ignore a result if it + ;; returns false for in the command response + (map + (lambda (co-occupant) + (let ((result (<-wait player co-occupant 'get-commands + #:verb verb))) + (list + (message-ref result 'commands) + (message-ref result 'goes-by) + co-occupant))) + co-occupants)) + + ;; Append our own command handlers + (define our-commands + (player-self-commands player)) + + ;; TODO: Append our inventory's relevant command handlers + + ;; Now return a big ol sorted list of ((actor-id . command)) + (append + (sort-commands-append-actor (pk 'room-commands room-commands) + player-loc '()) ; room doesn't go by anything + (sort-commands-multi-actors co-occupant-commands) + (sort-commands-append-actor our-commands + (actor-id player) '()))) ; nor does player + +(define (sort-commands-append-actor commands actor-id goes-by) + (sort-commands-multi-actors + (map (lambda (command) (list command goes-by actor-id)) commands))) + +(define (sort-commands-multi-actors actors-and-commands) + (sort + actors-and-commands + (lambda (x y) + (> (command-priority (car (pk 'x x))) + (command-priority (car (pk 'y y))))))) + + +(define (find-command-winner sorted-candidates line) + "Find a command winner from a sorted list of candidates" + ;; A cache of results from matchers we've already seen + ;; TODO: fill this in + (define matcher-cache '()) + (call/ec + (lambda (return) + (for-each + (match-lambda + ((command actor-goes-by actor-id) + (let* ((matcher (command-matcher command)) + (matched (matcher line))) + (if (and matched + ;; Great, it matched, but does it also pass + ;; should-handle? + (apply (command-should-handle command) + actor-goes-by + matched)) ; matched is kwargs if truthy + (return (list (command-action command) + (pk 'earlier-actor-id actor-id) matched)) + #f)))) + sorted-candidates) + #f)))