//This file is terminal3d.h. #ifndef TERMINAL3DH #define TERMINAL3DH #include //for ostream and << #include //for rand #include //for size_t and ptrdiff_t #include //for sqrt #include //for fill, iterator_category, random_access_iterator_tag #include using namespace std; extern "C" { #include "term3d.h" } template class terminal3d { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef CHAR value_type; class different {}; private: CHAR _background; size_type _xmax; size_type _ymax; size_type _zmax; public: class element; class iterator #ifdef _MSC_VER : public std::iterator #endif { friend class terminal3d; friend class element; //Lippman p. 751, Stroustrup p. 279 public: typedef random_access_iterator_tag iterator_category; typedef ptrdiff_t difference_type; typedef CHAR value_type; typedef CHAR *pointer; typedef CHAR& reference; private: const terminal3d *const t; size_type i; //distance from begin to this iterator size_type x() const {return i % t->xmax();} size_type y() const {return i / t->xmax() % t->ymax();} size_type z() const {return i /(t->xmax() * t->ymax());} public: iterator(const terminal3d& initial_t, size_type x, size_type y, size_t z) : t(&initial_t), i(x + (y + z * t->ymax()) * t->xmax()) { } iterator& operator+=(const difference_type& d) { i += d; return *this; } iterator& operator-=(const difference_type& d) { i -= d; return *this; } const iterator operator+(difference_type d) const { iterator it = *this; return it += d; } const iterator operator-(difference_type d) const { iterator it = *this; return it -= d; } iterator& operator++() {return *this += 1;} iterator& operator--() {return *this -= 1;} const iterator operator++(int) { const iterator old = *this; ++*this; return old; } const iterator operator--(int) { const iterator old = *this; --*this; return old; } iterator& operator=(const iterator& other) { i = other.i; return *this; } difference_type operator-(const iterator& it) const throw (different) { if (t != it.t) { throw different(); } return i - it.i; } bool operator==(const iterator& it) const { return t == it.t && i == it.i; } bool operator<(const iterator& it) const throw (different) { if (t != it.t) { throw different(); } return i < it.i; } bool operator>(const iterator& it) const throw (different) { if (t != it.t) { throw different(); } return i > it.i; } bool operator!=(const iterator& it) const { return !(*this == it); //return !(operator==(*this, it)); } bool operator>=(const iterator& it) const throw (different) { return !(*this < it); } bool operator<=(const iterator& it) const throw (different) { return !(*this > it); } friend ostream& operator<<(ostream& ost, const iterator& it) { return ost << "(" << x() << ", " << y() << ", " << z() << ")"; } const element operator*() const throw (iterator) { return element(*this); } const element operator[](const difference_type& d) const throw (pair) { try { return *(*this + d); } catch (const iterator&) { throw make_pair(*this, d); } } }; class element { const iterator it; element(const iterator& initial_it) throw (iterator): it(initial_it) { if (!it.t->in_range(it)) { throw it; } } public: const element& operator=(CHAR c) const { term3d_put(it.x(), it.y(), it.z(), c); return *this; } operator CHAR() const {return term3d_get(it.x(), it.y(), it.z());} const element& operator+=(int i) const { return *this = static_cast(*this) + i; } const element& operator-=(int i) const { return *this = static_cast(*this) - i; } const element& operator++() const {return *this += 1;} const element& operator--() const {return *this -= 1;} const element operator++(int) const { const element old = *this; ++*this; return old; } const element operator--(int) const { const element old = *this; --*this; return old; } friend const element iterator::operator*() const throw (iterator); }; terminal3d(const char *ip, unsigned short port, CHAR initial_background = ' ') : _background(initial_background) { term3d_construct(ip, port); _xmax = term3d_xmax(); _ymax = term3d_ymax(); _zmax = term3d_zmax(); if (background() != static_cast(' ')) { fill(begin(), end(), background()); } } ~terminal3d() { fill(begin(), end(), ' '); term3d_destruct(); } CHAR background() const {return _background;} size_type xmax() const {return _xmax;} size_type ymax() const {return _ymax;} size_type zmax() const {return _zmax;} size_type size() const {return xmax() * ymax() * zmax();} iterator begin() const {return iterator(*this, 0, 0, 0);} iterator end() const {return iterator(*this, 0, 0, zmax());} static char key() {return term3d_key();} static void wait(int milliseconds) {term3d_wait(milliseconds);} static void beep() {term3d_beep();} public: bool in_range(const iterator& it) const { return it.x() < xmax() && it.y() < ymax() && it.z() < zmax(); } #ifdef _MSC_VER #define STD #else #define STD std #endif difference_type rand() const { return STD::rand() % 3 - 1 + ((STD::rand() % 3 - 1) * ymax() + STD::rand() % 3 - 1) * xmax(); } #undef STD static double distance(const iterator& it1, const iterator& it2) { const difference_type x = static_cast(it1.x()) - static_cast(it2.x()); const difference_type y = static_cast(it1.y()) - static_cast(it2.y()); const difference_type z = static_cast(it1.z()) - static_cast(it2.z()); return sqrt(x * x + y * y * z * z); } private: static difference_type signum(difference_type d) { return d < 0 ? -1 : d > 0; } public: difference_type step(const iterator& it1, const iterator& it2) const { return signum(it2.x() - it1.x()) + (signum(it2.y() - it1.y()) + signum(it2.z() - it1.z()) * ymax()) * xmax(); } typedef map keypad_t; keypad_t keypad() const { #ifdef _MSC_VER //Microsoft map does not have the constructor with 2 arguments. keypad_t k; k.insert(make_pair('h', -static_cast(1))); //left k.insert(make_pair('j', static_cast(xmax()))); //down k.insert(make_pair('k', -static_cast(xmax()))); //up k.insert(make_pair('l', static_cast(1))); //right k.insert(make_pair('f', -static_cast(xmax() * ymax())));//forward k.insert(make_pair('b', static_cast(xmax() * ymax())));//backward return k; #else static const pair a[] = { make_pair('h', -static_cast(1)), //left make_pair('j', static_cast(xmax())), //down make_pair('k', -static_cast(xmax())), //up make_pair('l', static_cast(1)), //right make_pair('f', -static_cast(xmax() * ymax())), //forward make_pair('b', static_cast(xmax() * ymax())), //backward }; static const size_t n = sizeof a / sizeof a[0]; return keypad_t(a, a + n); #endif } }; #endif