text: /**
   * @file
   * @author Lieutenant Debaser
   * @version 20210801
   *
   * @section LICENSE
   *
   * Unless stated otherwise, files that are a part of this program are distributed under the
   * Unlicense. The program is distributed without a warranty of any kind and fitness for any
   * particular application or use case cannot be guaranteed.
   *
   * For more information and a complete description of the Unlicense, please read
   *      https://unlicense.org
   *
   * @section DESCRIPTION
   *
   * The Pkm class is used to store and modify the data of PC and party member Pokemon data.
  */
  
  #ifndef LIB_G3SAVE_PKM_H
  #define LIB_G3SAVE_PKM_H
  
  #include <cstdint>
  #include <iostream>
  #include <string>
  #include <cstdlib>
  #include <ctime>
  
  #include "lib-g3save-index.h"
  #include "lib-g3save-char.h"
  
  // Language codes for Pkm class as used by the game save
  /*! Language code for Japanese game characters.*/
  #define LANG_JAP 0x0201	// Japanese
  
  /*! Language code for English game characters.*/
  #define LANG_ENG 0x0202	// English
  
  /*! Language code for French game characters.*/
  #define LANG_FRN 0x0203	// French
  
  /*! Language code for Italian game characters.*/
  #define LANG_ITL 0x0204	// Italian
  
  /*! Language code for German game characters.*/
  #define LANG_GRM 0x0205	// German
  
  /*! Language code for Korean game characters.*/
  #define LANG_KOR 0x0206	// Korean
  
  /*! Language code for Spanish game characters.*/
  #define LANG_SPN 0x0207	// Spanish
  
  /*! Language code used for eggs.*/
  #define LANG_EGG 0x0601	// Language code used for eggs
  
  
  // Data section codes for the Pkm class
  /*! Pkm data section containing:
   *      - Species information.
   *      - Held item.
   *      - Experienced gained.
   *      - PPUP usage per move.
   *      - Friendship with current trainer.
   */
  #define PKM_CURINF 0x00
  
  /*! Pkm data section containing:
   *      - Move list.
   *      - Current moves' PP.
   */
  #define PKM_ATTACK 0x01
  
  /*! Pkm data section containing:
   *      - Effort values (EVs).
   *      - Contest stats.
  */
  #define PKM_GROWTH 0x02
  
  /*! Pkm data section containing:
   *      - If Pokerus has infected the Pkm.
   *      - Met location.
   *      - Pokeball.
   *      - Individual values (IVs).
   *      - Ribbons obtained.
   *      - Obedience value.
  */
  #define PKM_ORIGIN 0x03
  
  
  // Game name values for setting the originating game of a Pkm
  /*! Game code for Sapphire version.*/
  #define SAPPHIRE 0x00
  
  /*! Game code for Ruby version.*/
  #define RUBY 0x01
  
  /*! Game code for Emerald version.*/
  #define EMERALD 0x02
  
  /*! Game code for FireRed version.*/
  #define FIRERED 0x03
  
  /*! Game code for LeafGreen version.*/
  #define LEAFGREEN 0x04
  
  /*! Game code for Colosseum version.*/
  #define COLOSSEUM 0x0F
  
  /*! Game code for XD: Gale of Darkness version.*/
  #define XD 0x0F
  
  
  class Pkm {
  public:
  
  	//Constructors
  	/**
  	 * Constructor that sets Pkm member data to default values
  	*/
  	Pkm ();
  
  	// Non-Data Section Modifying Functions
      /**
       * Get the value of the personality value.
       *
       * @return The value stored in the personality variable.
      */
  	uint32_t get_personality ();
  
      /**
       * Set the value of the personality value.
       *
       * @param val is the new personality value to be set; assumed to be in Big Endian.
      */
  	void set_personality (uint32_t val);
  
      /**
       * Get the value of both IDs (visible and hidden) as a single value.
       *
       * @return The value stored in the trainer_id variable.
      */
  	uint32_t get_trainer_id ();
  
      /**
       * Set the value of the trainer ID; affects both the visible and hidden trainer IDs.
       *
       * @param val is the value of the trainer ID to be set; assumed to be in Big Endian.
      */
  	void set_trainer_id (uint32_t val);
  
      /**
       * Set the value of a character within the encoded nickname string.
       *
       * @param val is the vlaue of the character to be set using in-game encoding.
       * @param position is the position within the nickname array that is to be set to the
       *      specified character.
       * @return If the character was set successfully.
      */
  	bool set_nickname_char (uint8_t val, uint8_t position);
  
      /**
       * Get the current nickname of the Pkm class.
       *
       * @return The nickname of the Pkm class as an ASCII string.
      */
  	std::string get_nickname ();
  
      /**
       * Set the nickname of the Pkm class using an array of characters that are encoded using the
       *      in-game encoding.
       *
       * @param val is an array of characters encoded using in-game character encoding; any array
       *      larger than 10 elements will be truncated.
      */
  	void set_nickname (uint8_t val []);
  
      /**
       * Set the nickname of the Pkm class using a string of ASCII characters.
       *
       * @param nickname is an ASCII string to be set as the nickname; any string that is longer than
       *      10 characters in length will be truncated.
       * @return If the nickname was set successfully.
      */
  	bool set_nickname (std::string nickname);
  
      /**
       * Get the region of origin as a string.
       *
       * @return A string indicating the region of origin.
      */
  	std::string get_language ();
  
      /**
       * Get the language code that indicates the region of origin.
       *
       * @return A language code indicating the region of origin; can be compared to LANG_ macros.
      */
  	uint16_t get_language_code ();
  
      /**
       * Set the language code that indicates the region of origin.
       *
       * @param code is a language code; LANG_ macros can be used in lieu of a value.
      */
  	void set_language_code (uint16_t code);
  
  	/**
  	 * Get a pointer to the first element of the original trainer name.
  	 *
  	 * @return A pointer to trainer_name [0].
  	*/
  	uint8_t* get_trainer_name_ptr ();
  
      /**
       * Set the value of a character within the encoded name string storing the original trainer
       *      name.
       *
       * @param val is the value of the character to be set using in-game encoding.
       * @param position is the position within the name array that will be set.
       * @return If the character was set successfully.
      */
  	bool set_trainer_name_char (uint8_t val, uint8_t position);
  
      /**
       * Get the name of the original trainer as an ASCII string.
       *
       * @return The name of the original trainer as an ASCII string; if an error occurs, an empty
       *      string is returned.
      */
  	std::string get_trainer_name ();
  
      /**
       * Set the name of the original trainer using in-game encoding.
       *
       * @param val is an array of characters encoded using in-game encoding.
      */
  	void set_trainer_name (uint8_t val []);
  
      /**
       * Set the name of the original trainer using an ASCII string.
       *
       * @param name is the ASCII encoding of the name to be set; if name is longer than 7
       *      characters, extra characters will be truncated.
      */
  	void set_trainer_name (std::string name);
  
      /**
       * Get the value of the byte used to store the markings used to organize in the PC Box.
       *
       * @return The byte storing markings:
       *      - 0b00001111
       *              ^ Heart
       *               ^ Triangle
       *                ^ Square
       *                 ^ Circle
      */
  	uint8_t get_markings ();
  
      /**
       * Set the value of the byte used to store the markings used to organize in the PC Box using a
       *      specified byte value.
      */
  	void set_markings (uint8_t val);
  
      /**
       * Set the value of the byte used to store the markings used to organize in the PC Box by
       *      specifying if each marking should be set.
       *
       * @param circle is if the circle marking should be shown.
       * @param square is if the square marking should be shown.
       * @param trianle is if the trianle marking should be shown.
       * @param heart is if the heart marking should be shown.
      */
  	void set_markings (bool circle, bool square, bool triangle, bool heart);
  
  
  	// Functions to be used on party members only
      /**
       * Get the 4-byte value used to keep track of status conditions.
       *
       * @return The value stored in the status_condition variable.
      */
  	uint32_t get_status_condition ();
  
      /**
       * Set the 4-byte value used to keep track of status conditions using an exact value.
       *
       * @param val is the the 4-byte value to be set for status_condition in Little Endian.
       * @return If the value was successfully set; will return false if the in_party flag is not
       *      set.
      */
  	bool set_status_condition (uint32_t val);
  
      /**
       * Set if a status condition has been inflicted using a string as input.
       *
       * @param condition is the name of the status condition to be set; valid conditions are:
       *      - clear            : Remove all status conditions.
       *      - sleep1 -> sleep7 : Sleep status condition; number after indicates number of turns
       *                           remaining for condition.
       *      - poison           : Poisoned status condition.
       *      - burn             : Burned status condition.
       *      - freeze           : Frozen status condition.
       *      - paralysis        : Paralyzed status condition.
       *      - toxic            : Badly poisoned (toxic) status condition.
       * @return If a status condition was set.
      */
  	bool set_status_condition (std::string condition);
  
      /**
       * Get the value of the byte used to store the level.
       *
       * @return The current level of the Pkm.
      */
  	uint8_t get_level ();
  
      /**
       * Set the value of the byte used to store the level.
       *
       * @param val is the new level.
       * @return If the operation was successful.
      */
  	bool set_level (uint8_t val);
  
      /**
       * Get the value of the byte used to keep track of Pokerus timing.
       *
       * @return The value of the byte used to keep track of if Pokerus has been contracted.
      */
  	uint8_t get_pokerus_timer ();
  
      /**
       * Set the value of the byte used to keep track of Pokerus timing.
       *
       * @param val is the value this byte is to be set to; 0xFF indicates no contraction of Pokerus
       *      and 0x00 indicates that Pokerus has been cured.
       * @return If the operation was successful.
      */
  	bool set_pokerus_timer (uint8_t val);
  
      /**
       * Get the value of the current HP stat as it appears in the party menu.
       *
       * @return The value of the current HP stat.
      */
  	uint16_t get_c_hp ();
  
      /**
       * Set the value of the current HP stat as it appears in the party menu.
       *
       * @param val is the value to which current HP will be set.
       * @return If the operation was successful; will return false if the in_party flag is false.
      */
  	bool set_c_hp (uint16_t val);
  
      /**
       * Get the value of the total HP stat as it appears in the party menu.
       *
       * @return The value of the total HP stat.
      */
  	uint16_t get_t_hp ();
  
      /**
       * Set the value of the total HP stat as it appears in the party menu.
       *
       * @param val is the value to which total HP will be set.
       * @return If the operation was successful; will return false if the in_party flag is false.
      */
  	bool set_t_hp (uint16_t val);
  
      /**
       * Get the value of the attack stat as it appears in the party menu.
       *
       * @return The value of the attack stat.
      */
  	uint16_t get_attack ();
  
      /**
       * Set the value of the attack stat as it appears in the party menu.
       *
       * @param val is the value to which attack will be set.
       * @return If the operation was successful; will return false if the in_party flag is false.
      */
  	bool set_attack (uint16_t val);
  
      /**
       * Get the value of the defense stat as it appears in the party menu.
       *
       * @return The value of the defense stat.
      */
  	uint16_t get_defense ();
  
      /**
       * Set the value of the defense stat as it appears in the party menu.
       *
       * @param val is the value to which defense will be set.
       * @return If the operation was successful; will return false if the in_party flag is false.
      */
  	bool set_defense (uint16_t val);
  
      /**
       * Get the value of the special attack stat as it appears in the party menu.
       *
       * @return The value of the speed stat.
      */
  	uint16_t get_speed ();
  
      /**
       * Set the value of the speed stat as it appears in the party menu.
       *
       * @param val is the value to which speed will be set.
       * @return If the operation was successful; will return false if the in_party flag is false.
      */
  	bool set_speed (uint16_t val);
  
      /**
       * Get the value of the special attack stat as it appears in the party menu.
       *
       * @return The value of the special attack stat.
      */
  	uint16_t get_sp_attack ();
  
      /**
       * Set the value of the special attack stat as it appears in the party menu.
       *
       * @param val is the value to which special attack will be set.
       * @return If the operation was successful; will return false if the in_party flag is false.
      */
  	bool set_sp_attack (uint16_t val);
  
      /**
       * Get the value of the special defense stat as it appears in the party menu.
       *
       * @return The value of the special defense stat.
      */
  	uint16_t get_sp_defense ();
  
      /**
       * Set the value of the special defense stat as it appears in the party menu.
       *
       * @param val is the value to which special defense will be set.
       * @return If the operation was successful; will return false if the in_party flag is false.
      */
  	bool set_sp_defense (uint16_t val);
  
  
  	// Data Section Modifying Functions
      /**
       * Read the 48 bytes of the data section starting at the location pointed to by data_ptr and
       *      store them in encrypted_data.
      */
  	void read_data_section ();
  
      /**
       * Write the encrypted_data data array to its corresponding place within the save based off of
       *      the location pointed to by data_ptr.
      */
  	void write_data_section ();
  
      /**
       * Calculate the order of the subsections held within the data section based on a %24 value.
       *
       * @param mod24_val is the personality value of the Pkm %24.
       * @return Returns false if mod24_val is greater than 23.
      */
  	bool calc_data_order (uint8_t mod24_val);
  
      /**
       * Recalculate the order of the subsections within the data sections and move the subsections
       *      to reflect this new value.
       *
       * @return If the operation was successful.
      */
  	bool recalc_data_order ();
  
      /**
       * Get the value of a byte in the encrypted_data data array.
       *
       * @param position is the address within encrypted_data where the byte is to be sourced.
       * @return The value of the byte at the specified position; returns 0x00 if an invalid position
       *      is specified.
      */
  	uint8_t get_encrypted_byte (uint8_t position);
  
      /**
       * Set a byte in the encrypted_data data array.
       *
       * @param val is the byte value to be set in the array.
       * @param position is the address within encrypted_data where the byte is to be set.
       * @return If teh byte was successfully set.
      */
  	bool set_encrypted_byte (uint8_t val, uint8_t position);
  
      /**
       * Get the value of a byte in the decypted_data data array.
       *
       * @param position is the address within decrypted_data where the byte is to be sourced.
       * @return The value of the byte at the specified position; returns 0x00 if an invalid position
       *      is specified.
      */
  	uint8_t get_decrypted_byte (uint8_t position);
  
      /**
       * Set a byte in the decrypted_data data array.
       *
       * @param val is the byte value to be set in the array.
       * @param position is the address within decrypted_data where the byte is to be set.
       * @return If the byte was set successfully.
      */
  	bool set_decrypted_byte (uint8_t val, uint8_t position);
  
      /**
       * Calculate the checksum used to verify the data in the 48 byte data section and store the
       *      result in checksum.
       *
       * @return The checksum generated during calculation.
      */
  	uint16_t calc_checksum ();
  
      /**
       * Generate the data key used to encrypt and decrypt the 48 byte data section and store the
       *      the result in data_key.
      */
  	void generate_data_key ();
  
      /**
       * Generate a data key and decrypt the encrypted data array; the the result in decrypted_data.
      */
  	void decrypt_data ();
  
      /**
       * Generate a data key and encrypt the decrypted data array; put the result in encrypted_data.
      */
  	void encrypt_data ();
  
  
  	// For PKM_CURINF data section
      /**
       * Get the species ID of the Pkm.
       *
       * @return The internal species ID of the class instance.
      */
  	uint16_t get_species ();
  
      /**
       * Set the species of the Pkm based on an ID.
       *
       * @param spec_id is the internal ID of a species.
      */
  	void set_species (uint16_t spec_id);
  
      /**
       * Set the species of the Pkm based on an input name.
       *
       * @param spec_name is the name of the species that will be set for the Pkm.
       * @param pkm_list is the Index in which spec_nae will be searched for.
       * @return If the species was set successfully based on the input name.
      */
  	bool set_species (std::string spec_name, Index pkm_list);
  
      /**
       * Get the ID of the item being held.
       *
       * @return The ID of the item being held by the Pkm.
      */
  	uint16_t get_held_item ();
  
      /**
       * Set the item being held based on an item id.
       *
       * @param item_id is an internal ID for an item that can be held.
       * @return If the item was successfully set based on the ID.
      */
  	bool set_held_item (uint16_t item_id);
  
  	/**
  	 * Set the item being held based on an input name.
  	 *
  	 * @param item_name is the name of the item to be searched for.
  	 * @param item_list is the Index in which item_name will be searched for.
  	 * @return If the item was successfully set based on the input string.
  	*/
  	bool set_held_item (std::string item_name, Index item_list);
  
  	/**
  	 * Get the amount of experience gained by a Pkm through battle.
  	 *
  	 * @return The 4-byte value used to store experience.
  	*/
  	uint32_t get_experience ();
  
  	/**
  	 * Set the amount of experience obtained.
  	 *
  	 * @param xp is the numeric quantity of experience gained through battling; different Pkm
  	 *		species level at different rates, so the level produced from setting this value may
  	 *		differ depending on the type.
  	 * @return Success of the operation.
  	*/
  	bool set_experience (uint32_t xp);
  
  	/**
  	 * Get the PPUP bonus byte.
  	 *
  	 * @return The value of the PPUP bonus byte.
  	*/
  	uint8_t get_pp_bonus ();
  
  	/**
  	 * Set the PPUP bonus byte using a verbose value.
  	 *
  	 * @param bonus_val is the value the PPUP byte will be set to; two bits are allocated per move
  	 *		with the lowest-order bits being for move 4 and the highest-order bits being for move 1.
  	*/
  	void set_pp_bonus (uint8_t bonus_val);
  
  	/**
  	 * Set the PPUP bonuses for all moves. Maximum parameter values are 0x03 (3).
  	 *
  	 * @param m1_val is the PPUP bonus for the first move.
  	 * @param m2_val is the PPUP bonus for the second move.
  	 * @param m3_val is the PPUP bonus for the third move.
  	 * @param m4_val is the PPUP bonus for the fourth move.
  	 * @return Success of the operation; any parameter that is larger than 0x03 will cause this
  	 *		function to return false.
  	*/
  	bool set_pp_bonus (uint8_t m1_val, uint8_t m2_val, uint8_t m3_val, uint8_t m4_val);
  
  	/**
  	 * Get the friendship value of a Pkm for its current trainer.
  	 *
  	 * @return A friendship value in the range of 0 (min) to 255 (max).
  	*/
  	uint8_t get_friendship ();
  
  	/**
  	 * Set the friendship value of a Pkm for the current trainer.
  	 *
  	 * @param val is the friendship value to be set.
  	*/
  	void set_friendship (uint8_t val);
  
  
  	// For PKM_ATTACK data section
  	/**
  	 * Get the internal ID of an attack a Pkm possesses.
  	 *
  	 * @param attack_index is the position of the attack in the list of moves; valid values are
  	 *		0 - 3.
  	 * @return The ID of the move; returns 0xFFFF if an invalid attack_index is provided.
  	*/
  	uint16_t get_move (uint8_t attack_index);
  
  	/**
  	 * Set an attack using a specific internal ID.
  	 *
  	 * @param attack_index is the position of the attack in the list of moves; valid moves are
  	 *		0 - 3.
  	 * @param attack_id is an internal ID used by the game to determine an attack.
  	 * @return Success of the operation.
  	*/
  	bool set_move (uint8_t attack_index, uint16_t attack_id);
  
  	/**
  	 * Set an attack using an Index of attacks and a search term.
  	 *
  	 * @param attack_index is the position of the attack in the list of moves; valid moves are
  	 *		0 - 3.
  	 * @param attack_name is the name of the attack to be searched for within the Index;
  	 *		capitalization does not matter.
  	 * @param attack_list is an Index of name-value pairs containing information for attacks.
  	 * @return Success of the operation.
  	*/
  	bool set_move (uint8_t attack_index, std::string attack_name, Index attack_list);
  
  	/**
  	 * Get the PP remaining for one of the moves.
  	 *
  	 * @param attack_index is the position of the attack in the list of moves; valid values are
  	 *		0 - 3.
  	 * @return The PP remaining for a move; returns 0x00 (0) if an invalid attack_index was used.
  	*/
  	uint8_t get_pp (uint8_t attack_index);
  
  	/**
  	 * Set the PP of one of the moves.
  	 *
   	 * @param attack_index is the position of the attack in the Pkm's list of moves; valid values
  	 *		are 0 - 3.
   	 * @param val is the number to set the PP to.
  	 * @return Success of the operation.
  	*/
  	bool set_pp (uint8_t attack_index, uint8_t val);
  
  
  	// For PKM_GROWTH data section
  	// Get and set effort values
  	/**
  	 * Get the number of points that have gone into the HP effort value.
   	 * 
  	 * @return The number of points that have gone into the HP effort value; returns 255 (0xFF)
  	 * 		if unable to find the data section with this value.
  	*/
  	uint8_t get_ev_hp ();
  
  	/**
  	 * Set the number of points obtained for the HP effort value.
   	 *
  	 * @param val is the number of points to go into HP; a number in the range 0 - 255.
  	 * @return Success of the operation.
  	*/
  	bool set_ev_hp (uint8_t val);
  
  	/**
   	 * Get the number of points that ahve gone into the attack effort value.
  	 *
  	 * @return The number of points that have gone into the attack effort value; returns
  	 *		255 (0xFF) if unable to find the data section with this value.
  	*/
  	uint8_t get_ev_attack ();
  
  	/**
  	 * Set the number of points obtained for the attack effort value.
   	 *
  	 * @param val is the number of points to go into attack; a number in the range 0 -255.
  	 * @return Success of the operation.
  	*/
  	bool set_ev_attack (uint8_t val);
  
  	/**
  	 * Get the number of points that have gone into the defense effort value.
  	 *
  	 * @return The number of points that have gone into the defense effort value; returns
  	 *		255 (0xFF) if unable to find the data section with this value.
  	*/
  	uint8_t get_ev_defense ();
  
  	/**
  	 * Set the number of points obtained for the defense effort value.
  	 *
  	 * @param val is the number of points to go into defense; a number in the range 0 - 255.
  	 * @return Success of the operation.
  	*/
  	bool set_ev_defense (uint8_t val);
  
  	/**
  	 * Get the number of points that have gone into the speed effort value.
  	 *
  	 * @return The number of points that have gone into the speed effort value; returns 255 (0xFF)
  	 *		if unable to find the data section with this value.
  	*/
  	uint8_t get_ev_speed ();
  
  	/**
  	 * Set the number of points obtained for the speed effort value.
  	 *
  	 * @param val is the number of points to go into speed; a number in the range 0 - 255.
  	 * @return Success of the operation.
  	*/
  	bool set_ev_speed (uint8_t val);
  
  	/**
  	 * Get the number of points obtained for the special attack effort value.
   	 *
  	 * @return The number of points that have gone into the special attack effort value; returns
  	 *		255 (0xFF) if unable to find the data section with this value.
  	*/
  	uint8_t get_ev_sp_attack ();
  
  	/**
  	 * Set the number of points obtained for the special attack effort value.
   	 *
  	 * @param val is the number of points to go into special attack; a number in the range 0 -255.
  	 * @return Success of the operation.
  	*/
  	bool set_ev_sp_attack (uint8_t val);
  
  	/**
   	 * Get the number of points obtained for the special defense effort value.
  	 *
  	 * @return The number of points that have gone into the special defense effort value; returns
  	 *		255 (0xFF) if unable to find the data section with this value.
  	*/
  	uint8_t get_ev_sp_defense ();
  
  	/**
  	 * Set the number of points obtained for the special defense effort value.
  	 *
  	 * @param val is the number of points to go into special defense; a number in the range 0 - 255.
  	 * @return Success of the operation.
  	*/
  	bool set_ev_sp_defense (uint8_t val);
  	
  	
  	// Get and set contest stats
  	/**
  	 * Get the value for the contest stat coolness.
  	 *
  	 * @return The value of the coolness stat; returns 255 (0xFF) if unable to find the data
  	 *		section with this value.
  	*/
  	uint8_t get_contest_coolness ();
  
  	/**
  	 * Set the value for the contest stat coolness.
  	 *
  	 * @param val is the value coolness will be set to; a number in the range 0 - 255.
  	 * @return Success of the operation.
  	*/
  	bool set_contest_coolness (uint8_t val);
  
  	/**
  	 * Get the value for the contest stat beauty.
  	 *
  	 * @return The value of the beauty stat; returns 255 (0xFF) if unable to find the data section
  	 *		with this value.
  	*/
  	uint8_t get_contest_beauty ();
  
  	/**
  	 * Set the value for the contest stat beauty.
  	 *
  	 * @param val is the value beauty will be set to; a number in the range 0 - 255.
  	 * @return Success of the operation.
  	*/
  	bool set_contest_beauty (uint8_t val);
  
  	/**
  	 * Get the value for the contest stat cuteness.
  	 *
  	 * @return The value of the cuteness stat; returns 255 (0xFF) if unable to find the data section
  	 *		with this value.
  	*/
  	uint8_t get_contest_cuteness ();
  
  	/**
  	 * Set the value for the contest stat cuteness.
  	 *
  	 * @param val is the value cuteness will be set to; a number in the range 0 - 255.
  	 * @return Success of the operation.
  	*/
  	bool set_contest_cuteness (uint8_t val);
  
  	/**
  	 * Get the value for the contest stat smartness.
  	 *
  	 * @return The value of the smartness stat; returns 255 (0xFF) if unable to find the data
  	 *		section with this value.
  	*/
  	uint8_t get_contest_smartness ();
  
  	/**
  	 * Set the value for the contest stat smartness.
  	 *
  	 * @param val is the value toughness will be set to; a number in the range 0 - 255.
  	 * @return Success of the operation.
  	*/
  	bool set_contest_smartness (uint8_t val);
  
  	/**
  	 * Get the value for the contest stat toughness.
  	 *
  	 * @return The value of the toughness stat; returns 255 (0xFF) if unable to find the data
  	 *		section with this value.
  	*/
  	uint8_t get_contest_toughness ();
  
  	/**
  	 * Set the value for the contest stat toughness.
  	 *
  	 * @param val is the value toughness will be set to; a number in the range 0 - 255.
  	 * @return Success of the operation.
  	*/
  	bool set_contest_toughness (uint8_t val);
  
  	/**
  	 * Get the byte used to keep track of the number of Pokeblocks consumed.
  	 *
  	 * @return The value of the feel byte; returns 255 (0xFF) if unable to find the data section
  	 *		with this value.
  	*/
  	uint8_t get_contest_feel ();
  
  	/**
  	 * Set the byte used to keep track of the number of Pokeblocks consumed.
  	 *
  	 * @param val is the value the feel should be set to; a number in the range 0 - 255.
  	 * @return Success of the operation.
  	*/
  	bool set_contest_feel (uint8_t val);
  
  
  	// For PKM_ORIGIN data section
  	/**
  	 * Get the value of the byte used to indicate the status of Pokerus.
  	 *
  	 * @return A byte containing the strain and days remaining for Pokerus.
  	*/
  	uint8_t get_pokerus_byte ();
  
  	/**
  	 * Set the value of the byte used to indicate Pokerus status.
  	 *
  	 * @param val is the value of the byte to be set.
  	 * @return Success of the operation.
  	*/
  	bool set_pokerus_byte (uint8_t val);
  
  	/**
  	 * Set the duration a Pokerus strain should last.
  	 *
  	 * @param day_duration is a value 1 - 4.
  	 * @return Success of the operation.
  	*/
  	bool set_pokerus_duration (int day_duration);
  
  	/**
  	 * Get the location ID of encounter.
  	 *
  	 * @return The internal location ID an encounter took place.
  	*/
  	uint8_t get_met_location ();
  
  	/**
  	 * Set the location of encounter based on an input value.
  	 *
  	 * @param val is an internal location ID.
  	 * @return Success of the operation
  	*/
  	bool set_met_location (uint8_t val);
  
  	/**
  	 * Set the location of encounter based on an input name.
  	 *
  	 * @param location_name is an input string that will be searched for in an index.
  	 * @param loc_list is an Index class containing location names and IDs.
  	 * @return Success of the operation.
  	*/
  	bool set_met_location (std::string location_name, Index loc_list);
  
  	/**
  	 * Get the 16-bit value detailing under what conditions capture occurred.
  	 *
  	 * @return A 16-bit Big Endian value containing capture condition information.
  	*/
  	uint16_t get_capture_condition ();
  
  	/**
  	 * Set the 16-bit value detailing under what conditions capture occurred.
  	 *
  	 * @param val is a 16-bit Big Endian value that will be converted to Little Endian.
  	 * @return Success of the operation.
  	*/
  	bool set_capture_condition (uint16_t val);
  
  	/**
  	 * Get the level of encounter for a Pkm.
  	 *
  	 * @return The level of encounter; only bits 0 - 6 of the return value are used.
  	*/
  	uint8_t get_level_met ();
  
  	/**
  	 * Set the level of encounter.
  	 *
  	 * @param val is the level value to be set; only bits 0 - 6 are used.
  	 * @return Success of the operation. 
  	*/
  	bool set_level_met (uint8_t val);
  
  	/**
  	 * Get the ID of the game the class instance was encountered in.
  	 *
  	 * @return A 4-bit ID indicating the game encountered in; macros have been specified in this
  	 *		file for these IDs.
  	*/
  	uint8_t get_game_of_origin ();
  
  	/**
  	 * Set the game of encounter for the instance.
  	 *
  	 * @param val is the internal value to be set; game code macros specified in this file can be
  	 *		used as function parameters.
  	 * @return Success of the operation.
  	*/
  	bool set_game_of_origin (uint8_t val);
  
  	/**
  	 * Get the ID of the ball used to capture a Pkm.
  	 *
  	 * @return A 4-bit ID indicating the ball used to capture. IDs are:
  	 *		- 0bxxxx0001: Master
  	 *		- 0bxxxx0010: Ultra
  	 *		- 0bxxxx0011: Great
  	 *		- 0bxxxx0100: Poke
  	 *		- 0bxxxx0101: Safari
  	 *		- 0bxxxx0110: Net
  	 *		- 0bxxxx0111: Dive
  	 *		- 0bxxxx1000: Nest
  	 *		- 0bxxxx1001: Repeat
  	 *		- 0bxxxx1010: Timer
  	 *		- 0bxxxx1011: Luxury
  	 *		- 0bxxxx1100: Premier
  	*/
  	uint8_t get_ball_type ();
  
  	/**
  	 * Set the ball used to capture a Pkm based on hex value.
  	 *
  	 * @param val is an ID value for the ball; only the lower 4 bits are used
  	 * @return Success of the operation.
  	*/
  	bool set_ball_type (uint8_t val);
  
  	/**
  	 * Set the ball used to capture a Pkm based on an input name.
  	 *
  	 * @param ball_name is an in-game name of a ball. Valid values include:
  	 *		- Master
  	 *		- Ultra
  	 *		- Great
  	 *		- Poke
  	 *		- Safari
  	 *		- Net
  	 *		- Dive
  	 *		- Nest
  	 *		- Repeat
  	 *		- Timer
  	 *		- Luxury
  	 *		- Premier
  	 *		Capitalization does not matter.
  	 * @return Success of the operation.
  	*/
  	bool set_ball_type (std::string ball_name);
  
  	/**
  	 * Get the bit used to determine original trainer gender.
  	 *
  	 * @return A byte with the lowest-order bit set to either 0 (Male) or 1 (Female).
  	*/
  	uint8_t get_trainer_gender ();
  
  	/**
  	 * Set the bit used to determine a Pkm's original trainer's gender.
  	 *
  	 * @param val is the value to be used to set the trainer gender; only the lowest-order bit will
  	 *		be used and is interpreted as follows:
  	 *		- 0bxxxxxxx0 = Male
  	 *		- 0bxxxxxxx1 = Female
  	 * @return If the operation was successful.
  	*/
  	bool set_trainer_gender (uint8_t val);
  
  	/**
  	 * Get the 32-bit value dedicated to IVs, the egg bit, and the ability bit.
  	 *
  	 * @return Big Endian representation of the 32-bit value.
  	*/
  	uint32_t get_inate_attributes ();
  
  	/**
  	 * Set the 32-bit value dedicated to IVs, the egg bit, and the ability bit.
  	 *
  	 * @param val is a 32-bit Big Endian value that will be converted to Little Endian and written
  	 *		to the class instance.
  	 * @return If the operation was successful.
  	*/
  	bool set_inate_attributes (uint32_t val);
  
  	/**
  	 * Get the IV value for the HP stat.
  	 *
  	 * @return The quantity of HP IVs an instance has; will be in the range of 0 - 31.
  	*/
  	uint8_t get_iv_hp ();
  
  	/**
  	 * Set the IV value for the HP stat.
  	 *
  	 * @param val is the quantity of HP IVs that will be had after the operation; only the lower
  	 *		5 bits of this value are used.
  	 * @return Success of the operation.
  	*/
  	bool set_iv_hp (uint8_t val);
  
  	/**
  	 * Get the IV value for the attack stat.
  	 *
  	 * @return The quantity of attack IVs an instance has; will be in the range of 0 - 31.
  	*/
  	uint8_t get_iv_attack ();
  
  	/**
  	 * Set the IV value for the attack stat.
  	 *
  	 * @param val is the quantity of attack IVs that will be had after the operation; only the
  	 *		lower 5 bits of this value are used.
  	 * @return Success of the operation.
  	*/
  	bool set_iv_attack (uint8_t val);
  
  	/**
  	 * Get the IV value for the defense stat.
  	 *
  	 * @return The quantity of defense IVs an instance has; will be in the range of 0 - 31.
  	*/
  	uint8_t get_iv_defense ();
  
  	/**
  	 * Set the IV value for the defense stat.
  	 *
  	 * @param val is the quantity of defense IVs that will be had after the operation; only the
  	 * 		lower 5 bits of this value are used.
  	 * @return Success of the operation.
  	*/
  	bool set_iv_defense (uint8_t val);
  
  	/**
  	 * Get the IV value for the speed stat.
  	 *
  	 * @return The quantity of speed IVs an instance has; will be in the range of 0 - 31.
  	*/
  	uint8_t get_iv_speed ();
  
  	/**
  	 * Set the IV value for the speed stat.
  	 *
  	 * @param val is the quantity of speed IVs that will be had after the operation; only the
  	 *		lower 5 bits of this value are used.
   	 * @return Success of the operation.
  	*/
  	bool set_iv_speed (uint8_t val);
  
  	/**
  	 * Get the IV value for the special attack stat.
  	 *
  	 * @return The quantity of special attack IVs an instance has; will be in the range of 0 - 31.
  	*/
  	uint8_t get_iv_sp_attack ();
  
  	/**
  	 * Set the IV value for the special defense stat.
  	 *
  	 * @param val is the quantity of special attack IVs that will be had after the operation; only
  	 *		the lower 5 bits of this value are used.
   	 * @return Success of the operation.
  	*/
  	bool set_iv_sp_attack (uint8_t val);
  
  	/**
  	 * Get the IV value for the special defense stat.
  	 *
  	 * @return The quantity of special defense IVs an instance has; will be in the range of 0 - 31.
  	*/
  	uint8_t get_iv_sp_defense ();
  
  	/**
  	 * Set the IV value for the special defense stat.
  	 *
  	 * @param val is the quantity of special defense IVs that will be had after the operation; only
  	 *		the lower 5 bits of this value are used.
  	 * @return Success of the operation.
  	*/
  	bool set_iv_sp_defense (uint8_t val);
  
  	/**
  	 * Determine if the egg bit has been set.
  	 *
  	 * @return The value of the egg bit; only the lowest-order bit will be used.
  	*/
  	uint8_t get_egg_status ();
  
      /**
       * Set the bit used to determine if the Pkm will appear as an egg in game.
       *
       * @param is_egg determines whether the egg bit should be 0 (false; not an egg) or 1
       *      (true; is an egg).
       * @return If the egg bit was set successfully.
      */
  	bool set_egg_status (bool is_egg);
  
      /**
       * Get the value of the ability bit.
       *
       * @return The value of the ability bit; only the lowest-order bit will be used.
      */
  	uint8_t get_ability_number ();
  
      /**
       * Set the ability bit.
       *
       * @param val is the value the ability bit will be set to; only the lowest-order bit will be
       *      used for this operation.
       * @return If the ability bit was successfully set.
      */
  	bool set_ability_number (uint8_t val);
  
      /**
       * Toggle the bit used to indicate which ability a Pkm possesses.
       *
       * @return If the ability bit was successfully set.
      */
  	bool toggle_ability_number ();
  
      /**
       * Get the 32-bit value that stores which ribbons have been obtained for a Pkm.
       *
       * @return A 32-bit value in Big Endian indicating which ribbons have been obtained.
      */
  	uint32_t get_ribbons ();
  
      /**
       * Set the 32-bit value used to indicate which ribbons have been obtained.
       *
       * @param val is the value the 32 bits will be set to.
       * @return If the ribbon value was set successfully.
      */
  	bool set_ribbons (uint32_t val);
  
      /**
       * Get the value of the bit used to determine if certain species will obey.
       *
       * @return If the obedience bit is set.
      */
  	bool get_obedience ();
  
      /**
       * Set the obedience bit used to determine if certain species will obey.
       *
       * @param is_obedient determines whether the bit should be set to 0 (false; is not obedient) or 
       *      1 (true; is obedient).
       * @return If the bit was successfully set.
      */
  	bool set_obedience (bool is_obedient);
  
  
  	// Utility and flag functions
      /**
       * Set the pointer that is used to store the starting address of the Pkm data.
       *
       * @param addr is a pointer to the byte within the Save data that is the first byte of the
       *      block of data used to store a Pkm.
      */
  	void set_ptr (uint8_t* addr);
  
      /**
       * Get the pointer that is stored in data_ptr, which indicates the start location of the Pkm
       *      class data.
       *
       * @return A pointer to the starting address of the Pkm class instance.
      */
  	uint8_t* get_ptr ();
  
      /**
       * Set the value for the in_party flag to indicate whether the Pkm class instance is in the
       *      player's party or not.
       *
       * @param party_status is the value the in_party flag should be set to.
      */
  	void set_party_status (bool party_status);
  
      /**
       * Get the state of the in_party flag used to indicate whether the additional data indicating
       *      current stats of the instance is necessitated.
       *
       * @return The value of the in_party flag.
      */
  	bool get_party_status ();
  
      /**
       * Set the value for the is_valid flag to indicate whether the data is valid.
       *
       * @param validity is the value the is_valid flag should be set to.
      */
  	void set_validity (bool validity);
  
      /**
       * Get the state of the is_valid flag used to determine if the Pkm class instance is
       *      recognizable to the game.
       *
       * @return The value of the is_valid flag.
      */
  	bool get_validity ();
  
      /**
       * Ensures all flags and checksums for Pkm class are properly set; can be used to prepare
       *      a Pkm class to be written back to a Block or Save.
      */
  	void prepare ();
  
      /**
       * Sets data within Pkm class to random values. May potentially produce game-breaking Pkm.
      */
  	void randomize ();
  
      /**
       * Calculates whether the Pkm class is shiny or not based on the hidden and visible trainer
       *      IDs and the personality value.
       *
       * @return If the the personality values and trainer IDs evaluate to be shiny values.
      */
  	bool calc_is_shiny ();
  
      /**
       * Set whether the Pkm should be shiny. Modifies the visible trainer ID, but maintains the
       *      hidden trainer ID and personality values.
       *
       * @param make_shiny determines whether the Pkm should be shiny or not.
      */
  	void set_shiny (bool make_shiny);
  
  
  	// Debugging
      /**
       * Print all information relating to the Pkm class to stdout.
      */
  	void debug_print_pkm_info ();
  
      /**
       * Print the decrypted data section of the Pkm class to stdout.
      */
  	void debug_print_decrypted_data ();
  
  private:
  	// Pointer to the location in memory where the Pkm's data starts
  	uint8_t* data_ptr = NULL;
  
  	// Variables use for a number of things, including encrypting the 48-byte data section
  	uint32_t personality = 0x00000000;
  	uint32_t trainer_id = 0x00000000;
  
  	// Information visible to the player in game
  	uint8_t nickname [10] = {0xFF};
  	uint16_t original_language = 0x0000;
  	uint8_t trainer_name [7] = {0xFF};
  	uint8_t markings = 0x00;
  
  	// Checksum for 48-byte data section
  	uint16_t checksum = 0x0000;
  
  	// Data section supplementary variables
  	uint8_t data_order [4] = {0x00};
  	uint32_t data_key = 0x00000000;
  
  	// Encrypted and decrypted data for Pkm
  	uint8_t encrypted_data [48] = {0x00};
  	uint8_t decrypted_data [48] = {0x00};
  
  	// Information on transient stats of Pkm
  	uint32_t status_condition = 0x00000000;
  	uint8_t level = 0x00;
  	uint8_t pokerus_t_counter = 0x00;
  
  	// Current values of stats that are only present if Pkm is in the player's party
  	uint16_t c_hp = 0x0000;
  	uint16_t t_hp = 0x0000;
  	uint16_t attack = 0x0000;
  	uint16_t defense = 0x0000;
  	uint16_t speed = 0x0000;
  	uint16_t sp_attack = 0x0000;
  	uint16_t sp_defense = 0x0000;
  
  	// Internal flags about pkm
  	bool in_party = false;
  	bool is_shiny = false;
  	bool uptodate_checksum = false;
  	bool is_valid = true;
  };
  
  #endif
  