AI Work/Combat Prediction
Post MTG Forge Related Programming Questions Here
	Moderators: timmermac, Agetian, friarsol, Blacksmith, KrazyTheFox, CCGHQ Admins
			22 posts
			 • Page 1 of 2 • 1, 2
		
	
AI Work/Combat Prediction
 by friarsol » 04 Feb 2011, 05:50
by friarsol » 04 Feb 2011, 05:50 
As part of my AI improvement work I'm now allowing the AI to activate spells/abilities during other phases. The very early work has quietly slipped into the SVN and you can now see the AI activating Tims (Prodigal Sorcerer) at the End of the Human's turn instead of during their main phase, at least when pinging players is concerned. 
The new added responsiveness is pretty cool so far. I've already caught myself about to attack when the AI decides to Shatter an artifact during my main phase that I was going to use in combat.
The next thing I wanted to do was rewrite the Regeneration AI, since right now it "guesses" to regenerate things, and it would be much better to be responsive.
This is mostly for Sloth since I know he's worked the most in combat recently, but if anyone else happens to know feel free to chime in. So does anyone know if there is some type of combat destruction function right now?
Ideally, I would pass in a combatant. It would take creatures attacking/blocking it, plus a few other keywords into consideration (deathtouch, wither/infect, etc) and return true or false based on whether or not it would be destroyed. If it gets its toughness reduced to 0, that would actually return false, since that isn't destruction. But if it gets hit by deathtouch or lethal damage, then it would return true.
For blockers it might be a bit trickier because of Issue 77 (http://code.google.com/p/cardforge/issues/detail?id=77). Since we're really supposed to know the order damage is dealt to blockers, if we knew that information deciding if something would be destroyed would be much easier. Since we don't, we'd have to assume the creature we're checking is the first. Anyway, I'm rambling. If anyone has any suggestions or requests while I'm tweaking AIs feel free to add it here.
			
		The new added responsiveness is pretty cool so far. I've already caught myself about to attack when the AI decides to Shatter an artifact during my main phase that I was going to use in combat.
The next thing I wanted to do was rewrite the Regeneration AI, since right now it "guesses" to regenerate things, and it would be much better to be responsive.
This is mostly for Sloth since I know he's worked the most in combat recently, but if anyone else happens to know feel free to chime in. So does anyone know if there is some type of combat destruction function right now?
Ideally, I would pass in a combatant. It would take creatures attacking/blocking it, plus a few other keywords into consideration (deathtouch, wither/infect, etc) and return true or false based on whether or not it would be destroyed. If it gets its toughness reduced to 0, that would actually return false, since that isn't destruction. But if it gets hit by deathtouch or lethal damage, then it would return true.
For blockers it might be a bit trickier because of Issue 77 (http://code.google.com/p/cardforge/issues/detail?id=77). Since we're really supposed to know the order damage is dealt to blockers, if we knew that information deciding if something would be destroyed would be much easier. Since we don't, we'd have to assume the creature we're checking is the first. Anyway, I'm rambling. If anyone has any suggestions or requests while I'm tweaking AIs feel free to add it here.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: AI Work/Combat Prediction
 by Sloth » 04 Feb 2011, 11:52
by Sloth » 04 Feb 2011, 11:52 
I will try write you a function like this Sol. Most of it is done already. It just needs some structure changes.
EDIT: The function is finished. It's the boolean function combatantWouldBeDestroyed(Card combatant, Combat combat) in CombatUtil. To get the actual combat, use AllZone.Combat.
			
		EDIT: The function is finished. It's the boolean function combatantWouldBeDestroyed(Card combatant, Combat combat) in CombatUtil. To get the actual combat, use AllZone.Combat.
- 
				 
 Sloth
- Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: AI Work/Combat Prediction
 by friarsol » 04 Feb 2011, 14:39
by friarsol » 04 Feb 2011, 14:39 
Awesome. I'll check it out so i can finish up Regeneration.Sloth wrote:I will try write you a function like this Sol. Most of it is done already. It just needs some structure changes.
EDIT: The function is finished. It's the boolean function combatantWouldBeDestroyed(Card combatant, Combat combat) in CombatUtil. To get the actual combat, use AllZone.Combat.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: AI Work/Combat Prediction
 by jeffwadsworth » 09 Feb 2011, 02:19
by jeffwadsworth » 09 Feb 2011, 02:19 
I was minding my own business and laying down a typical beatdown when the AI casted a First Volley on my Arc Runner during my main 1 phase!  I cursed Sol under my breath.
			
		- jeffwadsworth
- Super Tester Elite
- Posts: 1172
- Joined: 20 Oct 2010, 04:47
- Location: USA
- Has thanked: 287 times
- Been thanked: 70 times
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: AI Work/Combat Prediction
 by Chris H. » 09 Feb 2011, 03:35
by Chris H. » 09 Feb 2011, 03:35 
`jeffwadsworth wrote:I was minding my own business and laying down a typical beatdown when the AI casted a First Volley on my Arc Runner during my main 1 phase! I cursed Sol under my breath.
In my play testing over the last couple of days I have seen several eye openers like this ... awesome. A sign of things to come.

- 
				 
 Chris H.
- Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: AI Work/Combat Prediction
 by Sloth » 09 Feb 2011, 06:23
by Sloth » 09 Feb 2011, 06:23 
I really appreciate your work to improve the AI, Sol. The AI is really what forge is about.
			
		- 
				 
 Sloth
- Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: AI Work/Combat Prediction
 by friarsol » 09 Feb 2011, 15:01
by friarsol » 09 Feb 2011, 15:01 
I agree. And it's coming along bit by bit. Some of these changes that I'm making affect other parts of the AI which will probably need to be upgraded to handle the new abilities.Sloth wrote:I really appreciate your work to improve the AI, Sol. The AI is really what forge is about.
Example: If the AI has a blocker with regeneration that can be afforded, it should block the creature it would absorb the most damage from (considering trample) but not block a wither or infect creature (that would kill it). We probably would need to keep track of the available mana versus the "planned to be used" mana. So this would work properly.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Good Job
 by mtgrares » 09 Feb 2011, 19:23
by mtgrares » 09 Feb 2011, 19:23 
Great work friarsol.  I will definitely enjoy playing against a smarter Forge.
Truthfully I tried to improve Forge's AI but it is just so hard to pin down to specifics. Also my lack of familiarity with the code didn't help since many things have been changed.
			
		Truthfully I tried to improve Forge's AI but it is just so hard to pin down to specifics. Also my lack of familiarity with the code didn't help since many things have been changed.
- mtgrares
- DEVELOPER
- Posts: 1352
- Joined: 08 Sep 2008, 22:10
- Has thanked: 3 times
- Been thanked: 12 times
Re: AI Work/Combat Prediction
 by Masher8 » 25 Feb 2011, 20:34
by Masher8 » 25 Feb 2011, 20:34 
Seeing as I've made some modifications to the attacking AI this seems as good a place to put this query as any. 
When a creature has a blocking trigger that pumps it (for example Royal Trooper) the function CombatUtil.canDestroyBlocker doesn't take this into account. I guess the same may go for the attacking pump triggers. I've spent quite a bit of time reading the code to try to figure out how to add this but I can't see how this could be achieved.
			
		When a creature has a blocking trigger that pumps it (for example Royal Trooper) the function CombatUtil.canDestroyBlocker doesn't take this into account. I guess the same may go for the attacking pump triggers. I've spent quite a bit of time reading the code to try to figure out how to add this but I can't see how this could be achieved.
- Masher8
- Posts: 18
- Joined: 05 Feb 2011, 13:57
- Has thanked: 0 time
- Been thanked: 0 time
Re: AI Work/Combat Prediction
 by Sloth » 26 Feb 2011, 15:42
by Sloth » 26 Feb 2011, 15:42 
I guess this won't be easy, but I will give it try.Masher8 wrote:Seeing as I've made some modifications to the attacking AI this seems as good a place to put this query as any.
When a creature has a blocking trigger that pumps it (for example Royal Trooper) the function CombatUtil.canDestroyBlocker doesn't take this into account. I guess the same may go for the attacking pump triggers. I've spent quite a bit of time reading the code to try to figure out how to add this but I can't see how this could be achieved.
Some propositions for the attack class:
1. aiAggression is a nice idea. It would be easier to understand your code though, if a high number would indicate a high aggression. It seems to be mixed at the moment (5 is highest and 4 is lowest).
2.You don't need the canCauseDamage variable. Creatures that won't deal damage get filtered out here(at the very top of the class):
- Code: Select all
- attackers = attackers.filter(new CardListFilter()
 {
 public boolean addCard(Card c)
 {
 return (0 < getAttack(c) || c.getName().equals("Guiltfeeder")) && ! valuable.contains(c.getName());
 }
 });
3.If I'm reading it correctly, there should be no ! before isWorthLessThanAllKillers here:
- Code: Select all
- // if the creature cannot block and can kill all opponents they might as well attack, they do nothing staying back
 if(canKillAllDangerous && !CombatUtil.canBlock(attacker) && !isWorthLessThanAllKillers){
 System.out.println(attacker.getName() + " = attacking because they can't block, expecting to kill or damage player");
 return true;
 }
- Code: Select all
- // see if this attacking creature can destroy this defender, if not record that it can't kill everything
 if(!CombatUtil.canDestroyBlocker(defender, attacker)){
 // make exception for walls, they are usually extra tough but not dangerous unless they have
 // high power, so check for walls that can kill but ignore others
 if(!(defender.isWall() && defender.getNetCombatDamage() <= 0)){
 canKillAllDangerous = false; // there is a dangerous creature that can survive an attack from this creature
 }
- 
				 
 Sloth
- Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: AI Work/Combat Prediction
 by Hellfish » 26 Feb 2011, 16:14
by Hellfish » 26 Feb 2011, 16:14 
You may be able to use the AI trigger hooks Sol has been hard at work adding, at least to determine wether or not the AI would want the trigger to occur. Beyond that I'm not sure there is any other recourse than a full-on Min-Max solution.
			So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
		Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
- 
				 
 Hellfish
- Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: AI Work/Combat Prediction
 by Masher8 » 27 Feb 2011, 14:58
by Masher8 » 27 Feb 2011, 14:58 
Yes, having looked at it it seems far from simple, but it is leading to some suicidal attacks and stupid behaviour which is a bit of a shame. I think it'll have to be detected eventually, I don't normally construct decks with this kind of creature but they pop up in sealed and quest.Sloth wrote:I guess this won't be easy, but I will give it try.
Yes, really the idea was to equip the AI with a few different attacking approaches and then look at the context to try to see which is the most suitable, then apply it. It doesn't always work but in the absence of a minimax type approach this kind of hard coding of a set of heuristics seemed the best bet.Sloth wrote:Some propositions for the attack class:
1. aiAggression is a nice idea. It would be easier to understand your code though, if a high number would indicate a high aggression. It seems to be mixed at the moment (5 is highest and 4 is lowest).
Level 4 has ended up being retrofitted from it's original purpose to quite a conservative approach, but at the time I just wanted to get something out that improved things having promised to produce something. I intend to get a lot of it tidied up and modularised into functions so it can potentially be more generally useful as well as tidier.
getNetCombatDamage is something I found while trying to solve problems I was having with Doran Siege Tower.Sloth wrote:2.You don't need the canCauseDamage variable. Creatures that won't deal damage get filtered out here(at the very top of the class):You should update this filter though (your getNetCombatDamage is much better than getAttack).
- Code: Select all
attackers = attackers.filter(new CardListFilter()
{
public boolean addCard(Card c)
{
return (0 < getAttack(c) || c.getName().equals("Guiltfeeder")) && ! valuable.contains(c.getName());
}
});
The canCauseDamage variable was added after a 0/1 bird of paradise was repeatedly attacking in one my test scenarios, so I guess the earlier filtering isn't working as expected in this context or I'm accessing a different collection or something. I'll certainly have another look at this.
I think you're right, this has "late night code revision" written all over it!Sloth wrote:3.If I'm reading it correctly, there should be no ! before isWorthLessThanAllKillers here:
- Code: Select all
// if the creature cannot block and can kill all opponents they might as well attack, they do nothing staying back
if(canKillAllDangerous && !CombatUtil.canBlock(attacker) && !isWorthLessThanAllKillers){
System.out.println(attacker.getName() + " = attacking because they can't block, expecting to kill or damage player");
return true;
}
 
 I'll test it and commit the change if testing checks out.
The wall exception is a result of lots of testing and development being done against decks with no walls, then seeing it's appalling performance against a deck with walls. This is because the general consideration is to compare how much damage each player can potentially cause in their turn which means walls are filtered out of the reckoning at an early stage.Sloth wrote:4. The inner if clause here still doesn't make sense to me. Can you explain what you want to do with it?
- Code: Select all
// see if this attacking creature can destroy this defender, if not record that it can't kill everything
if(!CombatUtil.canDestroyBlocker(defender, attacker)){
// make exception for walls, they are usually extra tough but not dangerous unless they have
// high power, so check for walls that can kill but ignore others
if(!(defender.isWall() && defender.getNetCombatDamage() <= 0)){
canKillAllDangerous = false; // there is a dangerous creature that can survive an attack from this creature
}
If you ignore the wall exception for a moment, this code block records if the attacking creature can kill the defending creature, and if it can't to note it can't kill all the defending creatures. The result of this in a lot of combat scenarios is that creatures won't attack if there doesn't seem to be any point. However if the human has for example a Wall of Ice (and importantly because the whole 'should attack' function assesses one creature at a time) this could lead to a number of creatures hanging back when they're in no real danger and would benefit from attacking as a group as the wall can only block one. This exception checks to see if the defender being examined is a wall with the potential to cause damage (i.e. power more than 0) and is therefore to be counted as "dangerous" or not. It comes down to: if the defender being considered is a wall and it can't cause damage don't include it in calculations to see whether this creature is wasting it's time attacking against high toughness defenders.
It's really just a band aid until I come up with something better. The main goal, to eliminate a stupid AI behaviour in obviously attacking circumstances, is achieved but not ideally or with enough subtlety to guarantee an optimal AI choice in a wide range of circumstances. It still leads to a stupid behaviour, where they attack repeatedly if there are more than enough 0 power walls to block them all, but at least it stops Shield Spheres hanging around forever. Definitely something I plan to revisit.
- Masher8
- Posts: 18
- Joined: 05 Feb 2011, 13:57
- Has thanked: 0 time
- Been thanked: 0 time
Re: AI Work/Combat Prediction
 by Sloth » 27 Feb 2011, 16:16
by Sloth » 27 Feb 2011, 16:16 
Thanks for clearing things up Masher. I'm working on the P/T bonus predictions. They will be integrated into canDestroyBlocker and canDestroyAttacker.
I hope you don't mind me discussing your code openly.
			
		I hope you don't mind me discussing your code openly.
- 
				 
 Sloth
- Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: AI Work/Combat Prediction
 by Masher8 » 27 Feb 2011, 18:19
by Masher8 » 27 Feb 2011, 18:19 
Those would be very useful additions I think if they can be made to work.Sloth wrote:Thanks for clearing things up Masher. I'm working on the P/T bonus predictions. They will be integrated into canDestroyBlocker and canDestroyAttacker.
I hope you don't mind me discussing your code openly.
The discussion is fine by me, code review by another pair of eyes is one of the best ways to improve quality, and on an open source effort getting explanations of difficult sections out there so people know what they're maintaining is important. I'm well aware I'm not cemented as a permanent fixture on the coding team.

- Masher8
- Posts: 18
- Joined: 05 Feb 2011, 13:57
- Has thanked: 0 time
- Been thanked: 0 time
			22 posts
			 • Page 1 of 2 • 1, 2
		
	
Who is online
Users browsing this forum: No registered users and 24 guests
