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
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
#include <cassert>
#include <vector>
#include "NimGame.h"

NimGame::NimGame(unsigned int number_of_heaps_, unsigned int maxtake_) :
      number_of_heaps(number_of_heaps_), maxtake(maxtake_),
      /* make heap_size a vector of number_of_heaps elements */
      heap_size(number_of_heaps_),
      next_player(PLAYER1)
{
}

unsigned int NimGame::get_number_of_heaps() const {
   return number_of_heaps;
}

void NimGame::set_heap_size(unsigned int index, unsigned int size) {
   assert(index < number_of_heaps);
   heap_size[index] = size;
}

unsigned int NimGame::get_heap_size(unsigned int index) const {
   assert(index<get_number_of_heaps());

   return heap_size[index];
}

bool NimGame::finished() const {
    for (unsigned int i=0; i<get_number_of_heaps(); ++i) {
        if (get_heap_size(i)!=0) {
            return false;
        }
    }
    return true;
}

NimGame::Player NimGame::winner() const {
    assert(finished());

    return (next_player==PLAYER1) ? PLAYER2
                                  : PLAYER1;
}

NimGame::Player NimGame::get_next_player() const {
    return next_player;
}

bool NimGame::valid_move(NimMove move) const {
    if (move.get_heap()>=get_number_of_heaps()) {
        return false;
    }
    if (move.get_count()>maxtake && maxtake!=0) {
        return false;
    }
    if (move.get_count()>get_heap_size(move.get_heap())) {
        return false;
    }
    if (move.get_count()==0) {
        return false;
    }
    return true;
}

void NimGame::execute_move(NimMove move) {
    assert(!finished());
    assert(valid_move(move));


    set_heap_size(move.get_heap(), get_heap_size(move.get_heap())-move.get_count());
    next_player = (next_player==PLAYER1) ? PLAYER2
                                         : PLAYER1;
}

unsigned int NimGame::nim_value() const {
    unsigned int res = 0;

    for (unsigned int index=0; index<get_number_of_heaps(); ++index) {
        res ^= (maxtake!=0) ? get_heap_size(index) % (maxtake+1)
                            : get_heap_size(index);
    }
    return res;
}