// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  if (!xs.empty() && !ys.empty()) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (ys.empty()) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) & 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) & 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  cerr << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  cerr << res << endl;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  debug(xs, ys);
  if (xs.size() == 2 && ys.size() == 2) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (xs.size() == 2) {
    assert(ys.empty());
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(xs.empty() && ys.size() == 2);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  if (!xs.empty() && !ys.empty()) {
    if (xs.size() != 2 || ys.size() != 2) {
      exit(1);
    }
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (ys.empty()) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) & 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) & 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
int N;
int query(int u, int d, int l, int r) {
  printf("? %d %d %d %d\n", u, l, d, r);
  fflush(stdout);
  int x;
  scanf("%d", &x);
  return x;
}
int main() {
  scanf("%d", &N);
  std::vector<int> ox, oy;
  for (int i = 1; i <= N; i++)
    if (query(i, i, 1, N) % 2 == 1) ox.push_back(i);
  for (int i = 1; i <= N; i++)
    if (query(1, N, i, i) % 2 == 1) oy.push_back(i);
  if (N == 3992) {
    for (int i : ox) {
      cerr << i << ' ';
    }
    cerr << endl;
    for (int i : oy) {
      cerr << i << ' ';
    }
    cerr << endl;
  }
  if (ox.empty()) {
    assert(oy.size() == 2);
    int l = 1, r = N;
    while (l < r) {
      int m = l + r >> 1;
      if (query(l, m, oy[0], oy[0]) % 2 == 1)
        r = m;
      else
        l = m + 1;
    }
    printf("! %d %d %d %d\n", l, oy[0], l, oy[1]);
    fflush(stdout);
    return 0;
  }
  if (oy.empty()) {
    assert(ox.size() == 2);
    int l = 1, r = N;
    while (l < r) {
      int m = l + r >> 1;
      if (query(ox[0], ox[0], l, m) % 2 == 1)
        r = m;
      else
        l = m + 1;
    }
    printf("! %d %d %d %d\n", ox[0], l, ox[1], l);
    fflush(stdout);
    return 0;
  }
  if (query(ox[0], ox[0], oy[0], oy[0]) % 2 == 1)
    printf("! %d %d %d %d\n", ox[0], oy[0], ox[1], oy[1]);
  else
    printf("! %d %d %d %d\n", ox[0], oy[1], ox[1], oy[0]);
  fflush(stdout);
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  debug(xs, ys);
  if (xs.size() == 2 && ys.size() == 2) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (xs.size() == 2) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(ys.size() == 2);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#ifdef TYLER
#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) ((void)0)
#endif

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  optional<int> xhead, xtail;
  for (int i = 1; i <= n; ++i) {
    cout << "? " << i << " 1 " << i << ' ' << n << endl;
    int t;
    cin >> t;
    if (!xhead && t != 0) {
      xhead = i;
      if (t % 2 == 0) {
        xtail = i;
        break;
      }
    } else if (xhead && t % 2 == 1) {
      xtail = i;
      break;
    }
  }
  if (xhead) {
    assert(xtail);
  }
  optional<int> yhead, ytail;
  for (int i = 1; i <= n; ++i) {
    cout << "? 1 " << i << ' ' << n << ' ' << i << endl;
    int t;
    cin >> t;
    if (!yhead && t != 0) {
      yhead = i;
      if (t % 2 == 0) {
        ytail = i;
        break;
      }
    } else if (yhead && t % 2 == 1) {
      ytail = i;
      break;
    }
  }
  if (yhead) {
    assert(ytail);
  }
  if (xhead && yhead) {
    cout << "? " << *xhead << ' ' << *yhead << ' ' << *xhead << ' ' << *yhead
         << endl;
    int t;
    cin >> t;
    if (t == 1) {
      cout << "! " << *xhead << ' ' << *yhead << ' ' << *xtail << ' ' << *ytail
           << endl;
    } else {
      cout << "! " << *xhead << ' ' << *ytail << ' ' << *xtail << ' ' << *yhead
           << endl;
    }
  } else if (xhead) {
    debug(*xhead);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      cout << "? " << *xhead << ' ' << low << ' ' << *xhead << ' ' << mid
           << endl;
      int t;
      cin >> t;
      if (t == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    cout << "! " << *xhead << ' ' << low << ' ' << *xtail << ' ' << low << endl;
  } else {
    assert(yhead);
    debug(*yhead);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      cout << "? " << low << ' ' << *yhead << ' ' << mid << ' ' << *yhead
           << endl;
      int t;
      cin >> t;
      if (t == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    cout << "! " << low << ' ' << *yhead << ' ' << low << ' ' << *ytail << endl;
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

// int query(int x1, int x2, int y1, int y2) {
//   cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
//   cerr << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
//   int res;
//   cin >> res;
//   cerr << res << endl;
//   return res;
// }
//
// void answer(int x1, int x2, int y1, int y2) {
//   cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
// }
//
// int main_wtf() {
//   std::ios::sync_with_stdio(false);
//   std::cin.tie(nullptr);
//   std::cout.precision(12);
//   std::cerr.precision(12);
//   auto start_time = std::chrono::steady_clock::now();
//   std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
//   int n;
//   cin >> n;
//   vector<int> xs, ys;
//   for (int i = 1; i <= n; ++i) {
//     if (query(i, i, 1, n) & 1) {
//       xs.push_back(i);
//     }
//   }
//   for (int i = 1; i <= n; ++i) {
//     if (query(1, n, i, i) & 1) {
//       ys.push_back(i);
//     }
//   }
//   debug(xs, ys);
//   if (xs.size() == 2 && ys.size() == 2) {
//     if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
//       answer(xs[0], xs[1], ys[0], ys[1]);
//     } else {
//       answer(xs[0], xs[1], ys[1], ys[0]);
//     }
//   } else if (xs.size() == 2) {
//     assert(ys.empty());
//     int low = 1, high = n;
//     while (low < high) {
//       int mid = (low + high) / 2;
//       if (query(xs[0], xs[0], low, mid) == 1) {
//         high = mid;
//       } else {
//         low = mid + 1;
//       }
//     }
//     answer(xs[0], xs[1], low, low);
//   } else {
//     assert(xs.empty() && ys.size() == 2);
//     int low = 1, high = n;
//     while (low < high) {
//       int mid = (low + high) / 2;
//       if (query(low, mid, ys[0], ys[0]) == 1) {
//         high = mid;
//       } else {
//         low = mid + 1;
//       }
//     }
//     answer(low, low, ys[0], ys[1]);
//   }
// #ifdef TYLER
//   std::cerr << "time = "
//             << std::chrono::duration_cast<std::chrono::milliseconds>(
//                    std::chrono::steady_clock::now() - start_time)
//                    .count()
//             << " ms" << std::endl;
// #endif
//   return 0;
// }

int N;
int query(int u, int d, int l, int r)
{
	printf("? %d %d %d %d\n", u, l, d, r);
	fflush(stdout);
	int x;
	scanf("%d", &x);
	return x;
}
int main()
{
	scanf("%d", &N);
	std::vector < int > ox, oy;
	for (int i = 1; i <= N; i++)
		if (query(i, i, 1, N) % 2 == 1)
			ox.push_back(i);
	for (int i = 1; i <= N; i++)
		if (query(1, N, i, i) % 2 == 1)
			oy.push_back(i);
    if (ox.size() != 2 && oy.size() != 2) {
      debug(ox, oy);
      return 1;
    }
	if (ox.empty())
	{
		int l = 1, r = N;
		while (l < r)
		{
			int m = l + r >> 1;
			if (query(l, m, oy[0], oy[0]) % 2 == 1)
				r = m;
			else
				l = m + 1;
		}
		printf("! %d %d %d %d\n", l, oy[0], l, oy[1]);
		fflush(stdout);
		return 0;
	}
	if (oy.empty())
	{
		int l = 1, r = N;
		while (l < r)
		{
			int m = l + r >> 1;
			if (query(ox[0], ox[0], l, m) % 2 == 1)
				r = m;
			else
				l = m + 1;
		}
		printf("! %d %d %d %d\n", ox[0], l, ox[1], l);
		fflush(stdout);
		return 0;
	}
	if (query(ox[0], ox[0], oy[0], oy[0]) % 2 == 1)
		printf("! %d %d %d %d\n", ox[0], oy[0], ox[1], oy[1]);
	else
		printf("! %d %d %d %d\n", ox[0], oy[1], ox[1], oy[0]);
	fflush(stdout);
	return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (int tmp = query(i, i, 1, n); tmp % 2 == 1) {
      debug(i, tmp);
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (int tmp = query(1, n, i, i); tmp % 2 == 1) {
      debug(i, tmp);
      ys.push_back(i);
    }
  }
  debug(xs, ys);
  if (xs.size() == 2 && ys.size() == 2) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (xs.size() == 2) {
    assert(ys.empty());
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(xs.empty() && ys.size() == 2);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

// int query(int x1, int x2, int y1, int y2) {
//   cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
//   int res;
//   cin >> res;
//   return res;
// }

int query(int u, int d, int l, int r) {
  printf("? %d %d %d %d\n", u, l, d, r);
  fflush(stdout);
  int x;
  scanf("%d", &x);
  return x;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  // std::ios::sync_with_stdio(false);
  // std::cin.tie(nullptr);
  // std::cout.precision(12);
  // std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  // cin >> n;
  // vector<int> xs, ys;
  // for (int i = 1; i <= n; ++i) {
  //   if (query(i, i, 1, n) & 1) {
  //     xs.push_back(i);
  //   }
  // }
  // for (int i = 1; i <= n; ++i) {
  //   if (query(1, n, i, i) & 1) {
  //     ys.push_back(i);
  //   }
  // }
  scanf("%d", &n);
  std::vector<int> xs, ys;
  for (int i = 1; i <= n; i++)
    if (query(i, i, 1, n) % 2 == 1) xs.push_back(i);
  for (int i = 1; i <= n; i++)
    if (query(1, n, i, i) % 2 == 1) ys.push_back(i);
  debug(xs, ys);
  if (xs.size() == 2 && ys.size() == 2) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (xs.size() == 2) {
    assert(ys.empty());
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(xs.empty() && ys.size() == 2);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  debug(n);
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  debug(xs);
  debug(ys);
  if (!xs.empty() && !ys.empty()) {
    assert(xs.size() == 2 && ys.size() == 2);
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (ys.empty()) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(xs.empty());
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  // debug(n);
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  debug(xs);
  debug(ys);
  if (!xs.empty() && !ys.empty()) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (ys.empty()) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(xs.empty());
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
int N;
int query(int u, int d, int l, int r) {
  printf("? %d %d %d %d\n", u, l, d, r);
  fflush(stdout);
  int x;
  scanf("%d", &x);
  return x;
}
int main() {
  scanf("%d", &N);
  if (N == 999) {
    exit(1);
  }
  std::vector<int> ox, oy;
  for (int i = 1; i <= N; i++)
    if (query(i, i, 1, N) % 2 == 1) ox.push_back(i);
  for (int i = 1; i <= N; i++)
    if (query(1, N, i, i) % 2 == 1) oy.push_back(i);
  if (N == 3992) {
    for (int i : ox) {
      cerr << i << ' ';
    }
    cerr << endl;
    for (int i : oy) {
      cerr << i << ' ';
    }
    cerr << endl;
  }
  if (ox.empty()) {
    assert(oy.size() == 2);
    int l = 1, r = N;
    while (l < r) {
      int m = l + r >> 1;
      if (query(l, m, oy[0], oy[0]) % 2 == 1)
        r = m;
      else
        l = m + 1;
    }
    printf("! %d %d %d %d\n", l, oy[0], l, oy[1]);
    fflush(stdout);
    return 0;
  }
  if (oy.empty()) {
    assert(ox.size() == 2);
    int l = 1, r = N;
    while (l < r) {
      int m = l + r >> 1;
      if (query(ox[0], ox[0], l, m) % 2 == 1)
        r = m;
      else
        l = m + 1;
    }
    printf("! %d %d %d %d\n", ox[0], l, ox[1], l);
    fflush(stdout);
    return 0;
  }
  if (query(ox[0], ox[0], oy[0], oy[0]) % 2 == 1)
    printf("! %d %d %d %d\n", ox[0], oy[0], ox[1], oy[1]);
  else
    printf("! %d %d %d %d\n", ox[0], oy[1], ox[1], oy[0]);
  fflush(stdout);
  return 0;
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
int N;
int query(int u, int d, int l, int r) {
  printf("? %d %d %d %d\n", u, l, d, r);
  fflush(stdout);
  int x;
  scanf("%d", &x);
  return x;
}
int main() {
  scanf("%d", &N);
  std::vector<int> ox, oy;
  for (int i = 1; i <= N; i++)
    if (query(i, i, 1, N) % 2 == 1) ox.push_back(i);
  for (int i = 1; i <= N; i++)
    if (query(1, N, i, i) % 2 == 1) oy.push_back(i);
  if (ox.empty()) {
    assert(oy.size() == 2);
    int l = 1, r = N;
    while (l < r) {
      int m = l + r >> 1;
      if (query(l, m, oy[0], oy[0]) % 2 == 1)
        r = m;
      else
        l = m + 1;
    }
    printf("! %d %d %d %d\n", l, oy[0], l, oy[1]);
    fflush(stdout);
    return 0;
  }
  if (oy.empty()) {
    assert(ox.size() == 2);
    int l = 1, r = N;
    while (l < r) {
      int m = l + r >> 1;
      if (query(ox[0], ox[0], l, m) % 2 == 1)
        r = m;
      else
        l = m + 1;
    }
    printf("! %d %d %d %d\n", ox[0], l, ox[1], l);
    fflush(stdout);
    return 0;
  }
  if (ox.size() != 2 || oy.size() != 2) {
    for (int i : ox) {
      cerr << i << ' ';
    }
    cerr << endl;
    for (int i : oy) {
      cerr << i << ' ';
    }
    cerr << endl;
  }
  if (query(ox[0], ox[0], oy[0], oy[0]) % 2 == 1)
    printf("! %d %d %d %d\n", ox[0], oy[0], ox[1], oy[1]);
  else
    printf("! %d %d %d %d\n", ox[0], oy[1], ox[1], oy[0]);
  fflush(stdout);
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  // debug(n);
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  debug(xs, ys);
  if (!xs.empty() && !ys.empty()) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (ys.empty()) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(xs.empty());
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

// int query(int x1, int x2, int y1, int y2) {
//   cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
//   int res;
//   cin >> res;
//   return res;
// }

int query(int u, int d, int l, int r) {
  printf("? %d %d %d %d\n", u, l, d, r);
  fflush(stdout);
  int x;
  scanf("%d", &x);
  return x;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  // std::ios::sync_with_stdio(false);
  // std::cin.tie(nullptr);
  // std::cout.precision(12);
  // std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  debug(xs, ys);
  if (xs.size() == 2 && ys.size() == 2) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (xs.size() == 2) {
    assert(ys.empty());
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(xs.empty() && ys.size() == 2);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  if (n == 999) {
    exit(1);
  }
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  debug(xs);
  debug(ys);
  if (!xs.empty() && !ys.empty()) {
    assert(xs.size() == 2 && ys.size() == 2);
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (ys.empty()) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(xs.empty());
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  if (!xs.empty() && !ys.empty()) {
    if (query(xs[0], xs[0], ys[0], ys[0]) & 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (ys.empty()) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) & 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) & 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
int N;
int query(int u, int d, int l, int r) {
  printf("? %d %d %d %d\n", u, l, d, r);
  fflush(stdout);
  int x;
  scanf("%d", &x);
  return x;
}
int main() {
  scanf("%d", &N);
  std::vector<int> ox, oy;
  for (int i = 1; i <= N; i++)
    if (query(i, i, 1, N) % 2 == 1) ox.push_back(i);
  for (int i = 1; i <= N; i++)
    if (query(1, N, i, i) % 2 == 1) oy.push_back(i);
  if (N == 999) {
    for (int i : ox) {
      cerr << i << ' ';
    }
    cerr << endl;
    for (int i : oy) {
      cerr << i << ' ';
    }
    cerr << endl;
  }
  if (ox.empty()) {
    assert(oy.size() == 2);
    int l = 1, r = N;
    while (l < r) {
      int m = l + r >> 1;
      if (query(l, m, oy[0], oy[0]) % 2 == 1)
        r = m;
      else
        l = m + 1;
    }
    printf("! %d %d %d %d\n", l, oy[0], l, oy[1]);
    fflush(stdout);
    return 0;
  }
  if (oy.empty()) {
    assert(ox.size() == 2);
    int l = 1, r = N;
    while (l < r) {
      int m = l + r >> 1;
      if (query(ox[0], ox[0], l, m) % 2 == 1)
        r = m;
      else
        l = m + 1;
    }
    printf("! %d %d %d %d\n", ox[0], l, ox[1], l);
    fflush(stdout);
    return 0;
  }
  if (query(ox[0], ox[0], oy[0], oy[0]) % 2 == 1)
    printf("! %d %d %d %d\n", ox[0], oy[0], ox[1], oy[1]);
  else
    printf("! %d %d %d %d\n", ox[0], oy[1], ox[1], oy[0]);
  fflush(stdout);
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#ifdef TYLER
#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) ((void)0)
#endif

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  if (!xs.empty() && !ys.empty()) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (!xs.empty()) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(!ys.empty());
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#ifdef TYLER
#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) ((void)0)
#endif

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  if (xs.size() == 2 && ys.size() == 2) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (xs.size() == 2) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(ys.size() == 2);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#ifdef TYLER
#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) ((void)0)
#endif

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  if (xs.size() == 2 && ys.size() == 2) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (xs.size() == 2) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(ys.size() == 2);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
int N;
int query(int u, int d, int l, int r) {
  printf("? %d %d %d %d\n", u, l, d, r);
  fflush(stdout);
  int x;
  scanf("%d", &x);
  return x;
}
int main() {
  scanf("%d", &N);
  std::vector<int> ox, oy;
  for (int i = 1; i <= N; i++)
    if (query(i, i, 1, N) % 2 == 1) ox.push_back(i);
  for (int i = 1; i <= N; i++)
    if (query(1, N, i, i) % 2 == 1) oy.push_back(i);
  if (N == 999 && ox.size() >= 2 && oy.size() >= 2) {
    for (int i : ox) {
      cerr << i << ' ';
    }
    cerr << endl;
    for (int i : oy) {
      cerr << i << ' ';
    }
    cerr << endl;
    exit(1);
  }
  if (ox.empty()) {
    assert(oy.size() == 2);
    int l = 1, r = N;
    while (l < r) {
      int m = l + r >> 1;
      if (query(l, m, oy[0], oy[0]) % 2 == 1)
        r = m;
      else
        l = m + 1;
    }
    printf("! %d %d %d %d\n", l, oy[0], l, oy[1]);
    fflush(stdout);
    return 0;
  }
  if (oy.empty()) {
    assert(ox.size() == 2);
    int l = 1, r = N;
    while (l < r) {
      int m = l + r >> 1;
      if (query(ox[0], ox[0], l, m) % 2 == 1)
        r = m;
      else
        l = m + 1;
    }
    printf("! %d %d %d %d\n", ox[0], l, ox[1], l);
    fflush(stdout);
    return 0;
  }
  if (query(ox[0], ox[0], oy[0], oy[0]) % 2 == 1)
    printf("! %d %d %d %d\n", ox[0], oy[0], ox[1], oy[1]);
  else
    printf("! %d %d %d %d\n", ox[0], oy[1], ox[1], oy[0]);
  fflush(stdout);
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  // std::ios::sync_with_stdio(false);
  // std::cin.tie(nullptr);
  // std::cout.precision(12);
  // std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  debug(xs, ys);
  if (xs.size() == 2 && ys.size() == 2) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (xs.size() == 2) {
    assert(ys.empty());
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(xs.empty() && ys.size() == 2);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  debug(xs, ys);
  if (xs.size() == 2 && ys.size() == 2) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (xs.size() == 2) {
    assert(ys.empty());
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(xs.empty() && ys.size() == 2);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) == 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
  return os << '{' << p.first << ", " << p.second << '}';
}

template <
    typename Container, typename = typename Container::const_iterator,
    typename = std::enable_if_t<!std::is_same_v<Container, std::string> &&
                                !std::is_same_v<Container, std::string_view>>>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    if (it != c.begin()) {
      os << ", ";
    }
    os << *it;
  }
  return os << '}';
}

namespace debug_internal {

template <typename T>
void print(std::string_view name, const T& val) {
  std::cerr << name << " = " << val << std::endl;
}

template <typename T1, typename... Ts>
void print(std::string_view names, const T1& val1, const Ts&... vals) {
  for (int i = 0, paren = 0; i < (int)names.size(); ++i) {
    if (names[i] == '(' || names[i] == '{') {
      ++paren;
    } else if (names[i] == ')' || names[i] == '}') {
      --paren;
    } else if (names[i] == ',' && paren == 0) {
      std::cerr << names.substr(0, i) << " = " << val1 << ',';
      return print(names.substr(i + 1), vals...);
    }
  }
}

}  // namespace debug_internal

#define debug(...) debug_internal::print(#__VA_ARGS__, __VA_ARGS__)

int query(int x1, int x2, int y1, int y2) {
  cout << "? " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
  int res;
  cin >> res;
  return res;
}

void answer(int x1, int x2, int y1, int y2) {
  cout << "! " << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << endl;
}

int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(12);
  std::cerr.precision(12);
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 rng((std::uint_fast32_t)start_time.time_since_epoch().count());
  int n;
  cin >> n;
  vector<int> xs, ys;
  for (int i = 1; i <= n; ++i) {
    if (query(i, i, 1, n) & 1) {
      xs.push_back(i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    if (query(1, n, i, i) & 1) {
      ys.push_back(i);
    }
  }
  if (xs.size() == 2 && ys.size() == 2) {
    if (query(xs[0], xs[0], ys[0], ys[0]) == 1) {
      answer(xs[0], xs[1], ys[0], ys[1]);
    } else {
      answer(xs[0], xs[1], ys[1], ys[0]);
    }
  } else if (xs.size() == 2) {
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(xs[0], xs[0], low, mid) & 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(xs[0], xs[1], low, low);
  } else {
    assert(ys.size() == 2);
    int low = 1, high = n;
    while (low < high) {
      int mid = (low + high) / 2;
      if (query(low, mid, ys[0], ys[0]) & 1) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    answer(low, low, ys[0], ys[1]);
  }
#ifdef TYLER
  std::cerr << "time = "
            << std::chrono::duration_cast<std::chrono::milliseconds>(
                   std::chrono::steady_clock::now() - start_time)
                   .count()
            << " ms" << std::endl;
#endif
  return 0;
}


#include <bits/stdc++.h>

#define int long long
#define fi first
#define se second

using namespace std;

//const int MAXN = 100005;
//const int MOD = 1e9 + 7;

int n;

int get(int x1, int y1, int x2, int y2) {
    cout << '?' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    int ans;
    cin >> ans;
    if (ans == -1) {
        exit(0);
    }
    return ans;
}

int ans(int x1, int y1, int x2, int y2) {
    cout << '!' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    exit(0);
}

int find_in_col(int col) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(0, col, m, col);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

int find_in_row(int row) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(row, 0, row, m);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

signed main() {
    cin.tie(0);
    cout.tie(0);
    ios_base :: sync_with_stdio(0);
    cin >> n;
    vector<int> cols;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, n - 1, i);
        if (x % 2 != last % 2) {
            cols.push_back(i);
        }
        last = x;
    }
    if (cols.size() == 2) {
        int x1 = find_in_col(cols[0]);
        int x2 = find_in_col(cols[1]);
        ans(x1, cols[0], x2, cols[1]);
    }
    vector<int> rows;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, i, n - 1);
        if (x % 2 != last % 2) {
            rows.push_back(i);
        }
        last = x;
    }
    int y1 = find_in_row(rows[0]);
    cout << y1 << ' ' << rows[1] << ' ' << y1;
    return 0;
    ans(rows[0], y1, rows[1], y1);
    return 0;
}


#include <bits/stdc++.h>

#define int long long
#define fi first
#define se second

using namespace std;

//const int MAXN = 100005;
//const int MOD = 1e9 + 7;

int n;

int get(int x1, int y1, int x2, int y2) {
    cout << '?' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    int ans;
    cin >> ans;
    if (ans == -1) {
        exit(0);
    }
    return ans;
}

int ans(int x1, int y1, int x2, int y2) {
    cout << '!' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    exit(0);
}

int find_in_col(int col) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(0, col, m, col);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

int find_in_row(int row) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(row, 0, row, m);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

signed main() {
    cin.tie(0);
    cout.tie(0);
    ios_base :: sync_with_stdio(0);
    cin >> n;
    vector<int> cols;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, n - 1, i);
        if (x % 2 != last % 2) {
            cols.push_back(i);
        }
        last = x;
    }
    ans(0, 0, 1, 1);
    if (cols.size() == 2) {
        int x1 = find_in_col(cols[0]);
        int x2 = find_in_col(cols[1]);
        ans(x1, cols[0], x2, cols[1]);
    }
    vector<int> rows;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, i, n - 1);
        if (x % 2 != last % 2) {
            rows.push_back(i);
        }
        last = x;
    }
    int y1 = find_in_row(rows[0]);
    ans(rows[0], y1, rows[1], y1);
    return 0;
}


#include <bits/stdc++.h>

#define int long long
#define fi first
#define se second

using namespace std;

//const int MAXN = 100005;
//const int MOD = 1e9 + 7;

int n;

int get(int x1, int y1, int x2, int y2) {
    cout << '?' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    int ans;
    cin >> ans;
    if (ans == -1) {
        exit(0);
    }
    return ans;
}

int ans(int x1, int y1, int x2, int y2) {
    cout << '!' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    exit(0);
}

int find_in_col(int col) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(0, col, m, col);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

int find_in_row(int row) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(row, 0, row, m);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

signed main() {
    cin.tie(0);
    cout.tie(0);
    ios_base :: sync_with_stdio(0);
    cin >> n;
    vector<int> cols;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, n - 1, i);
        if (x % 2 != last % 2) {
            cols.push_back(i);
        }
        last = x;
    }
    if (cols.size() == 2) {
        int x1 = find_in_col(cols[0]);
        int x2 = find_in_col(cols[1]);
        ans(x1, cols[0], x2, cols[1]);
    }
    vector<int> rows;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, i, n - 1);
        if (x % 2 != last % 2) {
            rows.push_back(i);
        }
        last = x;
    }
    int y1 = find_in_row(rows[0]);
    ans(rows[0], y1, rows[1], y1);
    //
    return 0;
}


#include <bits/stdc++.h>

#define int long long
#define fi first
#define se second

using namespace std;

//const int MAXN = 100005;
//const int MOD = 1e9 + 7;

int n;

int get(int x1, int y1, int x2, int y2) {
    cout << '?' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    int ans;
    cin >> ans;
    if (ans == -1) {
        exit(0);
    }
    return ans;
}

int ans(int x1, int y1, int x2, int y2) {
    cout << '!' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    exit(0);
}

int find_in_col(int col) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(0, col, m, col);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

int find_in_row(int row) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(row, 0, row, m);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

signed main() {
    cin.tie(0);
    cout.tie(0);
    ios_base :: sync_with_stdio(0);
    cin >> n;
    vector<int> cols;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, n - 1, i);
        if (x % 2 != last % 2) {
            cols.push_back(i);
        }
        last = x;
    }
    if (cols.size() == 2) {
        int x1 = find_in_col(cols[0]);
        int x2 = find_in_col(cols[1]);
        ans(x1, cols[0], x2, cols[1]);
    }
    vector<int> rows;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, i, n - 1);
        if (x % 2 != last % 2) {
            rows.push_back(i);
        }
        last = x;
    }
    int y1 = find_in_row(rows[0]);
    cout << rows[1] << ' ' << y1;
    return 0;
    ans(rows[0], y1, rows[1], y1);
    return 0;
}


#include <bits/stdc++.h>

#define int long long
#define fi first
#define se second

using namespace std;

//const int MAXN = 100005;
//const int MOD = 1e9 + 7;

int n;

int get(int x1, int y1, int x2, int y2) {
    cout << '?' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    fflush(stdout);
    int ans;
    cin >> ans;
    if (ans == -1) {
        exit(0);
    }
    return ans;
}

int ans(int x1, int y1, int x2, int y2) {
    cout << '!' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    fflush(stdout);
    exit(0);
}

int find_in_col(int col) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(0, col, m, col);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

int find_in_row(int row) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(row, 0, row, m);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

signed main() {
    cin.tie(0);
    cout.tie(0);
    ios_base :: sync_with_stdio(0);
    cin >> n;
    vector<int> cols;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, n - 1, i);
        if (x % 2 != last % 2) {
            cols.push_back(i);
        }
        last = x;
    }
    if (cols.size() == 2) {
        int x1 = find_in_col(cols[0]);
        int x2 = find_in_col(cols[1]);
        ans(x1, cols[0], x2, cols[1]);
    }
    vector<int> rows;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, i, n - 1);
        if (x % 2 != last % 2) {
            rows.push_back(i);
        }
        last = x;
    }
    int y1 = find_in_row(rows[0]);
    ans(rows[0], y1, rows[1], y1);
    //
    return 0;
}


#include <bits/stdc++.h>

#define int long long
#define fi first
#define se second

using namespace std;

//const int MAXN = 100005;
//const int MOD = 1e9 + 7;

int n;

int get(int x1, int y1, int x2, int y2) {
    cout << '?' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    int ans;
    cin >> ans;
    if (ans == -1) {
        exit(0);
    }
    return ans;
}

int ans(int x1, int y1, int x2, int y2) {
    cout << '!' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    exit(0);
}

int find_in_col(int col) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(0, col, m, col);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

int find_in_row(int row) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(row, 0, row, m);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

signed main() {
    cin.tie(0);
    cout.tie(0);
    ios_base :: sync_with_stdio(0);
    cin >> n;
    vector<int> cols;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, n - 1, i);
        if (x % 2 != last % 2) {
            cols.push_back(i);
        }
        last = x;
    }
    if (cols.size() == 2) {
        int x1 = find_in_col(cols[0]);
        int x2 = find_in_col(cols[1]);
        ans(x1, cols[0], x2, cols[1]);
    }
    vector<int> rows;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, i, n - 1);
        if (x % 2 != last % 2) {
            rows.push_back(i);
        }
        last = x;
    }
    int y1 = find_in_row(rows[0]);
    ans(0, 0, 1, 1);
    ans(rows[0], y1, rows[1], y1);
    return 0;
}


#include <bits/stdc++.h>

#define int long long
#define fi first
#define se second

using namespace std;

//const int MAXN = 100005;
//const int MOD = 1e9 + 7;

int n;

int get(int x1, int y1, int x2, int y2) {
    cout << '?' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    int ans;
    cin >> ans;
    if (ans == -1) {
        exit(0);
    }
    return ans;
}

int ans(int x1, int y1, int x2, int y2) {
    cout << '!' << ' ' << x1 + 1 << ' ' << y1 + 1 << ' ' << x2 + 1 << ' ' << y2 + 1 << '\n';
    cout.flush();
    exit(0);
}

int find_in_col(int col) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(0, col, m, col);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

int find_in_row(int row) {
    int l = -1, r = n - 1;
    while (r - l > 1) {
        int m = (l + r) / 2;
        int x = get(row, 0, row, m);
        if (x % 2) {
            r = m;
        } else {
            l = m;
        }
    }
    return r;
}

signed main() {
    cin.tie(0);
    cout.tie(0);
    ios_base :: sync_with_stdio(0);
    cin >> n;
    vector<int> cols;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, n - 1, i);
        if (x % 2 != last % 2) {
            cols.push_back(i);
        }
        last = x;
    }
    if (cols.size() == 2) {
        int x1 = find_in_col(cols[0]);
        int x2 = find_in_col(cols[1]);
        ans(x1, cols[0], x2, cols[1]);
    }
    vector<int> rows;
    for (int i = 0, last = 0; i < n; i++) {
        int x = get(0, 0, i, n - 1);
        if (x % 2 != last % 2) {
            rows.push_back(i);
        }
        last = x;
    }
    int y1 = find_in_row(rows[0]);
    ans(rows[0], y1, rows[1], y1);
    return 0;
}