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) { /* * 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()); }
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()); }
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)); }