protected override bool TryPlacePiece(BoardState board, PieceDefinition piece, out PieceBitmap resultBitmap, out int resultX, out int resultY) { _evaluator.BeginEvaluation(board); resultBitmap = null; resultX = -1; resultY = -1; int bestScore = int.MinValue; //Exhaustively place it and make new child nodes for (var index = 0; index < piece.PossibleOrientations.Length; index++) { var bitmap = piece.PossibleOrientations[index]; var searchWidth = BoardState.Width - bitmap.Width + 1; var searchHeight = BoardState.Height - bitmap.Height + 1; //TODO? If this is the first piece, remove mirrors/rotations from the children //if (isFirstPiece) //{ // //TODO: This doesn't stop diagonal mirrors // searchWidth = (BoardState.Width - bitmap.Width) / 2 + 1; // searchHeight = (BoardState.Height - bitmap.Height) / 2 + 1; //} for (int x = 0; x < searchWidth; x++) { for (int y = 0; y < searchHeight; y++) { if (board.CanPlace(bitmap, x, y)) { var clone = board; clone.Place(bitmap, x, y); var score = _evaluator.Evaluate(in clone, x, x + bitmap.Width, y, y + bitmap.Height); if (score > bestScore) { resultBitmap = bitmap; resultX = x; resultY = y; bestScore = score; } } } } } return(resultBitmap != null); }
private void ExpandByPlacing(SearchNode root) { // This code mostly taken from WeightedTreeSearchPreplacer _expandPlacingUtility.Clear(); var piece = root.State.PieceToPlace; var isFirstPiece = root.State.PlayerBoardState[root.State.ActivePlayer].IsEmpty; var board = root.State.PlayerBoardState[root.State.PieceToPlacePlayer]; var children = root.Children; BoardEvaluator.BeginEvaluation(board); //Exhaustively place it and make new child nodes for (var index = 0; index < piece.PossibleOrientations.Length; index++) { var bitmap = piece.PossibleOrientations[index]; var searchWidth = BoardState.Width - bitmap.Width + 1; var searchHeight = BoardState.Height - bitmap.Height + 1; //If this is the first piece, remove mirrors/rotations from the children if (isFirstPiece) { //TODO: This doesn't stop diagonal mirrors searchWidth = (BoardState.Width - bitmap.Width) / 2 + 1; searchHeight = (BoardState.Height - bitmap.Height) / 2 + 1; } for (int x = 0; x < searchWidth; x++) { for (int y = 0; y < searchHeight; y++) { if (board.CanPlace(bitmap, x, y)) { //evaluate child nodes var copy = board; copy.Place(bitmap, x, y); var utility = BoardEvaluator.Evaluate(in copy, x, x + bitmap.Width, y, y + bitmap.Height); //Insertion sort us in to the children list SearchNode child = null; for (var i = 0; i < children.Count; i++) { //We should be here if (utility > _expandPlacingUtility[i]) { if (children.Count == MaxChildrenPerPiece) { //Children is already full, grab the last one and reuse it child = children[MaxChildrenPerPiece - 1]; children.RemoveAt(MaxChildrenPerPiece - 1); children.Insert(i, child); _expandPlacingUtility.Insert(i, utility); } else { //Not full yet, just insert us here child = NodePool.Value.Get(); children.Insert(i, child); _expandPlacingUtility.Insert(i, utility); } break; } } //Didn't find a place to put us, but children isn't full yet if (child == null && children.Count < MaxChildrenPerPiece) { //Insert us last child = NodePool.Value.Get(); children.Add(child); _expandPlacingUtility.Add(utility); } //Populate the child if (child != null) { child.PlaceBitmap = bitmap; child.PlaceX = x; child.PlaceY = y; } } } } } //Properly apply the placement in the children for (var i = 0; i < children.Count; i++) { var c = children[i]; root.State.CloneTo(c.State); c.State.PerformPlacePiece(c.PlaceBitmap, c.PlaceX, c.PlaceY); c.Parent = root; } }