AI which sleeps, then awakens

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.
Steelclad Brian
Posts: 110
Joined: November 15th, 2005, 5:26 am

AI which sleeps, then awakens

Post by Steelclad Brian »

Okay, I'm working on a scenario in which the player is supposed to assault a sleeping camp of enemy forces. In a perfect world what I'd like to happen is that the enemy are all set to that "guardian" special AI type, up until an event or somesuch triggers, at which point they all become normal AI.

Is it possible to do either specifically what I said, or a reasonable facsimile thereof? Ultimately, I simply want the enemy troops to be passive and sit on the hexes they were spawned on up until the player decides to attack.

It appears that setting the ai to use the idle algorithm doesn't work, since there does not appear to be any way to change ai algorithms mid-game and it doesn't work with ranges of turns.

There also doesn't appear to be a way to change a special ai setting for a unit. :(

I considered manipulating values like caution, aggressiveness etc., but I'm afraid that instead of causing the units to guard the locations they're placed in, it will instead cause the AI to simply take up new defensive positions.

Any suggestions? Currently I have the entire enemy camp set to guardian, but the scenario was actually more fun when the entire camp was aggressive from the start, if inappropriate. I'm trying to find a middle ground between the two.
scott
Posts: 5243
Joined: May 12th, 2004, 12:35 am
Location: San Pedro, CA

Post by scott »

You can't do what you want directly.

method 1:
One way to get around it is to switch their sides.
Make side 2 the idle side (with ai_algorithm) and side 3 the normal side.
Create an event that triggers upon an attack that stores all of the side 2 units, loops through the units, and switches their sides/unstores the units.

method 2:
Using guardian ai might come close enough to what you want. Set up the side with normal AI parameters and create your units with guardian ai set. Then, using the same event that triggers upon an attack, you can store all of the units, loop through the units, create a new unit of the same type in the same location of each unit, then throw out the stored units.
Hope springs eternal.
Wesnoth acronym guide.
User avatar
turin
Lord of the East
Posts: 11662
Joined: January 11th, 2004, 7:17 pm
Location: Texas
Contact:

Post by turin »

With regards to Method 2: ai_special= is almost certainly stored when you store the unit. So, you wouldn't have to replace the units (which would have the negative effect of removing any damage you dealt when attacking for the first time), but instead just loop through them, change ai_special= from guardian to null, then unstore them.
For I am Turin Turambar - Master of Doom, by doom mastered. On permanent Wesbreak. Will not respond to private messages. Sorry!
And I hate stupid people.
The World of Orbivm
scott
Posts: 5243
Joined: May 12th, 2004, 12:35 am
Location: San Pedro, CA

Post by scott »

http://wesnoth.org/wiki/InternalActionsWML

I wish there were more you could manipulate, but I don't know if this is the case. I would be really interested in knowing if ai_special is actually preserved.

This is what is stored in the saved game file when you store a unit:
the wiki author wrote: When a unit is stored, the following values may be manipulated with [set_variable]
description
experience
facing
gender
canrecruit
overlays
goto_x
goto_y
hitpoints
moves
resting
side
type
unrenamable
upkeep
user_description
x
y
[variables]
[status]
[modifications]
Hope springs eternal.
Wesnoth acronym guide.
User avatar
turin
Lord of the East
Posts: 11662
Joined: January 11th, 2004, 7:17 pm
Location: Texas
Contact:

Post by turin »

Yeah... it would probably be under [modifications]. Although I'd have to check that.
For I am Turin Turambar - Master of Doom, by doom mastered. On permanent Wesbreak. Will not respond to private messages. Sorry!
And I hate stupid people.
The World of Orbivm
Steelclad Brian
Posts: 110
Joined: November 15th, 2005, 5:26 am

Post by Steelclad Brian »

I'm looking through the WML Reference wiki to try and figure out how to do what you suggest, but I must admit I'm not making a lot of progress. Is there a scenario which cycles through all of the units and then modifies them that I could look at? I tried looking at the Valley of Statues hoping that there was something complex to the unstoning of units, but I was disappointed to find out that it just used [unstone_unit][/unstone_unit] to unstone everything on the map. :roll:

EDIT: I forgot to mention, I'm trying the "switch sides" method first. I have an idle enemy side 2, and then I'm going to copy them into an active side 3.

EDIT2: Okay. I've tried this out, but nothing happens when a unit is attacked.

Code: Select all

[event]
name=attack
	[store_unit]
		[filter]
			side=2
		[/filter]
		variable=orc_units
		kill=yes
	[/store_unit]
	{FOREACH orc_units i}
		[set_variable]
			name=orc_units[i].side
			value=3
		[/set_variable]
	{NEXT i}
	{FOREACH orc_units j}
		[unstore_unit]
			variable=orc_units[$j]
		[/unstore_unit]
	{NEXT j}
[/event]
Note that I haven't declared anything as an array or anything - I'm not even sure if thats possible or necessary in WML.
User avatar
zookeeper
WML Wizard
Posts: 9742
Joined: September 11th, 2004, 10:40 pm
Location: Finland

Post by zookeeper »

Code: Select all

[set_variable]
         name=orc_units[i].side 
I think you'd need to use:

Code: Select all

[set_variable]
         name=orc_units[$i].side 
Steelclad Brian
Posts: 110
Joined: November 15th, 2005, 5:26 am

Post by Steelclad Brian »

That did it, thanks.
User avatar
turin
Lord of the East
Posts: 11662
Joined: January 11th, 2004, 7:17 pm
Location: Texas
Contact:

Post by turin »

There's no reason to do two different {FOREACH } tags. It will work just as well, and run faster, if you combine them, like this:

Code: Select all

{FOREACH orc_units i}
[set_variable]
name=orc_units[$i].side
value=3
[/set_variable]
[unstore_unit]
variable=orc_units[$i]
[/unstore_unit]
{NEXT i} 
For I am Turin Turambar - Master of Doom, by doom mastered. On permanent Wesbreak. Will not respond to private messages. Sorry!
And I hate stupid people.
The World of Orbivm
Steelclad Brian
Posts: 110
Joined: November 15th, 2005, 5:26 am

Post by Steelclad Brian »

I loaded up this scenario earlier and was very surprised to discover this trick no longer works. When it goes to unstore units after storing them, only one of the original units remains - the others are wiped out. Is this a WML change? What is going on here?

It appears that it is no longer storing the units in an array - instead I just get a single unit. If this is a WML change, is there some place I can go to keep updated on how it changes?
scott
Posts: 5243
Joined: May 12th, 2004, 12:35 am
Location: San Pedro, CA

Post by scott »

After the units are stored but before they are unstored, save your game and inspect the file. The stored variable along with whatever the units are stored are present in the file. Verify that all the units you want are being stored. Then, post the WML code that you are using at the moment.
Hope springs eternal.
Wesnoth acronym guide.
claus
Posts: 186
Joined: April 4th, 2005, 5:51 am

Post by claus »

In 1.1 only one unit is stored no matter how many units match the filter. Did test it with evacuation from eastern invasion (commented the [clear_variable] and most of the enemies out for easier testing). It looks like the kill from the [store_unit] there (uses kill=yes) did work, because the [kill] (with fire_event=yes) afterwards did not trigger any of the die events (first time i lost all except a knight, which means the die events for gweddry, dacyn and owaec should have been triggered, if they died to [kill], second time owaec was the lucky survivor). (the second time the store had only one unit (the first time i forgot to comment the [clear_variable] out)

If i would have to make a guess what goes wrong, i would say it looks like all units are stored, but all to storename[0].
Steelclad Brian
Posts: 110
Joined: November 15th, 2005, 5:26 am

Post by Steelclad Brian »

I tried crawling through a save file which had the "unstore unit" part removed before creation, so no units would be theoretically unstored. I couldn't find anything resembling units stored in variables though - admittedly the guts of the saved file were a confusing mess, but I suspect that I'd be able to find 10 or so units saved.
claus
Posts: 186
Joined: April 4th, 2005, 5:51 am

Post by claus »

If you disable binary saves (preferences->advanced preferences) and save after the store happens, you should find the store by searching for [orc_units] (assuming that the name of the variable is still orc_units).
Steelclad Brian
Posts: 110
Joined: November 15th, 2005, 5:26 am

Post by Steelclad Brian »

Well I found what appears to be a unit stored. The line in the save file goes:

EDIT: okay yeesh when I tried to copy paste it it caused the post to end prematurely. Apparently it can't print some of the characters from the saved game file. Regardless, there appears to be a single unit stored from what should be an entire side's worth of orc units.

This fits with what I actually observed, which was a single Goblin Spearman would be unstored and all of the other units would die.

So it appears that the new versions of Wesnoth simply do not allow [store_unit] to store more then a single unit. Is there some way I can work around this, such as using an array and a loop to store every unit? Do I have to do something special to declare the variable as an array?

Also, is this considered a bug that might be fixed in the future, or the new implementation of [store_unit]?

Thanks for all the help by the way guys.
Post Reply