/******************************************************************/
/* ACM ICPC 2012-2013                                             */
/* Northeastern European Regional Contest                         */
/* St Petersburg - Barnaul - Tashkent - Tbilisi, December 2, 2012 */
/******************************************************************/
/* Problem L. Labyrinth of the Minotaur                           */
/*                                                                */
/* Original idea         Georgiy Korneev                          */
/* Problem statement     Georgiy Korneev                          */
/* Test set              Georgiy Korneev                          */
/******************************************************************/
/* Checker                                                        */
/*                                                                */
/* Author                Georgiy Korneev                          */
/******************************************************************/

import ru.ifmo.testlib.Checker;
import ru.ifmo.testlib.InStream;
import ru.ifmo.testlib.Outcome;

import java.util.ArrayDeque;
import java.util.Queue;

import static ru.ifmo.testlib.Outcome.Type.*;

public class Check implements Checker {
    class Coordinates {
        final int y;
        final int x;

        Coordinates(int y, int x) {
            this.y = y;
            this.x = x;
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof Coordinates) {
                Coordinates that = (Coordinates) o;
                return x == that.x && y == that.y;
            }
            return false;
        }

        @Override
        public int hashCode() {
            return 31 * y + x;
        }
    }

    boolean[][] visited;
    Queue<Coordinates> queue = new ArrayDeque<>();
    int w, h;
    char[][] labyrinth;

    static class Ans {
        boolean impossible;
        int s;
        int x;
        int y;

        Ans(InStream out) {
            impossible = "Impossible".equals(out.nextToken());
            if (!impossible) {
                out.reset();
                s = out.nextInt();
                x = out.nextInt() - 1;
                y = out.nextInt() - 1;
            }
            if (!out.seekEoF())
                throw new Outcome(PE, String.format("Extra data in output file"));
        }
    }

    public Outcome test(InStream inf, InStream ouf, InStream ans) {
        w = inf.nextInt();
        h = inf.nextInt();
        inf.nextLine();
        labyrinth = new char[h][w];
        for (int i =  0; i < h; i++) {
            labyrinth[i] = inf.nextLine().toCharArray();
        }

        Ans ja = new Ans(ans);
        Ans pa = new Ans(ouf);

        if (pa.impossible) {
            if (ja.impossible) {
                return new Outcome(OK, String.format("Impossible"));
            }
            return new Outcome(WA, String.format("Impossible, when solution exists"));
        }

        int s = pa.s;
        int x = pa.x;
        int y = pa.y;

        checkRange(s, 1, Math.min(h, w), "s");
        checkRange(x + 1, 1, w, "x");
        checkRange(y + 1, 1, h, "x");
        checkRange(x + s, 1, w, "x + s");
        checkRange(y + s, 1, h, "y + s");

        if (!(x != 0 || y != 0)) {
            throw new Outcome(WA, String.format("Cannot block entrance"));
        }
        if (!(x + s != w || y + s != h)) {
            throw new Outcome(WA, String.format("Cannot block lair"));
        }

        for (int i = y; i < y + s; i++) {
            for (int j = x; j < x + s; j++) {
                if (labyrinth[i][j] == '#') {
                    return new Outcome(WA, String.format("Cell (%d, %d) already blocked %c", i + 1, i + 1, labyrinth[i][j]));
                }
                labyrinth[i][j] = '#';
            }
        }

        visited = new boolean[h][w];
        visit(0, 0);
        while (!queue.isEmpty()) {
            Coordinates c = queue.remove();
            visit(c.y + 1, c.x);
            visit(c.y - 1, c.x);
            visit(c.y, c.x + 1);
            visit(c.y, c.x - 1);
        }

        boolean condition = !visited[h - 1][w - 1];
        if (!condition) {
            throw new Outcome(WA, String.format("There is a path from entrance to lair"));
        }

        if (ja.impossible) {
            return new Outcome(FAIL, String.format("Contestant found solution, while jury does not"));
        }
        if (s < ja.s) {
            return new Outcome(FAIL, String.format("Contestant found better solution"));
        }
        if (!(s == ja.s)) {
            throw new Outcome(WA, String.format("size = %d, while %d is enough", s, ja.s));
        }
        return new Outcome(OK, String.format("size = %d", s));
    }

    private void visit(int y, int x) {
        if (0 <= x && x < w && 0 <= y && y < h && labyrinth[y][x] == '.') {
            if (!visited[y][x]) {
                visited[y][x] = true;
                queue.add(new Coordinates(y, x));
            }
        }
    }

    private void checkRange(int v, int l, int r, String what) {
        if (!(l <= v && v <= r)) {
            throw new Outcome(WA, String.format("%s out of range %d..%d: %d", what, l, r, v));
        }
    }
}

