@Override
	public List<EncounterSet> getEncounters(boolean useTimeOfDay) {
		List<EncounterSet> encounters = new ArrayList<EncounterSet>();

		// grass & water
		List<Integer> usedOffsets = new ArrayList<Integer>();
		int tableOffset = romEntry.getValue("WildPokemonTableOffset");
		int tableBank = bankOf(tableOffset);
		int mapID = -1;

		while (readWord(tableOffset) != 0xFFFF) {
			mapID++;
			int offset = calculateOffset(tableBank, readWord(tableOffset));
			int rootOffset = offset;
			if (!usedOffsets.contains(offset)) {
				usedOffsets.add(offset);
				// grass and water are exactly the same
				for (int a = 0; a < 2; a++) {
					int rate = rom[offset++] & 0xFF;
					if (rate > 0) {
						// there is data here
						EncounterSet thisSet = new EncounterSet();
						thisSet.rate = rate;
						thisSet.offset = rootOffset;
						thisSet.displayName = (a == 1 ? "Surfing"
								: "Grass/Cave") + " on " + mapNames[mapID];
						for (int slot = 0; slot < 10; slot++) {
							Encounter enc = new Encounter();
							enc.level = rom[offset] & 0xFF;
							enc.pokemon = pokes[pokeRBYToNumTable[rom[offset + 1] & 0xFF]];
							thisSet.encounters.add(enc);
							offset += 2;
						}
						encounters.add(thisSet);
					}
				}
			} else {
				for (EncounterSet es : encounters) {
					if (es.offset == offset) {
						es.displayName += ", " + mapNames[mapID];
					}
				}
			}
			tableOffset += 2;
		}

		// old rod
		int oldRodOffset = romEntry.getValue("OldRodOffset");
		EncounterSet oldRodSet = new EncounterSet();
		oldRodSet.displayName = "Old Rod Fishing";
		Encounter oldRodEnc = new Encounter();
		oldRodEnc.level = rom[oldRodOffset + 2] & 0xFF;
		oldRodEnc.pokemon = pokes[pokeRBYToNumTable[rom[oldRodOffset + 1] & 0xFF]];
		oldRodSet.encounters.add(oldRodEnc);
		encounters.add(oldRodSet);

		// good rod
		int goodRodOffset = romEntry.getValue("GoodRodOffset");
		EncounterSet goodRodSet = new EncounterSet();
		goodRodSet.displayName = "Good Rod Fishing";
		for (int grSlot = 0; grSlot < 2; grSlot++) {
			Encounter enc = new Encounter();
			enc.level = rom[goodRodOffset + grSlot * 2] & 0xFF;
			enc.pokemon = pokes[pokeRBYToNumTable[rom[goodRodOffset + grSlot
					* 2 + 1] & 0xFF]];
			goodRodSet.encounters.add(enc);
		}
		encounters.add(goodRodSet);

		// super rod
		if (romEntry.isYellow) {
			int superRodOffset = romEntry.getValue("SuperRodTableOffset");
			while ((rom[superRodOffset] & 0xFF) != 0xFF) {
				int map = rom[superRodOffset++] & 0xFF;
				EncounterSet thisSet = new EncounterSet();
				thisSet.displayName = "Super Rod Fishing on " + mapNames[map];
				for (int encN = 0; encN < 4; encN++) {
					Encounter enc = new Encounter();
					enc.level = rom[superRodOffset + 1] & 0xFF;
					enc.pokemon = pokes[pokeRBYToNumTable[rom[superRodOffset] & 0xFF]];
					thisSet.encounters.add(enc);
					superRodOffset += 2;
				}
				encounters.add(thisSet);
			}
		} else {
			// red/blue
			int superRodOffset = romEntry.getValue("SuperRodTableOffset");
			int superRodBank = bankOf(superRodOffset);
			List<Integer> usedSROffsets = new ArrayList<Integer>();
			while ((rom[superRodOffset] & 0xFF) != 0xFF) {
				int map = rom[superRodOffset++] & 0xFF;
				int setOffset = calculateOffset(superRodBank,
						readWord(superRodOffset));
				superRodOffset += 2;
				if (!usedSROffsets.contains(setOffset)) {
					usedSROffsets.add(setOffset);
					EncounterSet thisSet = new EncounterSet();
					thisSet.displayName = "Super Rod Fishing on "
							+ mapNames[map];
					thisSet.offset = setOffset;
					int pokesInSet = rom[setOffset++] & 0xFF;
					for (int encN = 0; encN < pokesInSet; encN++) {
						Encounter enc = new Encounter();
						enc.level = rom[setOffset] & 0xFF;
						enc.pokemon = pokes[pokeRBYToNumTable[rom[setOffset + 1] & 0xFF]];
						thisSet.encounters.add(enc);
						setOffset += 2;
					}
					encounters.add(thisSet);
				} else {
					for (EncounterSet es : encounters) {
						if (es.offset == setOffset) {
							es.displayName += ", " + mapNames[map];
						}
					}
				}
			}
		}

		return encounters;
	}