aboutsummaryrefslogtreecommitdiffstatsci
path: root/src/BoardWidget.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/BoardWidget.cs')
-rw-r--r--src/BoardWidget.cs209
1 files changed, 172 insertions, 37 deletions
diff --git a/src/BoardWidget.cs b/src/BoardWidget.cs
index 7188a41..456bfe5 100644
--- a/src/BoardWidget.cs
+++ b/src/BoardWidget.cs
@@ -3,7 +3,9 @@
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
+using System.Collections.Generic;
using System.ComponentModel;
+using System.IO;
using Crow;
using Crow.Drawing;
//using vkvg;
@@ -13,10 +15,13 @@ namespace vkChess
public class BoardWidget : Widget
{
Picture sprites;
+ string filePath;
+ IList<string> moves;
+ string[,] currentBoard;
Piece[,] board;
[DefaultValue(null)]
- public virtual Piece[,] Board {
+ public Piece[,] Board {
get { return board; }
set {
if (board == value) {
@@ -28,15 +33,84 @@ namespace vkChess
RegisterForGraphicUpdate ();
}
}
- public BoardWidget ():base()
+ public virtual IList<string> Moves {
+ get => moves;
+ set {
+ if (moves == value)
+ return;
+
+ if (moves is ObservableList<string> ol) {
+ ol.ListAdd -= Lines_ListAdd;
+ ol.ListRemove -= Lines_ListRemove;
+ ol.ListClear -= Lines_ListClear;
+ }
+
+ moves = value;
+
+ if (moves is ObservableList<string> olNew) {
+ olNew.ListAdd += Lines_ListAdd;
+ olNew.ListRemove += Lines_ListRemove;
+ olNew.ListClear += Lines_ListClear;
+ }
+
+ NotifyValueChanged ("Moves", moves);
+
+ replayAllMoves ();
+
+ RegisterForGraphicUpdate ();
+ }
+ }
+ public string FilePath {
+ get => FilePath;
+ set {
+ if (filePath == value)
+ return;
+ filePath = value;
+ NotifyValueChangedAuto (filePath);
+ RegisterForGraphicUpdate ();
+
+ if (string.IsNullOrEmpty (filePath))
+ resetCurrentBoard ();
+ else
+ loadFromFile ();
+ }
+ }
+ public BoardWidget (): base()
{
sprites = new SvgPicture ("data/Pieces.svg");
}
+ static readonly string[,] boardInit = {
+ {"wr", "wp", "", "", "", "", "bp", "br"},
+ {"wk", "wp", "", "", "", "", "bp", "bk"},
+ {"wb", "wp", "", "", "", "", "bp", "bb"},
+ {"wq", "wp", "", "", "", "", "bp", "bq"},
+ {"wK", "wp", "", "", "", "", "bp", "bK"},
+ {"wb", "wp", "", "", "", "", "bp", "bb"},
+ {"wk", "wp", "", "", "", "", "bp", "bk"},
+ {"wr", "wp", "", "", "", "", "bp", "br"}
+ };
+ void Lines_ListAdd (object sender, ListChangedEventArg e)
+ {
+ processMove (currentBoard, e.Element.ToString());
+ RegisterForRedraw ();
+ }
+ void Lines_ListRemove (object sender, ListChangedEventArg e)
+ {
+ replayAllMoves ();
+ RegisterForRedraw ();
+ }
+ void Lines_ListClear (object sender, ListClearEventArg e)
+ {
+ resetCurrentBoard();
+ RegisterForRedraw ();
+ }
protected override void onDraw (Context gr)
{
base.onDraw (gr);
+ this.setFontForContext (gr);
+
/*gr.FontFace = Font.Name;
gr.FontSize = (uint)Font.Size;*/
@@ -88,47 +162,108 @@ namespace vkChess
}
gr.Fill ();
- if (board == null)
- return;
- for (int x = 0; x < 8; x++) {
- for (int y = 0; y < 8; y++) {
- if (board [x, y] == null)
- continue;
+ if (board != null) {
+ for (int x = 0; x < 8; x++) {
+ for (int y = 0; y < 8; y++) {
+ if (board [x, y] == null)
+ continue;
- string spriteName;
- if (board [x, y].Player == ChessColor.White)
- spriteName = "w";
- else
- spriteName = "b";
+ string spriteName;
+ if (board [x, y].Player == ChessColor.White)
+ spriteName = "w";
+ else
+ spriteName = "b";
- switch (board[x,y].Type) {
- case PieceType.Pawn:
- spriteName += "p";
- break;
- case PieceType.Rook:
- spriteName += "r";
- break;
- case PieceType.Knight:
- spriteName += "k";
- break;
- case PieceType.Bishop:
- spriteName += "b";
- break;
- case PieceType.King:
- spriteName += "K";
- break;
- case PieceType.Queen:
- spriteName += "q";
- break;
+ switch (board[x,y].Type) {
+ case PieceType.Pawn:
+ spriteName += "p";
+ break;
+ case PieceType.Rook:
+ spriteName += "r";
+ break;
+ case PieceType.Knight:
+ spriteName += "k";
+ break;
+ case PieceType.Bishop:
+ spriteName += "b";
+ break;
+ case PieceType.King:
+ spriteName += "K";
+ break;
+ case PieceType.Queen:
+ spriteName += "q";
+ break;
+ }
+ sprites.Paint (IFace, gr,new Rectangle(
+ (int)(gridX + x * cellSize),
+ (int)(gridY + (7 - y) * cellSize),
+ (int)cellSize,
+ (int)cellSize),spriteName);
+ }
+ }
+ } else if (moves != null && currentBoard != null) {
+ for (int x = 0; x < 8; x++) {
+ for (int y = 0; y < 8; y++) {
+ if (string.IsNullOrEmpty(currentBoard [x, y]))
+ continue;
+ sprites.Paint (IFace, gr,new Rectangle(
+ (int)(gridX + x * cellSize),
+ (int)(gridY + (7 - y) * cellSize),
+ (int)cellSize,
+ (int)cellSize),currentBoard[x, y]);
}
- sprites.Paint (IFace, gr,new Rectangle(
- (int)(gridX + x * cellSize),
- (int)(gridY + (7 - y) * cellSize),
- (int)cellSize,
- (int)cellSize),spriteName);
}
}
}
+ void loadFromFile () {
+ try {
+ using (Stream stream = new FileStream (filePath, FileMode.Open))
+ using (StreamReader sw = new StreamReader (stream))
+ Moves = sw.ReadLine ().Split (' ');
+ } catch (Exception ex) {
+ Crow.MessageBox.ShowModal (IFace, MessageBox.Type.Error, $"Failed loading {filePath}\n{ex.Message}");
+ }
+ }
+ void resetCurrentBoard () => currentBoard = boardInit.Clone() as string[,];
+ void replayAllMoves () {
+ resetCurrentBoard ();
+ if (moves == null)
+ return;
+ int i = 0;
+
+ lock (VkChess.movesMutex) {
+ foreach (string move in moves) {
+ try {
+ processMove (currentBoard, move);
+ } catch {
+ Console.WriteLine ($"move: {move} i:{i}");
+ }
+ i++;
+ }
+ }
+ }
+ void processMove (string[,] board, string move) {
+ ReadOnlySpan<char> m = move.AsSpan();
+ Point p0 = VkChess.getChessCell (m.Slice (0, 2));
+ Point p1 = VkChess.getChessCell (m.Slice (2, 2));
+
+ if (board[p0.X, p0.Y][1] == 'p') {//pawn
+ if (m.Length == 5) //pawnPromotion
+ board[p0.X, p0.Y] = board[p0.X, p0.Y][0].ToString() + m[4];
+ else if (p0.X != p1.X && string.IsNullOrEmpty (board[p1.X, p1.Y]))//prise en passant
+ board[p0.X, p1.Y] = null;
+ }else if (board[p0.X, p0.Y][1] == 'K' && Math.Abs(p0.X - p1.X) > 1) {//rook
+ if (p0.X - p1.X < 0) {//small rock
+ board[5, p0.Y] = board[7, p0.Y];
+ board[7, p0.Y] = null;
+ } else { //big rock
+ board[3, p0.Y] = board[0, p0.Y];
+ board[0, p0.Y] = null;
+ }
+ }
+ board[p1.X, p1.Y] = board[p0.X, p0.Y];
+ board[p0.X, p0.Y] = null;
+ }
}
}