public void GetAllPlacingAction() { if (turn == BoardBehaviourScript.Turn.AITurn) { if (AIHandCards.Count == 0) { //EndTurn Nothing To Play } else { //Generate All Possible Placing List <List <CardBehaviourScript> > temp = ProducePlacing(AIHandCards, AIMana); for (int i = 0; i < temp.Count; i++) { AIGameState State = new AIGameState(PlayerTableCards, AIHandCards, AITableCards, PlayerHero, AIHero, maxMana, PlayerMana, AIMana, turn, this); //if(temp[i].Count>0) for (int j = 0; j < temp[i].Count; j++) { State.PlaceCard(temp[i][j]); } State.Calculate_State_Score(); ChildsStatus.Add(State); } } } //Debug.Log("DonePlacing"); }
protected override void ThinkAction() { // Retornamos una accion aleatoria. AIGameState gameState = gameController.GetGameState(); List <AIRawSlimeAction> legalActions = gameState.GetLegalActions(); if (legalActions.Count != 0) { thoughtAction = legalActions[(int)((new System.Random()).Next(legalActions.Count))].CopyToRealAction(gameController); } }
void _GetAllAttackingActions() { if (turn == BoardBehaviourScript.Turn.AITurn) { /* * foreach (CardBehaviourScript AICard in AITableCards) * { * if (AICard.canPlay) * { * foreach (CardBehaviourScript PlayerCard in PlayerTableCards) * { * //AICard Attack PlayerCard * AIGameState State = new AIGameState(PlayerTableCards, AIHandCards, AITableCards, PlayerHero, AIHero, maxMana, PlayerMana, AIMana, turn); * State.CardAttackCard(AICard,PlayerCard); * State.Calculate_State_Score(); * ChildsStatus.Add(State); * //Save State * } * } * } */ //Generate All Possible Placing List <List <CardBehaviourScript> > temp = ProduceAllAttackCombinations(AITableCards); foreach (var PlayerCard in PlayerTableCards) { for (int i = 0; i < temp.Count; i++) { AIGameState State = new AIGameState(PlayerTableCards, AIHandCards, AITableCards, PlayerHero, AIHero, maxMana, PlayerMana, AIMana, turn, this); for (int j = 0; j < temp[i].Count; j++) { if (temp[i][j].canPlay) { if (temp[i][j].cardtype == CardBehaviourScript.CardType.Monster) { State.CardAttackCard(temp[i][j], PlayerCard); } else if (temp[i][j].cardtype == CardBehaviourScript.CardType.Magic) { if (temp[i][j].cardeffect == CardBehaviourScript.CardEffect.ToSpecific) { State.CardMagicCard(temp[i][j], PlayerCard); } } } } State.Calculate_State_Score(); ChildsStatus.Add(State); } } } }
void _GetAllAttackingHeroActions() { List <List <CardBehaviourScript> > temp = ProduceAllAttackCombinations(AITableCards); for (int i = 0; i < temp.Count; i++) { AIGameState State = new AIGameState(PlayerTableCards, AIHandCards, AITableCards, PlayerHero, AIHero, maxMana, PlayerMana, AIMana, turn, this); for (int j = 0; j < temp[i].Count; j++) { if (temp[i][j].canPlay) { State.CardAttackHero(temp[i][j], PlayerHero); } } State.Calculate_State_Score(); ChildsStatus.Add(State); } }
public AIGameState( //List<CardBehaviourScript> PlayerHand, List <CardBehaviourScript> PlayerTable, List <CardBehaviourScript> AIHand, List <CardBehaviourScript> AITable, HeroBehaviourScript _PlayerHero, HeroBehaviourScript _AIHero, int _MaxMana, int _PlayerMana, int _AIMana, BoardBehaviourScript.Turn _Turn, AIGameState Parent ) { ParentState = Parent; if (ParentState == null) { Index = 0; } else { Index = ParentState.Index + 1; Actions = new Queue <Action>(ParentState.Actions); } //PlayerHandCards = CardListCopier.DeepCopy(PlayerHand); PlayerTableCards = CardListCopier.DeepCopy(PlayerTable); PlayerHero = _PlayerHero.Clone() as HeroBehaviourScript; AIHandCards = CardListCopier.DeepCopy(AIHand); AITableCards = CardListCopier.DeepCopy(AITable); AIHero = _AIHero.Clone() as HeroBehaviourScript; maxMana = _MaxMana; PlayerMana = _PlayerMana; AIMana = _AIMana; turn = _Turn; Calculate_State_Score(); //if (Index <= BoardBehaviourScript.instance.AILEVEL) //{ // GetAllPlacingAction(); // GetAllAttackingActions(); //} AllStates.Add(this); }
public AIGameState GetSuccessor(AIRawSlimeAction action) { AIGameState succ = GetCopy(); int actionSlimeId = action.GetMainSlimeId(); // Aplicamos la accion al sucesor. switch (action.GetAction()) { case ActionType.ATTACK: succ.Attack(actionSlimeId, action.GetTargetSlimeId()); break; case ActionType.CONQUER: succ.Conquer(actionSlimeId, action.GetTileVector()); break; case ActionType.SPLIT: succ.Split(actionSlimeId, action.GetTileVector()); break; case ActionType.MOVE: succ.Move(actionSlimeId, action.GetTileVector()); break; case ActionType.FUSION: succ.Fusion(actionSlimeId, action.GetTargetSlimeId()); break; case ActionType.EAT: succ.Eat(actionSlimeId); break; } succ.UpdatePlayers(); return(succ); }
void AIGetPlacing() { AIGameState InitialState = new AIGameState(/*MyHandCards,*/ MyTableCards, AIHandCards, AITableCards, MyHero, AIHero, maxMana, MyMana, AIMana, turn, null); InitialState.GetAllPlacingAction(); //Find Best Score float MaxScore = float.MinValue; AIGameState BestState = new AIGameState(); foreach (AIGameState item in AIGameState.AllStates) { if (item.State_Score > MaxScore) { MaxScore = item.State_Score; BestState = item; } } int count = BestState.Actions.Count; //GetActions for (int i = 0; i < count; i++) { AIGameState.Action a; a = BestState.Actions.Dequeue(); if (a.OpCode == 0) { foreach (var item in AIHandCards) { if (item.GetComponent <CardBehaviourScript>()._name == a.Card1) { PlaceCard(item.GetComponent <CardBehaviourScript>()); break; } } } } AIGameState.AllStates.Clear(); }
// Aplica algoritmo minmax con poda alpha beta para calcular la mejor accion. protected AIRawSlimeAction GetActionWithAlphaBeta(AIGameState state) { playerId = state.GetCurrentPlayer().GetId(); turn = state.GetCurrentTurn(); float playerSlimes = state.GetCurrentPlayer().GetSlimes().Count; //depth = (int)Mathf.Max(minDepth, maxDepth-Mathf.Floor(playerSlimes/depthSlimeFactor)); // Normalmente trabajaremos con profundidad 2. Si en cualquiera de estos dos pasos de profundidad hay que analizar mas de 3 slimes, // solamente bajaremos 1 grado de profundidad (sino demasiado coste). if (playerSlimes > 2 || (state.GetRemainingActions() <= 1 && state.GetNextPlayer().GetSlimes().Count > 3)) { depth = 2; } /*if(playerSlimes > 3 || * (state.GetRemainingActions() <= 1 && state.GetNextPlayer().GetSlimes().Count > 4)) depth = 2;*/ //Debug.Log("DEPTH: " + depth); return(GetMaxValueAction(state, 0, double.MinValue, double.MaxValue).Key); }
void AIGetAttacks() { AIState InitialState = AIStateCalculator.AddComponent <AIState>(); InitialState.NewState2(MyTableCards, AIHandCards, AITableCards, Player, AIplayer, maxMana, MyMana, AIMana, turn, null); InitialState.GetAllAttackingActions(AILEVEL); //Find Best Score float MaxScore = float.MinValue; AIGameState BestState = new AIGameState(); foreach (AIGameState item in AIGameState.AllStates) { if (item.State_Score > MaxScore) { MaxScore = item.State_Score; BestState = item; } } //Debug.Log("Best choice Index" + BestState.Index); int count = BestState.Actions.Count; //GetActions for (int i = 0; i < count; i++) { AIGameState.Action a; a = BestState.Actions.Dequeue(); if (a.OpCode == 1) { foreach (var item in AITableCards)//Find Card1 { if (item.GetComponent <CardDisplay>().card.name == a.Card1) { currentCard = item; break; } } foreach (var item in MyTableCards)//Find Card2 { if (item.GetComponent <CardDisplay>().card.name == a.Card2) { targetCard = item; break; } } if (currentCard != null && targetCard != null)//MakeAction { currentCard.GetComponent <CardDisplay>().card.AttackCard(currentCard.GetComponent <CardDisplay>().card, targetCard.GetComponent <CardDisplay>().card, true, delegate { currentCard.GetComponent <CardDisplay>().card.canPlay = false; }); } } else if (a.OpCode == 2) { foreach (var item in AITableCards)//Find Card1 { if (item.GetComponent <CardDisplay>().card.name == a.Card1) { currentCard = item; break; } } if (a.Hero == "MyHero") { //targetHero = MyHero; } if (currentCard != null && targetHero != null) { //currentCard.AttackHero(currentCard, MyHero, true, delegate //{ //currentCard.canPlay = false; //}); } } else if (a.OpCode == 3) { foreach (var item in AITableCards)//Find Card1 { if (item.GetComponent <CardDisplay>().card.name == a.Card1) { currentCard = item; break; } } foreach (var item in MyTableCards)//Find Card2 { if (item.GetComponent <CardDisplay>().card.name == a.Card2) { targetCard = item; break; } } if (currentCard != null && targetCard != null)//MakeAction { currentCard.GetComponent <CardDisplay>().card.AddToMonster(currentCard.GetComponent <CardDisplay>().card, targetCard.GetComponent <CardDisplay>().card, true, delegate { currentCard.GetComponent <CardDisplay>().Destroy(currentCard.GetComponent <CardDisplay>().card); }); } } } //AIGameState.AllStates=new List< AIGameState > (); }
protected override double GetStateEvaluation(AIGameState state) { double score = 1000; RawPlayer winner = state.IsGameEndedAndWinner(); if (winner != null && winner.GetId() == playerId) { score += 10000; // if it wins } else if (winner != null || state.GetPlayerById(playerId) == null) { score -= 10000; // if it loses } else { RawPlayer player = state.GetPlayerById(playerId); int plConquered = player.GetConqueredTiles().Count; int plSlimes = player.GetSlimes().Count; double totalPlayerMass = 0; int playerSlimesSplitable = 0; foreach (RawSlime sl in player.GetSlimes()) { totalPlayerMass += sl.GetMass(); if (sl.canSplit) { playerSlimesSplitable++; } } // INFO sobre los ENEMIGOS List <RawPlayer> enemies = state.GetPlayers().FindAll(p => true); enemies.Remove(player); int enemiesSlimes = 0; float totalEnemiesMass = 0; int enemiesThatCanAttackMe = 0; float minimumMass = Int16.MaxValue; foreach (RawPlayer enemy in enemies) { foreach (RawSlime sl in enemy.GetSlimes()) { enemiesSlimes++; totalEnemiesMass += sl.GetMass(); enemiesThatCanAttackMe += state.GetSlimesInAttackRange(sl).FindAll(r => r.GetPlayer().GetId() == player.GetId()).Count; minimumMass = Mathf.Min(sl.GetMass(), minimumMass); } } score += plConquered * 12; score += plSlimes * 10; score += playerSlimesSplitable * 5; score -= 200 * (enemies.Count); // Cuanto menos jugadores, mejor. score -= totalEnemiesMass; // Predileccio per atacar score -= enemiesSlimes * 100; // slime morta score -= enemiesThatCanAttackMe * 2; // Com menys enemics puguin atacarme, millor score -= minimumMass * 5; // Predileccio per atacar al que esta mes fluix } return(score * GetAIError()); }
protected override double GetStateEvaluation(AIGameState state) { return(0); }
protected override double GetStateEvaluation(AIGameState state) { double score = 1000; RawPlayer winner = state.IsGameEndedAndWinner(); if (winner != null && winner.GetId() == playerId) { score += 10000; // if it wins } else if (winner != null || state.GetPlayerById(playerId) == null) { score -= 10000; // if it loses } else { RawPlayer player = state.GetPlayerById(playerId); // INFO sobre el JUGADOR int playerSlimes = player.GetSlimes().Count; double totalPlayerMass = 0; int playerSlimesSplitable = 0; int playersOverConquered = 0; foreach (RawSlime sl in player.GetSlimes()) { totalPlayerMass += sl.GetMass(); if (sl.canSplit) { playerSlimesSplitable++; } if (player.GetConqueredTiles().Contains(sl.GetActualTile())) { playersOverConquered++; } } // INFO sobre los ENEMIGOS List <RawPlayer> enemies = state.GetPlayers().FindAll(p => true); enemies.Remove(player); int enemiesSlimes = 0; float totalEnemiesMass = 0; int enemiesThatCanAttackMe = 0; float minimumMass = Int16.MaxValue; foreach (RawPlayer enemy in enemies) { foreach (RawSlime sl in enemy.GetSlimes()) { enemiesSlimes++; totalEnemiesMass += sl.GetMass(); enemiesThatCanAttackMe += state.GetSlimesInAttackRange(sl).FindAll(r => r.GetPlayer().GetId() == player.GetId()).Count; minimumMass = Mathf.Min(sl.GetMass(), minimumMass); } } score += playerSlimes * 100; score += 4 * totalPlayerMass * GetAIError(); score += playerSlimesSplitable * 40 * GetAIError(); score += playersOverConquered * 40 * GetAIError(); score -= 200 * (enemies.Count); // Cuanto menos jugadores, mejor. score -= 10 * enemiesSlimes; score -= 2 * totalEnemiesMass; score -= enemiesThatCanAttackMe * 3; score -= minimumMass; } Debug.Log(score); return(score * GetAIError()); }
public AIGameState( //List<GameObject> PlayerHand, List <GameObject> PlayerTable, List <GameObject> AIHand, List <GameObject> AITable, HeroBehaviourScript _PlayerHero, HeroBehaviourScript _AIHero, int _MaxMana, int _PlayerMana, int _AIMana, BoardBehaviourScript.Turn _Turn, AIGameState Parent ) { ParentState = Parent; if (ParentState == null) { Index = 0; } else { Index = ParentState.Index + 1; Actions = new Queue <Action>(ParentState.Actions); } //List<CardBehaviourScript> _tempPlayerHand = new List<CardBehaviourScript>(); //foreach (var item in PlayerHand)_tempPlayerHand.Add( item.GetComponent<CardBehaviourScript>()); //PlayerHandCards = CardListCopier<List<CardBehaviourScript>>.DeepCopy(_tempPlayerHand); List <CardBehaviourScript> _tempPlayerTable = new List <CardBehaviourScript>(); foreach (var item in PlayerTable) { _tempPlayerTable.Add(item.GetComponent <CardBehaviourScript>()); } PlayerTableCards = CardListCopier.DeepCopy(_tempPlayerTable); PlayerHero = _PlayerHero.Clone() as HeroBehaviourScript; List <CardBehaviourScript> _tempAIHand = new List <CardBehaviourScript>(); foreach (var item in AIHand) { _tempAIHand.Add(item.GetComponent <CardBehaviourScript>()); } AIHandCards = CardListCopier.DeepCopy(_tempAIHand); List <CardBehaviourScript> _tempAITable = new List <CardBehaviourScript>(); foreach (var item in AITable) { _tempAITable.Add(item.GetComponent <CardBehaviourScript>()); } AITableCards = CardListCopier.DeepCopy(_tempAITable); AIHero = _AIHero.Clone() as HeroBehaviourScript; maxMana = _MaxMana; PlayerMana = _PlayerMana; AIMana = _AIMana; turn = _Turn; Calculate_State_Score(); //if (Index<=BoardBehaviourScript.instance.AILEVEL) //{ // GetAllPlacingAction(); // GetAllAttackingActions(); //} AllStates.Add(this); }
protected override double GetStateEvaluation(AIGameState state) { /* * CONTRINCANTES: * - Cuanto más masa, peor * - Cuanto menos slimes, mejor (me atacaran menos) * - Cuanto menos me puedan atacar, mejor * YO: * - Cuanto más masa, mejor * - Cuanto más slimes * - Cuanto más cerca de una slime enemiga con menos masa, mejor * CONQUERIR??? */ //bool hasRange = false; double score = 1000; RawPlayer winner = state.IsGameEndedAndWinner(); if (winner != null && winner.GetId() == playerId) { score += 10000; // if it wins } else if (winner != null || state.GetPlayerById(playerId) == null) { score -= 10000; // if it loses } else { RawPlayer player = state.GetPlayerById(playerId); // Contrincantes List <RawPlayer> enemies = state.GetPlayers().FindAll(p => true); enemies.Remove(player); // INFO sobre el JUGADOR int playerSlimes = player.GetSlimes().Count; double totalPlayerMass = 0; int distanceToEnemy = Int16.MaxValue; foreach (RawSlime sl in player.GetSlimes()) { totalPlayerMass += sl.GetMass(); distanceToEnemy = Mathf.Min(distanceToEnemy, state.GetDistanceToCloserEnemy(sl)); } // INFO sobre los ENEMIGOS int enemiesSlimes = 0; float totalEnemiesMass = 0; int enemiesThatCanAttackMe = 0; float minimumMass = Int16.MaxValue; foreach (RawPlayer enemy in enemies) { foreach (RawSlime sl in enemy.GetSlimes()) { enemiesSlimes++; totalEnemiesMass += sl.GetMass(); enemiesThatCanAttackMe += state.GetSlimesInAttackRange(sl).FindAll(r => r.GetPlayer().GetId() == player.GetId()).Count; minimumMass = Mathf.Min(sl.GetMass(), minimumMass); } } //Debug.Log("TOTAL AI MASS: " + totalPlayerMass); score += totalPlayerMass; // Ens interessa tenir molta massa. score += playerSlimes * 5; // Si pot dividirse per arribar al objectiu, ho fara score -= totalEnemiesMass * 10; // Predileccio per atacar score -= enemiesSlimes * 100; // slime morta score -= distanceToEnemy; // Com menys distancia millor score -= enemiesThatCanAttackMe * 2; // Com menys enemics puguin atacarme, millor score -= minimumMass * 5; // Predileccio per atacar al que esta mes fluix score -= enemies.Count * 200; // Predileccio per acabar amb un jugador. } return(score * GetAIError()); }
private KeyValuePair <AIRawSlimeAction, double> GetMaxValueAction(AIGameState state, int depth, double alpha, double beta) { counter++; /*Si nos pasamos de profundidad o el fantasma no puede hacer ninguna acción, estamos ante una hoja y devolvemos * la puntuación del estado actual y ninguna acción, obviamente.*/ List <AIRawSlimeAction> legalActions = state.GetLegalActions(depth > 0); if (depth >= this.depth || legalActions.Count <= 0) { return(new KeyValuePair <AIRawSlimeAction, double>(null, GetStateEvaluation(state))); } //Debug.Log("MAXING: " + legalActions.Count + "actions (DEPTH=" + depth + ")"); AIRawSlimeAction bestAction = null; double bestValue = double.MinValue; foreach (AIRawSlimeAction action in legalActions) { AIGameState successor = state.GetSuccessor(action); int succDepth = depth + 1;//successor.GetCurrentTurn() - turn; double succValue; // Si aun es el turno del jugador de la IA, maximizamos, sino minimizamos. if (successor.IsGameEndedAndWinner() != null) { succValue = GetStateEvaluation(successor); } else if (playerId == successor.GetCurrentPlayer().GetId()) { succValue = GetMaxValueAction(successor, succDepth, alpha, beta).Value; } else { succValue = GetMinValueAction(successor, succDepth, alpha, beta).Value; } // Actualizamos el maximo si el actual es mayor. if (succValue > bestValue) { bestValue = succValue; bestAction = action; } // Si es valor mayor que beta (minimo actual del minValue), no hace falta seguir if (bestValue > beta) { return(new KeyValuePair <AIRawSlimeAction, double>(bestAction, bestValue)); } // Actualizamos el mejor valor del maxValue if (bestValue > alpha) { alpha = bestValue; } //if(depth == 0) Debug.Log("[MAX] " + succValue + "-" + action); } //if(depth == 0) Debug.Log("[MAX] CHOSEN: " + bestValue + "-" + bestAction); return(new KeyValuePair <AIRawSlimeAction, double>(bestAction, bestValue)); }
abstract protected double GetStateEvaluation(AIGameState state);