unown_form.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #include <stdint.h>
  2. #include "../pokemon_data.h"
  3. #include "unown_form.h"
  4. /* This is used to get the current IVs from the trade struct.
  5. * Unown form is calculated by taking the middle bytes of each nibble of IV,
  6. * pressing them in order to a single byte, and dividing that by 10 (rounded
  7. * down/floor). This will create a value from 0 to 25 that is a 1:1 mapping
  8. * of the English alphabet and is how Unown forms are represented.
  9. *
  10. * C integer division truncates to 0 rather than does any proper rounding.
  11. *
  12. * https://bulbapedia.bulbagarden.net/wiki/Individual_values#Unown's_letter
  13. */
  14. static uint8_t unown_ivs_get(PokemonData* pdata) {
  15. furi_assert(pdata);
  16. uint16_t ivs = pokemon_stat_get(pdata, STAT_IV, NONE);
  17. uint8_t ivs_mid;
  18. ivs_mid =
  19. (((ivs & 0x6000) >> 7) | ((ivs & 0x0600) >> 5) | ((ivs & 0x0060) >> 3) |
  20. ((ivs & 0x0006) >> 1));
  21. return ivs_mid;
  22. }
  23. static void unown_ivs_set(PokemonData* pdata, uint8_t ivs_mid) {
  24. furi_assert(pdata);
  25. uint16_t ivs = pokemon_stat_get(pdata, STAT_IV, NONE);
  26. /* Clear the middle bits of each nibble */
  27. ivs &= ~(0x6666);
  28. /* Set the updated ivs_mid in to those cleared bits */
  29. ivs |=
  30. (((ivs_mid & 0xC0) << 7) | ((ivs_mid & 0x30) << 5) | ((ivs_mid & 0x0C) << 3) |
  31. ((ivs_mid & 0x03) << 1));
  32. pokemon_stat_set(pdata, STAT_IV, NONE, ivs);
  33. }
  34. char unown_form_get(PokemonData* pdata) {
  35. uint8_t form = unown_ivs_get(pdata);
  36. /* The forumula is specifically the center two bits of each IV slapped
  37. * together and floor(/10)
  38. */
  39. form /= 10;
  40. form += 'A';
  41. return form;
  42. }
  43. /* Try and get to the desired form by adding/subtracting the current IVs */
  44. void unown_form_set(PokemonData* pdata, char letter) {
  45. uint8_t ivs = unown_ivs_get(pdata);
  46. uint8_t form;
  47. letter = toupper(letter);
  48. furi_check(isalpha(letter));
  49. while(1) {
  50. form = ((ivs / 10) + 'A');
  51. if(form == letter) break;
  52. if(form > letter)
  53. ivs--;
  54. else
  55. ivs++;
  56. }
  57. /* form is now the target letter, set IVs back up */
  58. unown_ivs_set(pdata, ivs);
  59. }