private static void Recursion(
int player,
List<int> free_dice,
Board board,
List<Move> moves_made,
ref List<Play> plays,
ref List<Play> partial_plays,
ref HashSet<string> board_hash)
{
string hash = board.HashString();
if (board_hash.Contains(hash))
return;
board_hash.Add(hash);
if (free_dice.Count == 0)
{
plays.Add(new Play(moves_made));
return;
}
bool further_moves = false;
if (board.CapturedCount(player) > 0)
{
for (int i = 0; i < free_dice.Count; i++)
{
int free_die = free_dice[i];
int to = 24 - free_die;
Move move = Move.CreateBarMove(to);
if (board.IsLegalMove(player, move, free_die))
{
further_moves = true;
if (board.PointCount(player, to) == -1)
move.AddHitPoint(to);
free_dice.RemoveAt(i);
moves_made.Add(move);
board.MakeMove(player, move);
Recursion(player, free_dice, board, moves_made, ref plays, ref partial_plays, ref board_hash);
board.UndoMove(player, move);
moves_made.RemoveAt(moves_made.Count - 1);
free_dice.Insert(i, free_die);
}
}
// No need to check for further moves here because bar moves are forced and if there aren't any, we can't move at all
if (!further_moves && plays.Count == 0 && moves_made.Count > 0)
{
partial_plays.Add(new Play(moves_made));
}
return;
}
further_moves = false;
for (int slot = 23; slot >= 0; slot--)
{
if (board.PointCount(player, slot) > 0)
{
for (int i = 0; i < free_dice.Count; i++)
{
int free_die = free_dice[i];
int to = slot - free_die;
Move move = (to >= 0) ? new Move(slot, to) : Move.CreateBearoffMove(slot);
if (board.IsLegalMove(player, move, free_die))
{
further_moves = true;
if (!move.IsBearOff && board.PointCount(player, to) == -1)
move.AddHitPoint(to);
free_dice.RemoveAt(i);
moves_made.Add(move);
board.MakeMove(player, move);
Recursion(player, free_dice, board, moves_made, ref plays, ref partial_plays, ref board_hash);
board.UndoMove(player, move);
moves_made.RemoveAt(moves_made.Count - 1);
free_dice.Insert(i, free_die);
}
}
}
}
if (!further_moves && plays.Count == 0 && moves_made.Count > 0)
{
partial_plays.Add(new Play(moves_made));
}
}