0 votes
by (530 points)
edited by

I'm transitioning my game from Harlowe to Sugarcube and trying to implement replacing.

Harlowe's replace macro made this really easy, allowing you to replace all of a certain word in a passage. So if I set "cat" to $c, and use (replace: $c)[dog], all of the "cat"s in the passage will be replaced by "dog". 

Sugarcube's replace macro seems to function completely differently. I'm not a huge CSS expert so I'm not too familiar with selectors, but from what I understand, you can only replace words you've wrapped in a <span> or <div>. There doesn't seem to be any good way for me to replace all instances of a string according to a variable instead. 

Any functions or macros in Sugarcube that are more similar to Harlowe's replace? Or any other ideas on how I might accomplish this?

EDIT: This replacement happens after the player clicks a link. Forgot to mention that.

3 Answers

0 votes
by (530 points)
 
Best answer

I found someone's custom macro: https://gist.github.com/ChapelR/803ec192cf5922f498652bd6a20a4bf8.

You can specify a block of text and replace certain words or letters in that block, which is much like Harlowe's replace except it doesn't apply to the whole passage, which is fine for my purposes.

function match (id, target, contents, macroName) {
    return $(document.createElement('span'))
        .attr({'id' : id, 'data-term' : target })
        .addClass('macro-' + macroName)
        .wiki(contents);
}

function change (id, replacement) {
    var $el = $(id),
        text = $el.text(),
        target = $el.attr('data-term'), 
        $content;
    
    target = new RegExp(target, 'g');
    
    text = text.replace(target, replacement);
    
    $content = $el.empty().wiki(text);
}

Macro.add('match', {
       tags : null,
    handler : function () {
        
        if (this.args.length < 2 || this.args.length > 2) {
            return this.error('incorrect number of arguments');
        }
		
        var id = Util.slugify(this.args[0]),
            target = this.args[1], $content;
		
        $content = match(id, target, this.payload[0].contents, this.name);
	
        $content.appendTo(this.output);
        
    }
});

Macro.add('change', {
    handler : function () {
        
        if (this.args.length < 2 || this.args.length > 2) {
            return this.error('incorrect number of arguments');
        }
        
        var id = Util.slugify(this.args[0]),
            replacement = this.args[1];
        
        change('#' + id, replacement);
        
    }
});

 

0 votes
by (23.6k points)

Depending on your setup, you can do something like this:

<<set $test to "My cat is a cat called cat">>
$test
<<set $test to $test.replace(/cat/g, "dog")>>
$test

 

by (530 points)

Didn't know you could manipulate a variable like that in Twine! I need the words to change when the player clicks a link though. So if I have this:

$test

<<link "Click">>
   <<set $test to $test.replace(/cat/g, "dog")>>
<<link>>

there should be a function after the "set" macro so the first "$test" changes to the new value and the player sees it.

by (23.6k points)

For that you can just use sugarcube's normal <<replace>> macro:

<span id="myText">$test</span>

<<link "Click">>
   <<set $test to $test.replace(/cat/g, "dog")>>
   <<replace "#myText">>$test<</replace>>
<</link>>

The problem with this solution is that it catches every instance of the three letters in your text. So if you have something like:

<<set $test to "My cat is a cat called cat, but there's a catch.">>

You'll get an unintended result, but maybe you can still make a use of this somehow.

0 votes
by (159k points)

note: There is no built-in functionality (that I can think of) for scanning the HTML generated from the contents of the current Passage to find and replace Plain Text, however you could use Java-script to do it if absolutely necessary (which is what Harlowe is doing) but I would suggest trying to find another solution before considering doing that.

 
It is unclear from your question if the replacement of 'cat' with 'dog' occurs:

a. Automatically based on some predetermined condition.whenever the said Passage is displayed:

<<silently>>
	<<if $variable is "value">>
		<<set _animal to "cat">>
	<<else>>
		<<set _animal to "dog">>
	<</if>>
<</silently>>\
Blah blah blah _animal blah blah blah _animal blah blah blah blah _animal.


b. After some interaction with the story by the Reader, like them selecting a link.
More information about what exactly that interaction is, is needed to design a solution.

by (530 points)
Where can I find Harlowe's implementation of replacing? Maybe I could make my own replace macro with that code.

Forgot to specify in the post, the replacing occurs after the player clicks a link, so it should retroactively replace the words in the passage.
...