Buggy python submission (verdict: Time Limit Exceeded):
import sys

# D - Wizard in Maze
def get_index(s):
	return int(s) - 1


def search_nearby(h, w):
# 上下左右に隣接するマスを探索
	search(h + 1, w, False)
	search(h - 1, w, False)
	search(h, w + 1, False)
	search(h, w - 1, False)


def search_using_warp(h, w):
  # ワープ魔法で移動できるマスを探索
  for i in range(-2, 3):
    search(h - 2, w + i)
    search(h + 2, w + i)

  for i in range(-2, 3):
    if i != 0:
      search(h - 1, w + i)
      search(h + 1, w + i)

  search(h, w + 2)
  search(h, w - 2)


def search(h, w, is_using_warp = True):
  global is_reached
  global que
  global next_que

  if can_reach(h, w):
	  is_reached[h][w] = True
	  next_que.append([h, w])

	  if not is_using_warp:
	    que.append([h, w])


def can_reach(h, w):
	global H
	global W
	global maze

	if h < 0 or h >= H or w < 0 or w >= W:
		return False
	elif maze[h][w] == '#':
		return False
	elif is_reached[h][w]:
		return False
	else:
		return True


from collections import deque
import copy

H, W = map(int, input().split())
Ch, Cw = map(get_index, input().split())
Dh, Dw = map(get_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

next_que = deque()
next_que.append([Ch, Cw])
mp = 0

while len(next_que) > 0:
  que = copy.deepcopy(next_que)

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_nearby(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

  que = copy.deepcopy(next_que)
  next_que.clear()
  mp += 1

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_using_warp(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

print(-1)

Fixed submission:
import sys

# D - Wizard in Maze
def get_index(s):
	return int(s) - 1


def search_nearby(h, w):
# 上下左右に隣接するマスを探索
	search(h + 1, w, False)
	search(h - 1, w, False)
	search(h, w + 1, False)
	search(h, w - 1, False)


def search_using_warp(h, w):
  # ワープ魔法で移動できるマスを探索
  for i in range(-2, 3):
    search(h - 2, w + i)
    search(h + 2, w + i)

  for i in range(-2, 3):
    if i != 0:
      search(h - 1, w + i)
      search(h + 1, w + i)

  search(h, w + 2)
  search(h, w - 2)


def search(h, w, is_using_warp = True):
  global is_reached
  global que
  global next_que

  if can_reach(h, w):
	  is_reached[h][w] = True
	  next_que.append([h, w])

	  if not is_using_warp:
	    que.append([h, w])


def can_reach(h, w):
	global H
	global W
	global maze

	if h < 0 or h >= H or w < 0 or w >= W:
		return False
	elif maze[h][w] == '#':
		return False
	elif is_reached[h][w]:
		return False
	else:
		return True


from collections import deque
import copy

H, W = map(int, input().split())
Ch, Cw = map(get_index, input().split())
Dh, Dw = map(get_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

next_que = deque()
next_que.append([Ch, Cw])
mp = 0

while len(next_que) > 0:
  que = copy.deepcopy(next_que)

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_nearby(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

  que = copy.deepcopy(next_que)
  next_que.clear()
  mp += 1

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_using_warp(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

print(-1)

Buggy python submission (verdict: Time Limit Exceeded):
import sys

# D - Wizard in Maze
def get_index(s):
	return int(s) - 1


def search(h, w):
  global que
  
  if can_reach(h, w):
    que.append([h, w])


def can_reach(h, w):
	global H
	global W
	global maze
	
	if h < 0 or h >= H or w < 0 or w >= W:
		return False
	elif maze[h][w] == '#':
		return False
	else:
		return True
	

from collections import deque
import copy

H, W = map(int, input().split())
Ch, Cw = map(get_index, input().split())
Dh, Dw = map(get_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

costs = [[-1] * W for _ in range(H)]
que = deque()
que.append([Ch, Cw])

next_que = deque()
next_que.append([Ch, Cw])

# コスト(ワープ魔法を使った回数)
i = 0

while len(next_que) > 0:
  que = copy.deepcopy(next_que)
  next_que.clear()
  
  # コストiで到達可能なマスを列挙
  while len(que) > 0:
	  h, w = que.popleft()
	  costs[h][w] = i
	
	  next_que.append([h, w])
	
	  # 上下左右に隣接するマスを探索
	  search(h + 1, w)
	  search(h - 1, w)
	  search(h, w + 1)
	  search(h, w - 1)
	 
  i += 1

print(costs[Dh][Dw])


Fixed submission:
import sys

# D - Wizard in Maze
def get_index(s):
	return int(s) - 1


def search_nearby(h, w):
# 上下左右に隣接するマスを探索
	search(h + 1, w, False)
	search(h - 1, w, False)
	search(h, w + 1, False)
	search(h, w - 1, False)


def search_using_warp(h, w):
  # ワープ魔法で移動できるマスを探索
  for i in range(-2, 3):
    search(h - 2, w + i)
    search(h + 2, w + i)

  for i in range(-2, 3):
    if i != 0:
      search(h - 1, w + i)
      search(h + 1, w + i)

  search(h, w + 2)
  search(h, w - 2)


def search(h, w, is_using_warp = True):
  global is_reached
  global que
  global next_que

  if can_reach(h, w):
	  is_reached[h][w] = True
	  next_que.append([h, w])

	  if not is_using_warp:
	    que.append([h, w])


def can_reach(h, w):
	global H
	global W
	global maze

	if h < 0 or h >= H or w < 0 or w >= W:
		return False
	elif maze[h][w] == '#':
		return False
	elif is_reached[h][w]:
		return False
	else:
		return True


from collections import deque
import copy

H, W = map(int, input().split())
Ch, Cw = map(get_index, input().split())
Dh, Dw = map(get_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

next_que = deque()
next_que.append([Ch, Cw])
mp = 0

while len(next_que) > 0:
  que = copy.deepcopy(next_que)

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_nearby(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

  que = copy.deepcopy(next_que)
  next_que.clear()
  mp += 1

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_using_warp(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

print(-1)

Buggy python submission (verdict: Time Limit Exceeded):
import sys

# D - Wizard in Maze
def conv_index(s):
	return int(s) - 1


def search(h, w, set_, mp):
  global Dh
  global Dw
  global can_goal
  global ans

  if h == Dh and w == Dw:
    can_goal = True
    ans.append(mp)
  elif not can_reach(h, w, set_):
    return
  else:
    route = copy.copy(set_)
    route.add(coord(h, w))

    if need_to_use_mp(h, w, route):
      mp += 1

      for i in range(-2, 3):
        search(h - 2, w + i, route, mp)
        search(h + 2, w + i, route, mp)

      for i in range(-2, 3):
        if i != 0:
          search(h - 1, w + i, route, mp)
          search(h + 1, w + i, route, mp)

      search(h, w - 2, route, mp)
      search(h, w + 2, route, mp)
    else:
      search(h - 1, w, route, mp)
      search(h + 1, w, route, mp)
      search(h, w - 1, route, mp)
      search(h, w + 1, route, mp)


def can_reach(h, w, route):
	global H
	global W
	global maze

	if h < 0 or h > H - 1 or w < 0 or w > W - 1:
		return False
	elif maze[h][w] == '#':
		return False
	elif coord(h, w) in route:
		return False
	else:
		return True


def coord(h, w):
  return str(h) + ' ' + str(w)


def need_to_use_mp(h, w, route):
	any_can_reach = False

	if can_reach(h - 1, w, route):
		any_can_reach = True

	if can_reach(h + 1, w, route):
		any_can_reach = True

	if can_reach(h, w - 1, route):
		any_can_reach = True

	if can_reach(h, w + 1, route):
		any_can_reach = True

	if not any_can_reach:
		return True


import copy
sys.setrecursionlimit(1000000)

H, W = map(int, input().split())
Ch, Cw = map(conv_index, input().split())
Dh, Dw = map(conv_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

can_goal = False
ans = []

search(Ch, Cw, set(), 0)

if not can_goal:
	print(-1)
elif len(ans) == 0:
	print(0)
else:
	print(min(ans))


Fixed submission:
import sys

# D - Wizard in Maze
def get_index(s):
	return int(s) - 1


def search_nearby(h, w):
# 上下左右に隣接するマスを探索
	search(h + 1, w, False)
	search(h - 1, w, False)
	search(h, w + 1, False)
	search(h, w - 1, False)


def search_using_warp(h, w):
  # ワープ魔法で移動できるマスを探索
  for i in range(-2, 3):
    search(h - 2, w + i)
    search(h + 2, w + i)

  for i in range(-2, 3):
    if i != 0:
      search(h - 1, w + i)
      search(h + 1, w + i)

  search(h, w + 2)
  search(h, w - 2)


def search(h, w, is_using_warp = True):
  global is_reached
  global que
  global next_que

  if can_reach(h, w):
	  is_reached[h][w] = True
	  next_que.append([h, w])

	  if not is_using_warp:
	    que.append([h, w])


def can_reach(h, w):
	global H
	global W
	global maze

	if h < 0 or h >= H or w < 0 or w >= W:
		return False
	elif maze[h][w] == '#':
		return False
	elif is_reached[h][w]:
		return False
	else:
		return True


from collections import deque
import copy

H, W = map(int, input().split())
Ch, Cw = map(get_index, input().split())
Dh, Dw = map(get_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

next_que = deque()
next_que.append([Ch, Cw])
mp = 0

while len(next_que) > 0:
  que = copy.deepcopy(next_que)

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_nearby(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

  que = copy.deepcopy(next_que)
  next_que.clear()
  mp += 1

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_using_warp(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

print(-1)

Buggy python submission (verdict: Time Limit Exceeded):
import sys

# D - Wizard in Maze
def conv_index(s):
	return int(s) - 1


def search(h, w, set_, mp):
  global Dh
  global Dw
  global can_goal
  global ans

  route = copy.copy(set_)

  if h == Dh and w == Dw:
    can_goal = True
    ans.append(mp)
  elif not can_reach(h, w, route):
    return
  else:
    route.add(coord(h, w))

    if need_to_use_mp(h, w, route):
      mp += 1

      for i in range(-2, 3):
        search(h - 2, w + i, route, mp)
        search(h + 2, w + i, route, mp)

      for i in range(-2, 3):
        if i != 0:
          search(h - 1, w + i, route, mp)
          search(h + 1, w + i, route, mp)

      search(h, w - 2, route, mp)
      search(h, w + 2, route, mp)
    else:
      search(h - 1, w, route, mp)
      search(h + 1, w, route, mp)
      search(h, w - 1, route, mp)
      search(h, w + 1, route, mp)


def can_reach(h, w, route):
	global H
	global W
	global maze

	if h < 0 or h > H - 1 or w < 0 or w > W - 1:
		return False
	elif maze[h][w] == '#':
		return False
	elif coord(h, w) in route:
		return False
	else:
		return True


def coord(h, w):
  return str(h) + ' ' + str(w)


def need_to_use_mp(h, w, route):
	any_can_reach = False

	if can_reach(h - 1, w, route):
		any_can_reach = True

	if can_reach(h + 1, w, route):
		any_can_reach = True

	if can_reach(h, w - 1, route):
		any_can_reach = True

	if can_reach(h, w + 1, route):
		any_can_reach = True

	if not any_can_reach:
		return True


import copy
sys.setrecursionlimit(1000000)

H, W = map(int, input().split())
Ch, Cw = map(conv_index, input().split())
Dh, Dw = map(conv_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

can_goal = False
ans = []

search(Ch, Cw, set(), 0)

if not can_goal:
	print(-1)
elif len(ans) == 0:
	print(0)
else:
	print(min(ans))


Fixed submission:
import sys

# D - Wizard in Maze
def get_index(s):
	return int(s) - 1


def search_nearby(h, w):
# 上下左右に隣接するマスを探索
	search(h + 1, w, False)
	search(h - 1, w, False)
	search(h, w + 1, False)
	search(h, w - 1, False)


def search_using_warp(h, w):
  # ワープ魔法で移動できるマスを探索
  for i in range(-2, 3):
    search(h - 2, w + i)
    search(h + 2, w + i)

  for i in range(-2, 3):
    if i != 0:
      search(h - 1, w + i)
      search(h + 1, w + i)

  search(h, w + 2)
  search(h, w - 2)


def search(h, w, is_using_warp = True):
  global is_reached
  global que
  global next_que

  if can_reach(h, w):
	  is_reached[h][w] = True
	  next_que.append([h, w])

	  if not is_using_warp:
	    que.append([h, w])


def can_reach(h, w):
	global H
	global W
	global maze

	if h < 0 or h >= H or w < 0 or w >= W:
		return False
	elif maze[h][w] == '#':
		return False
	elif is_reached[h][w]:
		return False
	else:
		return True


from collections import deque
import copy

H, W = map(int, input().split())
Ch, Cw = map(get_index, input().split())
Dh, Dw = map(get_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

next_que = deque()
next_que.append([Ch, Cw])
mp = 0

while len(next_que) > 0:
  que = copy.deepcopy(next_que)

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_nearby(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

  que = copy.deepcopy(next_que)
  next_que.clear()
  mp += 1

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_using_warp(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

print(-1)

Buggy python submission (verdict: Time Limit Exceeded):
import sys

# D - Wizard in Maze
def conv_index(s):
	return int(s) - 1


def search(h, w, set_, mp):
  global Dh
  global Dw
  global can_goal
  global ans

  route = copy.copy(set_)

  if h == Dh and w == Dw:
    can_goal = True
    ans.append(mp)
  elif not can_reach(h, w, route):
    return
  else:
    route.add(coord(h, w))

    if need_to_use_mp(h, w, route):
      mp += 1

      for i in range(-2, 3):
        search(h - 2, w + i, route, mp)
        search(h + 2, w + i, route, mp)

      for i in range(-2, 3):
        if i != 0:
          search(h - 1, w + i, route, mp)
          search(h + 1, w + i, route, mp)

      search(h, w - 2, route, mp)
      search(h, w + 2, route, mp)
    else:
      search(h - 1, w, route, mp)
      search(h + 1, w, route, mp)
      search(h, w - 1, route, mp)
      search(h, w + 1, route, mp)


def can_reach(h, w, route):
	global H
	global W
	global maze

	if h < 0 or h > H - 1 or w < 0 or w > W - 1:
		return False
	elif maze[h][w] == '#':
		return False
	elif coord(h, w) in route:
		return False
	else:
		return True


def coord(h, w):
  return str(h) + ' ' + str(w)


def need_to_use_mp(h, w, route):
	any_can_reach = False

	if can_reach(h - 1, w, route):
		any_can_reach = True

	if can_reach(h + 1, w, route):
		any_can_reach = True

	if can_reach(h, w - 1, route):
		any_can_reach = True

	if can_reach(h, w + 1, route):
		any_can_reach = True

	if not any_can_reach:
		return True


import copy
sys.setrecursionlimit(1000000)

H, W = map(int, input().split())
Ch, Cw = map(conv_index, input().split())
Dh, Dw = map(conv_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

can_goal = False
ans = []

search(Ch, Cw, set(), 0)

if not can_goal:
	print(-1)
elif len(ans) == 0:
	print(0)
else:
	print(min(ans))

Fixed submission:
import sys

# D - Wizard in Maze
def get_index(s):
	return int(s) - 1


def search_nearby(h, w):
# 上下左右に隣接するマスを探索
	search(h + 1, w, False)
	search(h - 1, w, False)
	search(h, w + 1, False)
	search(h, w - 1, False)


def search_using_warp(h, w):
  # ワープ魔法で移動できるマスを探索
  for i in range(-2, 3):
    search(h - 2, w + i)
    search(h + 2, w + i)

  for i in range(-2, 3):
    if i != 0:
      search(h - 1, w + i)
      search(h + 1, w + i)

  search(h, w + 2)
  search(h, w - 2)


def search(h, w, is_using_warp = True):
  global is_reached
  global que
  global next_que

  if can_reach(h, w):
	  is_reached[h][w] = True
	  next_que.append([h, w])

	  if not is_using_warp:
	    que.append([h, w])


def can_reach(h, w):
	global H
	global W
	global maze

	if h < 0 or h >= H or w < 0 or w >= W:
		return False
	elif maze[h][w] == '#':
		return False
	elif is_reached[h][w]:
		return False
	else:
		return True


from collections import deque
import copy

H, W = map(int, input().split())
Ch, Cw = map(get_index, input().split())
Dh, Dw = map(get_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

next_que = deque()
next_que.append([Ch, Cw])
mp = 0

while len(next_que) > 0:
  que = copy.deepcopy(next_que)

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_nearby(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

  que = copy.deepcopy(next_que)
  next_que.clear()
  mp += 1

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_using_warp(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

print(-1)

Buggy python submission (verdict: Time Limit Exceeded):
import sys

# D - Wizard in Maze
def conv_index(s):
	return int(s) - 1


def search(h, w, reached, magic):
  global Dh
  global Dw
  global can_goal
  global ans

  is_reached = copy.deepcopy(reached)

  if h == Dh and w == Dw:
    is_reached[Dh][Dw] = True
    can_goal = True
    ans.append(magic)
  elif not can_reach(h, w, is_reached):
    return
  else:
    is_reached[h][w] = True

    if need_to_use_magic(h, w, is_reached):
      m = magic + 1

      for i in range(-2, 3):
        search(h - 2, w + i, is_reached, m)
        search(h + 2, w + i, is_reached, m)

      for i in range(-2, 3):
        if i != 0:
          search(h - 1, w + i, is_reached, m)
          search(h + 1, w + i, is_reached, m)

      search(h, w - 2, is_reached, m)
      search(h, w + 2, is_reached, m)
    else:
      search(h - 1, w, is_reached, magic)
      search(h + 1, w, is_reached, magic)
      search(h, w - 1, is_reached, magic)
      search(h, w + 1, is_reached, magic)


def can_reach(h, w, is_reached):
	global H
	global W
	global maze

	if h < 0 or h > H - 1 or w < 0 or w > W - 1:
		return False
	elif is_reached[h][w]:
		return False
	elif maze[h][w] == '#':
		return False
	else:
		return True


def need_to_use_magic(h, w, is_reached):
	any_can_reach = False

	if can_reach(h - 1, w, is_reached):
		any_can_reach = True

	if can_reach(h + 1, w, is_reached):
		any_can_reach = True

	if can_reach(h, w - 1, is_reached):
		any_can_reach = True

	if can_reach(h, w + 1, is_reached):
		any_can_reach = True

	if not any_can_reach:
		return True


import copy
sys.setrecursionlimit(1000000)

H, W = map(int, input().split())
Ch, Cw = map(conv_index, input().split())
Dh, Dw = map(conv_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

can_goal = False
ans = []

search(Ch, Cw, is_reached, 0)

if not can_goal:
	print(-1)
elif len(ans) == 0:
	print(0)
else:
	print(min(ans))

Fixed submission:
import sys

# D - Wizard in Maze
def get_index(s):
	return int(s) - 1


def search_nearby(h, w):
# 上下左右に隣接するマスを探索
	search(h + 1, w, False)
	search(h - 1, w, False)
	search(h, w + 1, False)
	search(h, w - 1, False)


def search_using_warp(h, w):
  # ワープ魔法で移動できるマスを探索
  for i in range(-2, 3):
    search(h - 2, w + i)
    search(h + 2, w + i)

  for i in range(-2, 3):
    if i != 0:
      search(h - 1, w + i)
      search(h + 1, w + i)

  search(h, w + 2)
  search(h, w - 2)


def search(h, w, is_using_warp = True):
  global is_reached
  global que
  global next_que

  if can_reach(h, w):
	  is_reached[h][w] = True
	  next_que.append([h, w])

	  if not is_using_warp:
	    que.append([h, w])


def can_reach(h, w):
	global H
	global W
	global maze

	if h < 0 or h >= H or w < 0 or w >= W:
		return False
	elif maze[h][w] == '#':
		return False
	elif is_reached[h][w]:
		return False
	else:
		return True


from collections import deque
import copy

H, W = map(int, input().split())
Ch, Cw = map(get_index, input().split())
Dh, Dw = map(get_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

next_que = deque()
next_que.append([Ch, Cw])
mp = 0

while len(next_que) > 0:
  que = copy.deepcopy(next_que)

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_nearby(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

  que = copy.deepcopy(next_que)
  next_que.clear()
  mp += 1

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_using_warp(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

print(-1)

Buggy python submission (verdict: Time Limit Exceeded):
import sys

# D - Wizard in Maze
def conv_index(s):
	return int(s) - 1


def search(h, w, reached, magic):
  global Dh
  global Dw
  global can_goal
  global ans

  is_reached = copy.deepcopy(reached)

  if h == Dh and w == Dw:
    is_reached[Dh][Dw] = True
    can_goal = True
    ans.append(magic)
  elif not can_reach(h, w, is_reached):
    return
  else:
    is_reached[h][w] = True

    if need_to_use_magic(h, w, is_reached):
      m = magic + 1

      for i in range(-2, 3):
        search(h - 2, w + i, is_reached, m)
        search(h + 2, w + i, is_reached, m)

      for i in range(-2, 3):
        if i != 0:
          search(h - 1, w + i, is_reached, m)
          search(h + 1, w + i, is_reached, m)

      search(h, w - 2, is_reached, m)
      search(h, w + 2, is_reached, m)
    else:
      search(h - 1, w, is_reached, magic)
      search(h + 1, w, is_reached, magic)
      search(h, w - 1, is_reached, magic)
      search(h, w + 1, is_reached, magic)


def can_reach(h, w, is_reached):
	global H
	global W
	global maze

	if h < 0 or h > H - 1 or w < 0 or w > W - 1:
		return False
	elif is_reached[h][w]:
		return False
	elif maze[h][w] == '#':
		return False
	else:
		return True


def need_to_use_magic(h, w, is_reached):
	any_can_reach = False

	if can_reach(h - 1, w, is_reached):
		any_can_reach = True

	if can_reach(h + 1, w, is_reached):
		any_can_reach = True

	if can_reach(h, w - 1, is_reached):
		any_can_reach = True

	if can_reach(h, w + 1, is_reached):
		any_can_reach = True

	if not any_can_reach:
		return True


import copy
sys.setrecursionlimit(1000000)

H, W = map(int, input().split())
Ch, Cw = map(conv_index, input().split())
Dh, Dw = map(conv_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

can_goal = False
ans = []

search(Ch, Cw, is_reached, 0)

if not can_goal:
	print(-1)
elif len(ans) == 0:
	print(0)
else:
	print(min(ans))

Fixed submission:
import sys

# D - Wizard in Maze
def get_index(s):
	return int(s) - 1


def search_nearby(h, w):
# 上下左右に隣接するマスを探索
	search(h + 1, w, False)
	search(h - 1, w, False)
	search(h, w + 1, False)
	search(h, w - 1, False)


def search_using_warp(h, w):
  # ワープ魔法で移動できるマスを探索
  for i in range(-2, 3):
    search(h - 2, w + i)
    search(h + 2, w + i)

  for i in range(-2, 3):
    if i != 0:
      search(h - 1, w + i)
      search(h + 1, w + i)

  search(h, w + 2)
  search(h, w - 2)


def search(h, w, is_using_warp = True):
  global is_reached
  global que
  global next_que

  if can_reach(h, w):
	  is_reached[h][w] = True
	  next_que.append([h, w])

	  if not is_using_warp:
	    que.append([h, w])


def can_reach(h, w):
	global H
	global W
	global maze

	if h < 0 or h >= H or w < 0 or w >= W:
		return False
	elif maze[h][w] == '#':
		return False
	elif is_reached[h][w]:
		return False
	else:
		return True


from collections import deque
import copy

H, W = map(int, input().split())
Ch, Cw = map(get_index, input().split())
Dh, Dw = map(get_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

next_que = deque()
next_que.append([Ch, Cw])
mp = 0

while len(next_que) > 0:
  que = copy.deepcopy(next_que)

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_nearby(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

  que = copy.deepcopy(next_que)
  next_que.clear()
  mp += 1

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_using_warp(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

print(-1)

Buggy python submission (verdict: Time Limit Exceeded):
import sys

# D - Wizard in Maze
def conv_index(s):
	return int(s) - 1


def search(h, w, reached, magic, route):
  global Dh
  global Dw
  global can_goal
  global ans

  is_reached = copy.deepcopy(reached)

  if h == Dh and w == Dw:
    is_reached[Dh][Dw] = True
    can_goal = True
    ans.append(magic)
		
    #print(magic)
    #print(route + '\n' + str(Dh + 1) + ' ' + str(Dw + 1))
    #print('----------')
  elif not can_reach(h, w, is_reached):
    return
  else:
    is_reached[h][w] = True
    r = copy.copy(route)
    r += '\n' + str(h + 1) + ' ' + str(w + 1)

    if need_to_use_magic(h, w, is_reached):
      m = magic + 1

      for i in range(-2, 3):
        search(h - 2, w + i, is_reached, m, r)
        search(h + 2, w + i, is_reached, m, r)

      for i in range(-2, 3):
        if i != 0:
          search(h - 1, w + i, is_reached, m, r)
          search(h + 1, w + i, is_reached, m, r)

      search(h, w - 2, is_reached, m, r)
      search(h, w + 2, is_reached, m, r)
    else:
      search(h - 1, w, is_reached, magic, r)
      search(h + 1, w, is_reached, magic, r)
      search(h, w - 1, is_reached, magic, r)
      search(h, w + 1, is_reached, magic, r)


def can_reach(h, w, is_reached):
	global H
	global W
	global maze

	if h < 0 or h > H - 1 or w < 0 or w > W - 1:
		return False
	elif is_reached[h][w]:
		return False
	elif maze[h][w] == '#':
		return False
	else:
		return True


def need_to_use_magic(h, w, is_reached):
	any_can_reach = False

	if can_reach(h - 1, w, is_reached):
		any_can_reach = True

	if can_reach(h + 1, w, is_reached):
		any_can_reach = True

	if can_reach(h, w - 1, is_reached):
		any_can_reach = True

	if can_reach(h, w + 1, is_reached):
		any_can_reach = True

	if not any_can_reach:
		return True


import copy
sys.setrecursionlimit(1000000)

H, W = map(int, input().split())
Ch, Cw = map(conv_index, input().split())
Dh, Dw = map(conv_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

can_goal = False
ans = []

#search(Ch, Cw, 0)
import copy
search(Ch, Cw, is_reached, 0, '')

if not can_goal:
	print(-1)
elif len(ans) == 0:
	print(0)
else:
	print(min(ans))

Fixed submission:
import sys

# D - Wizard in Maze
def get_index(s):
	return int(s) - 1


def search_nearby(h, w):
# 上下左右に隣接するマスを探索
	search(h + 1, w, False)
	search(h - 1, w, False)
	search(h, w + 1, False)
	search(h, w - 1, False)


def search_using_warp(h, w):
  # ワープ魔法で移動できるマスを探索
  for i in range(-2, 3):
    search(h - 2, w + i)
    search(h + 2, w + i)

  for i in range(-2, 3):
    if i != 0:
      search(h - 1, w + i)
      search(h + 1, w + i)

  search(h, w + 2)
  search(h, w - 2)


def search(h, w, is_using_warp = True):
  global is_reached
  global que
  global next_que

  if can_reach(h, w):
	  is_reached[h][w] = True
	  next_que.append([h, w])

	  if not is_using_warp:
	    que.append([h, w])


def can_reach(h, w):
	global H
	global W
	global maze

	if h < 0 or h >= H or w < 0 or w >= W:
		return False
	elif maze[h][w] == '#':
		return False
	elif is_reached[h][w]:
		return False
	else:
		return True


from collections import deque
import copy

H, W = map(int, input().split())
Ch, Cw = map(get_index, input().split())
Dh, Dw = map(get_index, input().split())

maze = []

for _ in range(H):
	maze.append(input())

is_reached = [[False] * W for _ in range(H)]

next_que = deque()
next_que.append([Ch, Cw])
mp = 0

while len(next_que) > 0:
  que = copy.deepcopy(next_que)

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_nearby(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

  que = copy.deepcopy(next_que)
  next_que.clear()
  mp += 1

	# コストiで到達可能なマスを列挙
  while len(que) > 0:
    h, w = que.popleft()
    is_reached[h][w] = True

    search_using_warp(h, w)

  if is_reached[Dh][Dw]:
    print(mp)
    exit()

print(-1)