Функционально на шахматной доске работает всё, кроме проверки шахмат во время тестера замка в векторе. Как будто оно не записывает правило в pseudoLegalMove. Может ли вектор работать для такого типа вещей? Я новичок в C #, учусь и потратил несколько дней, пытаясь решить эту проблему. Я думаю, что вместо этого мне нужно выполнить эту проверку в bool или что-то в этом роде, чтобы он записал незаконный ход в псевдоLegalMove. Кроме того, все остальное работает правильно... например, enpassant, doublepawnpush и т. д. Любая помощь от человека, который программировал шахматную доску, была бы фантастической!
Я думаю, именно в этом и заключается проблема..
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using System;
namespace Emychess.GameRules
{
///
/// Behaviour that specifies the chess rules to follow
///
///
/// Rule checking can be turned on and off with
///
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class DefaultRules : UdonSharpBehaviour
{
//this is where Udon(Sharp)'s limitations make the code a bit hard to design in a sane way
// legal moves are passed around as Vector2 arrays, which emulate list functionality by using a legalMovesIgnoreMarker to indicate elements to be skipped (for quick removal)
// and legalMovesEndMarker to indicate the end of the list
// this also means that functions receiving it need to always check what kind of move it was (regular, castling, en passant, double push) and find which object was supposed to be captured
// a workaround could be using Object[] arrays to work as structs, to put all move information inside it, but that comes with its own annoyances
//TODO decouple rules more from rest of the scripts
///
/// Whether anarchy mode is enabled, set with
///
[UdonSynced]
public bool anarchy=false;
///
/// Value that indicates the end of a move list
///
[HideInInspector]
public Vector2 legalMovesEndMarker;
///
/// Value that can be skipped when iterating over a move list
///
[HideInInspector]
public Vector2 legalMovesIgnoreMarker;
///
/// Directions that a generic sliding piece can move in. Also the queen's legal directions.
///
private Vector2[] slideDirections;
///
/// Directions that a rook can move in
///
private Vector2[] rookDirections;
///
/// Directions that a bishop can move in
///
private Vector2[] bishopDirections;
private int[] rookColumns;
public void Start()
{
legalMovesEndMarker = new Vector2(-1, -1);
legalMovesIgnoreMarker = new Vector2(-2, -2);
rookColumns = new[] { 0, 7 };
slideDirections = new [] { new Vector2(-1,0),new Vector2(1,0),new Vector2(0,-1),new Vector2(0,1),new Vector2(-1,1),new Vector2(-1,-1),new Vector2(1,1),new Vector2(1,-1)};
rookDirections = new Vector2[4];
for(int i = 0; i < 4; i++) { rookDirections[i] = slideDirections[i]; }
bishopDirections = new Vector2[4];
for(int i = 0; i < 4; i++) { bishopDirections[i] = slideDirections[7 - i]; }
}
///
/// Used when generating move lists, "appends" a move at the specified index, returns the incremented index, also sets the legalMovesEndMarker if the last element in the array is reached
///
///
///
///
///
/// If the append was successful, index incremented by 1
private int AppendMove(int index, int x,int y,Vector2[] legalMoves)
{
int newindex = index;
if (x < 0 || x > 7 || y < 0 || y > 7) { return newindex; }
if (index < legalMoves.Length)
{
legalMoves[index] = new Vector2(x, y);
if(index < legalMoves.Length - 1)
{
legalMoves[index + 1] = legalMovesEndMarker;//used to mark the end of the """"list""""
newindex++;
}
}
return newindex;
}
///
/// Gets all the pseudo-legal moves (legal moves that don't take in account king check) that a piece can make, for fully legal moves, check
///
/// Piece of which to find the legal moves
/// Board's state in grid form, see
/// A reference to a pawn that did a double push in the previous turn (for en passant), null if none
/// A reference to the board behaviour (UdonSharp doesn't support static methods)
/// List of pseudo-legal moves
public Vector2[] GetAllPseudoLegalMovesGrid(Piece movedPiece,Piece[] grid,Piece PawnThatDidADoublePushLastRound,Board board)
{
Vector2[] legalMoves = new Vector2[64]; // SADLY still no lists, so gotta do this the cursed way
int index = 0;
legalMoves[index] = legalMovesEndMarker;
string type = movedPiece.type;
int x = movedPiece.x;
int y = movedPiece.y;
bool white = movedPiece.white;
bool hasMoved = movedPiece.hasMoved;
//AppendMove will check if the move is out of the board, so no need to check that here
if (type == "pawn")
{
int dir = white ? 1 : -1;
if (board.GetGridPiece(x,y+dir,grid)==null){
index = AppendMove(index, x, y + dir, legalMoves);
if (!hasMoved)
{
if (board.GetPiece(x, y + dir* 2) == null) {
index = AppendMove(index, x, y + dir * 2, legalMoves);
}
}
}
Piece pieceCaptureLeft = board.GetGridPiece(x - 1, y + dir,grid);
Piece pieceCaptureRight = board.GetGridPiece(x + 1, y + dir,grid);
if (pieceCaptureLeft != null && pieceCaptureLeft.white!=white)
{
index = AppendMove(index, x - 1, y + dir, legalMoves);
}
if (pieceCaptureRight!= null && pieceCaptureRight.white!=white)
{
index = AppendMove(index, x + 1, y + dir, legalMoves);
}
//EN PASSANT
Piece pieceLeft = board.GetGridPiece(x - 1, y,grid);
Piece pieceRight = board.GetGridPiece(x + 1, y,grid);
if (pieceLeft!=null && pieceLeft == PawnThatDidADoublePushLastRound && pieceLeft.white!=white)
{
if (board.GetGridPiece(x - 1, y + dir,grid) == null)
{
index = AppendMove(index, x - 1, y + dir, legalMoves);
}
}
if (pieceRight!=null && pieceRight == PawnThatDidADoublePushLastRound && pieceRight.white!=white)
{
if (board.GetGridPiece(x + 1, y + dir,grid) == null)
{
index = AppendMove(index, x + 1, y + dir, legalMoves);
}
}
}
else if (type == "king")
{
for(int i = -1; i < 2; i++)
{
for(int j = -1; j < 2; j++)
{
Piece squarepiece = board.GetGridPiece(x + i, y + j,grid);
if(squarepiece==null||(squarepiece!=null && squarepiece.white != white))
{
index = AppendMove(index, x + i, y + j, legalMoves);
}
}
}
if (!hasMoved)
{
if (true)//|| !isKingInCheck(movedPiece.GetVec(), board.grid, board, board.PawnThatDidADoublePushLastRound, white)) //TODO very WEIRD stuff happens if I check if the king is in check here (which is necessary because castling is not allowed when the king is in check)
{
foreach (int rookColumn in rookColumns)
{
Piece startRook = board.GetGridPiece(rookColumn, y,grid);
if (startRook!=null && startRook.type == "rook" && !startRook.hasMoved && startRook.white == white)
{
bool free = true;
for(int i = Mathf.Min(x, rookColumn) + 1; i < Mathf.Max(x, rookColumn); i++)
{
if (board.GetGridPiece(i, y,grid) != null) free = false;
}
if (free)
{
int dir = Mathf.Min(x, rookColumn) == x ? 1 : -1;
index = AppendMove(index, x + dir * 2, y, legalMoves);
}
}
}
}
}
}
else if (type == "rook" || type == "bishop" || type == "queen")
{
Vector2[] allowedDirections=slideDirections;
if (type == "rook") allowedDirections = rookDirections;
else if (type == "bishop") allowedDirections = bishopDirections;
foreach(Vector2 direction in allowedDirections)
{
Vector2 pos = new Vector2(x, y);
while (true)
{
pos += direction;
if (!board.isValidCoordinate((int)pos.x, (int)pos.y)) break;
Piece obstaclePiece = board.GetGridPiece((int)pos.x,(int)pos.y,grid);
if (obstaclePiece != null && obstaclePiece.white == white) break;
index = AppendMove(index, (int)pos.x, (int)pos.y, legalMoves);
if (obstaclePiece != null) break;
}
}
}
else if (type == "knight")
{
Vector2 left, right;
foreach (Vector2 direction in rookDirections) //directions are the same as the rook
{
Vector2 pos = new Vector2(x, y);
pos += direction * 2;
if (direction.x == 0) { left = Vector2.left;right = Vector2.right; }
else { left = Vector2.up;right = Vector2.down; }
Vector2 leftPos = pos + left;
Vector2 rightPos = pos + right;
Piece leftPiece = board.GetGridPiece((int)leftPos.x,(int)leftPos.y,grid);
Piece rightPiece = board.GetGridPiece((int)rightPos.x, (int)rightPos.y, grid);
if (leftPiece == null || (leftPiece != null && leftPiece.white != white)){ index = AppendMove(index, (int)leftPos.x, (int)leftPos.y, legalMoves); }
if (rightPiece == null || (rightPiece != null && rightPiece.white != white)){ index = AppendMove(index, (int)rightPos.x, (int)rightPos.y, legalMoves); }
}
}
return legalMoves;
}
///
/// Gets all pseudo-legal moves for a piece on a board object, see
///
///
///
///
public Vector2[] GetAllPseudoLegalMoves(Piece piece,Board board)
{
return GetAllPseudoLegalMovesGrid(piece, board.grid, board.PawnThatDidADoublePushLastRound,board);
}
///
/// Optimization to detect if the king is in check, some basic sanity checks to see if a piece of the specified type could even reach the threatened position to begin with
///
///
///
///
///
public bool isCaptureFeasible(Vector2 opponentPosition,Vector2 threatenedPosition,string type)
{
if (type == "rook") return (opponentPosition.x == threatenedPosition.x | opponentPosition.y == threatenedPosition.y);
else if (type == "pawn") return (Mathf.Abs(opponentPosition.x - threatenedPosition.x) == 1 && Mathf.Abs(opponentPosition.y - threatenedPosition.y) == 1);
else if (type == "knight") return (Mathf.Abs(opponentPosition.x - threatenedPosition.x) < 3 && Mathf.Abs(opponentPosition.y - threatenedPosition.y) < 3);
else if (type == "bishop") return (Mathf.Abs(opponentPosition.x - threatenedPosition.x) == Mathf.Abs(opponentPosition.y - threatenedPosition.y));
else if (type == "queen") return (opponentPosition.x == threatenedPosition.x | opponentPosition.y == threatenedPosition.y) | (Mathf.Abs(opponentPosition.x - threatenedPosition.x) == Mathf.Abs(opponentPosition.y - threatenedPosition.y));
else if (type == "king") return (Mathf.Abs((opponentPosition-threatenedPosition).magnitude) 1))
{
PawnThatDidADoublePush = movedPiece;
}
Vector2 threatenedPos = movedPiece.type != "king" ? kingPos : pseudoLegalMove;
if (isKingInCheck(threatenedPos, testGrid, board, PawnThatDidADoublePush, movedPiece.white)) { pseudoLegalMoves[i] = legalMovesIgnoreMarker; }
}
}
}
return pseudoLegalMoves;
}
// if (!isKingInCheck(threatenedPos.x, threatenedPos.y, opponentPiece.type, opponentPiece.x, opponentPseudoLegalMove.x, opponentPseudoLegalMove.y, movedPiece.white))
// int dir = board(x, movedPiece.x);
// board copy = board.Copy();
// Position kingPosInCopy = fromPos;
// for (int i = 0; i < 2; i++)
// {
// new legalMoves(kingPosInCopy, kingPosInCopy + isKingInCheck).Execute(copy);
// kingPosInCopy += isKingInCheck;
// if (copy.isKingInCheck(player))
// {
// return false;
///
/// Gets the result of moving a piece to the specified position, as well as performing capture, en passant or castling
///
///
/// Will recalculate legal moves, if you already have a list of legal moves
/// (for example during ) use to pass them
///
///
///
///
///
/// 0 if the move is not allowed, 1 if the move was successful, 2 if the move resulted in a capture
public int Move(Piece movedPiece,int x,int y,Board board)
{
int result = 0;
if (anarchy)
{
Piece targetPiece = board.GetPiece(x, y);
result = 1;
if (targetPiece != null && targetPiece!=movedPiece) { targetPiece._Capture(); result = 2; }
movedPiece._SetPosition(x, y);
return result;
}
else
{
Vector2[] legalMoves = GetAllLegalMoves(movedPiece, board);
return MoveLegalCheck(movedPiece, x, y, board, legalMoves);
}
}
/// Board: 70 71 72 73 74 75 76 77 (Black)
/// 60 61 62 63 64 65 66 67
/// 50 41 52 53 54 55 56 57
/// 40 41 42 43 44 45 46 47 (x and y for each number)
/// 30 31 32 33 34 35 36 37
/// 20 21 22 23 24 25 26 27
/// 10 11 12 13 14 15 16 17
/// 00 01 02 03 04 05 06 07 (White)
///
///
///
///
///
/// 0 if the move is not allowed, 1 if the move was successful, 2 if the move resulted in a capture
///
/// Gets the result of moving a piece to a specified position, as well as performing capture, en passant or castling, based on the legal moves being passed
///
///
///
///
///
///
/// 0 if the move is not allowed, 1 if the move was successful, 2 if the move resulted in a capture
public int MoveLegalCheck(Piece movedPiece, int x, int y, Board board, Vector2[] legalMoves)
{
int result = 0;
Piece targetPiece = board.GetPiece(x, y);
Vector2 move = new Vector2(x, y);
bool legal = false;
foreach (Vector2 legalMove in legalMoves)
{
if (legalMove != legalMovesIgnoreMarker)
{
if (legalMove == legalMovesEndMarker) break;
if (move == legalMove) { legal = true; break; }
}
}
if (legal)
{
if (targetPiece != null) { targetPiece._Capture(); result = 2; } else { result = 1; }
if (movedPiece.type == "pawn" && movedPiece.x != x && board.GetPiece(x, y) == null)//EN PASSANT
{
board.PawnThatDidADoublePushLastRound._Capture();
result = 2;
}
if (movedPiece.type == "king" && Mathf.Abs(x - movedPiece.x) == 2) //CASTLING
{
int dir = Mathf.Min(x, movedPiece.x) == x ? -1 : 1;
Piece rookCastle = dir == 1 ? board.GetPiece(7, y) : board.GetPiece(0, y);
rookCastle._SetPosition(x + (dir * -1), y);
}
if (movedPiece.type == "pawn" && Mathf.Abs(y - movedPiece.y) == 2)
{
board.PawnThatDidADoublePushLastRound = movedPiece; //NOTICE, to have it be synced I also do the same check in the Piece refresh function (won't be synced for those who join right after this move, but it's fine)
}
else
{
board.PawnThatDidADoublePushLastRound = null;
}
movedPiece.hasMoved = true;
movedPiece._SetPosition(x, y);
return result;
}
else
{
movedPiece._SetPosition(movedPiece.x, movedPiece.y);
return 0;
}
}
///
/// Resets the board with all pieces in the correct starting positions
///
///
public void ResetBoard(Board board)
{
board.ReadFENString("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR");
}
///
/// Set anarchy mode (no rule checking)
///
///
public void SetAnarchy(bool enabled)
{
Networking.SetOwner(Networking.LocalPlayer, this.gameObject);
anarchy = enabled;
RequestSerialization();
}
}
}
Я могу опубликовать больше, если нужно..не хочу спамить или что-то в этом роде....вся доска состоит из 6 скриптов, поэтому
проблема с шахматной доской
Я пробовал несколько изменений, небольшие изменения... добавление if then перед командой замка, но безуспешно. я не очень разбираюсь в int и векторах... но что-то подсказывает мне, что мне нужно выполнить проверку замка в bool, чтобы записать псевдолегальные ходы....или я ошибаюсь....любые указания в правильное направление поможет на 100%, заранее спасибо!
Функционально на шахматной доске работает всё, кроме проверки шахмат во время тестера замка в векторе. Как будто оно не записывает правило в pseudoLegalMove. Может ли вектор работать для такого типа вещей? Я новичок в C #, учусь и потратил несколько дней, пытаясь решить эту проблему. Я думаю, что вместо этого мне нужно выполнить эту проверку в bool или что-то в этом роде, чтобы он записал незаконный ход в псевдоLegalMove. Кроме того, все остальное работает правильно... например, enpassant, doublepawnpush и т. д. Любая помощь от человека, который программировал шахматную доску, была бы фантастической! Я думаю, именно в этом и заключается проблема.. [code] ///
/// /// public Vector2[] GetAllLegalMoves(Piece movedPiece, Board board) //STACK OVERFLOW this is where i think the problem is? { Vector2[] pseudoLegalMoves = GetAllPseudoLegalMoves(movedPiece, board); Vector2 piecePos = movedPiece.GetVec(); Piece king = movedPiece.white ? board.whiteKing : board.blackKing; if (king != null) { Piece[] currentGrid = board.grid; //gets board grid Piece[] testGrid = new Piece[currentGrid.Length]; //gets king piece Vector2 kingPos = king.GetVec(); // gets king piece for (int i = 0; i < pseudoLegalMoves.Length; i++) { Vector2 pseudoLegalMove = pseudoLegalMoves[i]; //its like this doesn't write the illegal king move into the rules here or something
if (pseudoLegalMove == legalMovesEndMarker) { break; } else {
здесь он проверяет, что псевдолегальное перемещение проверено, чтобы замок мог произойти [code] using UdonSharp; using UnityEngine; using VRC.SDKBase; using VRC.Udon; using System;
namespace Emychess.GameRules { /// /// Behaviour that specifies the chess rules to follow /// /// /// Rule checking can be turned on and off with /// [UdonBehaviourSyncMode(BehaviourSyncMode.Manual)] public class DefaultRules : UdonSharpBehaviour { //this is where Udon(Sharp)'s limitations make the code a bit hard to design in a sane way // legal moves are passed around as Vector2 arrays, which emulate list functionality by using a legalMovesIgnoreMarker to indicate elements to be skipped (for quick removal) // and legalMovesEndMarker to indicate the end of the list // this also means that functions receiving it need to always check what kind of move it was (regular, castling, en passant, double push) and find which object was supposed to be captured // a workaround could be using Object[] arrays to work as structs, to put all move information inside it, but that comes with its own annoyances //TODO decouple rules more from rest of the scripts
/// /// Whether anarchy mode is enabled, set with /// [UdonSynced] public bool anarchy=false;
/// /// Value that indicates the end of a move list /// [HideInInspector] public Vector2 legalMovesEndMarker; /// /// Value that can be skipped when iterating over a move list /// [HideInInspector] public Vector2 legalMovesIgnoreMarker; /// /// Directions that a generic sliding piece can move in. Also the queen's legal directions. /// private Vector2[] slideDirections; /// /// Directions that a rook can move in /// private Vector2[] rookDirections; /// /// Directions that a bishop can move in /// private Vector2[] bishopDirections; private int[] rookColumns;
public void Start() { legalMovesEndMarker = new Vector2(-1, -1); legalMovesIgnoreMarker = new Vector2(-2, -2); rookColumns = new[] { 0, 7 }; slideDirections = new [] { new Vector2(-1,0),new Vector2(1,0),new Vector2(0,-1),new Vector2(0,1),new Vector2(-1,1),new Vector2(-1,-1),new Vector2(1,1),new Vector2(1,-1)}; rookDirections = new Vector2[4]; for(int i = 0; i < 4; i++) { rookDirections[i] = slideDirections[i]; } bishopDirections = new Vector2[4]; for(int i = 0; i < 4; i++) { bishopDirections[i] = slideDirections[7 - i]; } }
/// /// Used when generating move lists, "appends" a move at the specified index, returns the incremented index, also sets the legalMovesEndMarker if the last element in the array is reached /// ///
/// /// /// /// If the append was successful, index incremented by 1 private int AppendMove(int index, int x,int y,Vector2[] legalMoves) { int newindex = index; if (x < 0 || x > 7 || y < 0 || y > 7) { return newindex; } if (index < legalMoves.Length) { legalMoves[index] = new Vector2(x, y); if(index < legalMoves.Length - 1) { legalMoves[index + 1] = legalMovesEndMarker;//used to mark the end of the """"list"""" newindex++; } } return newindex;
}
/// /// Gets all the pseudo-legal moves (legal moves that don't take in account king check) that a piece can make, for fully legal moves, check /// /// Piece of which to find the legal moves /// Board's state in grid form, see /// A reference to a pawn that did a double push in the previous turn (for en passant), null if none /// A reference to the board behaviour (UdonSharp doesn't support static methods) /// List of pseudo-legal moves public Vector2[] GetAllPseudoLegalMovesGrid(Piece movedPiece,Piece[] grid,Piece PawnThatDidADoublePushLastRound,Board board) { Vector2[] legalMoves = new Vector2[64]; // SADLY still no lists, so gotta do this the cursed way int index = 0; legalMoves[index] = legalMovesEndMarker; string type = movedPiece.type; int x = movedPiece.x; int y = movedPiece.y; bool white = movedPiece.white; bool hasMoved = movedPiece.hasMoved; //AppendMove will check if the move is out of the board, so no need to check that here if (type == "pawn") { int dir = white ? 1 : -1; if (board.GetGridPiece(x,y+dir,grid)==null){ index = AppendMove(index, x, y + dir, legalMoves); if (!hasMoved) { if (board.GetPiece(x, y + dir* 2) == null) { index = AppendMove(index, x, y + dir * 2, legalMoves); } } } Piece pieceCaptureLeft = board.GetGridPiece(x - 1, y + dir,grid); Piece pieceCaptureRight = board.GetGridPiece(x + 1, y + dir,grid);
if (pieceCaptureLeft != null && pieceCaptureLeft.white!=white) { index = AppendMove(index, x - 1, y + dir, legalMoves); } if (pieceCaptureRight!= null && pieceCaptureRight.white!=white) { index = AppendMove(index, x + 1, y + dir, legalMoves); } //EN PASSANT Piece pieceLeft = board.GetGridPiece(x - 1, y,grid); Piece pieceRight = board.GetGridPiece(x + 1, y,grid); if (pieceLeft!=null && pieceLeft == PawnThatDidADoublePushLastRound && pieceLeft.white!=white) { if (board.GetGridPiece(x - 1, y + dir,grid) == null) { index = AppendMove(index, x - 1, y + dir, legalMoves); } } if (pieceRight!=null && pieceRight == PawnThatDidADoublePushLastRound && pieceRight.white!=white) { if (board.GetGridPiece(x + 1, y + dir,grid) == null) { index = AppendMove(index, x + 1, y + dir, legalMoves); } }
} else if (type == "king") { for(int i = -1; i < 2; i++) { for(int j = -1; j < 2; j++) { Piece squarepiece = board.GetGridPiece(x + i, y + j,grid); if(squarepiece==null||(squarepiece!=null && squarepiece.white != white)) { index = AppendMove(index, x + i, y + j, legalMoves); } } } if (!hasMoved) { if (true)//|| !isKingInCheck(movedPiece.GetVec(), board.grid, board, board.PawnThatDidADoublePushLastRound, white)) //TODO very WEIRD stuff happens if I check if the king is in check here (which is necessary because castling is not allowed when the king is in check) { foreach (int rookColumn in rookColumns) { Piece startRook = board.GetGridPiece(rookColumn, y,grid); if (startRook!=null && startRook.type == "rook" && !startRook.hasMoved && startRook.white == white) { bool free = true; for(int i = Mathf.Min(x, rookColumn) + 1; i < Mathf.Max(x, rookColumn); i++) { if (board.GetGridPiece(i, y,grid) != null) free = false; } if (free) { int dir = Mathf.Min(x, rookColumn) == x ? 1 : -1; index = AppendMove(index, x + dir * 2, y, legalMoves); } } } }
} } else if (type == "rook" || type == "bishop" || type == "queen") { Vector2[] allowedDirections=slideDirections; if (type == "rook") allowedDirections = rookDirections; else if (type == "bishop") allowedDirections = bishopDirections; foreach(Vector2 direction in allowedDirections) { Vector2 pos = new Vector2(x, y); while (true) { pos += direction; if (!board.isValidCoordinate((int)pos.x, (int)pos.y)) break; Piece obstaclePiece = board.GetGridPiece((int)pos.x,(int)pos.y,grid); if (obstaclePiece != null && obstaclePiece.white == white) break; index = AppendMove(index, (int)pos.x, (int)pos.y, legalMoves); if (obstaclePiece != null) break; } }
} else if (type == "knight") { Vector2 left, right; foreach (Vector2 direction in rookDirections) //directions are the same as the rook { Vector2 pos = new Vector2(x, y); pos += direction * 2; if (direction.x == 0) { left = Vector2.left;right = Vector2.right; } else { left = Vector2.up;right = Vector2.down; } Vector2 leftPos = pos + left; Vector2 rightPos = pos + right; Piece leftPiece = board.GetGridPiece((int)leftPos.x,(int)leftPos.y,grid); Piece rightPiece = board.GetGridPiece((int)rightPos.x, (int)rightPos.y, grid); if (leftPiece == null || (leftPiece != null && leftPiece.white != white)){ index = AppendMove(index, (int)leftPos.x, (int)leftPos.y, legalMoves); } if (rightPiece == null || (rightPiece != null && rightPiece.white != white)){ index = AppendMove(index, (int)rightPos.x, (int)rightPos.y, legalMoves); }
} } return legalMoves; }
/// /// Gets all pseudo-legal moves for a piece on a board object, see /// /// /// /// public Vector2[] GetAllPseudoLegalMoves(Piece piece,Board board) { return GetAllPseudoLegalMovesGrid(piece, board.grid, board.PawnThatDidADoublePushLastRound,board); }
/// /// Optimization to detect if the king is in check, some basic sanity checks to see if a piece of the specified type could even reach the threatened position to begin with /// /// /// /// /// public bool isCaptureFeasible(Vector2 opponentPosition,Vector2 threatenedPosition,string type) { if (type == "rook") return (opponentPosition.x == threatenedPosition.x | opponentPosition.y == threatenedPosition.y); else if (type == "pawn") return (Mathf.Abs(opponentPosition.x - threatenedPosition.x) == 1 && Mathf.Abs(opponentPosition.y - threatenedPosition.y) == 1); else if (type == "knight") return (Mathf.Abs(opponentPosition.x - threatenedPosition.x) < 3 && Mathf.Abs(opponentPosition.y - threatenedPosition.y) < 3); else if (type == "bishop") return (Mathf.Abs(opponentPosition.x - threatenedPosition.x) == Mathf.Abs(opponentPosition.y - threatenedPosition.y)); else if (type == "queen") return (opponentPosition.x == threatenedPosition.x | opponentPosition.y == threatenedPosition.y) | (Mathf.Abs(opponentPosition.x - threatenedPosition.x) == Mathf.Abs(opponentPosition.y - threatenedPosition.y)); else if (type == "king") return (Mathf.Abs((opponentPosition-threatenedPosition).magnitude) 1)) { PawnThatDidADoublePush = movedPiece; } Vector2 threatenedPos = movedPiece.type != "king" ? kingPos : pseudoLegalMove; if (isKingInCheck(threatenedPos, testGrid, board, PawnThatDidADoublePush, movedPiece.white)) { pseudoLegalMoves[i] = legalMovesIgnoreMarker; }
} }
} return pseudoLegalMoves;
} // if (!isKingInCheck(threatenedPos.x, threatenedPos.y, opponentPiece.type, opponentPiece.x, opponentPseudoLegalMove.x, opponentPseudoLegalMove.y, movedPiece.white))
// int dir = board(x, movedPiece.x); // board copy = board.Copy(); // Position kingPosInCopy = fromPos; // for (int i = 0; i < 2; i++) // { // new legalMoves(kingPosInCopy, kingPosInCopy + isKingInCheck).Execute(copy); // kingPosInCopy += isKingInCheck;
// if (copy.isKingInCheck(player)) // { // return false;
/// /// Gets the result of moving a piece to the specified position, as well as performing capture, en passant or castling /// /// /// Will recalculate legal moves, if you already have a list of legal moves /// (for example during ) use to pass them /// /// /// /// /// /// 0 if the move is not allowed, 1 if the move was successful, 2 if the move resulted in a capture public int Move(Piece movedPiece,int x,int y,Board board) { int result = 0; if (anarchy) { Piece targetPiece = board.GetPiece(x, y); result = 1; if (targetPiece != null && targetPiece!=movedPiece) { targetPiece._Capture(); result = 2; } movedPiece._SetPosition(x, y); return result; } else { Vector2[] legalMoves = GetAllLegalMoves(movedPiece, board); return MoveLegalCheck(movedPiece, x, y, board, legalMoves); }
}
/// Board: 70 71 72 73 74 75 76 77 (Black) /// 60 61 62 63 64 65 66 67 /// 50 41 52 53 54 55 56 57 /// 40 41 42 43 44 45 46 47 (x and y for each number) /// 30 31 32 33 34 35 36 37 /// 20 21 22 23 24 25 26 27 /// 10 11 12 13 14 15 16 17 /// 00 01 02 03 04 05 06 07 (White) /// /// /// /// /// /// 0 if the move is not allowed, 1 if the move was successful, 2 if the move resulted in a capture
/// /// Gets the result of moving a piece to a specified position, as well as performing capture, en passant or castling, based on the legal moves being passed /// /// /// /// /// /// /// 0 if the move is not allowed, 1 if the move was successful, 2 if the move resulted in a capture public int MoveLegalCheck(Piece movedPiece, int x, int y, Board board, Vector2[] legalMoves) { int result = 0; Piece targetPiece = board.GetPiece(x, y); Vector2 move = new Vector2(x, y); bool legal = false; foreach (Vector2 legalMove in legalMoves) { if (legalMove != legalMovesIgnoreMarker) { if (legalMove == legalMovesEndMarker) break; if (move == legalMove) { legal = true; break; } } } if (legal) { if (targetPiece != null) { targetPiece._Capture(); result = 2; } else { result = 1; }
if (movedPiece.type == "pawn" && movedPiece.x != x && board.GetPiece(x, y) == null)//EN PASSANT { board.PawnThatDidADoublePushLastRound._Capture(); result = 2; }
if (movedPiece.type == "king" && Mathf.Abs(x - movedPiece.x) == 2) //CASTLING { int dir = Mathf.Min(x, movedPiece.x) == x ? -1 : 1; Piece rookCastle = dir == 1 ? board.GetPiece(7, y) : board.GetPiece(0, y); rookCastle._SetPosition(x + (dir * -1), y);
}
if (movedPiece.type == "pawn" && Mathf.Abs(y - movedPiece.y) == 2) { board.PawnThatDidADoublePushLastRound = movedPiece; //NOTICE, to have it be synced I also do the same check in the Piece refresh function (won't be synced for those who join right after this move, but it's fine) } else { board.PawnThatDidADoublePushLastRound = null; } movedPiece.hasMoved = true; movedPiece._SetPosition(x, y);
/// /// Resets the board with all pieces in the correct starting positions /// /// public void ResetBoard(Board board) { board.ReadFENString("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR"); } /// /// Set anarchy mode (no rule checking) /// /// public void SetAnarchy(bool enabled) { Networking.SetOwner(Networking.LocalPlayer, this.gameObject); anarchy = enabled; RequestSerialization(); }
}
} [/code] Я могу опубликовать больше, если нужно..не хочу спамить или что-то в этом роде....вся доска состоит из 6 скриптов, поэтому проблема с шахматной доской Я пробовал несколько изменений, небольшие изменения... добавление if then перед командой замка, но безуспешно. я не очень разбираюсь в int и векторах... но что-то подсказывает мне, что мне нужно выполнить проверку замка в bool, чтобы записать псевдолегальные ходы....или я ошибаюсь....любые указания в правильное направление поможет на 100%, заранее спасибо!
Функционально на шахматной доске работает всё, кроме проверки шахмат во время тестера замка в векторе. Как будто оно не записывает правило в pseudoLegalMove. Может ли вектор работать для такого типа вещей? Я новичок в C #, учусь и потратил несколько...
Функционально на шахматной доске работает всё, кроме проверки шахмат во время тестера замка в векторе. Как будто оно не записывает правило в pseudoLegalMove. Может ли вектор работать для такого типа вещей? Я новичок в C #, учусь и потратил несколько...
Предположим, у меня есть две функции: func1 и func2. func1 возвращает список из 3 целых чисел, а func2 принимает кортеж из 3 целых чисел. Как мне преобразовать список в кортеж таким образом, чтобы можно было предотвратить ошибки с помощью средств...
Кто-нибудь знает прототип BFont::DrawString(wchar_t*, int, int, int, int, int, int) в библиотеке BFont++? Кажется, она была популярна где-то в 2003 году, мне бы хотелось получить прототип этой функции для модификации старой программы. Буду очень...