protected abstract List <Vector2i> GetMovesOccupied(GamePiece gamePiece, Vector2i from);
protected abstract bool IsMoveAllowed(GamePiece gamePiece, Vector2i from, Vector2i to);
public Grid(IEnumerable <GamePiece> tiles, Vector2u gridSize, Vector2f scale, uint gridLayers = 1, DragManager mouseManager = null, int dragLayer = -1, int dropLayer = -1, Vector2f dropScale = default, Vector2u cellSize = default) { if (dropScale == default) { dropScale = scale; } window = mouseManager.Window; if (tiles == null) { this.tiles = new List <GamePiece>(); } else { this.tiles = tiles.ToList(); } this.mapSize = gridSize; this.scale = scale; mapLayers = gridLayers; map = new int[gridSize.X, gridSize.Y, gridLayers]; if (cellSize == default) { tileSize = this.tiles[0].TextureRect.GetSize().ToVector2f(); } else { tileSize = (Vector2f)cellSize; } // apply scale to tiles for (var i = 0; i < this.tiles.Count; i++) { this.tiles[i].Scale = scale; } size = new Vector2f(gridSize.X * tileSize.X, gridSize.Y * tileSize.Y); scaledSize = new Vector2f(Size.X * scale.X, Size.Y * scale.Y); scaledTileSize = new Vector2f(tileSize.X * scale.X, tileSize.Y * scale.Y); // init map for (var z = 0; z < mapLayers; z++) { for (var y = 0; y < mapSize.Y; y++) { for (var x = 0; x < mapSize.X; x++) { map[x, y, z] = -1; } } } // mouse if (mouseManager != null) { if (dragLayer != -1) { GamePiece picked = null; int pickedIndex = -1; Action <Sprite> dropHandled = null; Vector2f dragOffset = default; Vector2i pickCoords = default; mouseManager.DragStart += (object sender, DragEventArgs e) => { if (Enabled) { if (e.Button == Mouse.Button.Left && e.DragStart.X >= Rect.Left && e.DragStart.Y >= Rect.Top && e.DragStart.X < Rect.Left + Rect.Width && e.DragStart.Y < Rect.Top + Rect.Height) { picked = SpritePicker(e.DragStart, dragLayer, out pickCoords); if (picked != null) { moves = GetMoves(picked, pickCoords); movesOccupied = GetMovesOccupied(picked, pickCoords); Debug.WriteLine($"[Grid] Picked {pickCoords.X},{pickCoords.Y}"); pickedIndex = map[pickCoords.X, pickCoords.Y, dragLayer]; dropHandled = sprite => { //map[pickCoords.X, pickCoords.Y, dragLayer] = -1; }; picked.Color = new Color(255, 255, 255, 0); draggingSprite = new GamePiece(picked); draggingSprite.Color = new Color(255, 255, 255, 200); dragOffset = (e.DragStart.ToVector2f() - draggingSprite.Position) * -1; // empty origial area var subgridSize = getSubGridSizeOfTile(picked); for (var y = 0; y < subgridSize.Y; y++) { for (var x = 0; x < subgridSize.X; x++) { map[pickCoords.X + x, pickCoords.Y + y, dragLayer] = -1; } } } } } }; mouseManager.Dragging += (object sender, DragEventArgs e) => { if (Enabled && draggingSprite != null) { var dp = e.DragCurrent.ToVector2f(); draggingSprite.Position = dp + dragOffset; } }; mouseManager.DragEnd += (object sender, DragEventArgs e) => { if (Enabled) { if (picked != null) { picked.Color = new Color(255, 255, 255, 255); picked = null; moves = null; movesOccupied = null; } if (draggingSprite != null) { if (!mouseManager.Drop(this, draggingSprite, dropHandled, e)) { // if the drop was unhandled, restore the item to its original location var subgridSize = getSubGridSizeOfTile(draggingSprite); if (subgridSize.X > 1 || subgridSize.Y > 1) { for (var y = 0; y < subgridSize.Y; y++) { for (var x = 0; x < subgridSize.X; x++) { map[pickCoords.X + x, pickCoords.Y + y, dropLayer] = pickedIndex - int.MinValue; } } } map[pickCoords.X, pickCoords.Y, dropLayer] = pickedIndex; } draggingSprite = null; } } }; } if (dropLayer != -1) { mouseManager.Dropped += (object sender, DropEventArgs e) => { if (Enabled) { if (e.DragStop.X >= Rect.Left && e.DragStop.Y >= Rect.Top && e.DragStop.X < Rect.Left + Rect.Width && e.DragStop.Y < Rect.Top + Rect.Height) { var p = e.Sprite.GetGlobalBounds().GetCenter().ToVector2i() + new Vector2i(0, 32); // move the drop point down so it is centered on the base of the chess piece //var p = (Vector2i)(e.Sprite.Position + (cellSize.ToVector2f() / 2.0f)); var tpi = ScreenToGridCoordinates(p); Debug.WriteLine($"[Grid] Dropped {tpi.X},{tpi.Y}"); var subgridSize = getSubGridSizeOfTile(e.Sprite); if (tpi.X >= 0 && tpi.X + (subgridSize.X - 1) < mapSize.X && tpi.Y >= 0 && tpi.Y + (subgridSize.Y - 1) < mapSize.Y) { var obstacleFound = false; /* * for (var y=tpi.Y; y<tpi.Y+subgridSize.Y; y++){ * for (var x=tpi.X; x<tpi.X+subgridSize.X; x++){ * if (map[x, y, dropLayer] != -1){ * obstacleFound=true; * break; * } * } * } */ // check if move is valid according to board state if (!obstacleFound) { obstacleFound = !IsMoveAllowed(e.Sprite, ScreenToGridCoordinates(e.DragStart), tpi); } //var index = map[tpi.X, tpi.Y, dropLayer]; //if (index == -1) if (!obstacleFound) { e.Sprite.Color = new Color(255, 255, 255, 255); if (!this.tiles.Contains(e.Sprite)) { this.tiles.Add(e.Sprite); } var tileIndex = this.tiles.IndexOf(e.Sprite); // if this item is larger than 1x1 fill the other grid cells with "shadow" indeces // so that items will not be able to overlap if (subgridSize.X > 1 || subgridSize.Y > 1) { for (var y = 0; y < subgridSize.Y; y++) { for (var x = 0; x < subgridSize.X; x++) { map[tpi.X + x, tpi.Y + y, dropLayer] = tileIndex - int.MinValue; } } } map[tpi.X, tpi.Y, dropLayer] = tileIndex; e.Sprite.Scale = dropScale; if (e.OnHandled != null) { e.OnHandled.Invoke(e.Sprite); e.Handled = true; OnMoved(); } } } } } }; } } moveMarker = new CircleShape(13); moveMarker.OutlineThickness = 1; moveMarker.FillColor = new Color(0, 0, 0, 64); moveMarker.OutlineColor = new Color(0, 0, 0, 32); moveMarker.Origin = moveMarker.GetGlobalBounds().GetCenter(); moveMarkerOccupied = new CircleShape(24); moveMarkerOccupied.FillColor = new Color(0, 0, 0, 0); moveMarkerOccupied.OutlineThickness = 6; moveMarkerOccupied.OutlineColor = new Color(0, 0, 0, 64); moveMarkerOccupied.Origin = moveMarkerOccupied.GetGlobalBounds().GetCenter(); }
protected override void OnMoved() { updateBoardFromGameState(); //Debug.WriteLine(chessGame.Pos.GenerateFen().ToString()); if (chessBoard.CurrentPlayer == Player.Black) { if (aiThinkingTask == null || aiThinkingTask.IsCompleted) { aiThinking = true; aiThinkingTask = Task.Run(async() => { try { var ai = new GameAI(); var best = ai.Search(chessBoard); var move = best; aiThinking = false; var fromIndex = move.from.ToInt(); var fromX = move.from.x; //fromIndex % 8; var fromY = move.from.y; // 7 - (fromIndex / 8); var tileIndex = map[fromX, fromY, 0]; var sprite = tiles[tileIndex]; var toIndex = move.to.ToInt(); var toX = move.to.x; //toIndex % 8; var toY = move.to.y; //7 - (toIndex / 8); var tile2Index = map[toX, toY, 0]; GamePiece pieceBeingTaken = null; if (tile2Index != -1) { pieceBeingTaken = tiles[tile2Index]; pieceBeingTaken.beingTaken = true; } var tilePosition = new Vector2f(toX * tileSize.X * scale.X, toY * tileSize.Y * scale.Y); var tileOffset = (ScaledTileSize - sprite.GetGlobalBounds().GetSize()) / 2.0f; tileOffset.Y -= 24; await sprite.MoveAsync(Position + tilePosition + tileOffset); chessBoard.Move(move); updateBoardFromGameState(); sprite.moveFinished = true; if (pieceBeingTaken != null) { pieceBeingTaken.beingTaken = false; } updateGameText(); //Debug.WriteLine(chessGame.Pos.GenerateFen().ToString()); } catch (Exception ex) { Debugger.Break(); } }); } } }