public static Node jump(final Obstacles obs, final Node prev, final int dx, final int dy, final OffsetPoint goal) {
		final Node cur = prev.derive(dx, dy);
		if (obs.blocked(cur)) {
			return null;
		}
		if (goal.equals(cur)) {
			return cur;
		}
		if ((dx | dy) == 0)
			return null;
		List<Node> next = getNext(obs, cur, dx, dy);
		if (dx != 0 && dy != 0 ? (next.size() > 3 || jump(obs, cur, dx, 0, goal) != null || jump(obs, cur, 0, dy, goal) != null)
				: next.size() > 1)
			return cur;
		// if (dy == 0) {
		// if (dx == 0) {
		// return null;
		// }
		// for (int i = -1; i <= 1; i += 2) {
		// final Node block = cur.derive(0, i);
		// final Node force = cur.derive(dx, i);
		// if ((obs.blocked(new Node(block, force)) || obs.blocked(new
		// Node(cur.getPrev(), block)))
		// && !obs.blocked(force)) {
		// return cur;
		// }
		// }
		// } else if (dx == 0) {
		// for (int i = -1; i <= 1; i += 2) {
		// final Node block = cur.derive(i, 0);
		// final Node force = cur.derive(i, dy);
		// if ((obs.blocked(new Node(block, force)) || obs.blocked(new
		// Node(cur.getPrev(), block)))
		// && !obs.blocked(force)) {
		// return cur;
		// }
		// }
		// } else {
		// for (int i = 0; i <= 1; i++) {
		// final int mdx = ((i + 1) % 2 * 2 - 1) * dx;
		// final int mdy = (i * 2 - 1) * dy;
		// final Node block = cur.derive(-i * dx, -(i + 1) % 2 * dy);
		// final Node force = cur.derive(mdx, mdy);
		// if ((obs.blocked(new Node(block, force)) || obs.blocked(new
		// Node(cur.getPrev(), block)))
		// && !obs.blocked(force)) {
		// return cur;
		// }
		// }
		// if ((jump(obs, cur, dx, 0, goal) != null || jump(obs, cur, 0, dy,
		// goal) != null)) {
		// return cur;
		// }
		// }
		return jump(obs, cur, dx, dy, goal);
	}