|
Post by SALARD on Feb 6, 2019 19:25:53 GMT
Hello anyone know of a proper way to add some AI to the code.
public static class ListExtensions
{
I was thinking to add some extensions on to this like PickBestATK - then do like a if atker atk is greater then defender atk to start off then go from there like comparing health and atk and such?
any thoughts on this? thanks!
|
|
|
Post by Admin on Feb 7, 2019 15:59:47 GMT
Creating an AI for a game like this is not going to be an easy task. You can start by asking yourself how you would make decisions, but I think you'll find that there are enough exceptions to the rule (especially because there is such a wide variety of continually evolving cards) that it can quickly grow in challenge. If it were me, I would try to create a few "simple" scoring methods, where I might score the visible board state as it is now, as well as the board state after playing each card with each of the potential targets. Then you can simply pick the play that gave the best score.
Alternatively, you can keep the AI stupid (players like feeling smarter than the AI anyway), but increase challenge based on the decks that the AI opponent plays with. If the opponent is able to summon high level creatures for low magic costs then it will feel challenging even when it makes "stupid" decisions.
|
|
|
Post by SALARD on Feb 7, 2019 20:47:09 GMT
the score method blows my mind and i am not even sure where i would start with that...gonna have to think that one through quite a bit.
I actually already have a bit of that alternative method - basically 3 levels of difficulty and i have different selections of decks for the different difficulties.
But right now for instance if i have an attack of 3 and another minion an attack of 2 and the minion of 2 attacks the other minion in my game its better to no attack that minion cause he would die...so i need to prevent that from happening - i could do that by just saying if foreach miniondefder if minionatker < miniondefder then skip else addtolistoftargetable - then list.random();
or i can look for the lowest minion defender's attack then attack that if the attacker's attack is still higher...attacking would be easier to construct but when you mix it with playing a certain card to boost attack etc - now we are getting into a level in its own...off to check the google world!
thanks for the scoring idea!
|
|
|
Post by SALARD on Feb 7, 2019 21:03:05 GMT
Here is something quick and easy i made for now - going to stretch it olut to include health or maybe take the lowest health of the defender targets of that list
bool EasyAttack() { var system = container.GetAspect<AttackSystem>(); if (system.validAttackers.Count == 0 || system.validTargets.Count == 0) return false; var attacker = system.validAttackers.Random(); List<Card> targets = new List<Card>();
foreach (var target in system.validTargets) { if ((attacker as ICombatant).attack > (target as ICombatant).attack) targets.Add(target); } Card AITarget; if (targets.Count > 0) { AITarget = targets.Random();
var action = new AttackAction(attacker, AITarget); container.Perform(action); } else (attacker as ICombatant).remainingAttacks--;
return true; }
|
|
|
Post by Admin on Feb 7, 2019 22:08:31 GMT
It's not a bad start, but keep in mind that there are exceptions even to what you've got so far (assuming your CCG also looks like Hearthstone). I wouldn't want to limit the possible attacks, but would want to check every possible attack, potentially even looking multiple plays into the future. Imagine a scenario where I have a weak minion attacking a really strong minion that happened to have low HP. Sure my card would be sacrificed, but the sacrifice would be worth it. Or in the opposite scenario, if I have a minion with high attack and low hp, I wouldn't want to attack a minion with low attack that could finish off my card, but would rather apply that damage to the hero instead.
A solution where you scored the board could do well in both scenarios. Imagine a score as something like (this is very simple and could be far more complex to include minion abilities, number of cards in your hand, etc): (hero.hp + sum(all minions.attack) + sum(all minions.defense)) - (enemy.hp + sum(all enemy minions.attack) + sum(all enemy minions.defense))
In the first scenario where a weak minion attacks and kills a stronger minion with low hp, the board state score would show an increase thanks to the sacrifice of the minion. In the second scenario where a strong minion could attack and kill a weaker minion but would also die, the board state score would decrease, indicating that the move should not be performed.
If you make the AI able to look a few moves into the future, you could potentially sacrifice multiple weak minions to kill a single stronger one. Hope that helps!
|
|
|
Post by legend on Feb 11, 2019 5:56:12 GMT
Very interesting...curios how would you go about makeing the method iterate through the different scenarios though without actually having to actually carry them out.
For instance you have the score which just has the total points of whatever displays on the field...but u need to run through that for every possible attack and card play...and let's say ur creature attacks and kills a enemy minion...how would u make it so that u don't actually attack that minion but the board state of the score would appear different...like a fake portion of the game...or a parallel universe of the game which attacks the minion up can grab the score and then apply to the actual game....brings back memories of quantum leap?
|
|
|
Post by Admin on Feb 11, 2019 14:19:02 GMT
Haha, I suppose programmers are like great wizards in full control of our universe's reality. In practice, you can make a copy or multiple copies of the entire game that is data-only and allow it to play out. This can require a bit of architectural skill - for example, in the data-only copy you don't care about playing animations etc, so that the various possibilities can be determined more quickly. You also have to make sure all your systems are designed properly so that the notifications from copies don't end up applying to the real game by mistake.
This is definitely an advanced-level challenge, so don't take it too lightly. There is nothing wrong with keeping the initial board scoring algorithm as something that could be determined without playing moves in advance - just try very simple logic and balance it with harder AI decks as needed to keep the game fun. Good luck!
|
|