1
0
Fork 0
mirror of https://gitlab.com/Oreolek/salet.git synced 2024-06-01 07:48:20 +03:00

Cycling rewrite, Raconteur's purge

- Rewrote cycling shortcuts into the library. It's more object-oriented
  now (and slightly less obvious, but we can get around that).
- Removed Raconteur situations entirely. Their functionality is 100%
  integrated now.
This commit is contained in:
Alexander Yakovlev 2016-01-19 10:03:01 +07:00
parent 407305a54c
commit 0ed470dae6
5 changed files with 85 additions and 127 deletions

View file

@ -22,21 +22,11 @@ actlink = (content, ref) ->
return "<a href='./#{ref}' class='once'>#{content}</a>"
textcycle = (content, ref) ->
return "<a href='./_replacer_#{ref}' class='cycle' id='#{ref}'>#{content}</a>"
# TODO: hide this somewhere in exports or autoreplacer shortcuts
cyclelink = (content) ->
return "<a href='./_replacer_cyclewriter' class='cycle' id='cyclewriter'>#{content}</a>"
# Cycling link. It's implied there can be only one per situation.
# You are welcome to improve this code.
cycle = (obj, character) ->
responses = obj.cycle_gallery()
character.sandbox.cycle_index ?= [] # initialize with empty array
character.sandbox.cycle_index[obj.name] ?= 0 # initialize with 0
response = responses[character.sandbox.cycle_index[obj.name]]
character.sandbox.cycle_index[obj.name]++
if character.sandbox.cycle_index[obj.name] == responses.length
character.sandbox.cycle_index[obj.name] = 0
return textcycle(response, 'cyclewriter')
# usage: writemd( system, "Text to write")
writemd = (system, text) ->
text = markdown(text)

View file

@ -19,10 +19,7 @@ room "plaza",
return "Upwards"
else
return "Town plaza"
cycle_gallery: () -> # it needs to be a function if you want localization
return [
"quirky", "distinct", "kooky", "crazy", "quaint"
]
cycle: ["quirky", "distinct", "kooky", "crazy", "quaint"]
ways: ["shop"]
before: (character, system, from) ->
if from == 'world'
@ -32,8 +29,6 @@ room "plaza",
"""
else
"You quickly find the central plaza."
writers:
cyclewriter: (character) -> cycle(this, character)
objects:
policeman: obj "policeman",
dsc: "There is a policeman nearby. You could ask him {{for directions.}}"
@ -65,14 +60,13 @@ room "lair",
dsc: """
The Lair of Yog-Sothoth is a very *n'gai* cave, full of *buggs-shoggogs* and *n'ghaa ng'aa*.
"""
objects: {
objects:
bugg: obj "bugg",
dsc: "You see a particularly beautiful slimy {{bugg.}}"
takeable: false
act: () =>
here().drop(@name)
return "You eat the bugg mass. Delicious and raw. Perhaps it's a good lair to live in."
}
dialogue "Yes", "merchant", "merchant", """
Yes.
@ -86,14 +80,13 @@ room "shop-inside",
dsc: """
The insides are painted pastel white, honouring The Great Milk Spill of 1985.
"""
objects: {
objects:
merchant: obj "merchant",
dsc: "A {{merchant}} eyes you warily."
takeable: false
act: (character, system) =>
undum.processClick("merchdialogue")
return ""
}
###
I want to be able to do this but I can't because I'm lost in all the `this` and @objects and `new`.

19
lib/cycle.coffee Normal file
View file

@ -0,0 +1,19 @@
# Cycling interface.
# Rooms: cycle through this.cycle_gallery
# Objects: cycle through this.cycle_gallery
cyclelink = (content) ->
return "<a href='./_replacer_cyclewriter' class='cycle' id='cyclewriter'>#{content}</a>"
cycle = (responses, name, character) ->
if typeof responses == "function"
responses = responses()
character.sandbox.cycle_index ?= [] # initialize with empty array
character.sandbox.cycle_index[name] ?= 0 # initialize with 0
response = responses[character.sandbox.cycle_index[name]]
character.sandbox.cycle_index[name]++
if character.sandbox.cycle_index[name] == responses.length
character.sandbox.cycle_index[name] = 0
return cyclelink(response)
module.exports = cycle

View file

@ -1,9 +1,9 @@
# I confess that this world model heavily borrows from INSTEAD engine. - A.Y.
undum = require('./undum.js')
RaconteurSituation = require('./situation.coffee')
obj = require('./obj.coffee')
markdown = require('./markdown.coffee')
cycle = require('./cycle.coffee')
way_to = (content, ref) ->
return "<a href='#{ref}' class='way' id='waylink-#{ref}'>#{content}</a>"
@ -60,12 +60,13 @@ update_ways = (ways, name) ->
for node in min_key
addClass(document.getElementById("waylink-#{node}"), "destination")
class SaletRoom extends RaconteurSituation
class SaletRoom extends undum.Situation
constructor: (spec) ->
RaconteurSituation.call(this, spec)
undum.Situation.call(this, spec)
for index, value of spec
this[index] = value
return this
visited: 0
title: "Room"
objects: {}
extendSection: false
@ -143,7 +144,7 @@ class SaletRoom extends RaconteurSituation
An internal function to get the room's description and the descriptions of
every object in this room.
###
look: (character, system, f) ->
look: (character, system, f) =>
update_ways(@ways, @name)
retval = ""
@ -173,24 +174,55 @@ class SaletRoom extends RaconteurSituation
You could interpret this as an EXAMINE verb or USE one, it's your call.
###
act: (character, system, action) =>
if (link = action.match(/^_act_(.+)$/)) #object action
if (link = action.match(/^_(act|cycle)_(.+)$/)) #object action
for name, thing of @objects
if name == link[1]
# If it's takeable, the player can take this object.
# If not, we check the "act" function.
if thing.takeable
character.sandbox.inventory.push thing
@drop name
cls(system)
@entering.fcall(this, character, system, @name)
return print(thing.take.fcall(thing, character, system))
if thing.act
return print(thing.act.fcall(thing, character, system))
if name == link[2]
if link[1] == "act"
# If it's takeable, the player can take this object.
# If not, we check the "act" function.
if thing.takeable
character.sandbox.inventory.push thing
@drop name
cls(system)
@entering.fcall(this, character, system, @name)
return print(thing.take.fcall(thing, character, system))
if thing.act
return print(thing.act.fcall(thing, character, system))
elseif link[1] == "cycle"
# TODO object cyclewriter
# the loop is done but no return came - match not found
console.error("Could not find #{link[1]} in current room.")
# default Raconteur action
return RaconteurSituation.prototype.act.call(this, character, system, action)
# we're done with objects, now check the regular actions
actionClass = action.match(/^_(\w+)_(.+)$/)
that = this
responses = {
writer: (ref) ->
content = that.writers[ref].fcall(that, character, system, action)
output = markdown(content)
system.writeInto(output, '#current-situation')
replacer: (ref) ->
content = that.writers[ref].fcall(that, character, system, action)
output = "<span>"+content+"</span>" # <p> tags are usually bad for replacers
system.replaceWith(output, '#'+ref)
inserter: (ref) ->
content = that.writers[ref].fcall(that, character, system, action)
output = markdown(content)
system.writeInto(output, '#'+ref)
}
if (actionClass)
# Matched a special action class
[responder, ref] = [actionClass[1], actionClass[2]]
if(!@writers.hasOwnProperty(actionClass[2]))
throw new Error("Tried to call undefined writer: #{action}");
responses[responder](ref);
else if (@actions.hasOwnProperty(action))
@actions[action].call(this, character, system, action);
else
throw new Error("Tried to call undefined action: #{action}");
# Marks every room in the game with distance to this room
destination: () =>
@ -205,6 +237,17 @@ class SaletRoom extends RaconteurSituation
node.distance = current_room.distance + 1
candidates.push(node)
register: () =>
if not @name?
console.error("Situation has no name")
return this
undum.game.situations[@name] = this
return this
writers:
cyclewriter: (character) ->
cycle(this.cycle, this.name, character)
room = (name, spec) ->
spec ?= {}
spec.name = name

View file

@ -1,87 +0,0 @@
###
This file is built on top of Raconteur.
Raconteur is copyright (c) 2015 Bruno Dias
This file is copyright (c) 2016 Alexander Yakovlev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
###
undum = require('./undum.js')
markdown = require('./markdown.coffee')
###
The prototype RaconteurSituation is the basic spec for situations
created with Raconteur. It should be able to handle any use case for Undum.
This prototype is fairly complex; see the API documentation.
###
RaconteurSituation = (spec) ->
if RaconteurSituation.arguments.length == 0
return
undum.Situation.call(this, spec)
for key, value of spec
this[key] ?= value
@visited = 0
return this
RaconteurSituation.inherits(undum.Situation)
###
Situation.prototype.act() is called by Undum whenever an action link
(Ie, a link that doesn't point at another situation or an external URL) is
clicked.
Raconteur's version of act() is set up to implement commonly used
functionality: "writer" links, "replacer" links, "inserter" links, and
generic "action" links that call functions which access the underlying
Undum API.
###
RaconteurSituation.prototype.act = (character, system, action) ->
actionClass = action.match(/^_(\w+)_(.+)$/)
that = this
responses = {
writer: (ref) ->
content = that.writers[ref].fcall(that, character, system, action)
output = markdown(content)
system.writeInto(output, '#current-situation')
replacer: (ref) ->
content = that.writers[ref].fcall(that, character, system, action)
output = "<span>"+content+"</span>" # <p> tags are usually bad for replacers
system.replaceWith(output, '#'+ref)
inserter: (ref) ->
content = that.writers[ref].fcall(that, character, system, action)
output = markdown(content)
system.writeInto(output, '#'+ref)
}
if (actionClass)
# Matched a special action class
[responder, ref] = [actionClass[1], actionClass[2]]
if(!@writers.hasOwnProperty(actionClass[2]))
throw new Error("Tried to call undefined writer: #{action}");
responses[responder](ref);
else if (@actions.hasOwnProperty(action))
@actions[action].call(this, character, system, action);
else
throw new Error("Tried to call undefined action: #{action}");
RaconteurSituation.prototype.register = () ->
if not @name?
console.error("Situation has no name")
return this
undum.game.situations[@name] = this
return this
module.exports = RaconteurSituation