Тест проверки шахматного замка C # в INT с использованием UnityC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Тест проверки шахматного замка C # в INT с использованием Unity

Сообщение Anonymous »

Функционально на шахматной доске работает всё, кроме проверки шахмат во время тестера замка в векторе. Как будто оно не записывает правило в pseudoLegalMove. Может ли вектор работать для такого типа вещей? Я новичок в C #, учусь и потратил несколько дней, пытаясь решить эту проблему. Я думаю, что вместо этого мне нужно выполнить эту проверку в bool или что-то в этом роде, чтобы он записал незаконный ход в псевдоLegalMove. Кроме того, все остальное работает правильно... например, enpassant, doublepawnpush и т. д. Любая помощь от человека, который программировал шахматную доску, была бы фантастической!
Я думаю, именно в этом и заключается проблема..

Код: Выделить всё

 /// 

/// 
/// 
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
{

Array.Copy(currentGrid, testGrid, currentGrid.Length);

board.MoveGridPieceVec(piecePos, pseudoLegalMove, testGrid);
Piece PawnThatDidADoublePush = null;
if (movedPiece.type == "pawn" && (Mathf.Abs(movedPiece.x - (int)pseudoLegalMove.x) > 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))
здесь он проверяет, что псевдолегальное перемещение проверено, чтобы замок мог произойти

Код: Выделить всё

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%, заранее спасибо!

Подробнее здесь: https://stackoverflow.com/questions/784 ... sing-unity
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Тест проверки шахматного замка C # в INT с использованием Unity
    Anonymous » » в форуме C#
    0 Ответы
    30 Просмотры
    Последнее сообщение Anonymous
  • Тест проверки шахматного замка C # в INT с использованием Unity
    Anonymous » » в форуме C#
    0 Ответы
    29 Просмотры
    Последнее сообщение Anonymous
  • Как преобразовать список[int, int, int] в кортеж[int, int, int], а не в кортеж[int, ...]
    Anonymous » » в форуме Python
    0 Ответы
    289 Просмотры
    Последнее сообщение Anonymous
  • Каков прототип этой функции? BFont::DrawString(wchar_t*, int, int, int, int, int, int) [закрыто]
    Anonymous » » в форуме C++
    0 Ответы
    109 Просмотры
    Последнее сообщение Anonymous
  • Приведение кортежа <int *, int, int, int*> к tuple<void*, int, int, void*> вызывает проблему использования стека ASAN за
    Anonymous » » в форуме C++
    0 Ответы
    124 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»