Is it possible to spell/grammar check player text in sugarcube?

You’d have to hook up some sort of javascript spell-checking library. And a quick search isn’t turning up anything that looks like it would be particularly easy to just drop in and use… :frowning:

1 Like

Ok thanks, I guess I’ll mark this the answer then if no one else thinks of something in the next day or two.

Thanks for your time guys.

If you have the Grammarly plugin installed, it should check spelling and grammar so long as the game runs in a browser window. I haven’t tried it individually though.

1 Like

Yeah I have Grammarly. It doesn’t seem to work tbh, but still, I need a solution within the game itself - I can’t expect players to all have Grammarly installed etc. if you know what I mean.

1 Like

I don’t know about grammar checking, but there’s the Open Source Spell Checker that you could use for spell checking. You can test it online here.

1 Like

Well, that’s disappointing. It works in AXMA 6.1 for the online editor - the Grammarly icon shows up and I can click to open the text in Grammarly with correction suggestions. However, I don’t think it would offer it in the released game, even if showing on a webpage. I could have sworn I got underlined text once while playing an old-school Twine 1 game online.

1 Like

Yeah don’t take my word for it though, because I’m a total noob and I’ve only installed Grammarly recently, so I may have settings wrong etc! :confused:

Here’s a quick example I wrote showing how Open Source Spell Checker could be used in Twine/SugarCube: Spellcheck Sample

You can download the source files from here:

If you import the “Spellcheck_Sample.html” into Twine (and edit the path in the JavaScript section) you can see how that code works, play around with it, and hopefully get it to do what you want.

Note that, while I included an improved word list with my code (dictionary source), you may still need to add more words to it if you have any words you expect to use which aren’t already in that dictionary. Also, keep in mind that if, for example, they misspell “they’re” as “there” or “their”, this won’t catch that, since those are all actual words. It also ignores capitalization, so proper names, like “Paris”, will not be marked as incorrect if they’re written in lowercase.

Hope that helps! :slight_smile:


Wow thanks so much! I’ll take a look at that right now. It looks amazing!!!

EDIT** ok yep that looks really sweet. Thankyou!
Would it be possible to not allow a player to progress to another passage if they have a certain number of errors that need fixing? I don’t know if that’s possible, but if it is, it would be a great way of stopping players just spamming words :stuck_out_tongue:

FYI, I wasn’t happy with the speed of the spellchecker, so I sped it up. It should work a bit faster now. Just download it again to get the updated code.

As far as preventing the player from progressing if there are too many errors, you could put the link to the next passage within a <span> and toggle the visibility of that span as necessary using a little jQuery code. For example:

<span id="hidtxt">[[Link]]</span>
<<button "Toggle link visibility">>
	<<run $("#hidtxt").toggle()>>
<<button "Hide link">>
	<<run $("#hidtxt").css("display", "none")>>
<<button "Show link">>
	<<run $("#hidtxt").css("display", "")>>

That shows how you can toggle, hide, or display things by using their ID. Just apply something like that to your own links, based on the length of text and the number of errors, and that should help.

Enjoy! :slight_smile:

P.S. If you want to be really mean, you could play a sound whenever they try to paste some text. :grin:

1 Like

Wow that is so cool! Thanks a million!

I’ll download again and have a play.

Ooh yes I do want to be mean haha. :laughing:
I didn’t know you could detect pasting!?

Yeah, some elements, like the <textarea> element, have a paste event. In fact, the code is already using that event to detect changes to the text.

If you look in the <<script>> section of the Start passage, you’ll see this code:

$(event.content).find("#textarea-varname").on("change input paste", null, "varname", setup.checkWords);

What that does is trigger the setup.checkWords() function (found in the JavaScript section) whenever the <<textarea>> text is changed, has input, or something is pasted there.

If you wanted some other code to only trigger on pasted text, you could add another line after that one like this:

$(event.content).find("#textarea-varname").on("paste", function (event) {
	/* Replace this line with your own JavaScript code, and it will be triggered when text is pasted. */

Now, whatever code you put within that function will trigger whenever they try to paste text into that <<textarea>>. (Change varname in that code if your <<textarea>> uses a different variable than $varName.)

If you need to call SugarCube macros from within that JavaScript you can use:

$.wiki("SugarCube code goes here");

(See the SugarCube documentation here for details.)

Have fun! :smiley:

1 Like

Wow this is so cool. And incredibly helpful!

I was pulling my hair out last night (I don’t know Javascript but I’m getting decentish with sugarcube macros), and I was literally saying to myself, “If only there was a way for me to set sugarcube variables etc. within the awesome JavaScripts that people (like you) post online!”
Looks like that wiki thing is the answer! THANK YOU! This will save me hours and hours of looking up Javascript things that I don’t really understand :rofl:

Well, if you need to access SugarCube story variables from JavaScript you can use State.variables.variableName (to access $variableName), or for temporary variables, use State.temporary.variableName (to access _variableName).

I’d definitely recommend at least skimming through the SugarCube documentation so you’re aware of methods like those.

Also, if it helps, I have a collection of other Twine/SugarCube sample code I’ve written that you might want to take a look at.

Enjoy! :slight_smile:

1 Like

Ah ok! I tested the State.variables and it seems to be working as you said! Thanks so much.

Yeah tbh I’m checking the SugarCube documentation all the time, but still a lot of it goes over my head. I think programmers don’t realise just how much they take for granted and how simple it needs to be for noobs like me! :sweat_smile:

Yeah thank you so much - I have been perusing your sample code. It looks so rad. I particularly love how you’ve set it out with examples etc. Really nice job!

Nah, when I first started with it, a lot of it went over my head too. I just skimmed though it, at first, so I could understand what was possible. Then, whenever I needed to do anything specific, I’d look it up again, read through the examples, and try stuff out until I understood it. I pretty much had the documentation open all the time when I first started.

The thing is, nobody is born knowing these things, so it’s all practice, read the documentation, practice, Google for help, practice, look at other people’s code, practice, oh, and did I mention practice?

Anyways, hopefully some of my stuff helps you figure things out a bit quicker than I did. :slight_smile:


Yeah true! Basically wherever the documentation is example heavy is where I’m more likely to understand hehe. Thanks so much for all your help!

Those hiding and showing links are so cool.

I think I can find the length easy enough by splitting the input variable into an array, but …
stupid question: How do I actually find the number of errors that the spellcheck found (so as to forward the player or not)?

In the setup.wordUpdate() function there’s a for() loop which checks each word. Within that loop, look for the if (words[i] !== suggestion) { ... } code. The code within that if() gets triggered each time an error is found. So, if you create a variable and set it to zero just before the for() loop (such as by doing var counter = 0;), then increment that variable within that if() statement (by doing counter += 1;), then that will count up the number of errors.

Then, after the for() loop you can use the variable (counter) to tell how many errors there were, and you can use words.length to tell how many words were typed. Using that information you can determine whether to show or hide the link.

So, the code around that for() loop might look something like this:

		// Add unrecognized words and suggestions to listbox.
		var counter = 0;
		for (var i = 0; i < words.length; i++) {
			if (setup.isProperty(wordSuggestions, words[i])) {
				suggestion = wordSuggestions[words[i]];
			} else {
				suggestion = find_similar(words[i], 0.7)[0][0];
				wordSuggestions[words[i]] = suggestion;
			opt = document.createElement("option");
			opt.value = words[i];
			if (suggestion === undefined) {
				opt.text = words[i] + " (???)";  // No suggestion.
			} else {
				opt.text = words[i] + " (" + suggestion + "?)";
			if (words[i] !== suggestion) {
				counter += 1;
				listbox.add(opt);  // Adds info to listbox.
		if ((words.length >= 10) && ((counter / words.length) <= 0.1)) {
			$("#hidtxt").css("display", "");  // Show the link.
		} else {
			$("#hidtxt").css("display", "none");  // Hide the link.

And that would show the link after 10 or more words were typed in, with 10% or less errors (i.e. 1 error per 10 words).

You can modify that code to work however you please.

Hope that helps! :slight_smile:

1 Like


I just put it into the Javascript as per your instructions and it worked like a charm!

I’ve book marked this page too so I can refer back to it later when I’m doing things in Javascript. You explained it really clearly. Thankyou so so much!