#include "global.h"
#include "file_system.h"
#include "item.h"
#include "moves.h"
#include "team_inventory.h"
#include "random.h"
#include "pokemon.h"
#include "random.h"
#include "subStruct_203B240.h"
#include "team_inventory.h"
#include "code_800D090.h"
#include "text_util.h"

#include <stddef.h>

#define GREEN_KECLEON_SHOP_SIZE 8
#define PURPLE_KECLEON_SHOP_SIZE 4

extern struct TeamInventory *gTeamInventory_203B460;
extern struct TeamInventory gUnknown_20389A8;
extern struct FileArchive gSystemFileArchive;
extern const char gItemParaFileName[];
extern const char gUnknown_8109794[];
extern const char gUnknown_81097A4[];
extern s32 gUnknown_81097B0[];
extern u8 gUnknown_81097C4[];
extern u16 gGummiStatBoostLUT[];
extern u8 gUnknown_202DE58[0x58];
extern u32 gUnknown_202DE30;
extern u8* gPtrTypeText;  // ptr to "Type\0"
extern u8* gPtrPPD0Text;  // ptr to "PP $d0 \0"
extern u32 gUnknown_810A3F0[100];
extern u32 gUnknown_81097E8[4];  // some sort of lookup table (16, 18, 20, 22)
extern u32 gUnknown_81097F8[4];  // some sort of lookup table (17, 19, 21, 23)
extern const char *gUnknown_810AF50[];
extern u8 gUnknown_8108F64[0x3f][32];  // some sort of bit lookup table
extern s16 gTypeGummiIQBoost[0x12][NUMBER_OF_GUMMIS];
extern u8 gInvalidItemIDs[0x10];

EWRAM_DATA struct OpenedFile *gItemParametersFile;
EWRAM_DATA struct Item *gItemParametersData;

extern u8 GetItemType(u8);
extern u32 GetItemUnkThrow(u8, u32);
extern s32 sub_8090FEC(s32 a1, u8* a2, u8 a3);
extern void sub_80073B8(u32);
extern u32 sub_8097DF0(char *, struct subStruct_203B240 **);
extern void sub_80078A4(u32, u32, u32, u32, u32);
extern void sub_80073E0(u32);
extern void xxx_format_and_draw(u32, u32, const u8 *, u32, u32);
extern s32 sub_8091E94(s32 a1, s32 a2, s32 a3);
extern void SortGreenKecleonShopInventory();
bool8 AddPurpleKecleonShopItem(u8);

void LoadItemParameters(void)
{
  gTeamInventory_203B460 = &gUnknown_20389A8;
  gItemParametersFile = OpenFileAndGetFileDataPtr(gItemParaFileName,&gSystemFileArchive);
  gItemParametersData = (struct Item *) gItemParametersFile->data;
}

struct TeamInventory *GetMoneyItemsInfo(void)
{
    return &gUnknown_20389A8;
}

void InitializeMoneyItems(void)
{
  s32 i;

  for(i = 0; i < INVENTORY_SIZE; i++)
  {
    gTeamInventory_203B460->teamItems[i].itemFlags = 0;
  }

  for(i = 0; i < STORAGE_SIZE; i++)
  {
    gTeamInventory_203B460->teamStorage[i] = 0;
  }

  for(i = 0; i < 8; i++)
  {
    xxx_init_unk230_substruct(i);
  }
  gTeamInventory_203B460->teamMoney = 0;
  gTeamInventory_203B460->teamSavings = 0;
}

s32 GetNumberOfFilledInventorySlots(void)
{
  s32 i;
  s32 count;

  count = 0;
  for(i = 0; i < INVENTORY_SIZE; i++)
  {
    if ((gTeamInventory_203B460->teamItems[i].itemFlags & ITEM_FLAG_EXISTS) != 0) {
      count++;
    }
  }
  return count;
}

bool8 IsThrowableItem(u8 itemIndex)
{
  if ((GetItemType(itemIndex) != ITEM_TYPE_THROWABLE) && (GetItemType(itemIndex) != ITEM_TYPE_ROCK))
    return FALSE;
  else
    return TRUE;
}

void xxx_init_itemslot_8090A8C(struct ItemSlot *slot, u8 itemIndex, u8 param_3)
{
  u32 uVar3;
  u32 uVar4;

  if (itemIndex != ITEM_ID_NOTHING) {
    slot->itemFlags = ITEM_FLAG_EXISTS;
    slot->itemIndex = itemIndex;
    if (IsThrowableItem(itemIndex)) {
        uVar3 = GetItemUnkThrow(itemIndex, 0);
        uVar4 = GetItemUnkThrow(itemIndex, 1);
        slot->numItems = RandomRange(uVar3, uVar4);
    }
    else if (GetItemType(itemIndex) == ITEM_TYPE_MONEY)
        slot->numItems  = 1;
    else
        slot->numItems  = 0;

    if (param_3 != 0)
        slot->itemFlags |= ITEM_FLAG_STICKY;

  }
  else {
    slot->itemFlags = 0;
    slot->itemIndex = ITEM_ID_NOTHING;
    slot->numItems  = 0;
  }
}

void xxx_init_helditem_8090B08(struct HeldItem *held, u8 itemIndex)
{
  u32 uVar2;
  u32 uVar3;

  if (itemIndex != ITEM_ID_NOTHING) {
    held->itemIndex = itemIndex;
    if (IsThrowableItem(itemIndex)) {
        uVar2 = GetItemUnkThrow(itemIndex,0);
        uVar3 = GetItemUnkThrow(itemIndex,1);
        held->numItems = RandomRange(uVar2, uVar3);
    }
    else if (GetItemType(itemIndex) == ITEM_TYPE_MONEY)
        held->numItems = 1;
    else
        held->numItems = 0;
  }
  else {
    held->itemIndex = 0;
    held->numItems = 0;
  }
}

void HeldItemToSlot(struct ItemSlot *slot, struct HeldItem *held)
{
    u8 is_throwable;

    if(held->itemIndex != ITEM_ID_NOTHING)
    {
        slot->itemFlags = ITEM_FLAG_EXISTS;
        slot->itemIndex = held->itemIndex;
        is_throwable = IsThrowableItem(slot->itemIndex);
        if(is_throwable != 0 || GetItemType(slot->itemIndex) == ITEM_TYPE_MONEY)
            slot->numItems = held->numItems;
        else if(slot->itemIndex == ITEM_ID_USED_TM)
            slot->numItems = held->numItems;
        else
            slot->numItems = 0;
    }
    else
    {
        slot->itemIndex = ITEM_ID_NOTHING;
        slot->numItems = 0;
        slot->itemFlags = 0;
    }
}

void SlotToHeldItem(struct HeldItem *held,struct ItemSlot *slot)
{
  if ((slot->itemFlags & ITEM_FLAG_EXISTS) != 0) {
    held->itemIndex = slot->itemIndex;
    held->numItems = slot->numItems;
  }
  else {
    held->itemIndex = ITEM_ID_NOTHING;
  }
}

u8 GetItemType(u8 index)
{
    return gItemParametersData[index].type;
}

s32 GetStackBuyValue(struct ItemSlot *param_1)
{
  if (param_1->itemIndex == ITEM_ID_POKE) {
    return GetMoneyValue(param_1);
  }
  else {
    if (IsThrowableItem(param_1->itemIndex)) {
      return gItemParametersData[param_1->itemIndex].buyPrice * param_1->numItems;
    }
    else {
      return gItemParametersData[param_1->itemIndex].buyPrice;
    }
  }
}

s32 GetStackSellValue(struct ItemSlot *param_1)
{
  if (param_1->itemIndex == ITEM_ID_POKE) {
    return GetMoneyValue(param_1);
  }
  else {
    if (IsThrowableItem(param_1->itemIndex)) {
      return gItemParametersData[param_1->itemIndex].sellPrice * param_1->numItems;
    }
    else {
      return gItemParametersData[param_1->itemIndex].sellPrice;
    }
  }
}

s32 GetStackBuyPrice(struct ItemSlot *param_1)
{
  if (!CanSellItem(param_1->itemIndex)) {
    return 0;
  }
  else {
    if (IsThrowableItem(param_1->itemIndex)) {
      return gItemParametersData[param_1->itemIndex].buyPrice * param_1->numItems;
    }
    else {
      return gItemParametersData[param_1->itemIndex].buyPrice;
    }
  }
}

s32 GetStackSellPrice(struct ItemSlot *param_1)
{
  if (!CanSellItem(param_1->itemIndex)) {
    return 0;
  }
  else {
    if (IsThrowableItem(param_1->itemIndex)) {
      return gItemParametersData[param_1->itemIndex].sellPrice * param_1->numItems;
    }
    else {
      return gItemParametersData[param_1->itemIndex].sellPrice;
    }
  }
}

s32 GetItemBuyPrice(u8 itemIndex)
{
    return gItemParametersData[itemIndex].buyPrice;
}

s32 GetItemSellPrice(u8 itemIndex)
{
    return gItemParametersData[itemIndex].sellPrice;
}

s32 GetItemOrder(u8 itemIndex)
{
    return gItemParametersData[itemIndex].order;
}

u8 GetItemPalette(u8 itemIndex)
{
    return gItemParametersData[itemIndex].palette;
}

u32 GetItemCategory(u8 itemIndex)
{
    return gItemParametersData[itemIndex].category;
}

u32 GetItemUnkThrow(u8 itemIndex, u32 r1)
{
    return gItemParametersData[itemIndex].unkThrow1B[r1];
}

u8 *GetItemDescription(u8 itemIndex)
{
    return gItemParametersData[itemIndex].descriptionPointer;
}

bool8 GetItemAIFlag(u8 itemIndex, u32 r1)
{
    return gItemParametersData[itemIndex].aiFlags[r1];
}

void sub_8090DC4(void* param_1,u8 itemIndex, struct unkStruct_8090F58* param_3)
{
  char acStack104 [80];
  struct ItemSlot unkItem;

  strncpy(acStack104,gItemParametersData[itemIndex].namePointer,0x50);
  xxx_init_itemslot_8090A8C(&unkItem,itemIndex,0);
  unkItem.numItems = 1;
  sub_8090F58(param_1,acStack104,&unkItem,param_3);
}

extern const u8 gUnknown_8109770[];
extern const u8 gUnknown_8109778[];
extern const u8 gUnknown_810977C[];
extern const u8 gUnknown_8109784[];
extern const u8 gUnknown_810978C[];

void sub_8090E14(u8* ext_buffer, struct ItemSlot* slot, struct unkStruct_8090F58* a3) {
  s32 unk8 = 0;
  u8 buffer[80];

  if (a3) {
    unk8 = a3->unk8 != 0;
  }

  if (GetItemType(slot->itemIndex) == ITEM_TYPE_THROWABLE) {
    // I feel like these labels might actually be there...
    if (unk8) {
      sprintf_2(buffer, gUnknown_8109770, gItemParametersData[slot->itemIndex].namePointer, slot->numItems);
    }
    else {
      sprintf_2(buffer, gUnknown_8109778, gItemParametersData[slot->itemIndex].namePointer);
    }
  }
  else if (GetItemType(slot->itemIndex) == ITEM_TYPE_ROCK) {
    if (unk8) {
      sprintf_2(buffer, gUnknown_8109770, gItemParametersData[slot->itemIndex].namePointer, slot->numItems);
    }
    else {
      sprintf_2(buffer, gUnknown_8109778, gItemParametersData[slot->itemIndex].namePointer);
    }
  }
  else if (slot->itemIndex == ITEM_ID_POKE) {
    sprintf_2(buffer, gUnknown_810977C, GetMoneyValue(slot));
  }
  else {
    strncpy(buffer, gItemParametersData[slot->itemIndex].namePointer, 80);
  }

  if (slot->itemFlags & ITEM_FLAG_STICKY) {
    sprintf_2(ext_buffer, gUnknown_8109784, buffer);
    strncpy(buffer, ext_buffer, 80);
  }

  if (a3) {
    if (a3->unk4 && (slot->itemFlags & ITEM_FLAG_SET)) {
      sprintf_2(ext_buffer, gUnknown_810978C, buffer);
      strncpy(buffer, ext_buffer, 80);
    }
    if ((*(u32*)a3 == 1) || (*(u32*)a3 == 3)) {
        if (slot->itemFlags & ITEM_FLAG_FOR_SALE) {
          sub_8090F58(ext_buffer, buffer, slot, a3);
          return;
        }
      strncpy(ext_buffer, buffer, 80);
      return;
    }
  }
  else {
    strncpy(ext_buffer, buffer, 80);
    return;
  }

  sub_8090F58(ext_buffer, buffer, slot, a3);
  return;
}

void sub_8090F58(void* a1, u8 *a2, struct ItemSlot *slot, struct unkStruct_8090F58* a4) {
  u32 unk0;
  s32 value;
  u8 buffer[40];

  if (!a4) {
    strncpy(a1, a2, 80);
    return;
  }
  else {
    unk0 = a4->unk0;
    switch (unk0) {
      case 1:
      case 2:
        value = GetStackBuyValue(slot);
        break;
      case 3:
      case 4:
        value = GetStackSellValue(slot);
        break;
      default:
        value = 0;
        break;
    }

    if (!value) {
      strncpy(a1, a2, 80);
      return;
    }
  }

  if (a4->unk6) {
    sub_8090FEC(value, buffer, 1);
    sprintf_2(a1, gUnknown_8109794, a2, a4->unk6, buffer);
  }
  else {
    sub_8090FEC(value, buffer, 0);
    sprintf_2(a1, gUnknown_81097A4, a2, buffer);
  }
}

s32 sub_8090FEC(s32 a1, u8* strbuf, u8 a3)
{
  s32 i, count;
  s32 cond = 0;

  count = 0;
  for (i = 0; i < 5; i++) {
    s32 div;

    div = 0;
    while (a1 >= gUnknown_81097B0[i]) {
        a1 -= gUnknown_81097B0[i];
        div++;
    }

    if (div > 9) {
      div = 9;
    }

    if (div) {
        cond = 1;
        *strbuf++ = gUnknown_81097C4[2 * div];
        *strbuf++ = (gUnknown_81097C4 + 1)[2 * div];  // weird staggered arrays...
        count++;
    }
    else if (cond) {
        *strbuf++ = gUnknown_81097C4[0];
        *strbuf++ = (gUnknown_81097C4 + 1)[0];  // weird staggered arrays...
        count++;
    }
    else if (a3) {
        *strbuf++ = 96;  // ` character?
    }
  }

  *strbuf++ = gUnknown_81097C4[2 * a1];
  *strbuf   = (gUnknown_81097C4 + 1)[2 * a1];
  count += 1;
  strbuf[1] = 0;  // null termination
  return count;
}

void FillInventoryGaps()
{
  // fill inventory gaps
  s32 slot_checking = 0;
  s32 last_filled = 0;

  do {
    while (slot_checking < INVENTORY_SIZE) {
      if (slot_checking[gTeamInventory_203B460->teamItems].itemFlags & ITEM_FLAG_EXISTS) {
        break;
      }
      // find next empty slot
      slot_checking++;
    }

    if (slot_checking == INVENTORY_SIZE) {
      break;
    }

    if (slot_checking > last_filled) {
      // shift it down
      gTeamInventory_203B460->teamItems[last_filled] = gTeamInventory_203B460->teamItems[slot_checking];
    }
    slot_checking++;
    last_filled++;
  } while (1);

  // clear out the rest of the slots
  for (; last_filled < INVENTORY_SIZE; last_filled++) {
      struct ItemSlot *slot;
#ifdef NONMATCHING
      slot = &gTeamInventory_203B460->teamItems[last_filled];
#else
      size_t offs = last_filled << 2;
      size_t _slot = offs;
      _slot += (size_t)gTeamInventory_203B460->teamItems;
      slot = (struct ItemSlot*)_slot; // &gTeamInventory_203B460->teamItems[end];
#endif
      slot->itemIndex = 0;
      slot->numItems = 0;
      slot->itemFlags = 0;
  }
}

s32 FindItemInInventory(u8 itemIndex)
{
  s32 i;
  for (i = 0; i < INVENTORY_SIZE; i++) {
    if ((gTeamInventory_203B460->teamItems[i].itemFlags & ITEM_FLAG_EXISTS) && (gTeamInventory_203B460->teamItems[i].itemIndex == itemIndex)) {
      return i;
    }
  }
  return -1;
}

s32 GetItemCountInInventory(u8 _itemIndex)
{
#ifdef NONMATCHING
  s32 count = 0;
  s32 i;
  for (i = 0; i < INVENTORY_SIZE; i++) {
    if ((gTeamInventory_203B460->teamItems[i].unk0 & 1) && (gTeamInventory_203B460->teamItems[i].itemIndex == _itemIndex)) {
      count++;
    }
  }
  return count;
#else
  // have to do hacky stuff to fix initialization order of r6 and r2
  u32 itemIndex = _itemIndex;
  s32 count = 0;
  struct ItemSlot *slot = gTeamInventory_203B460->teamItems;
  s32 one = 1;
  s32 i = 19;

  do {
    register u32 unk0 asm("r1") = slot->itemFlags;
    u32 bottom_bit = one;
    bottom_bit &= unk0;
    if (bottom_bit && (slot->itemIndex == itemIndex)) {
      count++;
    }
    slot++;
  } while(--i >= 0);
  return count;
#endif
}

s32 GetItemPossessionCount(u8 itemIndex)
{
  s32 item_count = GetItemCountInInventory(itemIndex);
  s32 i = 0;

  struct unkStruct_203B45C *_gRecruitedPokemonRef = gRecruitedPokemonRef;
  for (i = 0; i < NUM_SPECIES; i++) {
     struct PokemonStruct* pokemon = &_gRecruitedPokemonRef->pokemon[i];
    if ((1 & pokemon->unk0)
          && ((pokemon->unk0 >> 1) % 2)
          && (pokemon->heldItem.itemIndex != ITEM_ID_NOTHING)
          && (pokemon->heldItem.itemIndex == itemIndex)) {
      item_count++;
    }
  }
  return item_count;
}

void ShiftItemsDownFrom(s32 start)
{
  s32 i, j;
  for (i = start, j = start + 1; i < INVENTORY_SIZE - 1; i++, j++) {
    gTeamInventory_203B460->teamItems[i] = gTeamInventory_203B460->teamItems[j];
  }
  gTeamInventory_203B460->teamItems[INVENTORY_SIZE - 1].itemIndex = 0;
  gTeamInventory_203B460->teamItems[INVENTORY_SIZE - 1].itemFlags = 0;
}

void ClearItemSlotAt(u32 index)
{
  gTeamInventory_203B460->teamItems[index].itemIndex = ITEM_ID_NOTHING;
  gTeamInventory_203B460->teamItems[index].itemFlags = 0;
}

bool8 sub_809124C(u8 itemIndex, u8 param_3)
{
  struct ItemSlot temp;
  xxx_init_itemslot_8090A8C(&temp, itemIndex, param_3);
  return AddItemToInventory(&temp);
}

bool8 AddHeldItemToInventory(struct HeldItem* slot)
{
  struct ItemSlot temp;

  HeldItemToSlot(&temp, slot);
  return AddItemToInventory(&temp);
}

bool8 AddItemToInventory(const struct ItemSlot* slot)
{
  s32 i;

  // try to add item to inventory, return 1 if failed
  for (i = 0; i < INVENTORY_SIZE; i++) {
    UNUSED struct ItemSlot* current = &gTeamInventory_203B460->teamItems[i];
    if (!(i[gTeamInventory_203B460->teamItems].itemFlags & ITEM_FLAG_EXISTS)) {
      gTeamInventory_203B460->teamItems[i] = *slot;
      return FALSE;
    }
  }
  return TRUE;
}

void ConvertMoneyItemToMoney()
{
  s32 i = 0;

  do {
    UNUSED struct TeamInventory * _gTeamInventory_203B460 = gTeamInventory_203B460;
    UNUSED size_t offs = offsetof(struct TeamInventory, teamItems[i]);

    struct ItemSlot* current_slot = &gTeamInventory_203B460->teamItems[i];
    if ((current_slot->itemFlags & ITEM_FLAG_EXISTS) && (current_slot->itemIndex == ITEM_ID_POKE)) {
      u32 result;

      result = GetMoneyValue(current_slot);
      AddToTeamMoney(result);
      current_slot->itemIndex = 0;
      current_slot->numItems = 0;
      current_slot->itemFlags = 0;
    }
  } while (++i < INVENTORY_SIZE);
  FillInventoryGaps();

  i = 0;
  do {
    s32 lowest_index = -1;
    UNUSED size_t offs = offsetof(struct TeamInventory, teamItems[i]);

    bool8 item_occupied = i[gTeamInventory_203B460->teamItems].itemFlags & ITEM_FLAG_EXISTS;
    s32 next = i + 1;

    if (item_occupied) {
      s32 lowest_order = GetItemOrder(gTeamInventory_203B460->teamItems[i].itemIndex);
      s32 j;

      // find next lowest
      for (j = next; j < INVENTORY_SIZE; j++) {
        UNUSED size_t offs = offsetof(struct TeamInventory, teamItems[j]);
        if ((j[gTeamInventory_203B460->teamItems].itemFlags & ITEM_FLAG_EXISTS) && (lowest_order > GetItemOrder(gTeamInventory_203B460->teamItems[j].itemIndex))) {
          lowest_index = j;
          lowest_order = GetItemOrder(gTeamInventory_203B460->teamItems[j].itemIndex);
        }
      }

      if (lowest_index >= 0) {
        // swap the slots
        struct ItemSlot current = gTeamInventory_203B460->teamItems[i];
        gTeamInventory_203B460->teamItems[i] = gTeamInventory_203B460->teamItems[lowest_index];
        gTeamInventory_203B460->teamItems[lowest_index] = current;
      }
    }
  } while (++i < INVENTORY_SIZE);
  FillInventoryGaps();
}

void AddToTeamMoney(s32 amount)
{
  s32 clamped_money;
  gTeamInventory_203B460->teamMoney += amount;

  // clamp money
  clamped_money = 99999;
  if (gTeamInventory_203B460->teamMoney <= 99999) {
    if (gTeamInventory_203B460->teamMoney >= 0) {
      return;
    }
    clamped_money = 0;
  }
  gTeamInventory_203B460->teamMoney = clamped_money;
}

u16 GetItemMove(u8 index)
{
  return gItemParametersData[index].move;
}

u32 sub_80913E0(struct ItemSlot* slot, u32 a2, struct subStruct_203B240 ** a3)
{
  u8 buffer88[88];  // some struct

  GetItemDescription(slot->itemIndex);
  sub_8090DC4(buffer88, slot->itemIndex, 0);
  if (slot->itemIndex == ITEM_ID_USED_TM) {
    // empty TM
    sub_8090DC4(&gUnknown_202DE58, (u8)(slot->numItems + 125), 0);
  }
  sub_80073B8(a2);
  xxx_format_and_draw(16, 0, buffer88, a2, 0);

  xxx_format_and_draw(8, 24, GetItemDescription(slot->itemIndex), a2, 0);
  if (GetItemType(slot->itemIndex) == ITEM_TYPE_TM) {
    struct PokemonMove *buffer8 = (struct PokemonMove*) (buffer88 + 0x50);  // field in struct
    u16 move = GetItemMove(slot->itemIndex);
    u8 moves_data;
    const u8* typestring;
    u32 result;

    InitPokemonMove(buffer8, move);
    sub_80078A4(a2, 4, 82, 200, 7);
    xxx_format_and_draw(4, 84, gPtrTypeText, a2, 0);
    moves_data = GetMoveType(buffer8);
    typestring = GetUnformattedTypeString(moves_data);
    xxx_format_and_draw(64, 84, typestring, a2, 0);
    result = GetMoveMaxPP(buffer8);
    gUnknown_202DE30 = result;
    xxx_format_and_draw(128, 84, gPtrPPD0Text, a2, 0);
  }

  sub_80073E0(a2);
  return sub_8097DF0(GetItemDescription(slot->itemIndex), a3);
}

bool8 CanSellItem(u32 id)
{
  u8 id_;
  id = (u8)id;
  id_ = id;

  if((id != ITEM_ID_NOTHING)
      && (id != ITEM_ID_POKE)
      && (id != ITEM_ID_ROCK_PART)
      && (id != ITEM_ID_ICE_PART)
      && (id != ITEM_ID_STEEL_PART)
      && (id != ITEM_ID_MUSIC_BOX)
      && (GetItemSellPrice(id_))
      && (GetItemBuyPrice(id_))) {
          return TRUE;
    }
    return FALSE;
}

bool8 IsNotMoneyOrUsedTMItem(u8 id)
{
  if (id == ITEM_ID_NOTHING) {
    return FALSE;
  }
  else if (id == ITEM_ID_POKE) {
    return FALSE;
  }
  else if (id == ITEM_ID_USED_TM) {
    return FALSE;
  }
  return TRUE;
}

bool8 IsNotSpecialItem(u8 id)
{
  if (id == ITEM_ID_NOTHING) {
    return FALSE;
  }
  else if (id == ITEM_ID_POKE) {
    return FALSE;
  }
  else if (id == ITEM_ID_ROCK_PART) {
    return FALSE;
  }
  else if (id == ITEM_ID_ICE_PART) {
    return FALSE;
  }
  else if (id == ITEM_ID_STEEL_PART) {
    return FALSE;
  }
  else if (id == ITEM_ID_MUSIC_BOX) {
    return FALSE;
  }
  return TRUE;
}

bool8 IsEdibleItem(u8 id)
{
  if (!((GetItemType(id) == ITEM_TYPE_BERRY_SEED) || (GetItemType(id) == ITEM_TYPE_APPLE_GUMMI))) {
    return FALSE;
  }
  return TRUE;
}

bool8 IsHMItem(u8 id)
{
  if (id == ITEM_ID_CUT) {
    return TRUE;
  }
  else if (id == ITEM_ID_FLY) {
    return TRUE;
  }
  else if (id == ITEM_ID_SURF) {
    return TRUE;
  }
  else if (id == ITEM_ID_STRENGTH) {
    return TRUE;
  }
  else if (id == ITEM_ID_FLASH) {
    return TRUE;
  }
  else if (id == ITEM_ID_ROCK_SMASH) {
    return TRUE;
  }
  else if (id == ITEM_ID_WATERFALL) {
    return TRUE;
  }
  else if (id == ITEM_ID_DIVE) {
    return TRUE;
  }
  return FALSE;
}

u32 GetMoneyValue(struct ItemSlot* slot)
{
  return gUnknown_810A3F0[slot->numItems];
}

u32 GetMoneyValueHeld(struct HeldItem* slot)
{
  // potentially different slot type (used for held item)
  return gUnknown_810A3F0[slot->numItems];
}

void GetGummiItemStatBoost(struct PokemonStruct* pokemon, u8 itemIndex, u8 a3, struct unkStruct_80915F4* a4)
{
  // item stat buff?
  s8 result;

  a4->unk0 = (u16)-1;
  a4->unk2 = 0;
  result = IsGummiItem(itemIndex);
  if (result) {
    u8 pokemon_type_0 = GetPokemonType(pokemon->speciesNum, 0);
    u8 pokemon_type_1 = GetPokemonType(pokemon->speciesNum, 1);
    u32 gummi_index = itemIndex - ITEM_ID_WHITE_GUMMI + 1;
    s32 value0;
    s32 value1;
    s32 diff;
    u16 boost_amount;

    value0 = gTypeGummiIQBoost[pokemon_type_0][gummi_index];
    value1 = gTypeGummiIQBoost[pokemon_type_1][gummi_index];
    diff  = pokemon->IQ;

    pokemon->IQ += value0 + value1;
    diff = pokemon->IQ - diff;
    if (pokemon->IQ <= 0) {
      pokemon->IQ = 1;
    }
    if (pokemon->IQ > 999) {
      pokemon->IQ = 999;
    }

    boost_amount = 0;
    if (diff <= 8) {
      boost_amount = 1;
      if (diff <= 4) {
        boost_amount = 3;
        if (diff > 2) {
          boost_amount = 2;
        }
      }
    }
    a4->unk0 = boost_amount;
    if (!a3) {
      u16 boost_flags;
      if (!boost_amount && RandomCapped(16) == 10) {
        // supa gummi (all stats boost)
        boost_flags = 0xf;
      }
      else {
        s32 random_index = RandomCapped(4);
        u16* table = gGummiStatBoostLUT;
        boost_flags = table[random_index];
      }

      a4->unk2 = boost_flags;
      boost_flags = a4->unk2;
      if (a4->unk2 & 1) {
        if (pokemon->offense.att[OFFENSE_NRM] < 255) {
          pokemon->offense.att[OFFENSE_NRM]++;
        }
        else {
          // fix operand order
          u16 unk2 = a4->unk2;
          unk2 &= ~1;
          a4->unk2 &= unk2;
        }
      }
      if (a4->unk2 & 2) {
        if (pokemon->offense.att[OFFENSE_SP] < 255) {
          pokemon->offense.att[OFFENSE_SP]++;
        }
        else {
          a4->unk2 &= ~2;
        }
      }
      if (a4->unk2 & 4) {
        if (pokemon->offense.def[OFFENSE_NRM] < 255) {
          pokemon->offense.def[OFFENSE_NRM]++;
        }
        else {
          a4->unk2 &= ~4;
        }
      }
      if (a4->unk2 & 8) {
        if (pokemon->offense.def[OFFENSE_SP] < 255) {
          pokemon->offense.def[OFFENSE_SP] ++;
        }
        else {
          a4->unk2 &= ~8;
        }
      }
    }
  }
}

bool8 IsGummiItem(u8 itemIndex)
{
  if (itemIndex < ITEM_ID_WHITE_GUMMI) {
    return FALSE;
  }
  if (itemIndex > ITEM_ID_SILVER_GUMMI) {
    return FALSE;
  }
  return TRUE;
}

bool8 HasGummiItem()
{
  s32 i;
  for (i = 0; i < INVENTORY_SIZE; i++) {
    UNUSED size_t offs = offsetof(struct TeamInventory, teamItems[i]);
    if ((i[gTeamInventory_203B460->teamItems].itemFlags & ITEM_FLAG_EXISTS) && IsGummiItem(i[gTeamInventory_203B460->teamItems].itemIndex)) {
      return TRUE;
    }
  }
  return FALSE;
}

void MoveToStorage(struct ItemSlot* slot)
{
  if (IsThrowableItem(slot->itemIndex)) {
    gTeamInventory_203B460->teamStorage[slot->itemIndex] += slot->numItems;
  }
  else {
    gTeamInventory_203B460->teamStorage[slot->itemIndex]++;
  }

  if (gTeamInventory_203B460->teamStorage[slot->itemIndex] > 999) {
    gTeamInventory_203B460->teamStorage[slot->itemIndex] = 999;
  }
}

s32 xxx_count_inv_unk230()
{
  s32 i;
  s32 counter = 0;
  for (i = 0; i < 8; i++) {
    if (gTeamInventory_203B460->unk230[i].itemIndex) {
      counter++;
    }
  }
  return counter;
}

void xxx_init_unk230_substruct(u8 i)
{
  struct HeldItem* unk230;

  unk230 = &gTeamInventory_203B460->unk230[i];
  unk230->itemIndex = 0;
  unk230->numItems = 0;
}

struct HeldItem* xxx_get_inv_unk230_at_809185C(u8 i)
{
  return &gTeamInventory_203B460->unk230[i];
}

void xxx_fill_unk230_gaps()
{
  // fill unk230 gaps
  // basically the same as FillInventoryGaps
  s32 slot_checking = 0;
  s32 last_filled = 0;

  do {
    while (slot_checking < 8) {
      if (gTeamInventory_203B460->unk230[slot_checking].itemIndex) {
        break;
      }
      // find next empty slot
      slot_checking++;
    }

    if (slot_checking == 8) {
      break;
    }

    if (slot_checking > last_filled) {
      // shift it down
      gTeamInventory_203B460->unk230[last_filled] = gTeamInventory_203B460->unk230[slot_checking];
    }
    slot_checking++;
    last_filled++;
  } while (1);

  // clear out the rest of the slots
  for (; last_filled < 8; last_filled++) {
    xxx_init_unk230_substruct(last_filled);
  }
}

void SortGreenKecleonShopInventory() {
  s32 i;

  for (i = 0; i < 7; i++) {
    s32 j;
    for (j = i + 1; j < 8; j++) {
      s32 order_i = GetItemOrder(gTeamInventory_203B460->unk230[i].itemIndex);
      s32 order_j = GetItemOrder(gTeamInventory_203B460->unk230[j].itemIndex);
      if (order_i > order_j || (order_i == order_j && gTeamInventory_203B460->unk230[i].numItems < gTeamInventory_203B460->unk230[j].numItems)) {
        struct HeldItem str_i = gTeamInventory_203B460->unk230[i];
        gTeamInventory_203B460->unk230[i] = gTeamInventory_203B460->unk230[j];
        gTeamInventory_203B460->unk230[j] = str_i;
      }
    }
  }
}

void ChooseKecleonShopInventory(u8 a1) {
  u32 data[4];
  s32 i;

  memcpy(data, gUnknown_81097E8, 4 * sizeof(u32));
  for (i = 0; i < GREEN_KECLEON_SHOP_SIZE; i++) {
    xxx_init_unk230_substruct(i);
  }
  for (i = 0; i < GREEN_KECLEON_SHOP_SIZE; i++) {
    s32 rand_1 = RandomCapped(9999);
    s32 rand_2 = RandomCapped(9999);
    AddGreenKecleonShopItem(sub_8091E94(data[a1], rand_1, rand_2));
  }
  SortGreenKecleonShopInventory();
  ChoosePurpleKecleonShopInventory(a1);
}

bool8 AddGreenKecleonShopItem(u8 itemIndex) {
  struct HeldItem held;
  s32 i;

  xxx_init_helditem_8090B08(&held, itemIndex);  // initialize
  for (i = 0; i < 8; i++) {
    if (!gTeamInventory_203B460->unk230[i].itemIndex) {
      gTeamInventory_203B460->unk230[i] = held;
      return FALSE;
    }
  }
  return TRUE;
}

u32 xxx_count_non_empty_inv_unk250_8091A48() {
  s32 i;
  u32 count = 0;
  for (i = 0; i < 4; i++) {
    if (gTeamInventory_203B460->unk250[i].itemIndex) {
      count++;
    }
  }
  return count;
}

void xxx_init_inv_unk250_at_8091A74(u8 index) {
  struct HeldItem* unk250 = &gTeamInventory_203B460->unk250[index];
  unk250->itemIndex = 0;
  unk250->numItems = 0;
}

struct HeldItem* xxx_get_unk250_at_8091A90(u8 index) {
    return &gTeamInventory_203B460->unk250[index];
}

void xxx_fill_inv_unk250_gaps_8091AA8(void) {
  s32 slot_checking = 0;
  s32 last_filled = 0;

  do {
    while (slot_checking < 4) {
      if (gTeamInventory_203B460->unk250[slot_checking].itemIndex != ITEM_ID_NOTHING) {
        break;
      }
      slot_checking++;
    }

    if (slot_checking == 4) {
      break;
    }

    if (slot_checking > last_filled) {
      // shift it down
      gTeamInventory_203B460->unk250[last_filled] = gTeamInventory_203B460->unk250[slot_checking];
    }
    slot_checking++;
    last_filled++;
  } while (1);

  // clear out the rest of the slots
  for (; last_filled < 4; last_filled++) {
    xxx_init_inv_unk250_at_8091A74(last_filled);
  }
}

void SortPurpleKecleonShopInventory() {
  s32 i;

  for (i = 0; i < 3; i++) {
    s32 j;
    for (j = i + 1; j < 4; j++) {
      s32 order_i = GetItemOrder(gTeamInventory_203B460->unk250[i].itemIndex);
      s32 order_j = GetItemOrder(gTeamInventory_203B460->unk250[j].itemIndex);
      if (order_i > order_j || (order_i == order_j && gTeamInventory_203B460->unk250[i].numItems < gTeamInventory_203B460->unk250[j].numItems)) {
        struct HeldItem str_i = gTeamInventory_203B460->unk250[i];
        gTeamInventory_203B460->unk250[i] = gTeamInventory_203B460->unk250[j];
        gTeamInventory_203B460->unk250[j] = str_i;
      }
    }
  }
}

void ChoosePurpleKecleonShopInventory(u8 index) {
  u32 data[4];
  s32 i;

  memcpy(data, gUnknown_81097F8, 4 * sizeof(u32));
  for (i = 0; i < PURPLE_KECLEON_SHOP_SIZE; i++) {
    xxx_init_inv_unk250_at_8091A74(i);
  }
  for (i = 0; i < PURPLE_KECLEON_SHOP_SIZE; i++) {
    s32 rand_1 = RandomCapped(9999);
    s32 rand_2 = RandomCapped(9999);
    AddPurpleKecleonShopItem(sub_8091E94(data[index], rand_1, rand_2));
  }
  SortPurpleKecleonShopInventory();
}

bool8 AddPurpleKecleonShopItem(u8 itemIndex) {
  struct HeldItem held;
  s32 i;

  xxx_init_helditem_8090B08(&held, itemIndex);  // initialize
  for (i = 0; i < 4; i++) {
    if (!gTeamInventory_203B460->unk250[i].itemIndex) {
      gTeamInventory_203B460->unk250[i] = held;
      return FALSE;
    }
  }
  return TRUE;
}

s32 SaveTeamInventory(u8* unk0, u32 size)
{
  struct unkStruct_8094924 unk;
  s32 i;

  xxx_init_struct_8094924_save_809486C(&unk, unk0, size);
  for (i = 0; i < INVENTORY_SIZE; i++) {
    SaveItemSlot(&unk, &gTeamInventory_203B460->teamItems[i]);
  }
  for (i = 0; i < STORAGE_SIZE; i++) {
    SaveIntegerBits(&unk, &gTeamInventory_203B460->teamStorage[i], 10);
  }
  for (i = 0; i < 8; i++) {
    SaveHeldItem(&unk, &gTeamInventory_203B460->unk230[i]);
  }
  for (i = 0; i < 4; i++) {
    SaveHeldItem(&unk, &gTeamInventory_203B460->unk250[i]);
  }
  SaveIntegerBits(&unk, &gTeamInventory_203B460->teamMoney, 24);
  SaveIntegerBits(&unk, &gTeamInventory_203B460->teamSavings, 24);
  nullsub_102(&unk);
  return unk.unk8;
}

s32 RestoreTeamInventory(u8 *unk0, u32 size)
{
  struct unkStruct_8094924 unk;
  s32 i;

  xxx_init_struct_8094924_restore_809485C(&unk, unk0, size);
  for (i = 0; i < INVENTORY_SIZE; i++) {
    RestoreItemSlot(&unk, &gTeamInventory_203B460->teamItems[i]);
  }
  for (i = 0; i < STORAGE_SIZE; i++) {
    RestoreIntegerBits(&unk, &gTeamInventory_203B460->teamStorage[i], 10);
  }
  for (i = 0; i < 8; i++) {
    RestoreHeldItem(&unk, &gTeamInventory_203B460->unk230[i]);
  }
  for (i = 0; i < 4; i++) {
    RestoreHeldItem(&unk, &gTeamInventory_203B460->unk250[i]);
  }
  RestoreIntegerBits(&unk, &gTeamInventory_203B460->teamMoney, 24);
  RestoreIntegerBits(&unk, &gTeamInventory_203B460->teamSavings, 24);
  nullsub_102(&unk);
  return unk.unk8;
}

void RestoreHeldItem(struct unkStruct_8094924 *a1, struct HeldItem *item)
{
  RestoreIntegerBits(a1, &item->itemIndex, 8);
  RestoreIntegerBits(a1, &item->numItems, 7);
}

void SaveHeldItem(struct unkStruct_8094924 *a1, struct HeldItem *item)
{
  SaveIntegerBits(a1, &item->itemIndex, 8);
  SaveIntegerBits(a1, &item->numItems, 7);
}

void RestoreItemSlot(struct unkStruct_8094924 *a1, struct ItemSlot *slot)
{
  RestoreIntegerBits(a1, &slot->itemFlags, 8);
  RestoreIntegerBits(a1, &slot->numItems, 7);
  RestoreIntegerBits(a1, &slot->itemIndex, 8);
}

void SaveItemSlot(struct unkStruct_8094924 *a1, struct ItemSlot *slot)
{
  SaveIntegerBits(a1, &slot->itemFlags, 8);
  SaveIntegerBits(a1, &slot->numItems, 7);
  SaveIntegerBits(a1, &slot->itemIndex, 8);
}

const char *sub_8091E50(u8 index)
{
  return gUnknown_810AF50[index];
}

u32 xxx_bit_lut_lookup_8091E50(u8 i0, u8 i1)
{
  if (i0 > 0x3e)
    return 0;
  else
    return (gUnknown_8108F64[i0][i1 >> 3] >> (i1 & 7)) & 1;
}


extern u16* gUnknown_8108E58[];

struct UnkStruct_8091E94 {
  s16 unk0[12];
  s16 unk18[0xf0];
};

NAKED
s32 sub_8091E94(s32 a1, s32 a2, s32 a3)
{
#if 0
  // this is about as good as I got it so far
  s32 i;
  u8 item_type;
  s32 result;

  // struct of 12 + 0xf0 (NUMBER_OF_ITEM_IDS) hwords?
  struct UnkStruct_8091E94 s1;
  u16 s2[12 + 0xf0];
  s32 data_index;
  // 30000: level up exp required?

  data_index = 0;
  // compressed data?
  for (i = 0; i < 252; i++) {
    if (gUnknown_8108E58[a1 - 1][i] > 29999) {
      s32 j;
      for (j = gUnknown_8108E58[a1 - 1][i] - 30000; j != 0; j--) {
        s2[data_index++] = 0;
      }
    }
    else {
      s2[data_index++] = gUnknown_8108E58[a1 - 1][i];
    }
  }

  for (i = 0; i < 12; i++) {
    s1.unk0[i] = s2[i];
  }

  for (i = 0; i < 240; i++) {
    s1.unk18[i] = s2[12 + i];
  }

  item_type = 0;
  for (i = 0; i < 12; i++) {
    if (s1.unk0[i] && s1.unk0[i] >= a2){
      item_type = i;
      break;
    }
  }

  result = 70;
  if (item_type != 12) {
    s32 j;
    for (j = 0; j < 240; j++) {
      if (s1.unk18[j] && (GetItemType(j) == item_type) && (s1.unk18[j] >= a3)) {
        return result;
      }
    }
    result = j;
  }
  return result;
#else
  asm_unified("\tpush {r4-r7,lr}\n"
"\tmov r7, r10\n"
"\tmov r6, r9\n"
"\tmov r5, r8\n"
"\tpush {r5-r7}\n"
"\tldr r4, _08091EE4\n"
"\tadd sp, r4\n"
"\tmov r8, r1\n"
"\tmov r10, r2\n"
"\tldr r1, _08091EE8\n"
"\tsubs r0, 0x1\n"
"\tlsls r0, 2\n"
"\tadds r0, r1\n"
"\tmovs r3, 0\n"
"\tadd r1, sp, 0x18\n"
"\tmov r9, r1\n"
"\tldr r2, _08091EEC\n"
"\tmov r12, r2\n"
"\tadd r6, sp, 0x1F8\n"
"\tldr r2, [r0]\n"
"\tadds r7, r6, 0\n"
"\tmovs r4, 0\n"
"_08091EC0:\n"
"\tldrh r1, [r2]\n"
"\tcmp r1, r12\n"
"\tbls _08091EF4\n"
"\tldrh r0, [r2]\n"
"\tldr r1, _08091EF0\n"
"\tadds r0, r1\n"
"\tcmp r0, 0\n"
"\tbeq _08091EFC\n"
"\tmovs r5, 0\n"
"\tadds r1, r7, r4\n"
"_08091ED4:\n"
"\tstrh r5, [r1]\n"
"\tadds r1, 0x2\n"
"\tadds r4, 0x2\n"
"\tadds r3, 0x1\n"
"\tsubs r0, 0x1\n"
"\tcmp r0, 0\n"
"\tbne _08091ED4\n"
"\tb _08091EFC\n"
"\t.align 2, 0\n"
"_08091EE4: .4byte 0xfffffc10\n"
"_08091EE8: .4byte gUnknown_8108E58\n"
"_08091EEC: .4byte 0x0000752f\n"
"_08091EF0: .4byte 0xffff8ad0\n"
"_08091EF4:\n"
"\tadds r0, r6, r4\n"
"\tstrh r1, [r0]\n"
"\tadds r4, 0x2\n"
"\tadds r3, 0x1\n"
"_08091EFC:\n"
"\tadds r2, 0x2\n"
"\tcmp r3, 0xFB\n"
"\tble _08091EC0\n"
"\tmovs r3, 0xB\n"
"\tadd r2, sp, 0x1F8\n"
"\tmov r1, sp\n"
"_08091F08:\n"
"\tldrh r0, [r2]\n"
"\tstrh r0, [r1]\n"
"\tadds r2, 0x2\n"
"\tadds r1, 0x2\n"
"\tsubs r3, 0x1\n"
"\tcmp r3, 0\n"
"\tbge _08091F08\n"
"\tmov r2, r9\n"
"\tadd r1, sp, 0x210\n"
"\tmovs r3, 0xEF\n"
"_08091F1C:\n"
"\tldrh r0, [r1]\n"
"\tstrh r0, [r2]\n"
"\tadds r1, 0x2\n"
"\tadds r2, 0x2\n"
"\tsubs r3, 0x1\n"
"\tcmp r3, 0\n"
"\tbge _08091F1C\n"
"\tmovs r7, 0xC\n"
"\tmovs r6, 0\n"
"\tmov r0, sp\n"
"\tmovs r2, 0\n"
"\tldrsh r0, [r0, r2]\n"
"\tcmp r0, 0\n"
"\tbeq _08091F4A\n"
"\tmov r0, sp\n"
"\tmovs r1, 0\n"
"\tldrsh r0, [r0, r1]\n"
"\tcmp r0, r8\n"
"\tblt _08091F4A\n"
"\tmovs r7, 0\n"
"\tb _08091F66\n"
"_08091F46:\n"
"\tmov r8, r5\n"
"\tb _08091F9C\n"
"_08091F4A:\n"
"\tadds r6, 0x1\n"
"\tcmp r6, 0xB\n"
"\tbgt _08091F66\n"
"\tlsls r0, r6, 1\n"
"\tmov r2, sp\n"
"\tadds r1, r2, r0\n"
"\tmovs r2, 0\n"
"\tldrsh r0, [r1, r2]\n"
"\tcmp r0, 0\n"
"\tbeq _08091F4A\n"
"\tcmp r0, r8\n"
"\tblt _08091F4A\n"
"\tlsls r0, r6, 24\n"
"\tlsrs r7, r0, 24\n"
"_08091F66:\n"
"\tmovs r0, 0x46\n"
"\tmov r8, r0\n"
"\tcmp r7, 0xC\n"
"\tbeq _08091F9C\n"
"\tmovs r6, 0\n"
"\tmov r4, r9\n"
"_08091F72:\n"
"\tmovs r1, 0\n"
"\tldrsh r0, [r4, r1]\n"
"\tcmp r0, 0\n"
"\tbeq _08091F94\n"
"\tlsls r0, r6, 24\n"
"\tlsrs r5, r0, 24\n"
"\tadds r0, r5, 0\n"
"\tbl GetItemType\n"
"\tlsls r0, 24\n"
"\tlsrs r0, 24\n"
"\tcmp r0, r7\n"
"\tbne _08091F94\n"
"\tmovs r2, 0\n"
"\tldrsh r0, [r4, r2]\n"
"\tcmp r0, r10\n"
"\tbge _08091F46\n"
"_08091F94:\n"
"\tadds r4, 0x2\n"
"\tadds r6, 0x1\n"
"\tcmp r6, 0xEF\n"
"\tble _08091F72\n"
"_08091F9C:\n"
"\tmov r0, r8\n"
"\tmovs r3, 0xFC\n"
"\tlsls r3, 2\n"
"\tadd sp, r3\n"
"\tpop {r3-r5}\n"
"\tmov r8, r3\n"
"\tmov r9, r4\n"
"\tmov r10, r5\n"
"\tpop {r4-r7}\n"
"\tpop {r1}\n"
"\tbx r1\n");
#endif
}

void ClearAllItems_8091FB4() {
  s32 i;

  for (i = 0; i < INVENTORY_SIZE; i++) {
    struct ItemSlot* slot = &gTeamInventory_203B460->teamItems[i];
    if (slot->itemFlags & ITEM_FLAG_EXISTS) {
      slot->itemFlags &= 0xf7;
      if (slot->itemIndex == ITEM_ID_POKE) {
        AddToTeamMoney(GetMoneyValue(slot));
        slot->itemIndex = 0;
        slot->numItems = 0;
        slot->itemFlags = 0;
      }
    }
  }
  FillInventoryGaps();
  for (i = 0; i < NUM_SPECIES; i++) {
    struct PokemonStruct* pokemon;
#ifdef NONMATCHING
    pokemon = &i[gRecruitedPokemonRef->pokemon];
#else
    register size_t offset asm("r1") = offsetof(struct unkStruct_203B45C, pokemon[i]);
    struct PokemonStruct* p = gRecruitedPokemonRef->pokemon;
    size_t addr = offset + (size_t)p;
    pokemon = (struct PokemonStruct*)addr;
#endif

    if ((u8)pokemon->unk0 & 1) {
      if (pokemon->heldItem.itemIndex) {
        if (pokemon->heldItem.itemIndex == ITEM_ID_POKE) {
          AddToTeamMoney(GetMoneyValueHeld(&pokemon->heldItem));
          pokemon->heldItem.itemIndex = 0;
        }
      }
    }
  }
}

bool32 IsInvalidItemReward(u8 itemID)
{
  s32 index;

  if (itemID >= NUMBER_OF_ITEM_IDS)
      return TRUE;
  else {
    index = 0;
    while (gInvalidItemIDs[index] != NUMBER_OF_ITEM_IDS){
      if (gInvalidItemIDs[index] == itemID)
        return TRUE;
      index++;
    };
    return FALSE;
  }
}
