Devlog 0x7 - Generating Non-Capture Pawn Moves

Devlog 0x7. Today, I started the initial implementation of my generateMoves() function, which will eventually enumerate all possible moves in a chess position. My focus for this session was on the “quiet” (i.e., non-capturing) pawn moves for both White and Black pawns.

A summary of what's been accomplished

  • Iterating Over Pawns

    • I loop through the board’s piece bitboards, looking for either white pawns (bitboard.pieceEncoding.P) or black pawns (bitboard.pieceEncoding.p), depending on bitboard.sideToMove.
    • For each found pawn, I calculate its location using sourceSquare = @intCast(utils.getLSBindex(bitboardCopy)), then pop that bit from bitboardCopy to move on to the next pawn.
  • Single-Pawn Push

    • White pawns move “up” the board (sourceSquare - 8), while Black pawns move “down” (sourceSquare + 8).
    • A push is legal if the target square is on the board and unoccupied. I check this using:
    if (utils.getBit(bitboard.occupancies[@intFromEnum(bitboard.side.both)], targetSquare) == 0) {
        // ...
    }

If the move is legal, I print a debug message like this:

pawn push: e2e3
  • Pawn Promotion
    • If a White pawn is on the 7th rank (e.g., a7–h7) or a Black pawn is on the 2nd rank (a2–h2), a single push leads to promotion.
    • I currently print all promotion variants (=Q, =R, =N, =B) for debugging, e.g.:
pawn promotion: e7e8q
pawn promotion: e7e8r
pawn promotion: e7e8n
pawn promotion: e7e8b
  • Double-Pawn Push
    • If a White pawn is on the 2nd rank (or a Black pawn on the 7th rank) and the single-push square is free, I check if the square two steps away is also free. If yes, I log:
  double pawn push: e2e4.
  • This sets up potential en-passant situations for a subsequent move (though en-passant capture logic isn’t implemented here yet).

For brevity, I've decided not to include the source code for what's been implemented so far in the article, but you can always check that out here.

What’s Next

My next step will be to add capturing moves for pawns, including regular captures, en-passant, and promotion-capture scenarios. After that, I’ll handle other pieces (knights, bishops, rooks, queen, king) for both capturing and non-capturing moves.

Overall, I’m excited about how my implementation is working so far. With this groundwork laid for quiet pawn moves, I’m one step closer to a fully functional move generator. Stay tuned for updates on captures and other piece moves! See you tomorrow :)