<commit_before>/* Copyright 2014 <NAME>
 *
 * This file is part of Cyvasse Online.
 *
 * Cyvasse Online is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * Cyvasse Online is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with this program.
 * If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _CYVMATH_HEXAGON_HPP_
#define _CYVMATH_HEXAGON_HPP_

#include <functional>
#include <set>
#include <string>
#include <stdexcept>
#include <vector>
#include <cmath>

namespace cyvmath
{
	/* This should rather be a namespace, but namespaces cannot have template parameters.
	   hexagon<6>::Coordinate is way better understandable than hexagon::Coordinate<6>
	   so this is implemented as a template class with a deleted constructor.
	   The template parameter l stands for the edge length of the hexagon.
	 */
	template <int l>
	class hexagon
	{
		/* The smallest possible hexagon has 7 tiles and an edge lenth of 2
		   The largest possible hexagon in which the highest x and y can be represented
		   using a signed 8 bit integer has an edge length of 64 (=> width and height 127)
		 */
		static_assert(l >= 2,  "The minimum size of the hexagon edge length is 2.");
		static_assert(l <= 64, "The maximum size of the hexagon edge length is 64.");

		private:
			hexagon() = delete;

		public:
			/// A coordinate on the hexboard (see mockup/hexboard-coordinates-internal.svg)
			class Coordinate
			{
				private:
					int8_t _x;
					int8_t _y;

					int8_t z()
					{
						return -(_x + _y);
					}

					int16_t dump() const
					{
						return (_x << 8) | _y;
					}

					void throwInvalid()
					{
						throw std::invalid_argument("Coordinate not valid: "
						                            "{" + std::to_string(_x) +
						                            ", " + std::to_string(_y) + "}");
					}

				public:
					Coordinate(int8_t x, int8_t y)
						: _x(x)
						, _y(y)
					{
						if(!isValid())
							throwInvalid();
					}

					int8_t x() const
					{
						return _x;
					}

					int8_t y() const
					{
						return _y;
					}

					bool isValid() const
					{
						return (_x + _y) >= (l - 1) &&
						       (_x + _y) <= (l - 1) * 3;
					}

					operator bool() const
					{
						return isValid();
					}

					bool operator<(Coordinate other) const
					{
						return dump() < other.dump();
					}

					/** Get the distance to another coordinate in form of the amount
					    of single moves to adjacent tiles required to move there
					 */
					int8_t getDistance(Coordinate other) const
					{
						// I have no idea how or why this works, but it does.
						// Taken from http://keekerdc.com/2011/03/hexagon-grids-coordinate-systems-and-distance-calculations/
						return *(std::set<int>({abs(_x - other._x), abs(_y - other._y), abs(z() - other.z())}).rbegin());
					}

					/// Check if the given coordinate is reachable in one orthogonal move
					bool isOrthogonal(Coordinate other) const
					{
						return _x == other._x || _y == other._y || z() == other.z();
					}

					/** Like getDistance(), but return -1 if the given coordinate
					    is not reachable in one orthogonal move

					    An orthogonal move is a straight move in one of the six
					    directions of the neighboring hex-tiles.
					 */<commit_msg>Added simpler hashing possibility (though unused), operator== to hexagon<commit_after>/* Copyright 2014 <NAME>
 *
 * This file is part of Cyvasse Online.
 *
 * Cyvasse Online is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * Cyvasse Online is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with this program.
 * If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _CYVMATH_HEXAGON_HPP_
#define _CYVMATH_HEXAGON_HPP_

#include <functional>
#include <set>
#include <string>
#include <stdexcept>
#include <vector>
#include <cmath>

namespace cyvmath
{
	/* This should rather be a namespace, but namespaces cannot have template parameters.
	   hexagon<6>::Coordinate is way better understandable than hexagon::Coordinate<6>
	   so this is implemented as a template class with a deleted constructor.
	   The template parameter l stands for the edge length of the hexagon.
	 */
	template <int l>
	class hexagon
	{
		/* The smallest possible hexagon has 7 tiles and an edge lenth of 2
		   The largest possible hexagon in which the highest x and y can be represented
		   using a signed 8 bit integer has an edge length of 64 (=> width and height 127)
		 */
		static_assert(l >= 2,  "The minimum size of the hexagon edge length is 2.");
		static_assert(l <= 64, "The maximum size of the hexagon edge length is 64.");

		private:
			hexagon() = delete;

		public:
			/// A coordinate on the hexboard (see mockup/hexboard-coordinates-internal.svg)
			class Coordinate
			{
				private:
					int8_t _x;
					int8_t _y;

					int8_t z()
					{
						return -(_x + _y);
					}

					int16_t dump() const
					{
						return (_x << 8) | _y;
					}

					void throwInvalid()
					{
						throw std::invalid_argument("Coordinate not valid: "
						                            "{" + std::to_string(_x) +
						                            ", " + std::to_string(_y) + "}");
					}

				public:
					Coordinate(int8_t x, int8_t y)
						: _x(x)
						, _y(y)
					{
						if(!isValid())
							throwInvalid();
					}

					int8_t x() const
					{
						return _x;
					}

					int8_t y() const
					{
						return _y;
					}

					bool isValid() const
					{
						return (_x + _y) >= (l - 1) &&
						       (_x + _y) <= (l - 1) * 3;
					}

					operator bool() const
					{
						return isValid();
					}

					operator int() const
					{
						return dump();
					}

					bool operator==(Coordinate other) const
					{
						return _x == other._x && _y == other._y;
					}

					bool operator<(Coordinate other) const
					{
						return dump() < other.dump();
					}

					/** Get the distance to another coordinate in form of the amount
					    of single moves to adjacent tiles required to move there
					 */
					int8_t getDistance(Coordinate other) const
					{
						// I have no idea how or why this works, but it does.
						// Taken from http://keekerdc.com/2011/03/hexagon-grids-coordinate-systems-and-distance-calculations/
						return *(std::set<int>({abs(_x - other._x), abs(_y - other._y), abs(z() - other.z())}).rbegin());
					}

					/// Check if the given coordinate is reachable in one orthogonal move
					bool isOrthogonal(Coordinate other) const
					{
						return _x == other._x || _y == other._y || z() == other.z();
					}

					/** Like getDistance(), but return -1 if the given coordinate
					    is not reachable in one orthogonal move

					    An orthogonal move is a straight move in one of the six
					    directions of the neighboring hex-tiles.
					 */
{'fraction_non_alphanumeric': 0.09587790242629794, 'fraction_numerical': 0.010957474563005479, 'mean_word_length': 2.3745598591549295, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7002554', 'n_tokens_mistral': 2991, 'n_tokens_neox': 2222, 'n_words': 884}