// 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)); } }
// 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)); } }