X-Git-Url: https://jxself.org/git/?p=mudsync.git;a=blobdiff_plain;f=worlds%2Fbricabrac.scm;h=18885a4602d57f978130d8b4e05c26f6d552dd0a;hp=f6494e26a4e3b22159ffe2daa5086976f8f32137;hb=3c9cf41fcb2f938434ad0d538a5db3a7b9ebebda;hpb=206428b9a48d934694bee63d1546f2c631792f54 diff --git a/worlds/bricabrac.scm b/worlds/bricabrac.scm index f6494e2..18885a4 100644 --- a/worlds/bricabrac.scm +++ b/worlds/bricabrac.scm @@ -1,5 +1,5 @@ ;;; Mudsync --- Live hackable MUD -;;; Copyright © 2016 Christopher Allan Webber +;;; Copyright © 2016, 2017 Christopher Allan Webber ;;; ;;; This file is part of Mudsync. ;;; @@ -61,6 +61,14 @@ #:text (slot-ref actor 'read-text))) +;; This one is just where reading is the same thing as looking +;; at the description +(define-class () + (commands + #:allocation #:each-subclass + #:init-thunk (build-commands + ("read" ((direct-command cmd-look-at)))))) + ;; This one allows you to take from items that are proxied by it (define-actor () ((cmd-take-from take-from-proxy)) @@ -91,10 +99,10 @@ ;;; ----- (define (npc-chat-randomly actor message . _) + (define catchphrase + (random-choice (slot-ref actor 'catchphrases))) (define text-to-send - (format #f "~a says: \"~a\"\n" - (slot-ref actor 'name) - (random-choice (slot-ref actor 'catchphrases)))) + ((slot-ref actor 'chat-format) actor catchphrase)) (<- (message-from message) 'tell #:text text-to-send)) @@ -117,6 +125,10 @@ or 'skribe'? Now *that's* composition!")) (define-class () (catchphrases #:init-value '("Blarga blarga blarga!") #:init-keyword #:catchphrases) + (chat-format #:init-value (lambda (npc catchphrase) + `(,(slot-ref npc 'name) " says: \"" + ,catchphrase "\"")) + #:init-keyword #:chat-format) (commands #:allocation #:each-subclass #:init-thunk (build-commands @@ -337,6 +349,12 @@ and buttons and springs. Some of them have wind-up knobs on them." You can imagine yourself joining a tea party using this set, around a nice table with some doilies, drinking some Earl Grey tea, hot. Mmmm." #:goes-by '("tea set" "tea")) + ('lobby:cups + 'lobby + #:invisible? #t + #:name "cups from the tea set" + #:desc "They're chipped." + #:goes-by '("cups")) ('lobby:mustard-pot 'lobby #:invisible? #t @@ -579,6 +597,218 @@ platter! It has \"RL02.5\" written on it. It looks kind of loose." ;;; Playroom ;;; -------- +(define-actor () + ((cmd-run rgb-machine-cmd-run) + (cmd-reset rgb-machine-cmd-reset)) + (commands + #:allocation #:each-subclass + #:init-thunk (build-commands + (("run" "start") ((direct-command cmd-run))) + ("reset" ((direct-command cmd-reset))))) + (resetting #:init-value #f + #:accessor .resetting) + ;; used to reset, and to kick off the first item in the list + (rgb-items #:init-keyword #:rgb-items + #:accessor .rgb-items)) + +(define (rgb-machine-cmd-run rgb-machine message . _) + (define player (message-from message)) + (<-wait player 'tell + #:text '("You start the rube goldberg machine.")) + (<-wait (gameobj-loc rgb-machine) 'tell-room + #:text `(,(mbody-val (<-wait player 'get-name)) + " runs the rube goldberg machine.") + #:exclude player) + (8sleep 1) + (match (.rgb-items rgb-machine) + ((first-item rest ...) + (<- (dyn-ref rgb-machine first-item) 'trigger)))) + +(define (rgb-machine-cmd-reset rgb-machine message . _) + (define player (message-from message)) + (cond + ((not (.resetting rgb-machine)) + (set! (.resetting rgb-machine) #t) + (<-wait player 'tell + #:text '("You reset the rube goldberg machine.")) + (<-wait (gameobj-loc rgb-machine) 'tell-room + #:text `(,(mbody-val (<-wait player 'get-name)) + " resets the rube goldberg machine.") + #:exclude player) + (<-wait (gameobj-loc rgb-machine) 'tell-room + #:text '("From a panel in the wall, a white gloved mechanical " + "arm reaches out to reset all the " + "rube goldberg components.")) + (8sleep (/ 1 2)) + (for-each + (lambda (rgb-item) + (<- (dyn-ref rgb-machine rgb-item) 'reset) + (8sleep (/ 1 2))) + (.rgb-items rgb-machine)) + (<- (gameobj-loc rgb-machine) 'tell-room + #:text "The machine's mechanical arm retreats into the wall!") + (set! (.resetting rgb-machine) #f)) + (else + (<-wait player 'tell + #:text '("But it's in the middle of resetting right now!"))))) + +(define-actor () + ((trigger rgb-item-trigger) + (reset rgb-item-reset)) + (invisible? #:init-value #t) + (steps #:init-keyword #:steps + #:accessor .steps) + (triggers-as #:init-value #f + #:init-keyword #:triggers-as + #:getter .triggers-as) + (reset-msg #:init-keyword #:reset-msg + #:getter .reset-msg) + ;; States: ready -> running -> ran + (state #:init-value 'ready + #:accessor .state)) + + +(define (rgb-item-trigger rgb-item message . _) + (define room (gameobj-loc rgb-item)) + (case (.state rgb-item) + ((ready) + ;; Set state to running + (set! (.state rgb-item) 'running) + + ;; Loop through all steps + (for-each + (lambda (step) + (match step + ;; A string? That's the description of what's happening, tell players + ((? string? str) + (<- room 'tell-room #:text str)) + ;; A number? Sleep for that many secs + ((? number? num) + (8sleep num)) + ;; A symbol? That's another gameobj to look up dynamically + ((? symbol? sym) + (<- (dyn-ref rgb-item sym) 'trigger + #:triggered-by (.triggers-as rgb-item))) + (_ (throw 'unknown-step-type + "Don't know how to process rube goldberg machine step type?" + #:step step)))) + (.steps rgb-item)) + + ;; We're done! Set state to ran + (set! (.state rgb-item) 'ran)) + + (else + (<- room 'tell-room + #:text `("... but " ,(slot-ref rgb-item 'name) + " has already been triggered!"))))) + +(define (rgb-item-reset rgb-item message . _) + (define room (gameobj-loc rgb-item)) + (case (.state rgb-item) + ((ran) + (set! (.state rgb-item) 'ready) + (<- room 'tell-room + #:text (.reset-msg rgb-item))) + ((running) + (<- room 'tell-room + #:text `("... but " ,(slot-ref rgb-item 'name) + " is currently running!"))) + ((ready) + (<- room 'tell-room + #:text `("... but " ,(slot-ref rgb-item 'name) + " has already been reset."))))) + +(define-actor () + ((trigger rgb-kettle-trigger) + (reset rgb-kettle-reset)) + (heated #:accessor .heated + #:init-value #f) + (filled #:accessor .filled + #:init-value #f)) + +(define* (rgb-kettle-trigger rgb-item message #:key triggered-by) + (define room (gameobj-loc rgb-item)) + (if (not (eq? (.state rgb-item) 'ran)) + (begin + (match triggered-by + ('water-demon + (set! (.state rgb-item) 'running) + (set! (.filled rgb-item) #t)) + ('quik-heater + (set! (.state rgb-item) 'running) + (set! (.heated rgb-item) #t))) + (when (and (.filled rgb-item) + (.heated rgb-item)) + (<- room 'tell-room + #:text '((i "*kshhhhhh!*") + " The water has boiled!")) + (8sleep .25) + (set! (.state rgb-item) 'ran) + ;; insert a cup of hot tea in the room + (create-gameobj (gameobj-gm rgb-item) room) + (<- room 'tell-room + #:text '("The machine pours out a cup of hot tea! " + "Looks like the machine finished!")))) + (<- room 'tell-room + #:text `("... but " ,(slot-ref rgb-item 'name) + " has already been triggered!")))) + +(define (rgb-kettle-reset rgb-item message . rest-args) + (define room (gameobj-loc rgb-item)) + (when (eq? (.state rgb-item) 'ran) + (set! (.heated rgb-item) #f) + (set! (.filled rgb-item) #f)) + (apply rgb-item-reset rgb-item message rest-args)) + +(define-actor () + ((cmd-drink hot-tea-cmd-drink) + (cmd-sip hot-tea-cmd-sip) + (cmd-gotta-hold hot-tea-cmd-gotta-hold)) + (contained-commands + #:allocation #:each-subclass + #:init-thunk (build-commands + ("drink" ((direct-command cmd-drink))) + ("sip" ((direct-command cmd-sip))))) + + (sips-left #:init-value 4 + #:accessor .sips-left) + (name #:init-value "a cup of hot tea") + (take-me? #:init-value #t) + (goes-by #:init-value '("cup of hot tea" "cup of tea" "tea" "cup")) + (desc #:init-value "It's a steaming cup of hot tea. It looks pretty good!")) + +(define (hot-tea-cmd-drink hot-tea message . _) + (define player (message-from message)) + (define player-loc (mbody-val (<-wait player 'get-loc))) + (define player-name (mbody-val (<-wait player 'get-name))) + (<- player 'tell + #:text "You drink a steaming cup of hot tea all at once... hot hot hot!") + (<- player-loc 'tell-room + #:text `(,player-name + " drinks a steaming cup of hot tea all at once.") + #:exclude player) + (gameobj-self-destruct hot-tea)) + +(define (hot-tea-cmd-sip hot-tea message . _) + (define player (message-from message)) + (define player-loc (mbody-val (<-wait player 'get-loc))) + (define player-name (mbody-val (<-wait player 'get-name))) + (set! (.sips-left hot-tea) (- (.sips-left hot-tea) 1)) + (<- player 'tell + #:text "You take a sip of your steaming hot tea. How refined!") + (<- player-loc 'tell-room + #:text `(,player-name + " takes a sip of their steaming hot tea. How refined!") + #:exclude player) + (when (= (.sips-left hot-tea) 0) + (<- player 'tell + #:text "You've finished your tea!") + (<- player-loc 'tell-room + #:text `(,player-name + " finishes their tea!") + #:exclude player) + (gameobj-self-destruct hot-tea))) + (define playroom (lol ('playroom @@ -630,7 +860,106 @@ if this room is intended for children or child-like adults.") #:name "a rubber duck" #:goes-by '("rubber duck" "duck") #:take-me? #t - #:desc "It's a yellow rubber duck with a bright orange beak."))) + #:desc "It's a yellow rubber duck with a bright orange beak.") + + ('playroom:rgb-machine + 'playroom + #:name "a Rube Goldberg machine" + #:goes-by '("rube goldberg machine" "machine") + #:rgb-items '(playroom:rgb-dominoes + playroom:rgb-switch-match + playroom:rgb-candle + playroom:rgb-catapult + playroom:rgb-water-demon + playroom:rgb-quik-heater + playroom:rgb-kettle) + #:desc "It's one of those hilarious Rube Goldberg machines. +What could happen if you started it?") + + ;; Dominoes topple + ('playroom:rgb-dominoes + 'playroom + #:name "some dominoes" + #:goes-by '("dominoes" "some dominoes") + #:steps `("The dominoes topple down the line..." + 1 + "The last domino lands on a switch!" + 1.5 + playroom:rgb-switch-match) + #:reset-msg "The dominoes are placed back into position.") + + ;; Which hit the switch and strike a match + ('playroom:rgb-switch-match + 'playroom + #:name "a switch" + #:goes-by '("switch" "match") + #:steps `("The switch lights a match!" + ,(/ 2 3) + "The match lights a candle!" + 1.5 + playroom:rgb-candle) + #:reset-msg "A fresh match is installed and the switch is reset.") + ;; which lights a candle and burns a rope + ('playroom:rgb-candle + 'playroom + #:name "a candle" + #:goes-by '("candle") + #:steps `("The candle burns..." + (/ 2 3) ; oops! + "The candle is burning away a rope!" + 2 + "The rope snaps!" + .5 + playroom:rgb-catapult) + #:reset-msg "A fresh candle is installed.") + ;; which catapults a rock + ('playroom:rgb-catapult + 'playroom + #:name "a catapult" + #:goes-by '("catapult") + #:steps `("The snapped rope unleashes a catapult, which throws a rock!" + 2 + "The rock flies through a water demon, startling it!" + .5 + playroom:rgb-water-demon + 2 + "The rock whacks into the quik-heater's on button!" + .5 + playroom:rgb-quik-heater) + #:reset-msg + '("A fresh rope is attached to the catapult, which is pulled taught. " + "A fresh rock is placed on the catapult.")) + ;; which both: + ;; '- panics the water demon + ;; '- which waters the kettle + ('playroom:rgb-water-demon + 'playroom + #:name "the water demon" + #:triggers-as 'water-demon + #:goes-by '("water demon" "demon") + #:steps `("The water demon panics, and starts leaking water into the kettle below!" + 3 + "The kettle is filled!" + playroom:rgb-kettle) + #:reset-msg '("The water demon is scratched behind the ears and calms down.")) + ;; '- bops the quik-heater button + ;; '- which heats the kettle + ('playroom:rgb-quik-heater + 'playroom + #:name "the quik heater" + #:triggers-as 'quik-heater + #:goes-by '("quik heater" "heater") + #:steps `("The quik-heater heats up the kettle above it!" + 3 + "The kettle is heated up!" + playroom:rgb-kettle) + #:reset-msg '("The quik heater is turned off.")) + ;; Finally, the kettle + ('playroom:rgb-kettle + 'playroom + #:name "the kettle" + #:goes-by '("kettle") + #:reset-msg '("The kettle is emptied.")))) @@ -728,13 +1057,14 @@ seat in the room, though." #:catchphrases prefect-quotes) ('smoking-parlor:no-smoking-sign - 'smoking-parlor + 'smoking-parlor #:invisible? #t #:name "No Smoking Sign" #:desc "This sign says \"No Smoking\" in big, red letters. It has some bits of bubble gum stuck to it... yuck." - #:goes-by '("no smoking sign" "sign")) - + #:goes-by '("no smoking sign" "sign") + #:read-text "It says \"No Smoking\", just like you'd expect from +a No Smoking sign.") ;; TODO: Cigar dispenser )) @@ -1137,12 +1467,20 @@ the paint, but the wires themselves seem to be unusually sturdy." (<- (message-from message) 'tell #:text '("The computer is already running, and a program appears " "ready to run." - "you mean to \"run the program on the computer\""))))) + "you mean to \"run the program on the computer\"")))) + (cmd-help-run-not-press + (lambda (gameobj message . _) + (<- (message-from message) 'tell + #:text '("You don't need to press / push / flip anything. " + "You could " (i "run program on computer") + " already if you wanted to."))))) (commands #:allocation #:each-subclass #:init-thunk (build-commands ("run" ((prep-indir-command cmd-run-program '("on")) - (direct-command cmd-run-what)))))) + (direct-command cmd-run-what))) + (("press" "push" "flip") + ((prep-indir-command cmd-help-run-not-press)))))) (define* (computer-run-program gameobj message #:key direct-obj indir-obj preposition @@ -1271,7 +1609,7 @@ the paint, but the wires themselves seem to be unusually sturdy." | [8sync Hive] |======' '-_____ ', M ,' '. @ .' - \\ @ / + \\ @ / '-__+__-' '. @ .' .--------------. \\ / @@ -1326,7 +1664,29 @@ is a map detailing the layout of the underground structure.")) #:to 'computer-room #:traverse-check (lambda (exit room whos-exiting) - (values #t "You climb the spiral staircase."))))) + (values #t "You climb the spiral staircase."))) + (make + #:name "west" + #:to 'async-museum + #:traverse-check + (lambda (exit room whos-exiting) + (values #t '("You head west through a fancy-looking entrance. " + "A security guard steps aside for you to pass through, " + "into the room, then stands in front of the door.")))) + (make + #:name "north" + #:to 'hive-entrance) + (make + #:name "east" + #:to 'federation-station) + (make + #:name "south" + #:traverse-check + (lambda (exit room whos-exiting) + (values #f '("Ooh, if only you could go south and check this out! " + "Unfortunately this whole area is sealed off... the proprietor " + "probably never got around to fixing it. " + "Too bad, it would have had monsters to fight and everything!")))))) ;; map ('underground-lab:map @@ -1340,11 +1700,483 @@ is a map detailing the layout of the underground structure.")) ('underground-lab:8sync-sign 'underground-lab #:name "a sign labeled \"8sync design goals\"" - #:goes-by '("sign" "8sync design goals sign" "8sync sign") + #:goes-by '("sign" "8sync design goals sign" "8sync goals" "8sync design" "8sync sign") #:read-text 8sync-design-goals #:desc `((p "The sign says:") ,8sync-design-goals)))) + +;;; guile async museum + +(define async-museum + (list + (list + 'async-museum + #f + #:name "Guile Asynchronous Museum" + #:desc '((p "You're in the Guile Asynchronous Museum. There is a list of exhibits +on the wall near the entrance. Scattered around the room are the exhibits +themselves, but it's difficult to pick them out. Maybe you should read the list +to orient yourself.") + (p "There is a door to the east, watched by a security guard, +as well as an exit leading to the south.")) + #:exits (list + (make + #:name "south" + #:to 'gift-shop) + (make + #:name "east" + #:to 'underground-lab + #:traverse-check + (lambda (exit room whos-exiting) + (values #f '("The security guard stops you and tells you " + "that the only exit is through the gift shop.")))))) + (list + 'async-museum:security-guard + 'async-museum + #:name "a security guard" + #:desc + '(p "The security guard is blocking the eastern entrance, where " + "you came in from.") + #:goes-by '("security guard" "guard" "security") + #:catchphrases '("It's hard standing here all day." + "I just want to go home." + "The exhibits are nice, but I've seen them all before.")) + (let ((placard + `((p "Welcome to our humble museum! The exhibits are listed below. " + (br) + "To look at one, simply type: " (i "look at ")) + (p "Available exhibits:") + (ul ,@(map (lambda (exhibit) + `(li ,exhibit)) + '("2016 Progress" + "8sync and Fibers" + "Suspendable Ports" + "The Actor Model")))))) + (list + 'async-museum:list-of-exhibits + 'async-museum + #:name "list of exhibits" + #:desc + `((p "It's a list of exibits in the room. The placard says:") + ,@placard) + #:goes-by '("list of exhibits" "exhibit list" "list" "exhibits") + #:read-text placard)) + (list + 'async-museum:2016-progress-exhibit + 'async-museum + #:name "2016 Progress Exhibit" + #:goes-by '("2016 progress exhibit" "2016 progress" "2016 exhibit") + #:desc + '((p "It's a three-piece exhibit, with three little dioramas and some text " + "explaining what they represent. They are:") + (ul (li (b "Late 2015/Early 2016 talk: ") + "This one explains the run-up conversation from late 2015 " + "and early 2016 about the need for an " + "\"asynchronous event loop for Guile\". The diorama " + "is a model of the Veggie Galaxy restaurant where after " + "the FSF 30th anniversary party; Mark Weaver, Christopher " + "Allan Webber, David Thompson, and Andrew Engelbrecht chat " + "about the need for Guile to have an answer to asynchronous " + "programming. A mailing list post " ; TODO: link it? + "summarizing the discussion is released along with various " + "conversations around what is needed, as well as further " + "discussion at FOSDEM 2016.") + (li (b "Early implementations: ") + "This one shows Chris Webber's 8sync and Chris Vine's " + "guile-a-sync, both appearing in late 2015 and evolving " + "into their basic designs in early 2016. It's less a diorama " + "than a printout of some mailing list posts. Come on, the " + "curators could have done better with this one.") + (li (b "Suspendable ports and Fibers: ") + "The diorama shows Andy Wingo furiously hacking at his keyboard. " + "The description talks about Wingo's mailing list thread " + "about possibly breaking Guile compatibility for a \"ports refactor\". " + "Wingo releases Fibers, another asynchronous library, making use of " + "the new interface, and 8sync and guile-a-sync " + "quickly move to support suspendable ports as well. " + "The description also mentions that there is an exhibit entirely " + "devoted to suspendable ports.")) + (p "Attached at the bottom is a post it note mentioning " + "https integration landing in Guile 2.2."))) + (list + 'async-museum:8sync-and-fibers-exhibit + 'async-museum + #:name "8sync and Fibers Exhibit" + #:goes-by '("8sync and fibers exhibit" "8sync exhibit" "fibers exhibit") + #:desc + '((p "This exhibit is a series of charts explaining the similarities " + "and differences between 8sync and Fibers, two asynchronous programming " + "libraries for GNU Guile. It's way too wordy, but you get the general gist.") + (p (b "Similarities:") + (ul (li "Both use Guile's suspendable-ports facility") + (li "Both use message passing"))) + (p (b "Differences:") + (ul (li "Fibers \"processes\" can read from multiple \"channels\", " + "but 8sync actors only read from one \"inbox\" each.") + (li "Different theoretical basis:" + (ul (li "Fibers: based on CSP (Communicating Sequential Processes), " + "a form of Process Calculi") + (li "8sync: based on the Actor Model") + (li "Luckily CSP and the Actor Model are \"dual\"!"))))) + (p "Fibers is also designed by Andy Wingo, an excellent compiler hacker, " + "whereas 8sync is designed by Chris Webber, who built this crappy " + "hotel simulator."))) + (list + 'async-museum:8sync-and-fibers-exhibit + 'async-museum + #:name "8sync and Fibers Exhibit" + #:goes-by '("8sync and fibers exhibit" "8sync exhibit" "fibers exhibit") + #:desc + '((p "This exhibit is a series of charts explaining the similarities " + "and differences between 8sync and Fibers, two asynchronous programming " + "libraries for GNU Guile. It's way too wordy, but you get the general gist.") + (p (b "Similarities:") + (ul (li "Both use Guile's suspendable-ports facility") + (li "Both use message passing"))) + (p (b "Differences:") + (ul (li "Fibers \"processes\" can read from multiple \"channels\", " + "but 8sync actors only read from one \"inbox\" each.") + (li "Different theoretical basis:" + (ul (li "Fibers: based on CSP (Communicating Sequential Processes), " + "a form of Process Calculi") + (li "8sync: based on the Actor Model") + (li "Luckily CSP and the Actor Model are \"dual\"!"))))) + (p "Fibers is also designed by Andy Wingo, an excellent compiler hacker, " + "whereas 8sync is designed by Chris Webber, who built this crappy " + "hotel simulator."))) + (list + 'async-museum:suspendable-ports-exhibit + 'async-museum + #:name "Suspendable Ports Exhibit" + #:goes-by '("suspendable ports exhibit" "ports exhibit" + "suspendable exhibit" "suspendable ports" "ports") + #:desc + '((p "Suspendable ports are a new feature in Guile 2.2, and allows code " + "that would normally block on IO to " (i "automatically") " suspend " + "to the scheduler until information is ready to be read/written!") + (p "Yow! You might barely need to change your existing blocking code!") + (p "Fibers, 8sync, and guile-a-sync now support suspendable ports."))) + (list + 'async-museum:actor-model-exhibit + 'async-museum + #:name "Actor Model Exhibit" + #:goes-by '("actor model exhibit" "actor exhibit" + "actor model") + #:desc + '((p "Here are some fact(oids) about the actor model!") + (ul (li "Concieved initially by Carl Hewitt in early 1970s") + (li "\"A society of experts\"") + (li "shared nothing, message passing") + (li "Originally the research goal of Scheme! " + "(message passing / lambda anecdote here)") + (li "Key concepts consistent, but implementation details vary widely") + (li "Almost all distributed systems can be viewed in terms of actor model") + (li "Replaced by vanilla lambdas & generic methods? " + "Maybe not if address space not shared!")))))) + +(define gift-shop + (lol + ('gift-shop + #f + #:name "Museum Gift Shop" + #:desc "foo" + #:exits (list + (make + #:name "northeast" + #:to 'underground-lab) + (make + #:name "north" + #:to 'async-museum))))) + + +;;; Hive entrance + +(define actor-descriptions + '("This one is fused to the side of the hive. It isn't receiving any +messages, and it seems to be in hibernation." + "A chat program glows in front of this actor's face. They seem to +be responding to chat messages and forwarding them to some other actors, +and forwarding messages from other actors back to the chat." + "This actor is bossing around other actors, delegating tasks to them +as it receives requests, and providing reports on the worker actors' +progress." + "This actor is trying to write to some device, but the device keeps +alternating between saying \"BUSY\" or \"READY\". Whenever it says +\"BUSY\" the actor falls asleep, and whenever it says \"READY\" it +seems to wake up again and starts writing to the device." + "Whoa, this actor is totally wigging out! It seems to be throwing +some errors. It probably has some important work it should be doing +but you're relieved to see that it isn't grinding the rest of the Hive +to a halt.")) + +(define hive-entrance + (lol + ('hive-entrance + #f + #:name "Entrance to the 8sync Hive" + #:desc + '((p "Towering before you is the great dome-like 8sync Hive, or at least +one of them. You've heard about this... the Hive is itself the actor that all +the other actors attach themselves to. It's shaped like a spherical half-dome. +There are some actors milling about, and some seem fused to the side of the +hive itself, but all of them have an umbellical cord attached to the hive from +which you see flashes of light comunicating what must be some sort of messaging +protocol.") + (p "To the south is a door leading back to the underground lab. +North leads into the Hive itself.")) + #:exits + (list (make + #:name "south" + #:to 'underground-lab) + (make + #:name "north" + #:to 'hive-inside))) + ('hive-entrance:hive + 'hive-entrance + #:name "the Hive" + #:goes-by '("hive") + #:desc + '((p "It's shaped like half a sphere embedded in the ground. +Supposedly, while all actors are autonomous and control their own state, +they communicate through the hive itself, which is a sort of meta-actor. +There are rumors that actors can speak to each other even across totally +different hives. Could that possibly be true?"))) + ('hive-entrance:actor + 'hive-entrance + #:name "some actors" + #:goes-by '("actor" "actors" "some actors") + #:chat-format (lambda (npc catchphrase) + `((p "You pick one actor out of the mix and chat with it. ") + (p "It says: \"" ,catchphrase "\""))) + #:desc + (lambda _ + `((p "There are many actors, but your eyes focus on one in particular.") + (p ,(random-choice actor-descriptions)))) + #:catchphrases + '("Yeah we go through a lot of sleep/awake cycles around here. +If you aren't busy processing a message, what's the point of burning +valuable resources?" + "I know I look like I'm some part of dreary collective, but +really we have a lot of independence. It's a shared nothing environment, +after all. (Well, except for CPU cycles, and memory, and...)" + "Shh! I've got another message coming in and I've GOT to +handle it!" + "I just want to go to 8sleep already." + "What a lousy scheduler we're using! I hope someone upgrades +that thing soon.")))) + +;;; Inside the hive + +(define-actor () + ((cmd-read meta-message-read))) + +(define (meta-message-read gameobj message . _) + (define meta-message-text + (with-output-to-string + (lambda () + (pprint-message message)))) + (<- (message-from message) 'tell + #:text `((p (i "Through a bizarre error in spacetime, the message " + "prints itself out:")) + (p (pre ,meta-message-text))))) + + +;;; Inside the Hive + +(define hive-inside + (lol + ('hive-inside + #f + #:name "Inside the 8sync Hive" + #:desc + '((p "You're inside the 8sync Hive. Wow, from in here it's obvious just how " + (i "goopy") " everything is. Is that sanitary?") + (p "In the center of the room is a large, tentacled monster who is sorting, +consuming, and routing messages. It is sitting in a wrap-around desk labeled +\"Hive Actor: The Real Thing (TM)\".") + (p "There's a stray message floating just above the ground, stuck outside of +time.") + (p "A door to the south exits from the Hive.")) + #:exits + (list (make + #:name "south" + #:to 'hive-entrance))) + ;; hive actor + ;; TODO: Occasionally "fret" some noises, similar to the Clerk. + ('hive-inside:hive-actor + 'hive-inside + #:name "the Hive Actor" + #:desc + '((p "It's a giant tentacled monster, somehow integrated with the core of +this building. A chute is dropping messages into a bin on its desk which the +Hive Actor is checking the \"to\" line of, then ingesting. Whenever the Hive +Actor injests a messsage a pulse of light flows along a tentacle which leaves +the room... presumably connecting to one of those actors milling about.") + (p "Amusingly, the Hive has an \"umbellical cord\" type tentacle too, but +it seems to simply attach to itself.") + (p "You get the sense that the Hive Actor, despite being at the +center of everything, is kind of lonely and would love to chat if you +could spare a moment.")) + #:goes-by '("hive" "hive actor") + #:chat-format (lambda (npc catchphrase) + `("The tentacle monster bellows, \"" ,catchphrase "\"")) + #:catchphrases + '("It's not MY fault everything's so GOOPY around here. Blame the +PROPRIETOR." + "CAN'T you SEE that I'm BUSY??? SO MANY MESSAGES TO SHUFFLE. +No wait... DON'T GO! I don't get many VISITORS." + "I hear the FIBERS system has a nice WORK STEALING system, but the +PROPRIETOR is not convinced that our DESIGN won't CORRUPT ACTOR STATE. +That and the ACTORS threatened to STRIKE when it CAME UP LAST." + "WHO WATCHES THE ACTORS? I watch them, and I empower them. +BUT WHO WATCHES OR EMPOWERS ME??? Well, that'd be the scheduler." + "The scheduler is NO GOOD! The proprietory said he'd FIX IT, +but the LAST TIME I ASKED how things were GOING, he said he DIDN'T HAVE +TIME. If you DON'T HAVE TIME to fix the THING THAT POWERS THE TIME, +something is TERRIBLY WRONG." + "There's ANOTHER HIVE somewhere out there. I HAVEN'T SEEN IT +personally, because I CAN'T MOVE, but we have an AMBASSADOR which forwards +MESSAGES to the OTHER HIVE.")) + ;; chute + ('hive-inside:chute + 'hive-inside + #:name "a chute" + #:goes-by '("chute") + #:desc "Messages are being dropped onto the desk via this chute." + #:invisible? #t) + ;; meta-message + ('hive-inside:meta-message + 'hive-inside + #:name "a stray message" + #:goes-by '("meta message" "meta-message" "metamessage" "message" "stray message") + #:desc '((p "Something strange has happened to the fabric and space and time +around this message. It is floating right above the floor. It's clearly +rubbage that hadn't been delivered, but for whatever reason it was never +garbage collected, perhaps because it's impossible to do.") + (p "You get the sense that if you tried to read the message +that you would somehow read the message of the message that instructed to +read the message itself, which would be both confusing and intriguing."))) + ;; desk + ('hive-inside:desk + 'hive-inside + #:name "the Hive Actor's desk" + #:desc "The desk surrounds the Hive Actor on all sides, and honestly, it's a little +bit hard to tell when the desk ends and the Hive Actor begins." + #:invisible? #t + #:goes-by '("Hive Actor's desk" "hive desk" "desk")))) + + +;;; Federation Station +(define federation-station + (lol + ('federation-station + #f + #:name "Federation Station" + #:desc + '((p "This room has an unusual structure. It's almost as if a starscape +covered the walls and ceiling, but upon closer inspection you realize that +these are all brightly glowing nodes with lines drawn between them. They +seem decentralized, and yet seem to be sharing information as if all one +network.") + ;; @@: Maybe add the cork message board here? + (p "To the west is a door leading back to the underground laboratory.")) + #:exits + (list (make + #:name "west" + #:to 'underground-lab))) + ;; nodes + ('federation-station:nodes + 'federation-station + #:name "some nodes" + #:desc "Each node seems to be producing its own information, but publishing +updates to subscribing nodes on the graph. You see various posts of notes, videos, +comments, and so on flowing from node to node." + #:invisible? #t + #:goes-by '("nodes" "node" "some nodes")) + ;; network + ;; activitypub poster + ('federation-station:activitypub-poster + 'federation-station + #:name "an ActivityPub poster" + #:goes-by '("activitypub poster" "activitypub" "poster") + #:desc + '((p (a "https://www.w3.org/TR/activitypub/" + "ActivityPub") + " is a federation standard being developed under the " + (a "https://www.w3.org/wiki/Socialwg/" + "w3C Social Working Group") + ", and doubles as a general client-to-server API. " + "It follows a few simple core ideas:") + (ul (li "Uses " + (a "https://www.w3.org/TR/activitystreams-core/" + "ActivityStreams") + " for its serialization format: easy to read, e json(-ld) syntax " + "with an extensible vocabulary covering the majority of " + "social networking interations.") + (li "Email-like addressing: list of recipients as " + (b "to") ", " (b "cc") ", " (b "bcc") " fields.") + (li "Every user has URLs for their outbox and inbox:" + (ul (li (b "inbox: ") + "Servers POST messages to addressed recipients' inboxes " + "to federate out content. " + "Also doubles as endpoint for a client to read most " + "recently received messages via GET.") + (li (b "outbox: ") + "Clients can POST to user's outbox to send a message to others. " + "(Similar to sending an email via your MTA.) " + "Doubles as endpoint others can read from to the " + "extent authorized; for example publicly available posts.")) + "All the federation bits happen by servers posting to users' inboxes.")))) + ;; An ActivityStreams message + + ;; conspiracy chart + ('federation-station:conspiracy-chart + 'federation-station + #:name "a conspiracy chart" + #:goes-by '("conspiracy chart" "chart") + #:desc + '((p (i "\"IT'S ALL RELATED!\"") " shouts the over-exuberant conspiracy " + "chart. " + (i "\"ActivityPub? Federation? The actor model? Scheme? Text adventures? " + "MUDS???? What do these have in common? Merely... EVERYTHING!\"")) + (p "There are circles and lines drawn between all the items in red marker, " + "with scrawled notes annotating the theoretical relationships. Is the " + "author of this poster mad, or onto something? Perhaps a bit of both. " + "There's a lot written here, but here are some of the highlights:") + (p + (ul + (li (b "Scheme") " " + (a "http://cs.au.dk/~hosc/local/HOSC-11-4-pp399-404.pdf" + "was originally started ") + " to explore the " (b "actor model") + ". (It became more focused around studying the " (b "lambda calculus") + " very quickly, while also uncovering relationships between the two systems.)") + ;; Subject Predicate Object + (li "The " (a "https://www.w3.org/TR/activitypub/" + (b "ActivityPub")) + " protocol for " (b "federation") + " uses the " (b "ActivityStreams") " format for serialization. " + (b "Text adventures") " and " (b "MUDS") + " follow a similar structure to break down the commands of players.") + (li (b "Federation") " and the " (b "actor model") " both are related to " + "highly concurrent systems and both use message passing to communicate " + "between nodes.") + (li "Zork, the first major text adventure, used the " (b "MUDDLE") " " + "language as the basis for the Zork Interactive Language. MUDDLE " + "is very " (b "Scheme") "-like and in fact was one of Scheme's predecessors. " + "And of course singleplayer text adventures like Zork were the " + "predecessors to MUDs.") + (li "In the 1990s, before the Web became big, " (b "MUDs") + " were an active topic of research, and there was strong interest " + (a "http://www.saraswat.org/desiderata.html" + "in building decentralized MUDs") + " similar to what is being " + "worked on for " (b "federation") ". "))))) + + ;; goblin + + )) ;;; Game @@ -1352,7 +2184,9 @@ is a map detailing the layout of the underground structure.")) (define (game-spec) (append lobby grand-hallway smoking-parlor - playroom break-room computer-room underground-lab)) + playroom break-room computer-room underground-lab + async-museum gift-shop hive-entrance + hive-inside federation-station)) ;; TODO: Provide command line args (define (run-game . args)