Problem:
Karakuri Doll

からくり人形

English text is not available in this practice contest.

からくり人形師の JAG 氏は，長年の研究の果てに，伝統技術と最新技術を融合させたすばらしいお茶汲み人形の開発に成功した．このお茶汲み人形は，下の図のように格子に区切られた家の中で，台所（K）でお茶の入った湯飲みを乗せるとそれを主人（M）の居場所まで持っていき，主人が飲み終わった湯飲みを乗せると台所まで戻っていくという仕事をする．ただし，この人形は台所と主人の間の往復経路を自分で見つけられるほど賢くはない．使用者はこの人形にプログラムをあらかじめ入力して，人形がきちんと往復できるようにする必要がある．

図 F-1: 家の構造の例

人形が受理する命令は「左に曲がる」と「右に曲がる」の 2 つであり，人形に入力可能なプログラムは命令の有限な列である．人形は台所を出発した後，壁（図中「#」で表されたマス）にぶつかるまで前進し，壁にぶつかると最初の命令に従って左または右に方向転換する．以降，再び壁にぶつかるまで前進し，ぶつかったら次の命令を実行し，以下同様に物事が進む．方向転換してもなお壁にぶつかって前進できないときは，その場所から移動しないまま次の命令を実行する．壁にぶつかったとき，実行する命令が残っていなければ人形は停止する．これをプログラムの順実行と呼ぶ．

主人の居場所から台所に戻るときは，プログラムの命令列を逆順に実行し，さらに左右反対に方向転換する．これをプログラムの逆実行と呼ぶ．命令の実行順序および方向転換以外の挙動は順実行と同じである．

たとえば，上の図の家で，この人形に「右，右，左」というプログラムを与えると，往路では地点 a で右，地点 b で右，地点 c で左にそれぞれ方向転換して主人の居場所に到着する．また，復路では地点 c で右，地点 b で左，地点 a で左にそれぞれ方向転換して台所に帰還する．一方，「左，左」というプログラムを与えると，人形はまず地点 a で左に方向転換する．直進しようとするが，そのまま左側の壁にぶつかるため，地点 a にとどまったまま 2 番目の命令にしたがって左に方向転換する．そして直進して台所まで戻ってきたところで壁にぶつかり，命令が残っていないので停止する．

ところで，JAG 氏は大きな過ちを犯していた．実は，どのようなプログラムを与えても主人の居場所までたどり着けない場合が存在するのである．また，主人の居場所に着いたとしても，湯飲みを台所まで持って帰れない場合もある．

あなたの仕事は，ある家の中でこの人形を使ったときに，この人形が主人の居場所に到着できるか，そして台所に帰還できるかを判断するプログラムを書くことである．

Input

入力は複数のデータセットからなり，最後に 0 0 と書かれた行が入力の終わりを示す．データセットの数は 128 個以下である．

各データセットの最初の行には，家の大きさを表す 2 つの整数 W, H がスペース区切りで書かれる．これらの整数は 3 ≦ W ≦ 64, 3 ≦ H ≦ 16 を満たす．続く H 行は部屋の構造を意味する．各行は W 文字から構成され，「#」は壁を，「.」（ピリオド）は床を，「K」は台所を，「M」は主人の居場所をそれぞれ示す．これら以外の文字は含まれない．

この家の最外部は，常に壁（「#」）であることが保証されている．また「K」と「M」は，各データセットについて常に 1 つずつ存在して，3 方向が壁（「#」），残りの 1 方向が床（「.」）であると仮定してよい．

Output

各データセットに対して，以下の記述のとおりにメッセージを 1 行に出力しなさい．

どのようなプログラムを与えても主人の居場所に到着しない場合は「He cannot bring tea to his master.」

主人の居場所には到着するが，その後に台所に帰還するようにプログラムできない場合は「He cannot return to the kitchen.」

主人の居場所に到着して，台所に帰還するようにプログラムできる場合は「He can accomplish his mission.」

ここで，主人の居場所に到着するとは，人形を台所に置いて壁のない方向に向けた状態から，プログラムを順実行したときに，停止時点において主人の居場所に人形が存在することを指す．台所に帰還するとは，人形を主人の居場所に置いて壁のない方向に向けた状態から，プログラムを逆実行したときに，停止時点において台所に人形が存在することを指す．停止時点における人形の向きは問わない．また，往路，復路ともに，経路の途中で台所または主人を通過しても構わない．ただし，経路の途中で台所または主人を通過したとしても，停止時点において人形がそれ以外の場所にいるときは，主人の居場所に到着した，あるいは台所に帰還したとはみなされない．

Sample Input

5 3
#####
#K.M#
#####
9 5
#########
#.....###
#.###..M#
#K#######
#########
9 5
#########
#K......#
####.####
####M####
#########
9 5
#########
#M......#
####.####
####K####
#########
7 9
#######
#####M#
#####.#
#.....#
#.###.#
#.....#
#.#####
#K#####
#######
7 6
#######
#####.#
##....#
#K..#.#
###M#.#
#######
7 8
#######
##...##
###.#M#
#.....#
#.#...#
#.#..##
#.K####
#######
9 6
#########
###..##.#
##......#
#K....#.#
##..#M#.#
#########
9 6
#########
#.#######
#....#M.#
#.#...#.#
###K#...#
#########
12 7
############
###...####.#
##K#...M##.#
##.....#...#
#........#.#
###..#...#.#
############
23 16
#######################
#########...###########
##########.###.########
##########.....########
##########.#.#.###...##
########.#.#.######.###
########............###
########.###.######.###
############.######.###
#K...........######.###
####.#######.######.###
####.#######.######.###
####.................M#
####.#######.##########
###...#####...#########
#######################
46 16
##############################################
#..............#..############################
#..#..........#.#.###....#...................#
#.................###.#.#.#...............#..#
#...#..#....#...#.###.#......................#
#...#....#....#.#.###.#.#...#....#....#..#...#
#.#........#..........#.#.#....#....#....#...#
#...#...#.......###.#........#.........#...#.#
#.#...#.........###.#..##.......#........#...#
#...#........#..###.#..##.........#........#.#
#...............###.#..##..#.........#...#...#
############.######.#..##....................#
###########K...........#.########.############
###################...............M###########
##################.......#####################
##############################################
0 0

Output for the Sample Input

He can accomplish his mission.
He can accomplish his mission.
He cannot bring tea to his master.
He cannot return to the kitchen.
He can accomplish his mission.
He can accomplish his mission.
He cannot return to the kitchen.
He cannot return to the kitchen.
He can accomplish his mission.
He can accomplish his mission.
He cannot return to the kitchen.
He can accomplish his mission.

Solution in C++11 (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;

#define for_(i,a,b) for(int i=(a);i<(b);++i)
typedef pair< int, int > pii;

// L,U,R,D --- right:+1, left:-1
const int dx[4] = {-1,0,1,0};
const int dy[4] = {0,1,0,-1};
const int dc[2] = {-1,1};

int changeDirection(int f, int c) { return (f + dc[c] + 4) % 4; }

int W, H, pos_id[16][64];
string home_map[16];

int nextPos(int cx, int cy, int d) {
	while (home_map[cy + dy[d]][cx + dx[d]] != '#') {
		cx += dx[d];
		cy += dy[d];
	}
	return pos_id[cy][cx];
}

/***************** solver ********************/

int trans[1024][4][2];
vector< int > trans_rev[1024][4][2];
int start_id, start_dir, goal_id, goal_dir;
vector< int > wall_dir_at_K;

void constructTransition() {
	for_(i,0,1024) for_(j,0,4) for_(k,0,2) trans_rev[i][j][k] = vector< int >();
	wall_dir_at_K = vector< int >();
	
	int id = 1;
	for_(y,0,H) for_(x,0,W) {
		if (home_map[y][x] == 'K') pos_id[y][x] = 0;
		else if (home_map[y][x] == 'M') pos_id[y][x] = 1023;
		else if (home_map[y][x] == '.') pos_id[y][x] = id++;
	}
	
	int cnt = 0;
	for_(y,0,H) {
		for_(x,0,W) {
			if (home_map[y][x] == 'M' || home_map[y][x] == 'K') {
				for_(d,0,4) {
					int nx = x + dx[d], ny = y + dy[d];
					if (home_map[ny][nx] == '#') {
						if (home_map[y][x] == 'K') wall_dir_at_K.push_back(d);
						continue;
					}
				
					if (home_map[y][x] == 'M') {
						goal_id = nextPos(nx, ny, d);
						goal_dir = d;
					} else {
						start_id = nextPos(nx, ny, d);
						start_dir = d;
					}
				}
				++cnt;
			}
			if (cnt == 2) break;
		}
		if (cnt == 2) break;
	}
	
	for_(y,0,H) for_(x,0,W) {
		if (home_map[y][x] == '#') continue;
		id = pos_id[y][x];
		for_(f,0,4) for_(c,0,2) {
			int nxt_dir = changeDirection(f, c);
			int nxt_id = nextPos(x, y, nxt_dir);
			trans[id][f][c] = nxt_id;
			trans_rev[nxt_id][nxt_dir][c].push_back(id);
		}
	}
}

int SHIFT = 16, MASK = (1 << 16) - 1;
bool visM[1024][4];
bool vis[1024][4][1024][4];

inline int makeState(int id, int dir) { return (id | (dir << SHIFT)); }
inline int getID(int state) { return (state & MASK); }
inline int getDIR(int state) { return (state >> SHIFT); }

bool canReachMaster() {
	memset(visM, 0, sizeof(visM));
	
	queue< int > que;
	que.push(makeState(start_id, start_dir));
	visM[start_id][start_dir] = true;
	
	while (!que.empty()) {
		int s = que.front(); que.pop();
		int id = getID(s), dir = getDIR(s);
		if (id == 1023) return true;
		for_(c,0,2) {
			int nxt_id = trans[id][dir][c], nxt_dir = changeDirection(dir, c);
			if (!visM[nxt_id][nxt_dir]) {
				visM[nxt_id][nxt_dir] = true;
				que.push(makeState(nxt_id, nxt_dir));
			}
		}
	}
	
	return false;
}

bool canDo() {
	memset(vis, 0, sizeof(vis));
	
	queue< pii > que;
	for (int d : wall_dir_at_K) {
		que.push(pii(makeState(start_id, start_dir), makeState(0, d)));
		vis[start_id][start_dir][0][d] = true;
	}
	
	while (!que.empty()) {
		pii p = que.front(); que.pop();
		int id = getID(p.first), dir = getDIR(p.first);
		int rev_id = getID(p.second), rev_dir = getDIR(p.second);
		if (id == 1023 && rev_id == goal_id && rev_dir == goal_dir) return true;
		for_(c,0,2) {
			int nxt_id = trans[id][dir][c], nxt_dir = changeDirection(dir, c), nxt_rev_dir = changeDirection(rev_dir, c);
			for (int nxt_rev_id : trans_rev[rev_id][rev_dir][1 - c]) {
				if (!vis[nxt_id][nxt_dir][nxt_rev_id][nxt_rev_dir]) {
					vis[nxt_id][nxt_dir][nxt_rev_id][nxt_rev_dir] = true;
					que.push(pii(makeState(nxt_id, nxt_dir), makeState(nxt_rev_id, nxt_rev_dir)));
				}
			}
		}
	}
	
	return false;
}

void solve() {
	constructTransition();	
	if (canReachMaster()) {
		if (canDo()) puts("He can accomplish his mission.");
		else puts("He cannot return to the kitchen.");
	} else {
		puts("He cannot bring tea to his master.");
	}
}

int main() {
	while (1) {
		cin >> W >> H;
		if (H == 0) break;
		for_(y,0,H) cin >> home_map[y];
		solve();
	}
}