program BlackBoxAtom;
{
    Solution to the 1999 British Informatics Olympiad exam
    question 2: Black Box (Atom)

    Solution copyright (c) 1999 The British Informatics Olympiad (BIO).

    This program may be freely copied by persons or organisations
    involved in the British Informatics Olympiad or the International
    Olympiad in Informatics, on condition that no changes are made and
    this notice is not altered. Distribution for profit is forbidden
    unless permission is first obtained in writing from the BIO.

    This program is for educational purposes only and comes with no
    warranty, implied or otherwise, as to its fitness for any purpose.

    Author:     Antony Rix
    Internet:   http://www.christs.cam.ac.uk/bio/
    E-mail:     a.rix@lineone.net
    S-mail:     The British Informatics Olympiad
                Christ's College
                Cambridge CB2 3BU
                United Kingdom
}

{ Key constants. }
const Blank = 0;
const Atom = 1;
const Ray = 2;
const Hit = 3;

var
{ Array holding board. }
    Board: array[0..11,0..11] of integer;

{ Set up a blank board }
procedure init_board;
var i, j: integer;
begin
    for i := 0 to 11 do for j := 0 to 11 do
        Board[i][j] := Blank;
end;

{ Clear the trace of a ray from the board }
procedure reset_board;
var x, y: integer;
begin
    for x := 0 to 11 do for y := 0 to 11 do
    case Board[x][y] of
         Blank: Board[x][y] := Blank;
         Atom: Board[x][y] := Atom;
         Ray: Board[x][y] := Blank;
         Hit: Board[x][y] := Atom;
    end;
end;

{ Display the current board. }
procedure show_board;
var x, y: integer;
begin
    for y := 10 downto 1 do begin
        for x := 1 to 10 do
            case Board[x][y] of
                 Blank: write( '.' );
                 Atom: write( 'A' );
                 Ray: write( '+' );
                 Hit: write( '*' );
            end;
        writeln;
    end;
end;

{ Follow the path of the ray. }
procedure trace_ray( side: char; pos: integer );
var
    direct: integer;
    x, y, nx, ny: integer;
begin
    { Starting position and direction }
    if side = 'B' then begin direct := 0; x := pos; y := 1; end
    else if side = 'L' then begin direct := 1; y := pos; x := 1; end
    else if side = 'T' then begin direct := 2; x := pos; y := 10; end
    else if side = 'R' then begin direct := 3; y := pos; x := 10; end
    else exit;

    { Follow ray until it runs out of the box }
    while (x > 0) and (x < 11) and (y > 0) and (y < 11) do begin
        Board[x][y] := Ray;

        { Find new position then apply the rules }
        nx := x; ny := y;
        case direct of
            0: ny := y + 1;
            1: nx := x + 1;
            2: ny := y - 1;
            3: nx := x - 1;
        end;

        { If absorbed, show the hit and return }
        if Board[nx][ny] = Atom then begin
            Board[nx][ny] := Hit;
            show_board;
            writeln( 'Absorbed' );
            exit;
        end;

        { If reflected, simply return - the ray will retrace its path }
        if (direct = 0) or (direct = 2) then begin
            if (Board[nx-1][ny] = Atom) and (Board[nx+1][ny] = Atom) then begin
                show_board;
                writeln( 'Reflected' );
                exit;
            end;
        end
        else begin
            if (Board[nx][ny-1] = Atom) and (Board[nx][ny+1] = Atom) then begin
                show_board;
                writeln( 'Reflected' );
                exit;
            end;
        end;

        { Check for a deflection.  If we deflect, move back to the last
               position and change direction. }
        if (direct = 0) or (direct = 2) then begin
                if Board[nx-1][ny] = Atom then begin direct := 1; ny := y; end;
                if Board[nx+1][ny] = Atom then begin direct := 3; ny := y; end;
        end
        else begin
                if Board[nx][ny-1] = Atom then begin direct := 0; nx := x; end;
                if Board[nx][ny+1] = Atom then begin direct := 2; nx := x; end;
        end;

        { Update position }
        x := nx;
        y := ny;
    end;

    show_board;
    { Find exit point }
    if x = 0 then writeln( 'Exits at L ', y );
    if y = 0 then writeln( 'Exits at B ', x );
    if x = 11 then writeln( 'Exits at R ', y );
    if y = 11 then writeln( 'Exits at T ', x );
end;

procedure part2a;
var
    i, x, y: integer;
    side: char;
begin
    init_board;
    writeln( 'Enter 5 co-ordinates in the form x y' );

    for i := 1 to 5 do begin
        write( '>' );
        readln( x, y );
        Board[x][y] := Atom;
    end;
    show_board;
    writeln;

    { Main program loop: read in a character/number pair and then
      perform that action }
    repeat
        write( '>' );
        readln( side, i );
        side := upcase( side );
        if ( (side = 'T') or (side = 'B') or (side = 'L') or (side = 'R') )
            and (i > 0) and ( i < 11 ) then begin
            trace_ray( side, i );
            reset_board;
            writeln;
        end
        else if side <> 'X' then
            writeln( 'Invalid input "', side, ' ', i, '"' );
    until side = 'X';
    writeln( 'Program finished.' );
end;

begin
    part2a;
end.