Wesnoth formula language function "contains_string"

The place to post your WML questions and answers.

Moderators: Forum Moderators, Developers

Forum rules
  • Please use [code] BBCode tags in your posts for embedding WML snippets.
  • To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
Post Reply
hyper_cubed
Posts: 28
Joined: March 31st, 2018, 7:52 pm

Wesnoth formula language function "contains_string"

Post by hyper_cubed » April 14th, 2018, 4:36 pm

I am attempting to utilize the WFL in my code, specifically the contain_string(string, search_string) function.

Here is what I've got:

Code: Select all

			[variable]
				name=lookup
				equals=$contains_string('[x]' where x = $attacks_array[$idx_1].id, '[y]' where y = $magic_list_array[{grp_idx}].name)
			[/variable]
I'm not sure what I am doing wrong, or if i am able to pass WML variables into the WFL at all. The variable "lookup" in the code is set to one if condtions in other part of the code.

User avatar
Celtic_Minstrel
Developer
Posts: 1149
Joined: August 3rd, 2012, 11:26 pm
Contact:

Re: Wesnoth formula language function "contains_string"

Post by Celtic_Minstrel » April 17th, 2018, 2:06 am

In order to use WFL code in this context, you need to enclose the entire formula in parentheses. It's also strongly recommended to enclose the whole thing in double quotes, since not doing so will result in the + sign being parsed out by the WML, which means WFL will raise a syntax error. You don't use + in this case so it's not required, but it's recommended anyway.

Applying those two fixes to your snippet gives the following:

Code: Select all

[variable]
	name=lookup
	equals="$(contains_string('[x]' where x = $attacks_array[$idx_1].id, '[y]' where y = $magic_list_array[{grp_idx}].name))"
[/variable]
The $ substitution syntax is evaluated from right to left, which means that you can indeed include WML variables in a WFL formula similar to how you're doing it here. However, this should be thought of as similar to how the WML preprocessor works. The Wesnoth Formula Language knows nothing of WML variables; what's happening is that the contents of those variables are substituted in the WFL code before it's compiled into an executable form. That means that the result of substituting the WML variable into the formula must result in valid WFL code. In particular, if the WML variable contains a string (as seems to be the case here), you'll need to enclose the reference in single quotes if you want to references it as a string from the WFL.
Author of The Black Cross of Aleron campaign and Default++ era.
Maintainer of Steelhive.

hyper_cubed
Posts: 28
Joined: March 31st, 2018, 7:52 pm

Re: Wesnoth formula language function "contains_string"

Post by hyper_cubed » April 18th, 2018, 4:42 pm

Celtic_Minstrel wrote:
April 17th, 2018, 2:06 am
In order to use WFL code in this context, you need to enclose the entire formula in parentheses. It's also strongly recommended to enclose the whole thing in double quotes, since not doing so will result in the + sign being parsed out by the WML, which means WFL will raise a syntax error. You don't use + in this case so it's not required, but it's recommended anyway.

Applying those two fixes to your snippet gives the following:

Code: Select all

[variable]
	name=lookup
	equals="$(contains_string('[x]' where x = $attacks_array[$idx_1].id, '[y]' where y = $magic_list_array[{grp_idx}].name))"
[/variable]
The $ substitution syntax is evaluated from right to left, which means that you can indeed include WML variables in a WFL formula similar to how you're doing it here. However, this should be thought of as similar to how the WML preprocessor works. The Wesnoth Formula Language knows nothing of WML variables; what's happening is that the contents of those variables are substituted in the WFL code before it's compiled into an executable form. That means that the result of substituting the WML variable into the formula must result in valid WFL code. In particular, if the WML variable contains a string (as seems to be the case here), you'll need to enclose the reference in single quotes if you want to references it as a string from the WFL.
Man, that is super useful. I read up about that but didn't find it super clear.

I ended up solving it with lua though after I got frustrated with wfl.

Here was my solution just in case it may help someone else.

Code: Select all

#define find_string string string_query
[lua]
	code =  << local t = ...;
			if(((string.find(string.lower(t.string), string.lower(t.string_query))) ~= nil))
			then
				wesnoth.set_variable("find_string", "1")
			end >>
	[args]
		string={string}
		string_query={string_query}
	[/args]
[/lua]
#enddef
The lua will return 1 on a successful query stored in the WML variable "find_string" and nil on a failure.
Once you call it then all you have to do is clear it with this:

Code: Select all

#define clear_find_string
[lua]
	code =  << wesnoth.set_variable("find_string", nil) >>
[/lua]
#enddef
Anyone reading this, Celtic Minstrel's solution is the superior solution as you don't have to clear the variable with the proposed WFL correction.

User avatar
Celtic_Minstrel
Developer
Posts: 1149
Joined: August 3rd, 2012, 11:26 pm
Contact:

Re: Wesnoth formula language function "contains_string"

Post by Celtic_Minstrel » April 19th, 2018, 2:35 am

For the record, you don't need to use Lua in a custom macro to clear the variable, you can just use {CLEAR_VARIABLE find_string}.
Author of The Black Cross of Aleron campaign and Default++ era.
Maintainer of Steelhive.

User avatar
Sapient
Inactive Developer
Posts: 4440
Joined: November 26th, 2005, 7:41 am
Contact:

Re: Wesnoth formula language function "contains_string"

Post by Sapient » April 19th, 2018, 3:33 pm

If you are trying to filter units, you may want to make use of lua_function attribute in StandardUnitFilter. That one just needs to return true/false, so there's no need to store a WML variable.

By the way, using Lua code as you have done is a nicer solution than using WFL because a variable substitution could easily create invalid WFL (for example, if the WML variable contains single-quote ' that would prematurely terminate the WFL string). However, I would suggest your lua code store something or clear the variable on false instead of only storing for true. That would eliminate the errors caused by failing to clear the variable.
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."

hyper_cubed
Posts: 28
Joined: March 31st, 2018, 7:52 pm

Re: Wesnoth formula language function "contains_string"

Post by hyper_cubed » April 22nd, 2018, 7:23 pm

Sapient wrote:
April 19th, 2018, 3:33 pm
If you are trying to filter units, you may want to make use of lua_function attribute in StandardUnitFilter. That one just needs to return true/false, so there's no need to store a WML variable.

By the way, using Lua code as you have done is a nicer solution than using WFL because a variable substitution could easily create invalid WFL (for example, if the WML variable contains single-quote ' that would prematurely terminate the WFL string). However, I would suggest your lua code store something or clear the variable on false instead of only storing for true. That would eliminate the errors caused by failing to clear the variable.
Hey, no I created a large database with base words with meta and sub data in order to easily categorize unit weapons (supposing that a modder has named their weapon something reasonable.

That way, I can "can" some macros that allow one to generate basic weapon local variables based on the types of weapons a unit has. This was useful because I could inject amla's dynamically into a unit based on if they have say a silly weapon called "the killing goedendag of eternal chaos" and I had injections that injected on a successful query of meta "hammer" and sub of "reach" well there is a name in the database of "goedendag" that would return true based on the "find_string" result which would drill down into my conditionals and grant the amla.

I must be honest, I have to force myself to worry about error handling. After this post, I think I might just implement that.
Celtic_Minstrel wrote:
April 19th, 2018, 2:35 am
For the record, you don't need to use Lua in a custom macro to clear the variable, you can just use {CLEAR_VARIABLE find_string}.
Awesome! Thanks celtic!
Last edited by Pentarctagon on April 22nd, 2018, 7:29 pm, edited 1 time in total.
Reason: Please avoid double posting - it's fine to reply to multiple people in the same post.

Post Reply