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
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
     100
     101
     102
     103
     104
     105
     106
     107
     108
     109
     110
     111
     112
     113
     114
     115
     116
     117
     118
#include <cassert>
#include <vector>
#include "NimGame.hpp"

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), resigned(false)
{
}

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

// **NEW**
unsigned int
NimGame::get_max_take() const
{
   return maxtake;
}


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
{
    if (resigned) {
        return true;
    }
    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.has_resigned()) {
        return true;
    }
    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));

    if (move.has_resigned()) {
        resignedtrue;
    } else {
        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;
}