emymin / emychess Goto Github PK
View Code? Open in Web Editor NEWUdon Chess Prefab for VRChat
License: GNU General Public License v3.0
Udon Chess Prefab for VRChat
License: GNU General Public License v3.0
when the queen is of the table and a pawn to the end of the board at opponent side, the pawn to queen swap broke. the opponent gets his color queen instead of mine. but the whole game also broke and no turns can be made any more.
The most recent release of VRChat's world package says that it requires a specific version of udonsharp despite being combined with the world package. I wanted to ensure that the package did get resolved. This issue isn't major as it works perfectly outside of it being considered an unresolved package.
The chess board will be stuck in a "playing" state even though no one can move any pieces any no one is able to reset the game. Whoever is the master of the instance is shown as both of the current players that are playing, but they also cannot reset the board and don't see themselves as a player on the game.
Hello, I enjoy the chessboard very much but small issue with the board logic. When castling would be illegal because a bishop line of sight would prevent castling, the board still let you castle.
If you plan future updates, here is a few suggestions:
1.Have a replay mode to rewatch the last played game.
2.An export feature where you can copy(clipboard) the notation of the game at the end of a match would be awesome.
Keep up the good work!
Nuka
It seems that the index.json is non-exist or is possibly corrupted. This prevents me from adding EmyChess as a Community Repository in the Creator Companion, so I have to use manual releases instead.
Is this something you have been made aware of or have been dealing with lately?
I'm new to Udon side of things when it comes to VRChat so I could just be doing something wrong. I followed your directions for adding the prefab to my world, but when I go to test build none of the buttons seem to work and I can't start Chess match. I'm using the the VRChat Creator Companion; with everything up to date
Hello, I've been working on my own version of EmmyChess and I managed to fix the castle bug. My current version is very different from the asset so I will post some of the code to fix castle for the asset. If you want to see the changes I've made to emmy chess you can check out the Vrchat Map "Cozy Space". I had to basicly not call functions directly in order to avoid the crashing issue that came up a lot, so it caused me to update bools and call the bools instead of the direct function. I hope this helps, I am very new to coding, fixing this took probably a straight month of work.
//(added to defaultrules)
//Top part -
[HideInInspector]
public bool BlackLeftCastle = true;
[HideInInspector]
public bool BlackRightCastle = true;
[HideInInspector]
public bool WhiteLeftCastle = true;
[HideInInspector]
public bool WhiteRightCastle = true;
[HideInInspector]
public bool BlackMoveLeftCastle = true;
[HideInInspector]
public bool BlackMoveRightCastle = true;
[HideInInspector]
public bool WhiteMoveLeftCastle = true;
[HideInInspector]
public bool WhiteMoveRightCastle = true;
[HideInInspector]
public bool WhitePiecesRightCastle = false;
[HideInInspector]
public bool WhitePiecesLeftCastle = false;
[HideInInspector]
public bool BlackPiecesRightCastle = false;
[HideInInspector]
public bool BlackPiecesLeftCastle = false; //I also added all these exactly the same to start() might not be important.
[HideInInspector]
[UdonSynced]
public bool CastleInCheck = false;
//Added functions -
// (pseudolegalmoves)
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 (white)
{
if (WhiteRightCastle && WhiteMoveRightCastle && WhitePiecesRightCastle && !CastleInCheck)
{
index = AppendMove(index, x + 2, y, legalMoves);
}
if (WhiteLeftCastle && WhiteMoveLeftCastle && WhitePiecesLeftCastle && !CastleInCheck)
{
index = AppendMove(index, x - 2, y, legalMoves);
}
}
else
{
if (BlackRightCastle && BlackMoveRightCastle && BlackPiecesRightCastle && !CastleInCheck)
{
index = AppendMove(index, x + 2, y, legalMoves);
}
if (BlackLeftCastle && BlackMoveLeftCastle && BlackPiecesLeftCastle && !CastleInCheck)
{
index = AppendMove(index, x - 2, y, legalMoves);
}
}
}
//(iskingincheck)
if (opponentPseudoLegalMove == legalMovesEndMarker) { break; }
else
{
if (opponentPseudoLegalMove == threatenedPos)
{
isKingChecked = true;
CastleInCheck = true; //this is all thats added in order to not directly call iskingincheck
break;
}
}
//(new)
public void CastleMoveCheck()
{
WhiteMoveRightCastle = true;
BlackMoveRightCastle = true;
WhiteMoveLeftCastle = true;
BlackMoveLeftCastle = true;
RequestSerialization();
}
public void CastleNotMoved(Piece movedPiece)
{
if (movedPiece.type == "king")
{
if (movedPiece.white)
{
WhiteMoveRightCastle = false;
WhiteMoveLeftCastle = false;
}
else
{
BlackMoveRightCastle = false;
BlackMoveLeftCastle = false;
}
}
else if (movedPiece.type == "rook")
{
if (movedPiece.white)
{
if (movedPiece.x == 0 && movedPiece.y == 0) // Left rook initial position for white
{
WhiteMoveLeftCastle = false;
}
else if (movedPiece.x == 7 && movedPiece.y == 0) // Right rook initial position for white
{
WhiteMoveRightCastle = false;
}
}
else
{
if (movedPiece.x == 0 && movedPiece.y == 7) // Left rook initial position for black
{
BlackMoveLeftCastle = false;
}
else if (movedPiece.x == 7 && movedPiece.y == 7) // Right rook initial position for black
{
BlackMoveRightCastle = false;
}
}
}
RequestSerialization();
}
public void CheckCastlePaths(Piece[] grid, Board board)
{
if (grid == null) { Debug.LogWarning("Empty grid, might be first turn"); return; }
// Check White Right Castle
WhitePiecesRightCastle = true;
for (int i = 5; i < 7; i++) // Check squares between king and right rook for white
{
if (board.GetGridPiece(i, 0, grid) != null) // Assuming white's back rank is y = 0
{
WhitePiecesRightCastle = false;
break;
}
}
// Check White Left Castle
WhitePiecesLeftCastle = true;
for (int i = 1; i < 4; i++) // Check squares between king and left rook for white
{
if (board.GetGridPiece(i, 0, grid) != null) // Assuming white's back rank is y = 0
{
WhitePiecesLeftCastle = false;
break;
}
}
// Check Black Right Castle
BlackPiecesRightCastle = true;
for (int i = 5; i < 7; i++) // Check squares between king and right rook for black
{
if (board.GetGridPiece(i, 7, grid) != null) // Assuming black's back rank is y = 7
{
BlackPiecesRightCastle = false;
break;
}
}
// Check Black Left Castle
BlackPiecesLeftCastle = true;
for (int i = 1; i < 4; i++) // Check squares between king and left rook for black
{
if (board.GetGridPiece(i, 7, grid) != null) // Assuming black's back rank is y = 7
{
BlackPiecesLeftCastle = false;
break;
}
}
RequestSerialization();
}
public void CheckCastleSafety(Piece[] grid, Board board)
{
// Check squares next to the White King
Vector2 whiteKingPos = board.whiteKing.GetVec();
WhiteLeftCastle = !(IsSquareUnderAttack((int)whiteKingPos.x - 1, (int)whiteKingPos.y, false, grid, board) ||
IsSquareUnderAttack((int)whiteKingPos.x - 2, (int)whiteKingPos.y, false, grid, board));
WhiteRightCastle = !(IsSquareUnderAttack((int)whiteKingPos.x + 1, (int)whiteKingPos.y, false, grid, board) ||
IsSquareUnderAttack((int)whiteKingPos.x + 2, (int)whiteKingPos.y, false, grid, board));
// Check squares next to the Black King
Vector2 blackKingPos = board.blackKing.GetVec();
BlackLeftCastle = !(IsSquareUnderAttack((int)blackKingPos.x - 1, (int)blackKingPos.y, true, grid, board) ||
IsSquareUnderAttack((int)blackKingPos.x - 2, (int)blackKingPos.y, true, grid, board));
BlackRightCastle = !(IsSquareUnderAttack((int)blackKingPos.x + 1, (int)blackKingPos.y, true, grid, board) ||
IsSquareUnderAttack((int)blackKingPos.x + 2, (int)blackKingPos.y, true, grid, board));
RequestSerialization();
}
private bool IsSquareUnderAttack(int x, int y, bool byWhite, Piece[] grid, Board board)
{
foreach (Piece piece in board.GetAllPieces())
{
if (piece.white == byWhite)
{
Vector2[] pseudoLegalMoves = GetAllPseudoLegalMovesGrid(piece, grid, board.PawnThatDidADoublePushLastRound,
board);
foreach (Vector2 move in pseudoLegalMoves)
{
if (move == legalMovesEndMarker) break;
if (move.x == x && move.y == y)
{
return true;
}
}
}
}
return false;
}
//(modified GetAlllegalMoves)
public Vector2[] GetAllLegalMoves(Piece movedPiece, Board board)
{
Vector2[] pseudoLegalMoves = GetAllPseudoLegalMovesGrid(movedPiece, board.grid, board.PawnThatDidADoublePushLastRound, board);
Vector2 piecePos = movedPiece.GetVec();
Piece king = movedPiece.white ? board.whiteKing : board.blackKing;
if (king != null)
{
Vector2 kingPos = king.GetVec();
Piece[] currentGrid = board.grid;
Piece[] testGrid = new Piece[currentGrid.Length];
CastleInCheck = false; // Reset CastleInCheck to false initially <-----only line added.
for (int i = 0; i < pseudoLegalMoves.Length; i++)
{
Vector2 pseudoLegalMove = pseudoLegalMoves[i];
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;
}
//(modified Move)
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);
result = MoveLegalCheck(movedPiece, x, y, board, legalMoves);
// Call CastleNotMoved whenever a piece is moved <---------
if (result > 0)
{
CastleNotMoved(movedPiece);
}
return result;
}
}
//(modified MoveLegalCheck)
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")
{
if (movedPiece.white)
{
if (x - movedPiece.x == 2 && WhiteRightCastle && WhiteMoveRightCastle && WhitePiecesRightCastle && !CastleInCheck) // White right castle
{
Piece rookCastle = board.GetPiece(7, y);
rookCastle._SetPosition(x - 1, y);
}
else if (x - movedPiece.x == -2 && WhiteLeftCastle && WhiteMoveLeftCastle && WhitePiecesLeftCastle && !CastleInCheck) // White left castle
{
Piece rookCastle = board.GetPiece(0, y);
rookCastle._SetPosition(x + 1, y);
}
}
else
{
if (x - movedPiece.x == 2 && BlackRightCastle && BlackMoveRightCastle && BlackPiecesRightCastle && !CastleInCheck) // Black right castle
{
Piece rookCastle = board.GetPiece(7, y);
rookCastle._SetPosition(x - 1, y);
}
else if (x - movedPiece.x == -2 && BlackLeftCastle && BlackMoveLeftCastle && BlackPiecesLeftCastle && !CastleInCheck) // Black left castle
{
Piece rookCastle = board.GetPiece(0, y);
rookCastle._SetPosition(x + 1, y);
}
}
}
if (movedPiece.type == "pawn" && Mathf.Abs(y - movedPiece.y) == 2)
{
board.PawnThatDidADoublePushLastRound = movedPiece;
}
else
{
board.PawnThatDidADoublePushLastRound = null;
}
CastleNotMoved(movedPiece);
movedPiece.hasMoved = true;
movedPiece._SetPosition(x, y);
return result;
}
else
{
movedPiece._SetPosition(movedPiece.x, movedPiece.y);
return 0;
}
}
//(Board.cs Changes - Removed the castle move from board.cs)
public void MoveGridPiece(int ox, int oy, int tx, int ty, Piece[] grid)
{
Piece piece = GetGridPiece(ox, oy, grid);
// No en passant or castling logic
SetGridPiece(tx, ty, piece, grid);
SetGridPiece(ox, oy, null, grid);
}
/// <summary>
/// Simulate a piece's move on a grid, including capture, en passant and castling
/// </summary>
/// <param name="original">Starting position</param>
/// <param name="target">Target position</param>
/// <param name="grid"></param>
public void MoveGridPieceVec(Vector2 original, Vector2 target, Piece[] grid)
{
MoveGridPiece((int)original.x, (int)original.y, (int)target.x, (int)target.y, grid);
}
//(Chessmanger Changes)
//(Endturn)
board.currentRules.CheckCastlePaths(board.grid, board); // Check castle paths at end turn <-added
board.currentRules.CheckCastleSafety(board.grid, board); // Check castle safety at end turn<-added
_RefreshUI();
RequestSerialization();
//(startgame)
board.currentRules.CheckCastlePaths(board.grid, board); // Check castle paths at game start
board.currentRules.CheckCastleSafety(board.grid, board); // Check castle safety at game start
//(endgame)
board.currentRules.CastleMoveCheck();
Hello again. I noticed a little issue with your Chess Clock... everything works great! but.... you have the Chess clock set wrong. I looked up the official time rules to be sure of this. When a Chess match starts Black side starts the clock for White... your board is set to where White starts the clock for black, that's not the correct way to start a match.
Is there a way I can correct the clock in the scene? I tried on my own but couldn't seem to tweak the clock setup.
As soon as I try to import emychess into a VCC (vrchat creator companion) project, Unity immediately pops up its crash window and proceeds to crash the project. If I then open the project back up, A prefab message saying something about unpacking will persist and not go away unless I remove emychess from the files and then re-launch the project. I know this hasnt been updated since back in 2021 but it's one of the higher quality free chess boards that I love using. If you could fix it/update it that would be amazing~
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.