+ #:goes-by '("hard drive" "drive" "hard disk"))
+ ('computer-room:computer
+ <computer> 'computer-room
+ #:name "the computer"
+ #:desc '((p "It's a coat closet sized computer labeled \"PDP-11.5\". ")
+ (p "The computer is itself turned on, and it looks like it is "
+ "all set up for you to run a program on it."))
+ #:goes-by '("computer"))
+ ('computer-room:floor-panel
+ <floor-panel> 'computer-room
+ #:name "a floor panel"
+ #:desc (wrap-apply floor-panel-desc)
+ #:invisible? #t
+ #:goes-by '("floor panel" "panel"))))
+
+\f
+;;; * UNDERGROUND SECTION OF THE GAME! *
+
+\f
+;;; The lab
+
+(define underground-map-text
+ "\
+ _______ |
+ .-' @ '-. \\ ?????
+ .' '. .\\
+ | [8sync Hive] |======' '-_____
+ ', M ,'
+ '. @ .'
+ \\ @ /
+ '-__+__-'
+ '. @ .'
+ .--------------. \\ /
+ | [Guile Async | .-------+------.
+ | Museum] | | [Lab] #!#| .-------------.
+ | @| | MM | |[Federation |
+ | & ^ +##+@ || < +##| Station]|
+ | | | @ | | |
+ | & # | |*You-Are-Here*| '-------------'
+ | # ^ | #+-------+------'
+ '-------+------' # #
+ # # #
+ # # .-----------.
+ .-+----. # |# F |
+ |@?+%? +#### | ^ f## |
+ '------' | f f %|
+ |F [Mudsync |
+ | $ Swamp] |
+ '-----------'")
+
+(define 8sync-design-goals
+ '(ul (li (b "Actor based, shared nothing environment: ")
+ "Shared resources are hard to control and result in fighting
+deadlocks, etc. Escape the drudgery: only one actor controls a resource,
+and they only receive one message at a time (though they can \"juggle\"
+messages).")
+ (li (b "Live hackable: ")
+ "It's hard to plan out a concurrent system; the right structure
+is often found by evolving the system while it runs. Make it easy to
+build, shape, and change a running system, as well as observe and correct
+errors.")
+ (li (b "No callback hell: ")
+ "Just because you're calling out to some other asynchronous
+code doesn't mean you should need to chop up your program into a bunch of bits.
+Clever use of delimited continuations makes it easy.")))
+
+(define underground-lab
+ (lol
+ ('underground-lab
+ <room> #f
+ #:name "Underground laboratory"
+ #:desc '((p "This appears to be some sort of underground laboratory."
+ "There is a spiral staircase here leading upwards, where "
+ "it seems much brighter.")
+ (p "There are a number of doors leading in different directions:
+north, south, east, and west, as well as a revolving door to the southwest.
+It looks like it could be easy to get lost, but luckily there
+is a map detailing the layout of the underground structure."))
+ #:exits
+ (list (make <exit>
+ #:name "up"
+ #:to 'computer-room
+ #:traverse-check
+ (lambda (exit room whos-exiting)
+ (values #t "You climb the spiral staircase.")))
+ (make <exit>
+ #: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 <exit>
+ #:name "north"
+ #:to 'hive-entrance)
+ (make <exit>
+ #:name "east"
+ #:to 'federation-station)
+ (make <exit>
+ #: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!"))))
+ (make <exit>
+ #:name "southwest"
+ #:traverse-check
+ (lambda (exit room whos-exiting)
+ (values #f '("Hm, it's one of those revolving doors that only revolves in "
+ "one direction, and it isn't this one. You guess that while "
+ "this doesn't appear to be an entrance, it probably is an exit."))))))
+ ;; map
+ ('underground-lab:map
+ <readable> 'underground-lab
+ #:name "the underground map"
+ #:desc '("This appears to be a map of the surrounding area. "
+ "You could read it if you want to.")
+ #:read-text `(pre ,underground-map-text)
+ #:goes-by '("map" "underground map" "lab map"))
+
+ ('underground-lab:8sync-sign
+ <readable> 'underground-lab
+ #:name "a sign labeled \"8sync design goals\""
+ #: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))))
+
+\f
+;;; guile async museum
+
+(define async-museum
+ (list
+ (list
+ 'async-museum
+ <room> #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 <exit>
+ #:name "south"
+ #:to 'gift-shop)
+ (make <exit>
+ #: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
+ <chatty-npc> '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 <exhibit-name>"))
+ (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
+ <readable> '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
+ <readable-desc> '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
+ <readable-desc> '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
+ <readable-desc> '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
+ <readable-desc> '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
+ <readable-desc> '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
+ <room> #f
+ #:name "Museum Gift Shop"
+ #:desc '("There are all sorts of scrolls and knicknacks laying around here, "
+ "but they all seem glued in place and instead of a person manning the shop "
+ "there's merely a cardboard cutout of a person with a \"shopkeeper\" nametag. "
+ "You can pretty well bet that someone wanted to finish this room but ran out of "
+ "time.")
+ #:exits (list
+ (make <exit>
+ #:name "northeast"
+ #:to 'underground-lab
+ #:traverse-check
+ (lambda (exit room whos-exiting)
+ (values #t '("The revolving door spins as you walk through it. Whee!"))))
+ (make <exit>
+ #:name "north"
+ #:to 'async-museum)))))
+
+\f
+;;; 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
+ <room> #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 <exit>
+ #:name "south"
+ #:to 'underground-lab)
+ (make <exit>
+ #:name "north"
+ #:to 'hive-inside)))
+ ('hive-entrance:hive
+ <gameobj> '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
+ <chatty-npc> '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 <meta-message> (<readable>)
+ ((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)))))
+
+\f
+;;; Inside the Hive
+
+(define hive-inside
+ (lol
+ ('hive-inside
+ <room> #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 <exit>
+ #:name "south"
+ #:to 'hive-entrance)))
+ ;; hive actor
+ ;; TODO: Occasionally "fret" some noises, similar to the Clerk.
+ ('hive-inside:hive-actor
+ <chatty-npc> '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
+ <gameobj> '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
+ <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
+ <floor-panel> '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"))))