1/**
2 * The Forgotten Server - a free and open-source MMORPG server emulator
3 * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifndef FS_POSITION_H_5B684192F7034FB8857C8280D2CC6C75
21#define FS_POSITION_H_5B684192F7034FB8857C8280D2CC6C75
22
23enum Direction : uint8_t {
24 DIRECTION_NORTH = 0,
25 DIRECTION_EAST = 1,
26 DIRECTION_SOUTH = 2,
27 DIRECTION_WEST = 3,
28
29 DIRECTION_DIAGONAL_MASK = 4,
30 DIRECTION_NORTHEAST = DIRECTION_DIAGONAL_MASK | 0,
31 DIRECTION_SOUTHEAST = DIRECTION_DIAGONAL_MASK | 1,
32 DIRECTION_SOUTHWEST = DIRECTION_DIAGONAL_MASK | 2,
33 DIRECTION_NORTHWEST = DIRECTION_DIAGONAL_MASK | 3,
34
35 DIRECTION_LAST = DIRECTION_NORTHWEST,
36 DIRECTION_NONE = 8,
37};
38
39struct Position {
40 constexpr Position() = default;
41 constexpr Position(uint16_t x, uint16_t y, uint8_t z) : x(x), y(y), z(z) {}
42
43 template <int_fast32_t deltax, int_fast32_t deltay>
44 static bool areInRange(const Position &p1, const Position &p2) {
45 return Position::getDistanceX(p1, p2) <= deltax &&
46 Position::getDistanceY(p1, p2) <= deltay;
47 }
48
49 template <int_fast32_t deltax, int_fast32_t deltay, int_fast16_t deltaz>
50 static bool areInRange(const Position &p1, const Position &p2) {
51 return Position::getDistanceX(p1, p2) <= deltax &&
52 Position::getDistanceY(p1, p2) <= deltay &&
53 Position::getDistanceZ(p1, p2) <= deltaz;
54 }
55
56 static int_fast32_t getOffsetX(const Position &p1, const Position &p2) {
57 return p1.getX() - p2.getX();
58 }
59 static int_fast32_t getOffsetY(const Position &p1, const Position &p2) {
60 return p1.getY() - p2.getY();
61 }
62 static int_fast16_t getOffsetZ(const Position &p1, const Position &p2) {
63 return p1.getZ() - p2.getZ();
64 }
65
66 static int32_t getDistanceX(const Position &p1, const Position &p2) {
67 return std::abs(Position::getOffsetX(p1, p2));
68 }
69 static int32_t getDistanceY(const Position &p1, const Position &p2) {
70 return std::abs(Position::getOffsetY(p1, p2));
71 }
72 static int16_t getDistanceZ(const Position &p1, const Position &p2) {
73 return std::abs(Position::getOffsetZ(p1, p2));
74 }
75
76 uint16_t x = 0;
77 uint16_t y = 0;
78 uint8_t z = 0;
79
80 bool operator<(const Position &p) const {
81 if (z < p.z) {
82 return true;
83 }
84
85 if (z > p.z) {
86 return false;
87 }
88
89 if (y < p.y) {
90 return true;
91 }
92
93 if (y > p.y) {
94 return false;
95 }
96
97 if (x < p.x) {
98 return true;
99 }
100
101 if (x > p.x) {
102 return false;
103 }
104
105 return false;
106 }
107
108 bool operator>(const Position &p) const { return !(*this < p); }
109
110 bool operator==(const Position &p) const {
111 return p.x == x && p.y == y && p.z == z;
112 }
113
114 bool operator!=(const Position &p) const {
115 return p.x != x || p.y != y || p.z != z;
116 }
117
118 Position operator+(const Position &p1) const {
119 return Position(x + p1.x, y + p1.y, z + p1.z);
120 }
121
122 Position operator-(const Position &p1) const {
123 return Position(x - p1.x, y - p1.y, z - p1.z);
124 }
125
126 int_fast32_t getX() const { return x; }
127 int_fast32_t getY() const { return y; }
128 int_fast16_t getZ() const { return z; }
129};
130
131std::ostream &operator<<(std::ostream &, const Position &);
132std::ostream &operator<<(std::ostream &, const Direction &);
133
134#endif
135