Skip to content

Strategy selection techniques

Anderson edited this page Sep 11, 2016 · 9 revisions

##Built-in techniques

StarcraftNash has a few strategy selection techniques already implemented. They are commented below.

  • random_uniform: selects a strategy uniformly at random from the list of available strategies;
  • reply_score: selects the best-response against the last strategy selected by the opponent. It is based on the idea that the player can repeat its last strategy (especially if it is victorious). This method requires a score chart file with victory probabilities of each strategy against each other;
  • reply_history: similar to reply_score, but does not require the score chart file. Instead, it builds strategies' victory probabilities from history of previous matches;
  • rotate: inserts the available strategies in a circular list and selects the next strategy (in first launch, selects the first strategy in the list);
  • unique: a dummy method that always selects a single strategy;
  • frequentist: selects the best-response against opponent's most used strategy. This method requires a score chart file with victory probabilities of each strategy against each other;
  • frequentist_history: similar to frequentist, but does not require the score chart file. Instead, it builds strategies' victory probabilities from history of previous matches;
  • epsilon_greedy: selects a random strategy with probability epsilon and behaves as frequentist with probability 1 - epsilon;
  • nash: selects strategies according to a probability distribution given by the Nash equilibrium in the strategy selection metagame. The probability distribution must be provided in the configuration .xml file.
  • epsilon_nash: behaves as frequentist with probability epsilon and behaves as Nash with probability 1-epsilon.

Note that epsilon has different meanings for epsilon_greedy and epsilon_nash: in epsilon_greedy it controls the probability of exploration whereas in epsilon_nash it controls the probability of exploitation. In command line and configuration files, both "epsilons" have different names.

##Writing your own technique

To add a new custom technique, you will need to follow the next few steps:

  1. Create a new Class on the strategies/ folder;

  2. Inherit from the StrategyBase class;

     from strategy_base import StrategyBase
     from config import Config
     class CoolNewMethod(StrategyBase):
            ...
    
  3. Set a cool name for your method, such as 'cool_new_method' on the self.strategy_name variable;

     self.strategy_name = 'cool_new_method'
    
  4. Implement your own get_next_bot method;

This method must return the name of the bot that will play the next match for you.

The list of available bots is in the attribute self.bot_list.

You have access to the history of previous matches. You can query the choices you and your opponent made, and who won each match. To do this, use the following attributes and methods (they belong to StrategyBase class):

self.history_length(): returns the number of matches played so far
self.opponent_choice(match_index): Returns the name of opponent choice in the required match
self.my_choice(match_index): Returns the name of your choice in the required match
self.winner_choice(match_index): Returns the name of the choice that won the required match or None if it was a draw
self.match_result(match_index): Returns a code for the result of the required match (DRAW = 0, VICTORY = 1 or DEFEAT = -1). You can use the constants StrategyBase.DRAW, StrategyBase.VICTORY and StrategyBase.DEFEAT for comparison

With these methods you can "traverse" the list of matches doing whathever calculations you want. For example:

Repeat last choice if I won previous match, selects randomly otherwise

# by using -1 I go directly to last (most recent) match
if self.match_result(-1) == StrategyBase.VICTORY: 
    return self.my_choice(-1)
else:
    return random.choice(self.bot_list) # remember to import random!

Repeat my most victorious approach:

scores = {name : 0 for name in self.bot_list} # dict will store strategy names and score
for match in range(self.history_length()):
    my_choice = self.my_choice(match)
    scores[my_choice] += self.match_result(match) # victory adds one, defeat subtracts one

return max(scores, key=scores.get)

You are encouraged to implement more sophisticated strategies! For instance, you can make some calculation on opponent choices too ;)

  1. Import and add the new strategy to the list of allowed strategies on strategy_selector.py using the name previously defined;

     ...
     import cool_new_method #you must import the python module you just wrote
     ...
     
     class StrategySelector:
     
         strategies = {
             'cool_new_method': cool_new_method.CoolNewMethod,   # add your new strategy here
             'nash': nash.Nash,                                  # plays nash equilibrium
             'random_uniform': random_uniform.RandomUniform,     # plays uniformly random
             ...
         }
         ...
    
  2. Test your new strategy!

Clone this wiki locally