0

I could not find anything remotely close to this problem anywhere else on the internet. This is simply a bizarre issue. I am making a Chess game using Typescript. I have a Validator class that holds all the states of the game including an object representation for an Chess board, which is modified after each valid move. And that's where the bug occurs. Here is the board object ->

export interface BoardType {
    [file: string]: {
        [rank: string]: string;
    };
}

export const BoardMap: BoardType = {
    a: {
        '1': '',
        '2': '',
        '3': '',
        '4': '',
        '5': '',
        '6': '',
        '7': '',
        '8': '',
    },

then 7 more files. I have a function that takes this board object and adds the pieces according to the given FEN string. That function works correctly and is not relevant here. After running that function with the default FEN the board[a]['1'] would be 'R' (white Rook), board[g]['8'] would be 'n' (black Knight) and so on. Here is the code that updates the board and where the issue is most likely occurring ->

export const updateBoardMap = (
  piece: string,
  origin: string,
  dest: string,
  boardMap: BoardType
): BoardType => {
  // getOriginAndDestInfo works correctly
  const [originFile, originRank, destFile, destRank] = getOriginAndDestInfo(
    origin,
    dest
  );

  let boardMapToUpdate: BoardType = { ...boardMap };

  // Empty the original square and place the piece on the destination square
  boardMapToUpdate[originFile][originRank] = '';
  boardMapToUpdate[destFile][destRank] = piece;

  return boardMapToUpdate;
};

This updateBoardMap function is called here ->

private NewMove(): void {
    // Update the board map
    const updatedBoardMap = helpers.updateBoardMap(
      this.movingPiece,
      this.movingPiecesOrigin,
      this.movingPiecesDest,
      this.boardMap
    );
    
    this.boardMap = { ...updatedBoardMap };
    
    // Toggle the color's turn
    this.whitesTurn = !this.whitesTurn;
}

This is only called only if the move is valid. Alright, so here is the actual issue. The function updates the board most of the time correctly, about 50% of the time, but for the rest of the cases, it adds random pieces on random squares on the board with no pattern whatsoever. For example, if I play the move 1. e4, it sometimes adds a black pawn on e6 (the original e7 pawn is still there though) or a King on d5 etc. If I reload the page and play 1. e4 again, it might put pieces on totally random squares or will not do anything odd at all and work perfectly. I will post two scrreenshots of what it looks like.

Picture of bug 1

Picture of bug 1

You will see that after the first move, it adds random pieces on random squares. This is incredibly frustrating. This happens ONLY in the browser environment (Chrome) and never on Node. And since the validity of a move depends on boardMap I might not be able to play moves that should be valid. Like,if it puts a pawn on e6, I won't be able to play 1. ..e5 even though that move would have been valid without the bug.

I have 0 idea why this occurs. This is not a very complicated operation. I know that objects are passed by references so I am using the spread operator {...} both times. I have wrote extensive tests for this function with many moves and all of them pass. This issue never occurs in Node as I mentioned earlier. I have tested it in different ways many, many times and it always works. But as soon as I am on the browser, it shows up. There is no consistency or pattern and honestly I am out of ideas to solve this. I would highly appreciate someone solving this mystery for me. Thank you.

Barmar
  • 741,623
  • 53
  • 500
  • 612
arnab4477
  • 31
  • 1
  • 3
  • 1
    `{...boardMap}` makes a shallow copy of the object. It doesn't make copies of the nested objects. – Barmar Jan 20 '23 at 21:44
  • @Barmar let me check with Object..assign then. But I don't understand why it only occurs in Chrome and not in Node. If the bug is caused by a reference error, shouldn't it be there in the Node environment as well? – arnab4477 Jan 20 '23 at 21:49
  • `Object.assign()` is also a shallow copy. You need to do a deep copy. See the linked question. – Barmar Jan 20 '23 at 21:50
  • I don't know why you're not seeing it in node.js. – Barmar Jan 20 '23 at 21:51
  • @Barmar thank you. I used `JSON.parse(JSON.stringify(boardMap))` and there has not been any issue "so far". I am still not 100% sure because sometimes even with the shallow copy it worked perfectly a few times before suddenly giving unexpected results. So I might come back to this question later if the same thing happens. – arnab4477 Jan 20 '23 at 22:05
  • I think you just might not have been noticing the problems. There's nothing "random" about this. – Barmar Jan 20 '23 at 22:06
  • I am confused about the Nodejs as well but I am not knowledgeable enough about engines and environments to come to my own conclusion. Maybe the browser executes the code differently? I have run tests like 50 times and not a single time any bug occurs. But in the browser it happens at least 2-3 times for only 10 tries. – arnab4477 Jan 20 '23 at 22:08
  • I have console.logged the board many many times. And it gives different results for the exact same moves. Either no bug, or pieces in random squares. – arnab4477 Jan 20 '23 at 22:11
  • You'll need to post a [mre]. If you can provide an example that's not just due to references to the original objects, I'll reopen. – Barmar Jan 20 '23 at 22:13

0 Answers0