// A recursion which finds all possible move sequences, including permutations.
/*private static void Recursion(int player, List<int> free_dice, Board board, List<Move> moves_made, ref List<MoveHint> move_hints)
* {
* if (free_dice.Count == 0 || board.FinishedCount(player) == 15)
* {
* move_hints.Add(new MoveHint(new List<Move>(moves_made)));
* return;
* }
*
* 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))
* {
* if (board.SlotCount(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 move_hints);
*
* board.UndoMove(player, move);
*
* moves_made.RemoveAt(moves_made.Count - 1);
*
* free_dice.Insert(i, free_die);
* }
* }
*
* return;
* }
*
* for (int slot = 23; slot >= 0; slot--)
* {
* if (board.SlotCount(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))
* {
* if (board.SlotCount(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 move_hints);
*
* board.UndoMove(player, move);
*
* moves_made.RemoveAt(moves_made.Count - 1);
*
* free_dice.Insert(i, free_die);
* }
* }
* }
* }
*
* }*/
// A recursion which finds all legal moves, but only adds only one move per different end board position.
// This doesn't always find all bearoff moves, like with D31 on |_ _ _ O _ _|, it'll find 3/off but not 3/2/off. This is because the hash already contains the end position after 3/off.
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));
}
}