Looping through units to obtain their movement area and then implementing it into AI.

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.
Post Reply
BajMic
Posts: 44
Joined: January 24th, 2023, 1:22 am

Looping through units to obtain their movement area and then implementing it into AI.

Post by BajMic »

So I'm trying to code an AI of some skeleton commando units that jump out of the water. Once their assault is called, the block below is reactivated every turn. I tried moving it around between Turn Refresh and Turn End, adding
moves=max
, but it seems like it doesn't work.

What the block is supposed to do is every turn (i) it stores reachable areas for each unit (ii) assigns series of micro-ai's with varying CA scores to each unit individually, in order to move the unit into the most valuable hex available. Due to the placement of hexes (the closer to the 'goal' the more valuable), the units would gradually creep towards their objective by jumping from one strong hex to the other, hold advantageous ground (if ZoC-blocked), or keep a close formation with other allied units (if caught in weak hexes).

Code: Select all

	#Commando troops (once activated) follow a little more in-depth algorithm.
	#They will move towards the player keep, but avoid ending their move on weak hexes whenever possible, even if it means holding position on strong hexes.
	#Finally, if only weak hexes are available, they will try to stay close to each other.
	[event]
		name=waterbone_advances
		first_time_only=no
		[if]
			[variable]
				name=waterbone_assault
				equals=1
			[/variable]
			[then]
				[store_unit]
					[filter]
						side=2
						role=waterbone
					[/filter]
					variable=waterbone_troops
				[/store_unit]
				[foreach]
					array=waterbone_troops
					variable=waterbone_troop
					[do]
						[store_reachable_locations]
							[filter]
								side=2
								id=$waterbone_troop.id
							[/filter]
							range=movement
							variable=($waterbone_troop.id| + "_range")
						[/store_reachable_locations]
						[micro_ai]
							side=2
							ai_type=goto
							action=change
							ca_id=($waterbone_troop.id| + "_goal")
							remove_movement=yes
							[filter]
								side=2
								id=$waterbone_troop.id
							[/filter]
							[filter_location]
								find_in=($waterbone_troop.id| + "_range")
								[and]
									find_in=waterbone_goal
								[/and]
							[/filter_location]
							ca_score=400000
						[/micro_ai]
						[micro_ai]
							side=2
							ai_type=goto
							action=change
							ca_id=($waterbone_troop.id| + "_villages")
							remove_movement=yes
							[filter]
								side=2
								id=$waterbone_troop.id
							[/filter]
							[filter_location]
								find_in=($waterbone_troop.id| + "_range")
								[and]
									find_in=waterbone_villages
								[/and]
							[/filter_location]
							ca_score=380000
						[/micro_ai]
						[micro_ai]
							side=2
							ai_type=goto
							action=change
							ca_id=($waterbone_troop.id| + "_tier2")
							remove_movement=yes
							[filter]
								side=2
								id=$waterbone_troop.id
							[/filter]
							[filter_location]
								find_in=($waterbone_troop.id| + "_range")
								[and]
									find_in=waterbone_tier2
								[/and]
							[/filter_location]
							ca_score=360000
						[/micro_ai]
						[micro_ai]
							side=2
							ai_type=goto
							action=change
							ca_id=($waterbone_troop.id| + "_tier1")
							remove_movement=yes
							[filter]
								side=2
								id=$waterbone_troop.id
							[/filter]
							[filter_location]
								find_in=($waterbone_troop.id| + "_range")
								[and]
									find_in=waterbone_tier1
								[/and]
							[/filter_location]
							ca_score=340000
						[/micro_ai]
						[micro_ai]
							side=2
							ai_type=goto
							action=change
							ca_id=($waterbone_troop.id| + "_regroup")
							remove_movement=no
							[filter]
								side=2
								id=$waterbone_troop.id
							[/filter]
							[filter_location]
								find_in=($waterbone_troop.id| + "_range")
								[and]
									[filter]
										side=2
										type=Skeleton
										formula= moves < 2
									[/filter]
									radius=1
								[/and]
							[/filter_location]
							ca_score=100005
						[/micro_ai]
					[/do]
				[/foreach]
			[/then]
		[/if]

	[/event]
In every test, the units do not execute any of the micro_ai's. It also seemed like reachable locations didn't store properly.

I am also assuming the problem is with [store_reachable_locations], becauseI tried doing such loops with name concatenations before and they did work. Or were those just some exceptional cases, I don't know. Can anyone help me here? What am I doing wrong?
User avatar
Toranks
Translator
Posts: 168
Joined: October 21st, 2022, 8:59 pm
Location: Sevilla
Contact:

Re: Looping through units to obtain their movement area and then implementing it into AI.

Post by Toranks »

Try variable=$waterbone_troop.id|_range
Same with id= find_in= etc
User avatar
beetlenaut
Developer
Posts: 2827
Joined: December 8th, 2007, 3:21 am
Location: Washington State
Contact:

Re: Looping through units to obtain their movement area and then implementing it into AI.

Post by beetlenaut »

BajMic wrote: June 26th, 2023, 2:38 am It also seemed like reachable locations didn't store properly.
That is the problem, but it sounds like you aren't sure. Did you know that you can find out with :inspect? It would have allowed you to ask a more specific question and include a lot less code. Also, it seems like you didn't validate that part of the code before you went on to write all the micro_ais, because you didn't really know where to look for the problem. You should write as little code as possible and make sure it works before going on to the next bit.

The problem here is that you can't use dashes in a variable name, and the id's have them. (Or, at least, you shouldn't use dashes. I seem to remember them working in some contexts, but apparently this is one where they don't.) I would use the loop's index_var like this: variable="skeleton_" + $i| + "_range" or this: variable="skeleton_$i|_range".
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
BajMic
Posts: 44
Joined: January 24th, 2023, 1:22 am

Re: Looping through units to obtain their movement area and then implementing it into AI.

Post by BajMic »

After I have implemented suggestions from both Toranks and Beetlenaut, the AI started working.

I.e., I assigned custom id's to units and corrected the formats in ca_id and find_in.

Thanks for the help.

Btw. The WML wiki is lacking in explicit examples of string concatenation. I think it would help a lot.
Post Reply