1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
#ifndef OPTIMAL_NIM_PLAYER_HPP
#define OPTIMAL_NIM_PLAYER_HPP

#include <iostream>
#include <string>
#include "NimMove.hpp"
#include "NimMoveSelector.hpp"

template<typename Game>
struct OptimalNimPlayer {
   NimMove get_move(const Game& game) const {
      unsigned int number_of_heaps = game.get_number_of_heaps();
      NimMoveSelector selector;
      if (game.nim_value() == 0) {
     // bad luck
     for (unsigned int i = 0; i < number_of_heaps; ++i) {
        unsigned int max = game.get_heap_size(i);
        for (unsigned int count: game.moves) {
           if (count > max) break;
           selector.add(NimMove(i, count));
        }
     }
      } else {
     // find winning moves
     for (unsigned int i = 0; i < number_of_heaps; ++i) {
        unsigned int max = game.get_heap_size(i);
        for (unsigned int count: game.moves) {
           if (count > max) break;
           Game test = game;
           NimMove move(i, count);
           test.execute_move(move);
           if (test.nim_value() == 0) {
          selector.add(move);
           }
        }
     }
      }
      // select one of the selected moves by random
      return selector.get();
   }
};

#endif