More filter examples

The place to post your WML questions and answers.

Moderator: Forum Moderators

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.
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: More filter examples

Post by Sapient »

enclave wrote: radius comes even after all "and"s if not wrapped into an [and] himself?
Yes. The wiki says it too, although it gets often overlooked:
Note: [and],[or],and [not] extra location filters are considered after everything else in the containing filter (except radius, which is considered last in 1.3.8 and greater); they are then processed in the order encountered.
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
enclave
Posts: 936
Joined: December 15th, 2007, 8:52 am

Re: More filter examples

Post by enclave »

Sapient wrote: Yes. The wiki says it too, although it gets often overlooked:
that explains it all, thanks..!
enclave
Posts: 936
Joined: December 15th, 2007, 8:52 am

Re: More filter examples

Post by enclave »

7) lua wesnoth.get_locations with "not" in filter
local ns_test_locations = wesnoth.get_locations { {"not", { terrain = "W*,W*^*,Xv,_off^_usr" } }}
This will store all hexes of map which dont have water or not impassable (in this example I test only these 2: "Xv,_off^_usr", but in reality there is much more impassable types). So the key is to put double brackets before "not" if there is no filter previously... for example if there was filter it would "probably" look like so: local ns_test_locations = wesnoth.get_locations { x=10,y=10 {"not", { terrain = "W*,W*^*,Xv,_off^_usr" } }} -> so no double brackets...

7) lua wesnoth.get_locations with "not" and "and" in filter

Code: Select all

local my_location_container = wesnoth.get_locations { {"not", { terrain = "W*,W*^*,Xv,_off^_usr" }}, {"and", { x=1, y=1, radius=4 }}}
This is working equivalent of following WML filter code:

Code: Select all

[store_locations]
   [not]
      terrain=W*,W*^*,Xv,_off^_usr
   [/not]
   [and]
       x,y=1,1
       radius=4      
   [/and]
   variable=my_location_container
[/store_locations]
enclave
Posts: 936
Joined: December 15th, 2007, 8:52 am

Re: More filter examples

Post by enclave »

8) [store_locations] examples with radius.. stores king if he is on keep and then checks if there are any empty castles in his radius

Code: Select all

[store_unit]
	[filter]
		canrecruit=true
		side=$side_number
	   	   [filter_location]
		      terrain=Kh*
		   [/filter_location]
	[/filter]
	variable=king
[/store_unit]
Stores the king into king variable given that you only filter a specific keep type "Kh*" and if you only want to store king of the side who's turn is now.

Then you can filter for empty castle hexes to check if he can recruit any units..

Code: Select all

[if]
 [variable]
   name=king.length
   greater_than=0
 [/variable]
   [then]
	[store_locations]
		terrain=Ch*,Kh*,Chw*  ##only specific castles, for more castles terrains check editor or find codes somewhere
			[and]
			   [not]
			      [filter] ## hex is not occupied by ANY unit
			      [/filter]
			   [/not]
			[/and]
			[and]
			   [filter]
			      canrecruit=yes ## there is a leader in radius of 4 hexes
			      side=$side_number  ## the leader belongs to current moving side who's turn is now
			   [/filter]
			   radius=4  ## radius u want to check for castles around leader..
			[/and]
			variable=empty_castles
	[/store_locations]
	
	[if]
		[variable]
			name=empty_castles.length
			greater_than=0
		[/variable]
		[then]
                    {VARIABLE count 0}
                    {FOREACH empty_castles counter}
                       {VARIABLE_OP count add 1}
                     {NEXT counter}
                    [message]
                        message="There was a king on keep and there are $count empty castles where he could recruit units"
                    [/message]
                [/then]
         [/if]
   [/then]
[/if]
you could use this code to simulate that ai is recruiting specific units.. I use it as AI for recruits in my mod that doesn't have recruit list enabled.
User avatar
Celtic_Minstrel
Developer
Posts: 2166
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: More filter examples

Post by Celtic_Minstrel »

If you want all castles, just use C*,K*. Also, in your example, the Chw* is redundant since Ch* would also match anything it matches. Think of the * as meaning "anything can go here".
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
enclave
Posts: 936
Joined: December 15th, 2007, 8:52 am

Re: More filter examples

Post by enclave »

9) [store_locations] basic but with double radius a true nightmare...

The code will store only the hexes in radius of 4 from all units with ability "hc_build_new_city" and minus the area with villages and 3 hex around them.

Code: Select all

[store_locations]
   [and]
   [filter]
   ability=hc_build_new_city
   [/filter]
   radius=4
   [/and]
	[not]
	terrain=*^V*
	radius=3
	[/not]
variable=qc_filter_tester
[/store_locations]
The nightmare part was the [and][/and]. Without that it wouldnt work properly. While if we remove the terrain code
Spoiler:
then we can also remove [and][/and] and it will work perfectly fine..
wth... spent hours to figure it out. like usual..
enclave
Posts: 936
Joined: December 15th, 2007, 8:52 am

Re: More filter examples

Post by enclave »

10) [set_menu_item] that you can add to your add-on and experiment with filters.. It will visually show you what your filter does or could do...
Add this menu code inside event like prestart..
First part of code, do NOT change it:

Code: Select all

[event]
name=prestart
[set_menu_item]
		id=aa_qc_fmenu
		description=_"Test Filter"
		image="items/ball-magenta.png~SCALE(22,22)"
		[command]
		[store_map_dimensions]
variable=qc_map_dimensions
[/store_map_dimensions]
{VARIABLE qc_map_dimensions.bound_x $qc_map_dimensions.width}
{VARIABLE_OP qc_map_dimensions.bound_x add 1}
{VARIABLE qc_map_dimensions.bound_y $qc_map_dimensions.height}
{VARIABLE_OP qc_map_dimensions.bound_y add 1}
		{FOREACH qcc.qc_filter_tester nsfbci}
		[remove_item]
		x,y=$qcc.qc_filter_tester[$nsfbci].x,$qcc.qc_filter_tester[$nsfbci].y
halo="items/ball-magenta.png~O(60%)"
		[/remove_item]
		{NEXT nsfbci}
		[redraw]
		side=$side_number
		[/redraw]
		{CLEAR_VARIABLE qcc.qc_filter_tester}
[store_locations]
##Now here comes your filter.. for example:

Code: Select all

x=1,1,$qc_map_dimensions.width,$qc_map_dimensions.width
	y=1,$qc_map_dimensions.height,1,$qc_map_dimensions.height
	[not]
	x=0
	[/not]
	[not]
	y=0
	[/not]
	[not]
	x=$qc_map_dimensions.bound_x
	[/not]
	[not]
	y=$qc_map_dimensions.bound_y
	[/not]
## I think it will store 4 corners of the map and mark them with red balls if you have fog and shroud disabled.
## you can put there whatever you like and visually see what exactly it filtered out.
## Now second part of the code, do NOT change it:

Code: Select all

variable=qcc.qc_filter_tester
[/store_locations]
{FOREACH qcc.qc_filter_tester nsfbci}
		[item]
		redraw=no
		x,y=$qcc.qc_filter_tester[$nsfbci].x,$qcc.qc_filter_tester[$nsfbci].y
		halo="items/ball-magenta.png~O(60%)"
		[/item]
{NEXT nsfbci}
		[redraw]
		side=$side_number
		[/redraw]
		{CLEAR_VARIABLE qc_map_dimensions}
		[/command]
[/set_menu_item]
Now of course you can change whatever you like.. if you know what you are doing :D


11) goto [micro_ai] a very full of complications filter that would make a peasant look for a place to build new village and GO there, with a rule that villages should be at least 3 hex away from each other.

I had a problem with my micro_ai, the filter was very simple but it was freezing the screen.
The problem was because the filter was leaving too many decisions for goto.. so to increase the speed/performance I had to reduce the amount of decisions (result from filter) to make.. I done it successfully, the ai has no delays between moving peasants, all works really quickly.

Code: Select all

[micro_ai]
	side=$side_number ## the side that applies to micro_ai
	ai_type=goto
	action=add
	ca_id=iiiiiiiidddddd ## your unique id
	[filter]
		ability=build_new_city ## ability that peasant has
               ## type=Peasant ## or you could just use type instead of ability here
	[/filter]
  [filter_location]
[and]
[and]
x=1,1,26,26  ## if you have previously stored map dimensions or if you know the coordinates
	y=1,26,1,26  ## then you can use them as goals to 4 corners of the map
	radius=1 ## extend this a bit if your corners are full of water or other bad terrains
	[/and]
	[not]
	terrain=*^V*  ## there should be no village in the corner
	radius=3 ## with radius of 3
	[/not]
	[not]
	terrain=M*,H*,H*^* ## there should be no terrains like this in the corners
	[/not]
	[not]
	x=0 ## it should not include land outside the map boundaries
	[/not]
	[not]
	y=0 ## it should not include land outside the map boundaries
	[/not]
	[not]
	x=27 ## it should not include land outside the map boundaries
	[/not]
	[not]
	y=27 ## it should not include land outside the map boundaries
	[/not]
	[/and]
    [or] ## THIS MEANS THAT IT WILL NOT EXCLUDE THE FILTER WRAPPED BETWEEN OR, BUT IT WILL ADD THIS TO FILTER SO IT WILL USE BOTH
	[and]
   [filter]
   side=$side_number ## this is possibly not needed... but idk
   ability=hc_build_new_city ## use ability or type.. as you prefer
   [/filter]
   radius=3 ## this will be the area to look for a free space for a new village (3 hex around unit is because the smaller the better.. for speed performance)
   [/and]
	[not]
	terrain=*^V* ## there should be no village
	radius=3 ## in radius of 3 inside that unit area.. 
	[/not]
	[not]
	terrain=M*,H*,H*^* ## there should be no these bad terrains anywhere in unit radius (3 hex around unit)
	[/not]
	[/or]
[/filter_location]
	unique_goals=yes ## make manu peasants go in different places and not choose the same spot to go..
	ca_score=210001 ## priority of task
	avoid_enemies=1 ## try not to go near enemies, but not too much..
  [/micro_ai]
enclave
Posts: 936
Joined: December 15th, 2007, 8:52 am

Re: More filter examples

Post by enclave »

12) a basic lua filter for lua beginners.. (it may seem to be a simple filter, but it's not obvious how to make it work in lua) wesnoth.get_locations and also ipairs

We will try to store locations 1 hex radius around x1 and y1 but without x1 and y1 themselves.. and will create road around x1 y1 hex.

Code: Select all

[lua]
code = <<
local x1 = wesnoth.get_variable("x1") 
local y1 = wesnoth.get_variable("y1") 
for i,loc in ipairs(wesnoth.get_locations( {{"and",{ x=x1, y=y1, radius=1 }},{"and",{{"not",{ x=x1, y=y1 } } } } } )) do
    wesnoth.set_terrain(loc[1], loc[2], "Rr")
end
>>
[/lua]
This seems like an easy task, but all these brackets may become a nightmare without previous example..
The WML equivalent (untested, but should work) would look like:

Code: Select all

[store_locations]
 [and]
  x,y=$x1,$y1
  radius=1
 [/and]
 [and]
  [not]
   x,y=$x1,$y1
  [/not]
 [/and]
variable=some_locations_array
[/store_locations]
{FOREACH some_locations_array i}
[terrain]
terrain=Rr
x,y=$some_locations_array[$i].x,$some_locations_array[$i].y
[/terrain]
{NEXT i}
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: More filter examples

Post by Sapient »

[and][not] can be written as just [not]
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
enclave
Posts: 936
Joined: December 15th, 2007, 8:52 am

Re: More filter examples

Post by enclave »

Sapient wrote: May 16th, 2018, 2:06 pm [and][not] can be written as just [not]
you most probably 100% right, but with radius I'm trying to avoid short versions, due to previous terrible experience, where basic filters refused to work only because they were not having [and] tags... that's an example:
viewtopic.php?f=21&t=48125#p627408 doesn't work
viewtopic.php?f=21&t=48125#p627441 works
basically while I'm not a genious filter expert and not 100% sure which [and][not] will still work with just [not] I'd rather make it long.. but working..
PS. are you saying that [not] already includes [and] in it and will work in any case?
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: More filter examples

Post by Sapient »

I am 100% sure, yes.
are you saying that [not] already includes [and] in it
For the record, [and] is always implied. In practice, the only time you need to use [and] explicitly is to create a group that contains the effects of radius=, so radius will be processed sooner-- with the contained group-- rather than last. Although, in theory, there could be other times when it's useful to group a complex set of conditions together.
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
Post Reply