Answers.Body: <p>After my initial comment (where I suggest that it might not be enough info) I believe I actually came up with an idea.</p>
  <p>Start with the full set of pokemon. For every possible type, identify the count of pokemon that are strong against that type. For this, you'll end up with a <code>List&lt;(pokemonId, types, List&lt;weakAgainst&gt;)&gt;</code>.</p>
  <p>Minimize <code>List&lt;weakAgainst&gt;.Count()</code> and from the possible set of pokemonIds, select one at random. Without knowing anything else besides type, this pokemon is as good as any other with the same weakness count (this is the point of my original comment).</p>
  <p>From the list of weaknesses that this selected pokemon has, select a pokemon from your list that is strong against the weakness, minimizing the amount of weaknesses again. Likely more than one will match this criteria, again, select one at random.</p>
  <p>Keep repeating this pattern until you obtain the 6 in your team. This is, statistically speaking, one of the best teams that you can gather.</p>
  <p>For all the combinations that you might find here, some teams will have less weaknesses, since we're &quot;randomly&quot; walking down a tree of possibilities. This very much sounds like a <strong>minimax-prunning algorithm</strong>, where each pokemon selection (minimizing your weaknesses) can be met with potential opponents that will maximize your weak points.</p>
  <p>Simplified, put together:</p>
  <pre><code>input: allPokemon: list&lt;pokemonId, weakAgainst, strongAgainst&gt;
  
  var: teamWeakAgainst: []
  var: teamStrongAgainst: []
  var: selectedTeam: []
  
  while (size(selectedTeam) &lt; 6)
    goodMatches &lt;- allPokemon.max(p -&gt; size(p.strongAgainst.intersect(teamWeakAgainst)))
    goodMatches &lt;- goodMatches.min(p -&gt; size(p.weakAgainst))
    goodMatches &lt;- goodMatches.max(p -&gt; size(p.strongAgainst))
  
    selectedPokemon &lt;- goodMatches.random()
  
    teamWeakAgainst -= selectedPokemon.strongAgainst
    teamWeakAgainst += selectedPokemon.weakAgainst # not counting previously selected pokemon because the current one adds another &quot;weakness&quot;, even if it was already accounted for
  
    selectedTeam += selectedPokemon
  
  output: selectedTeam
  </code></pre>
  <p>From this algorithm is it not obvious where the &quot;max&quot; portion is. We're minimizing our losses (weaknesses) but we're considering all possible opponent teams equally, so there is no real maximization of the opponent choices. For a set of ideas, check below.</p>
  <p>Note that this algorithm will give you a set of &quot;teams&quot; that are equally good in the sense that they'll have the same amount of minimized weaknesses and maximized strengths against other possible teams. But even if pokemon are different, the numbers will be the same, just different types.</p>
  <p>For a more complex approach, you might want to consider how prevalent some pokemon are (you might not need to optimize against a super rare mythical type, but rather the very common types available in the game), how likely is it that certain pokemon can have better / faster attacks, what is the probability of battle IVs, how frequent can a trainer switch pokemon in battle, etc. Again, I know this is not what you asked for, but for the sake of the example, this will become so complex that instead of a search algorithm, a simulation (Monte Carlo?) approach might be simpler to build teams out of statistical testing.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-10-09T12:03:49.613Z
Answers.Text: I'm worried that this algorithm is going to generate an unbalanced team. For example, water is the most common type of Pokemon. Electric is only weak to ground. This means that electric Pokemon are always going to have the most amount of strengths and fewest amount of weaknesses. This algorithm then will generate 6 electric types. This needs to be accounted for somehow. Maybe a weight to someone minimize the value of Pokemon that already have a positive matchup?
Answers.UserDisplayName: Tyler Hilbert
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-10-09T18:50:27.693Z
Answers.Text: I see that it will subtract the pokemon from the weak against list so that accounts for the problem of generating 6 of the same type.                                                    So if I'm understanding this correctly it will find a team that will always have more strengths than weaknesses, but it will not have the maximum possible amount of strengths.
Answers.UserDisplayName: Tyler Hilbert
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-10-10T13:27:48.393Z
Answers.Text: Correct, it minimizes weaknesses as first metric and maximizes strengths as secondary metric. If it adds a water pokemon and that makes you weak against electric, it'll likely pick (for example) a rock type next.
Answers.UserDisplayName: Alpha
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-10-08T04:14:24.130Z
Answers.LastActivityDate: 2020-10-08T04:14:24.130Z
Answers.UserDisplayName: Alpha
Body: <p>Pokemon is a game where 2 players each select 6 Pokemon (a team) at the beginning of the game without knowing the other player's team. Every Pokemon has one or two types. Every type is either weak, neutral or strong against every other type. This means that every 2 Pokemon matchup will either have a winner or be a tie. This also means that any team can be ranked against any other team based on the number of winning matchups they have.</p>
  <p>I want to write a program that can find the optimal Pokemon team out of a set of 70 provided Pokemon.
  A team is considered optimal if it has the greatest number of winning matchups against any other team. Basically, I want to calculate which team will have the most amount of favorable matchups if you were to battle it against every other possible team.</p>
  <p>What algorithm would be best for doing this? It is not feasible to compute matchups for every possible team. Can I do some sort of A* search with enough pruning to make it computationally feasible?</p>
  
Tags: <ai-design><game-ai>
Title: How to find the optimal pokemon team
UserDisplayName: Tyler Hilbert
ThreadText: # How to find the optimal pokemon team
  
  (Asked by: username_0 on 2020-10-06)
  
  Pokemon is a game where 2 players each select 6 Pokemon (a team) at the beginning of the game without knowing the other player's team. Every Pokemon has one or two types. Every type is either weak, neutral or strong against every other type. This means that every 2 Pokemon matchup will either have a winner or be a tie. This also means that any team can be ranked against any other team based on the number of winning matchups they have.
  
  I want to write a program that can find the optimal Pokemon team out of a set of 70 provided Pokemon.
  A team is considered optimal if it has the greatest number of winning matchups against any other team. Basically, I want to calculate which team will have the most amount of favorable matchups if you were to battle it against every other possible team.
  
  What algorithm would be best for doing this? It is not feasible to compute matchups for every possible team. Can I do some sort of A\* search with enough pruning to make it computationally feasible?
  
  **Tags:** ai-design, game-ai
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2020-10-08. Score: 1 | Accepted answer
  
  After my initial comment (where I suggest that it might not be enough info) I believe I actually came up with an idea.
  Start with the full set of pokemon. For every possible type, identify the count of pokemon that are strong against that type. For this, you'll end up with a List<(pokemonId, types, List)>.
  Minimize List.Count() and from the possible set of pokemonIds, select one at random. Without knowing anything else besides type, this pokemon is as good as any other with the same weakness count (this is the point of my original comment).
  From the list of weaknesses that this selected pokemon has, select a pokemon from your list that is strong against the weakness, minimizing the amount of weaknesses again. Likely more than one will match this criteria, again, select one at random.
  Keep repeating this pattern until you obtain the 6 in your team. This is, statistically speaking, one of the best teams that you can gather.
  For all the combinations that you might find here, some teams will have less weaknesses, since we're "randomly" walking down a tree of possibilities. This very much sounds like a minimax-prunning algorithm, where each pokemon selection (minimizing your weaknesses) can be met with potential opponents that will maximize your weak points.
  Simplified, put together:
  input: allPokemon: list
  
  var: teamWeakAgainst: []
  var: teamStrongAgainst: []
  var: selectedTeam: []
  
  while (size(selectedTeam) < 6)
    goodMatches <- allPokemon.max(p -> size(p.strongAgainst.intersect(teamWeakAgainst)))
    goodMatches <- goodMatches.min(p -> size(p.weakAgainst))
    goodMatches <- goodMatches.max(p -> size(p.strongAgainst))
  
    selectedPokemon <- goodMatches.random()
  
    teamWeakAgainst -= selectedPokemon.strongAgainst
    teamWeakAgainst += selectedPokemon.weakAgainst # not counting previously selected pokemon because the current one adds another "weakness", even if it was already accounted for
  
    selectedTeam += selectedPokemon
  
  output: selectedTeam
  
  From this algorithm is it not obvious where the "max" portion is. We're minimizing our losses (weaknesses) but we're considering all possible opponent teams equally, so there is no real maximization of the opponent choices. For a set of ideas, check below.
  Note that this algorithm will give you a set of "teams" that are equally good in the sense that they'll have the same amount of minimized weaknesses and maximized strengths against other possible teams. But even if pokemon are different, the numbers will be the same, just different types.
  For a more complex approach, you might want to consider how prevalent some pokemon are (you might not need to optimize against a super rare mythical type, but rather the very common types available in the game), how likely is it that certain pokemon can have better / faster attacks, what is the probability of battle IVs, how frequent can a trainer switch pokemon in battle, etc. Again, I know this is not what you asked for, but for the sake of the example, this will become so complex that instead of a search algorithm, a simulation (Monte Carlo?) approach might be simpler to build teams out of statistical testing.
  
  > **Comments:**
  > **username_0**: I'm worried that this algorithm is going to generate an unbalanced team. For example, water is the most common type of Pokemon. Electric is only weak to ground. This means that electric Pokemon are always going to have the most amount of strengths and fewest amount of weaknesses. This algorithm then will generate 6 electric types. This needs to be accounted for somehow. Maybe a weight to someone minimize the value of Pokemon that already have a positive matchup?  
  > **username_0**: I see that it will subtract the pokemon from the weak against list so that accounts for the problem of generating 6 of the same type.                                                    So if I'm understanding this correctly it will find a team that will always have more strengths than weaknesses, but it will not have the maximum possible amount of strengths.  
  > **username_1**: Correct, it minimizes weaknesses as first metric and maximizes strengths as secondary metric. If it adds a water pokemon and that makes you weak against electric, it'll likely pick (for example) a rock type next.  
  
  ---
  
  