-sub style12_to_pos {
- my $str = shift;
- my %pos = ();
- my (@x) = split / /, $str;
-
- $pos{'board'} = [ @x[1..8] ];
- $pos{'toplay'} = $x[9];
- $pos{'ep_file_num'} = $x[10];
- $pos{'white_castle_k'} = $x[11];
- $pos{'white_castle_q'} = $x[12];
- $pos{'black_castle_k'} = $x[13];
- $pos{'black_castle_q'} = $x[14];
- $pos{'time_to_100move_rule'} = $x[15];
- $pos{'move_num'} = $x[26];
- $pos{'last_move'} = $x[29];
- $pos{'fen'} = make_fen(\%pos);
-
- return \%pos;
-}
-
-sub make_fen {
- my $pos = shift;
-
- # the board itself
- my (@board) = @{$pos->{'board'}};
- for my $rank (0..7) {
- $board[$rank] =~ s/(-+)/length($1)/ge;
- }
- my $fen = join('/', @board);
-
- # white/black to move
- $fen .= " ";
- $fen .= lc($pos->{'toplay'});
-
- # castling
- my $castling = "";
- $castling .= "K" if ($pos->{'white_castle_k'} == 1);
- $castling .= "Q" if ($pos->{'white_castle_q'} == 1);
- $castling .= "k" if ($pos->{'black_castle_k'} == 1);
- $castling .= "q" if ($pos->{'black_castle_q'} == 1);
- $castling = "-" if ($castling eq "");
- # $castling = "-"; # chess960
- $fen .= " ";
- $fen .= $castling;
-
- # en passant
- my $ep = "-";
- if ($pos->{'ep_file_num'} != -1) {
- my $col = $pos->{'ep_file_num'};
- my $nep = (qw(a b c d e f g h))[$col];
-
- if ($pos->{'toplay'} eq 'B') {
- $nep .= "3";
- } else {
- $nep .= "6";
- }
-
- #
- # Showing the en passant square when actually no capture can be made
- # seems to confuse at least Rybka. Thus, check if there's actually
- # a pawn of the opposite side that can do the en passant move, and if
- # not, just lie -- it doesn't matter anyway. I'm unsure what's the
- # "right" thing as per the standard, though.
- #
- if ($pos->{'toplay'} eq 'B') {
- $ep = $nep if ($col > 0 && substr($pos->{'board'}[4], $col-1, 1) eq 'p');
- $ep = $nep if ($col < 7 && substr($pos->{'board'}[4], $col+1, 1) eq 'p');
- } else {
- $ep = $nep if ($col > 0 && substr($pos->{'board'}[3], $col-1, 1) eq 'P');
- $ep = $nep if ($col < 7 && substr($pos->{'board'}[3], $col+1, 1) eq 'P');
- }
- }
- $fen .= " ";
- $fen .= $ep;
-
- # half-move clock
- $fen .= " ";
- $fen .= $pos->{'time_to_100move_rule'};
-
- # full-move clock
- $fen .= " ";
- $fen .= $pos->{'move_num'};
-
- return $fen;
-}
-
-sub make_move {
- my ($board, $from_row, $from_col, $to_row, $to_col, $promo) = @_;
- my $move = move_to_uci_notation($from_row, $from_col, $to_row, $to_col, $promo);
- my $piece = substr($board->[$from_row], $from_col, 1);
- my @nb = @$board;
-
- if ($piece eq '-') {
- die "Invalid move $move";
- }
-
- # white short castling
- if ($move eq 'e1g1' && $piece eq 'K') {
- # king
- substr($nb[7], 4, 1, '-');
- substr($nb[7], 6, 1, $piece);
-
- # rook
- substr($nb[7], 7, 1, '-');
- substr($nb[7], 5, 1, 'R');
-
- return \@nb;
- }
-
- # white long castling
- if ($move eq 'e1c1' && $piece eq 'K') {
- # king
- substr($nb[7], 4, 1, '-');
- substr($nb[7], 2, 1, $piece);
-
- # rook
- substr($nb[7], 0, 1, '-');
- substr($nb[7], 3, 1, 'R');
-
- return \@nb;
- }
-
- # black short castling
- if ($move eq 'e8g8' && $piece eq 'k') {
- # king
- substr($nb[0], 4, 1, '-');
- substr($nb[0], 6, 1, $piece);
-
- # rook
- substr($nb[0], 7, 1, '-');
- substr($nb[0], 5, 1, 'r');
-
- return \@nb;
- }
-
- # black long castling
- if ($move eq 'e8c8' && $piece eq 'k') {
- # king
- substr($nb[0], 4, 1, '-');
- substr($nb[0], 2, 1, $piece);
-
- # rook
- substr($nb[0], 0, 1, '-');
- substr($nb[0], 3, 1, 'r');
-
- return \@nb;
- }
-
- # check if the from-piece is a pawn
- if (lc($piece) eq 'p') {
- # attack?
- if ($from_col != $to_col) {
- # en passant?
- if (substr($board->[$to_row], $to_col, 1) eq '-') {
- if ($piece eq 'p') {
- substr($nb[$to_row + 1], $to_col, 1, '-');
- } else {
- substr($nb[$to_row - 1], $to_col, 1, '-');
- }
- }
- } else {
- if ($promo ne '') {
- if ($piece eq 'p') {
- $piece = $promo;
- } else {
- $piece = uc($promo);
- }
- }
- }
- }
-
- # update the board
- substr($nb[$from_row], $from_col, 1, '-');
- substr($nb[$to_row], $to_col, 1, $piece);
-
- return \@nb;
-}
-
-sub prettyprint_pv {