I may have accidentally started working on a text parser

So, I was writing a thing to allow players to enter a string of descriptive text, and have characters in game react to it intelligently. (Specifically I wanted players to be able to specify a color to dye their hair, and have characters comment/react.) In doing so, I kinda wrote a little subroutine that is basically the JavaScript string includes() method, which is to say that it just checks a one string against another to see if the first string contains the second.

Anyways, this should plug and play into anyone’s subroutine list fairly easily. It only requires one variable to be created, specifically log which will be set to true if the string is included, and false otherwise. There’s two required parameters (the string to check, and the string to check for), and two optional ones (a boolean case-sensative swtich, which defaults to false, and a boolean whole word check, which should force the subroutine to only return true if the string matches as a whole word, which defaults to true).

Or to put it into action, you can to check if “a quick fox jumped over the fence” contains the word “fox” with this:

*gosub includes "a quick fox jumped over the fence" "fox"
*if log
  There was a fox there!
*if not(log)
  I didn't notice a fox.

Or to be move involved, if you wanted to ask a player their hair color, the comment on it, you can do something like this:

*create hair_color
*input_text hair_color
*gosub includes hair_color "red"
*if log
  Did you know that only about one or two percent of the population has red hair?
*gosub includes hair_color "rainbow"
*if log
  Oh, you dyed your hair the colors of the rainbow? That's beautiful
...etc.

That the above code, even if a player enters “cherry red” or “copper red”, or “a deep, dark red like the the blood of my enemies”, it will make the comment about red hair.

Anyways anyways, I wanted to release this one because I’m only capable of testing so much on my own, and while I haven’t been able to find any bugs in it, I’m certain someone else will. If you do manage to find and error in it, please report it back to me so I can fix it.

Oh! And it dumps a bunch of text as a log if you run randomtest with “show full text” on. You know, in case you cared.

Code for anyone that wants to use it.
*label includes
*comment Required variable: log(false) [Required to retain information outside of subroutine scope]
*params s v
*comment param_1 s:(string) String to search.
*comment param_2 v:(string) Value to search for. 
*if param_count >= 3
	*temp c param_3
*else
	*temp c false
*comment param_3 c:(boolean) Case-sensitive: Check is case sensitive (optional: defaults to false)
*if param_count >= 4
	*temp w param_4
*else
	*temp w true
*comment param_4 w:(boolean) Whole words: Check only searches for whole words (breaks on spaces) (optional: defaults to true)
*temp x 1
*temp y 1
*comment x:place in string searching from; y:place in value searching from
*if not(c)
	*set s "$!!{s}"
	*set v "$!!{v}"
*label includes_check_letter
*if choice_randomtest

	RTLog: Checking character ${(x+(y-1))} of string (${(s#(x+(y-1)))}) against character ${y} of value (${v#y}):
*if (s#(x+(y-1))) = (v#y)
	*if choice_randomtest
		True
	*set y + 1
	*if y > length(v)
		*if choice_randomtest

			RTLog: Value matches part of string.
		*if not(w)
			*set log true
			*return
		*elseif w
			*if choice_randomtest

				RTLog: Checking if either current place to check in string (${(x+(y-1))}) is greater than string length (${length(s)}) or current place in string is a space:
			*if (x+(y-1)) > length(s)
				*if choice_randomtest
					String Ends
				*set log true
				*return
			*elseif (s#(x+(y-1))) = " "
				*if choice_randomtest
					String character (${(s#(x+(y-1)))}) is a space
				*set log true
				*return
			*else
				*if choice_randomtest
					False [String character is (${(s#(x+(y-1)))})]
				*goto includes_reset_check
		*else
			*bug
	*goto includes_check_letter
*if choice_randomtest
	False
*label includes_reset_check
*set y 1
*label includes_check_word
*set x + 1
*if x > length(s)
	*set log false
	*return
*if (choice_randomtest) and (w)

	RTLog: Checking if character ${x} of string (${s#x}) is a space:
*if (w) and ((s#x) = " ")
	*if choice_randomtest
		True
	*set x + 1
	*if x > length(s)
		*set log false
		*return
	*goto includes_check_letter
*elseif w
	*if choice_randomtest
		False
	*goto includes_check_word
*else
	*goto includes_check_letter
30 Likes

I was sadly searching the wiki for substring identification in choicescript last night.

This is great! You are great!

Yea, I was creating this from about from sometime late last night to about 3 or 4 in the morning. Kinda got the idea stuck in my head and had to get it out before I could continue.

Very reminiscent of the “vendor buy” type of mechanic in the old Ultima Online.
Nice job, Rachel!

Here’s a simpler (I think) version of what Rachel did.
It also doesn’t work as well? :smiley:

Code (copy and paste)
*temp phrase "hello"
*temp myphrase ""
*temp space " "
*temp counter 0
*temp counter2 0
*temp counter3 0
*temp limit 0
*temp character ""
*temp character2 ""
*temp newlength 0
*temp check1 ""

*choice
 #First
  *goto first
 #Second
  *goto second

*label first
*label start

Start!

*choice
 #say hello
  Say hello
  *input_text myphrase

*if phrase = myphrase
 You said: "hello"
 *goto start
*else
 I didn't understand. Please try again.
 *goto start


*label second

Start 2!

*choice
 #say hello 2
  Say hello 2
  *input_text myphrase

*set counter 0
*set counter2 length(myphrase)
*set check1 ""
*label check
*set counter +1
*set character myphrase#counter
*if counter < counter2
 *if character = space
  *goto space1
 *goto check


*label space1
*set newlength counter
*set counter3 0
*label checkstuff
*set counter3 +1
*if counter3 < newlength
 *set character2 myphrase#counter3
 *set check1 &character2
 *goto checkstuff
You typed in [b]${myphrase}[/b].
*line_break
The first word here is [b]${check1}[/b].
*line_break
*if check1 = phrase
 You said [b]${phrase}[/b].
*if check1 != phrase
 You did not say [b]${phrase}[/b].

Explanation:

The First option tests to see if what you entered matches the word it’s looking for exactly.
In other words…
The word it’s looking for is hello
If you type in hello
The game will tell you: You said: "hello"
If you type in anything else, the game will tell you: I didn't understand. Please try again.

The Second option tests to see if the first word in whatever you type in matches the word it’s looking for.
You can type in something like hello there friend
The game will tell you:

You typed in hello there friend.
The first word here is hello.
You said hello.

Otherwise, it tells you something like this:

You typed in hi there friend.
The first word here is hi.
You did not say hello.

I think with a little more tweaking I could get this to check the rest of the typed in phrase.
Unless someone else beats me to it, of course.

I mean, if you only care to match the first word, that’s as easy as:

*temp s "hello world"
*temp v "hello"
*temp x 1
*label loop
*if x > length(v)
  True
  *finish
*if (s#x) = (v#x)
  *set x + 1
  *goto loop
*else
  False
  *finish

I didn’t test it, but I’m fairly certain that will work. I mean, if someone wants me to add another optional boolean to make log report what place the word is in, or how many copies of the word are included, I can do that too. (It just wasn’t important to what I was doing at the time.)

Well ok yes, but for those of us who aren’t as smart as you, we need to work up to that level. :stuck_out_tongue_winking_eye:

I like this part here:

*if (s#x) = (v#x)

If I can try to explain that in words so that everyone is following…

the variable v represents the word the system is looking for.
the variable s represents the typed-in phrase.
the pound sign with x tells the system what character it’s on.

If x has a value of 1, and the word is hello, then the first character in hello is h

This is important because of the loop.
The loop goes all the way through and checks:

  • If the first character in the typed-in phrase is the same as the first character in the word it’s looking for.
  • If the second character (same as above)
  • If the third character (same as above)
  • All the way through to the end of the loop.

The result, in human terms, would be something like…
If hello = hello

So if the above is true, the system has found the word in the phrase.
Now that we understand that, it’s just a matter of creating a piece of code that will check the entire typed-in phrase against the search word (which is already done in the first post).

2 Likes