# Perl, 147 bytes

Includes +4 for ` -0p`

The program plays `X`. It will play a perfect game.

Input the board on STDIN, e.g.:

    tictaclatin.pl
    -X-O
    -X--
    X-X-
    O--O
    ^D

The ouptut will be the same board with all `X` replaced by `O` and vice versa. The empty spots will be filled with a number indicating the result if X would play there, with `1` meaning the result will be a win, `2` a draw and `3` a loss. A finished game just returns the same position with the colors reversed.

In this example the output would be:

    1O1X
    1O33
    O3O3
    X33X

So the position is a win for `X` if he plays in the 3 spots along the top and the left. All other moves lose.

This confusing output is actually convenient if you want to know how the game continues after a move. Since the program always plays `X` you have to swap `X` and `O` to see the moves for `O`. Here for example it's pretty clear that `X` wins by playing in the top left, but what about if `X` plays in the third position along the top ? Just copy the output, put an `O` in place of the move you select and replace all other numbers by `-` again, so here:

    -OOX
    -O--
    O-O-
    X--X

Resulting in:

    3XXO
    3X33
    X3X3
    O33O

Obviously every move by `O` should lose, so how does he lose if he plays in the top left ? Again do this by putting `O` in the top left and replacing the digits by `-`:

    OXXO
    -X--
    X-X-
    O--O

Giving:

    XOOX
    1O33
    O3O3
    X33X

So X has only one way to go for his win:

    XOOX
    OO--
    O-O-
    X--X

Giving

    OXXO
    XX33
    X3X3
    O33O

The situation for `O` remains hopeless. It's easy to see now that every move allows `X` to immediately win. Let's at least try to go for 3 O's in a row:

    OXXO
    XX--
    X-X-
    O-OO

Giving:

    XOOX
    OO13
    O3O3
    X3XX

`X` plays the only winning move (notice that this makes `XXOX` along the third column:

    XOOX
    OOO-
    O-O-
    X-XX

Here the output is:

    OXXO
    XXX-
    X-X-
    O-OO

because the game was already finished. You can see the win on the third column.

The actual program `tictaclatin.pl`:

    #!/usr/bin/perl -0p
    y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/sx;$@<=>0||s%-%$_="$`O$'";$$_||=2+do$0%eg&&(/1/||/2/-1)

Applied to the empty board this evaluates 9506699 positions which takes 30Gb and 41 minutes on my computer. The result is:

    2222
    2222
    2222
    2222

So every starting move draws. So the game is a draw.

The extreme memory usage is mostly caused by the recursion using `do$0`. Using this 154 byte version using a plain function needs 3Gb and 11 minutes:

    #!/usr/bin/perl -0p
    sub f{y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/sx;$@<=>0||s%-%$_="$`O$'";$$_||=2+&f%eeg&&(/1/||/2/-1)}f

which is more bearable. Both version of course get faster and use less memory as the board fills up.

In principle this 146 byte version should also work:

    #!/usr/bin/perl -0p
    y/XO/OX/,$@=-$@while/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^/sx,--$|;$@<=>0||s%-%$_="$`O$'";$$_||=2+do$0%eg&&(/1/||/2/-1)

but on my machine it triggers a perl bug and dumps core.

All versions will in principle still work if the 6 byte position caching done by `$$_||=` is removed but that uses so much time and memory that it only works for almost filled boards. But in theory at least I have a 140 byte solution.