I'm not sure if this is the right place to put this question, but it requires a fair amount of chess background so I decided to post it here.

Square notation describes moves by simply noting the square the piece moved from to the square the piece moved to. For example, e4 is e2-e4 and Nf3 is g1-f3.

Algebraic notation is far more common and is well-handled by most chess libraries.

Does anyone have any background working with the conversion between the two?

  • The conversion is very simple. What exactly are you looking for? – SmallChess Jun 13 '15 at 2:32
  • 1
    It's simple to perform as a human, but for mass data sets it is far more efficient to do this programmatically. For example, given a start FEN string square notation, convert this automatically to algebraic notation. – Andrew Ng Jun 13 '15 at 5:19
  • I can help but you need to specify your question. Are you looking for the algorithm? Are you looking for actual code? If so which language? C++ or JavaScript? – SmallChess Jun 13 '15 at 5:26
  • 1
    I'm mainly looking for an algorithm, but it looks as if something like this would require an existing chess library. I'm doing the code for this in Ruby. I imagine this is doable with chess.js and chessboard.js, but for the purposes of this project I don't think I can use these libraries. – Andrew Ng Jun 13 '15 at 6:10
  • No. You don't need an existing library. Do you have a chess move validator implemented? I mean, if I try to move my king four squares, can your program detect this illegal move? – SmallChess Jun 13 '15 at 8:13

To do what you want, you'll need a move validator. To make things clear, let's take a look at the Stockfish iOS chess playing app. The app uses the Stockfish chess engine. The outputs from the engine would be something like:

e2e4 e7e5 ...

But that's not what we want to see. We'd need to convert the outputs to something like:

1. e4 e5

How do we do it? The open-source Stockfish app has a function called move_to_san defined. Please download the full source code from the Stockfish web site. Here, we'll briefly go through the implementation.

const std::string move_to_san(Position &pos, Move m)

This is the header of the function. It takes a position object and a move. That's why I asked you whether you have a move validator implemented. You'll need a validator for this position object as we will see.

from = move_from(m);
to = move_to(m);
pc = pos.piece_on(move_from(m));

Here, we grab the source and destination square. We also need the moving piece.

else if(move_is_long_castle(m)
      || (int(to - from) == -2 && type_of_piece(pc) == KING))
    str = "O-O-O";
else if(move_is_short_castle(m)
      || (int(to - from) == 2 && type_of_piece(pc) == KING))
str = "O-O";

Next, we check if the move is a castle move. Note that it's a good idea to store the move as "e1 to h1". This is not what we normally expect, we always do move the e1 king to the g1 square then the h1 rook to the f1 square. The conditions in the code take care of that.

str = "";

if(type_of_piece(pc) == PAWN) {
    str += file_to_char(square_file(move_from(m)));

This is starting to get interesting. We build an empty buffer. Once we've done it, we'd need to ask if this is a pawn move. If it's a pawn move, convert it to an ASCI character. If our move is e2e4, the buffer would have been "e" by now.

  str += piece_type_to_char(type_of_piece(pc), true);

If this is not a pawn move, we convert the piece to a character. This can be done by a dictionary if you prefer.

  str += "x";

str += square_to_string(move_to(m));

Next, if it's a capture, we add an "x" to it. Then, we'll need to add the destination square.

if(move_promotion(m)) {
  str += "=";
  str += piece_type_to_char(move_promotion(m), true);


pos.do_move(m, u);
    str += pos.is_mate()? "#" : "+";
pos.undo_move(m, u);

Is this a check?

What have we learnt so far?

  1. We need an internal board representation. For example, the code pos.do_move(m, u) needs a mechanism to save the board. You can implement a bitboard, a mailbox or an object-oriented design.
  2. We need a way to tell where the move comes from, where it goes to etc. This can be done by simple logical operations.

Please download the Stockfish iOS source code. Study the code. You can post a new question if you're not sure what to do with the code and I'll help you.

Everything here is in C++. You might need to port the code to Ruby.

  • Thanks so much for your help, I'm taking a look through the source now. – Andrew Ng Jun 15 '15 at 19:26
  • Careful with piece-moves. If another piece of the same type as the moving piece may move to the destination square, the intended move must be disambiguated from the potential move of that other piece. E.g. if White may do Nb1d2 or Nf3d2, write Nbd2 or Nfd2; Nd2 is ambiguous. See chess.stackexchange.com/questions/2777 & chess.stackexchange.com/questions/1864 . Also remember to specify what piece a pawn promotes to. And add '=' if the move is stalemate. – Rosie F Jun 27 '16 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.