I4AKZYZM5LOD7SNZRNWY34KWOHE34QPEWO6TIGHYMJACXOJKBMPQC #### Generating movesWe created the attacks, now it is time to apply them. The `generateMoves()` function in`Board.zig` does exactly that. For every piece generates all the possible moves giventhe current Board state.Unlike the previous step this is for a given GameState, not some general rule.The `isSquareAttacked()` helps to determine if a castling move is possible or not. Wewill also use this function to discard invalid moves in next step.
#### Making movesAfter generating all possible moves it is time to make those moves. We are still in`Board.zig`, but we use the `makeMove()` function for that.This function takes a move, updates `GameState`'s `bitboards` and `occupancies`,sets the new side etc. The final result is a new `GameState`.This function finally checks if that is a valid move (eg. the king is not in check)with `isSquareAttacked()` and returns `true` or `false` accordingly.##### Preserving and restoring game statesWhen the chess engine makes a move the board state changes. We have to use `backup()` and`restore()` functions to reset the states after a given move.
The basic search is enhanced with the following techniques:- [Alpha-beta pruning](https://www.chessprogramming.org/Alpha-Beta)- [Checkmate and Stalemate detection](https://youtu.be/lAAdjCkWd9s)- [Quiescence Search](https://www.chessprogramming.org/Quiescence_Search)- [Move Scoring](https://www.chessprogramming.org/Move_Ordering)- [MVV-MLA](https://www.chessprogramming.org/MVV-LVA)- [Killer Move](https://www.chessprogramming.org/Killer_Move)- [History Heuristics](https://www.chessprogramming.org/History_Heuristic)These fancy names may seem intimidating, but implementing them is not that hard.