user1703: Added transposition table (this was tested alone and worked as expected), three fold repetition and null move pruning in my engine and wins more games but some of them end with three fold repetition even in win positions, played against the previous version
I keep a table history to save the current state of the board before making the move, to save the current zobrist key, move, en passant and castling
In make null function I just hash the en passant if exists, switch side, hash it and increment the fiftymove counter 
To check for repetitions I do this:
int i;
for (i = 4; i <= board->fiifty_move; i += 2) {
    if (board->zkey == board->history[board->ply - i].zkey) {
        return true;
    }
}

The question is when checking for repetition it will check also for null move positions, is that correct? If a null move is repeated can we take that as a move even that null move it just switching sides?
I've seen engines that has a array like: hist_rep[index++].zkey = curr_zkey; that is only to check for repetitions and the array is not filled in the make null move function
Others engines has a counter inside the repetition function to check if the position has been repeated before more than one time
for (...) {
    if (zkey[i] == curr_zkey) ++rep;
    if (rep == 2) return true;
}

What is the correct way?

user825: No. You shouldn't count null-move in repetitions because:

Null-move is fake
Null-move artificially creates a repetition when there is none

Your implementation is correct, but you might want to exclude null-move. Let's take a look at Stockfish:

https://github.com/official-stockfish/Stockfish/blob/master/src/position.cpp

bool Position::is_draw(int ply) const {

  if (st->rule50 > 99 && (!checkers() || MoveList<LEGAL>(*this).size()))
      return true;

  int end = std::min(st->rule50, st->pliesFromNull);

  if (end < 4)
    return false;

  StateInfo* stp = st->previous->previous;
  int cnt = 0;

  for (int i = 4; i <= end; i += 2)
  {
      stp = stp->previous->previous;

      // At root position ply is 1, so return a draw score if a position
      // repeats once earlier but after or at the root, or repeats twice
      // strictly before the root.
      if (   stp->key == st->key
          && ++cnt + (ply - i > 0) == 2)
          return true;
  }

  return false;
}

You already have st->rule50 in your code (board->fifty-move) but you don't have st->pliesFromNull.
Let's check what Stockfish author said about pilesFromNull.

http://www.talkchess.com/forum/viewtopic.php?start=0&t=35052&topic_view=flat&sid=46a5561bcd0c4d36796c0fbfe5158079

By Joona Kiiski (2010):
They are already excluded, note the use of st->pliesFromNull: 

Null moves can artificially create a repetition 
draw where instead there is no one. 

So use a second counter to reset history after a null move. 

You see, if the strongest engine in the world does it you have no reason for not doing it.
If you check the code carefully, the first time when you do a null-move pliesFromNull is 0.
void Position::do_null_move(StateInfo& newSt) {
    ....
    st->pliesFromNull = 0;
}

later the engine increments the counter in do_move:
++st->pliesFromNull;


1703: <p>Added transposition table (this was tested alone and worked as expected), three fold repetition and null move pruning in my engine and wins more games but some of them end with three fold repetition even in win positions, played against the previous version</p>

<p>I keep a table history to save the current state of the board before making the move, to save the current zobrist key, move, en passant and castling</p>

<p>In make null function I just hash the en passant if exists, switch side, hash it and increment the fiftymove counter </p>

<p>To check for repetitions I do this:</p>

<pre><code>int i;
for (i = 4; i &lt;= board-&gt;fiifty_move; i += 2) {
    if (board-&gt;zkey == board-&gt;history[board-&gt;ply - i].zkey) {
        return true;
    }
}
</code></pre>

<p>The question is when checking for repetition it will check also for null move positions, is that correct? If a null move is repeated can we take that as a move even that null move it just switching sides?</p>

<p>I've seen engines that has a array like: <code>hist_rep[index++].zkey = curr_zkey;</code> that is only to check for repetitions and the array is not filled in the make null move function</p>

<p>Others engines has a counter inside the repetition function to check if the position has been repeated before more than one time</p>

<pre><code>for (...) {
    if (zkey[i] == curr_zkey) ++rep;
    if (rep == 2) return true;
}
</code></pre>

<p>What is the correct way?</p>
 825: <p>No. You <strong>shouldn't</strong> count null-move in repetitions because:</p>

<ul>
<li>Null-move is fake</li>
<li>Null-move artificially creates a repetition when there is none</li>
</ul>

<p>Your implementation is correct, but you might want to exclude null-move. Let's take a look at Stockfish:</p>

<blockquote>
  <p><a href="https://github.com/official-stockfish/Stockfish/blob/master/src/position.cpp" rel="nofollow noreferrer">https://github.com/official-stockfish/Stockfish/blob/master/src/position.cpp</a></p>
</blockquote>

<pre><code>bool Position::is_draw(int ply) const {

  if (st-&gt;rule50 &gt; 99 &amp;&amp; (!checkers() || MoveList&lt;LEGAL&gt;(*this).size()))
      return true;

  int end = std::min(st-&gt;rule50, st-&gt;pliesFromNull);

  if (end &lt; 4)
    return false;

  StateInfo* stp = st-&gt;previous-&gt;previous;
  int cnt = 0;

  for (int i = 4; i &lt;= end; i += 2)
  {
      stp = stp-&gt;previous-&gt;previous;

      // At root position ply is 1, so return a draw score if a position
      // repeats once earlier but after or at the root, or repeats twice
      // strictly before the root.
      if (   stp-&gt;key == st-&gt;key
          &amp;&amp; ++cnt + (ply - i &gt; 0) == 2)
          return true;
  }

  return false;
}
</code></pre>

<p>You already have <code>st-&gt;rule50</code> in your code (<code>board-&gt;fifty-move</code>) but you don't have <code>st-&gt;pliesFromNull</code>.</p>

<p>Let's check what Stockfish author said about <code>pilesFromNull</code>.</p>

<blockquote>
  <p><a href="http://www.talkchess.com/forum/viewtopic.php?start=0&amp;t=35052&amp;topic_view=flat&amp;sid=46a5561bcd0c4d36796c0fbfe5158079" rel="nofollow noreferrer">http://www.talkchess.com/forum/viewtopic.php?start=0&amp;t=35052&amp;topic_view=flat&amp;sid=46a5561bcd0c4d36796c0fbfe5158079</a></p>
</blockquote>

<p>By Joona Kiiski (2010):</p>

<pre><code>They are already excluded, note the use of st-&gt;pliesFromNull: 

Null moves can artificially create a repetition 
draw where instead there is no one. 

So use a second counter to reset history after a null move. 
</code></pre>

<p>You see, if the strongest engine in the world does it you have no reason for not doing it.</p>

<p>If you check the code carefully, the first time when you do a null-move <code>pliesFromNull</code> is 0.</p>

<pre><code>void Position::do_null_move(StateInfo&amp; newSt) {
    ....
    st-&gt;pliesFromNull = 0;
}
</code></pre>

<p>later the engine increments the counter in <code>do_move</code>:</p>

<pre><code>++st-&gt;pliesFromNull;
</code></pre>
