Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed non-regional forms breeding incorrectly #4985

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions include/constants/regions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef GUARD_CONSTANTS_REGIONS_H
#define GUARD_CONSTANTS_REGIONS_H

// Core-series regions
enum Region
{
REGION_NONE,
REGION_KANTO,
REGION_JOHTO,
REGION_HOENN,
REGION_SINNOH,
REGION_UNOVA,
REGION_KALOS,
REGION_ALOLA,
REGION_GALAR,
REGION_HISUI,
REGION_PALDEA,
REGIONS_COUNT,
};

#endif // GUARD_CONSTANTS_REGIONS_H
1 change: 1 addition & 0 deletions include/daycare.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@ void ShowDaycareLevelMenu(void);
void ChooseSendDaycareMon(void);
u8 GetEggMovesBySpecies(u16 species, u16 *eggMoves);
bool8 SpeciesCanLearnEggMove(u16 species, u16 move);
void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon);

#endif // GUARD_DAYCARE_H
3 changes: 3 additions & 0 deletions include/pokemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "sprite.h"
#include "constants/items.h"
#include "constants/regions.h"
#include "constants/region_map_sections.h"
#include "constants/map_groups.h"
#include "contest_effect.h"
Expand Down Expand Up @@ -910,5 +911,7 @@ const u8 *GetMoveAnimationScript(u16 moveId);
void UpdateDaysPassedSinceFormChange(u16 days);
void TrySetDayLimitToFormChange(struct Pokemon *mon);
u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler);
u32 GetRegionalFormByRegion(u32 species, u32 region);
bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion);

#endif // GUARD_POKEMON_H
12 changes: 12 additions & 0 deletions include/regions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef GUARD_REGIONS_H
#define GUARD_REGIONS_H

#include "constants/regions.h"

static inline u32 GetCurrentRegion(void)
{
// TODO: Since there's no current multi-region support, we have this constant for the purposes of regional form comparisons.
return REGION_HOENN;
}

#endif // GUARD_REGIONS_H
34 changes: 29 additions & 5 deletions src/daycare.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "list_menu.h"
#include "overworld.h"
#include "item.h"
#include "regions.h"
#include "constants/form_change_types.h"
#include "constants/items.h"
#include "constants/hold_effects.h"
Expand Down Expand Up @@ -244,7 +245,7 @@ static void TransferEggMoves(void)
}
}

static void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon)
void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycareMon)
{
if (MonHasMail(mon))
{
Expand Down Expand Up @@ -979,9 +980,12 @@ STATIC_ASSERT(P_SCATTERBUG_LINE_FORM_BREED == SPECIES_SCATTERBUG_ICY_SNOW || (P_

static u16 DetermineEggSpeciesAndParentSlots(struct DayCare *daycare, u8 *parentSlots)
{
u16 i;
u16 species[DAYCARE_MON_COUNT];
u16 eggSpecies;
u32 i;
u32 species[DAYCARE_MON_COUNT];
u32 eggSpecies, parentSpecies;
bool32 hasMotherEverstone, hasFatherEverstone, motherIsForeign, fatherIsForeign;
bool32 motherEggSpecies, fatherEggSpecies;
u32 currentRegion = GetCurrentRegion();

for (i = 0; i < DAYCARE_MON_COUNT; i++)
{
Expand All @@ -998,7 +1002,24 @@ static u16 DetermineEggSpeciesAndParentSlots(struct DayCare *daycare, u8 *parent
}
}

eggSpecies = GetEggSpecies(species[parentSlots[0]]);
motherEggSpecies = GetEggSpecies(species[parentSlots[0]]);
fatherEggSpecies = GetEggSpecies(species[parentSlots[1]]);
hasMotherEverstone = ItemId_GetHoldEffect(GetBoxMonData(&daycare->mons[parentSlots[0]].mon, MON_DATA_HELD_ITEM)) == HOLD_EFFECT_PREVENT_EVOLVE;
hasFatherEverstone = ItemId_GetHoldEffect(GetBoxMonData(&daycare->mons[parentSlots[1]].mon, MON_DATA_HELD_ITEM)) == HOLD_EFFECT_PREVENT_EVOLVE;
motherIsForeign = IsSpeciesForeignRegionalForm(motherEggSpecies, currentRegion);
fatherIsForeign = IsSpeciesForeignRegionalForm(fatherEggSpecies, currentRegion);

if (hasMotherEverstone)
parentSpecies = motherEggSpecies;
else if (fatherIsForeign && hasFatherEverstone)
parentSpecies = fatherEggSpecies;
else if (motherIsForeign)
parentSpecies = GetRegionalFormByRegion(motherEggSpecies, currentRegion);
else
parentSpecies = motherEggSpecies;

eggSpecies = GetEggSpecies(parentSpecies);

if (eggSpecies == SPECIES_NIDORAN_F && daycare->offspringPersonality & EGG_GENDER_MALE)
eggSpecies = SPECIES_NIDORAN_M;
else if (eggSpecies == SPECIES_ILLUMISE && daycare->offspringPersonality & EGG_GENDER_MALE)
Expand Down Expand Up @@ -1043,6 +1064,9 @@ static void _GiveEggFromDaycare(struct DayCare *daycare)
u8 parentSlots[DAYCARE_MON_COUNT] = {0};
bool8 isEgg;

if (GetDaycareCompatibilityScore(daycare) == PARENTS_INCOMPATIBLE)
return;

species = DetermineEggSpeciesAndParentSlots(daycare, parentSlots);
if (P_INCENSE_BREEDING < GEN_9)
AlterEggSpeciesWithIncenseItem(&species, daycare);
Expand Down
68 changes: 68 additions & 0 deletions src/pokemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "constants/items.h"
#include "constants/layouts.h"
#include "constants/moves.h"
#include "constants/regions.h"
#include "constants/songs.h"
#include "constants/trainers.h"
#include "constants/union_room.h"
Expand Down Expand Up @@ -6977,3 +6978,70 @@ u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler)
return moveType;
return gMovesInfo[move].type;
}

bool32 IsSpeciesRegionalForm(u32 species)
{
return gSpeciesInfo[species].isAlolanForm
|| gSpeciesInfo[species].isGalarianForm
|| gSpeciesInfo[species].isHisuianForm
|| gSpeciesInfo[species].isPaldeanForm;
}

bool32 IsSpeciesRegionalFormFromRegion(u32 species, u32 region)
{
switch (region)
{
case REGION_ALOLA: return gSpeciesInfo[species].isAlolanForm;
case REGION_GALAR: return gSpeciesInfo[species].isGalarianForm;
case REGION_HISUI: return gSpeciesInfo[species].isHisuianForm;
case REGION_PALDEA: return gSpeciesInfo[species].isPaldeanForm;
default: return FALSE;
}
}

bool32 SpeciesHasRegionalForm(u32 species)
{
u32 formId;
const u16 *formTable = GetSpeciesFormTable(species);
for (formId = 0; formTable != NULL && formTable[formId] != FORM_SPECIES_END; formId++)
{
if (IsSpeciesRegionalForm(formTable[formId]))
return TRUE;
}
return FALSE;
}

u32 GetRegionalFormByRegion(u32 species, u32 region)
{
u32 formId = 0;
u32 firstFoundSpecies = 0;
const u16 *formTable = GetSpeciesFormTable(species);

if (formTable != NULL)
{
for (formId = 0; formTable[formId] != FORM_SPECIES_END; formId++)
{
if (firstFoundSpecies == 0)
firstFoundSpecies = formTable[formId];

if (IsSpeciesRegionalFormFromRegion(formTable[formId], region))
return formTable[formId];
}
if (firstFoundSpecies != 0)
return firstFoundSpecies;
}
return species;
}

bool32 IsSpeciesForeignRegionalForm(u32 species, u32 currentRegion)
{
u32 i;
for (i = 0; i < REGIONS_COUNT; i++)
{
if (currentRegion != i && IsSpeciesRegionalFormFromRegion(species, i))
return TRUE;
else if (currentRegion == i && SpeciesHasRegionalForm(species) && !IsSpeciesRegionalFormFromRegion(species, i))
return TRUE;
}
return FALSE;
}
131 changes: 131 additions & 0 deletions test/daycare.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#include "global.h"
#include "daycare.h"
#include "event_data.h"
#include "malloc.h"
#include "party_menu.h"
#include "regions.h"
#include "test/overworld_script.h"
#include "test/test.h"

// We don't run the StoreSelectedPokemonInDaycare special because it relies on calling the
// party select screen and the GetCursorSelectionMonId function, so we store directly to the struct.
#define STORE_IN_DAYCARE_AND_GET_EGG() \
StorePokemonInDaycare(&gPlayerParty[0], &gSaveBlock1Ptr->daycare.mons[0]); \
StorePokemonInDaycare(&gPlayerParty[0], &gSaveBlock1Ptr->daycare.mons[1]); \
RUN_OVERWORLD_SCRIPT( special GiveEggFromDaycare; );

TEST("(Daycare) Pokémon generate Eggs of the lowest member of the evolutionary family")
{
ASSUME(P_FAMILY_PIKACHU == TRUE);
ASSUME(P_GEN_2_CROSS_EVOS == TRUE);

ZeroPlayerPartyMons();
RUN_OVERWORLD_SCRIPT(
givemon SPECIES_PIKACHU, 100, gender=MON_MALE;
givemon SPECIES_PIKACHU, 100, gender=MON_FEMALE;
);
STORE_IN_DAYCARE_AND_GET_EGG();

EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_PICHU);
}

TEST("(Daycare) Pokémon offspring species is based off the mother's species")
{
u32 offspring = 0;
ASSUME(P_FAMILY_PIKACHU == TRUE);
ASSUME(P_GEN_2_CROSS_EVOS == TRUE);
ASSUME(P_FAMILY_RIOLU == TRUE);

ZeroPlayerPartyMons();
PARAMETRIZE { offspring = SPECIES_RIOLU; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PIKACHU, 100, gender=MON_MALE; givemon SPECIES_LUCARIO, 100, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_PICHU; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PIKACHU, 100, gender=MON_FEMALE; givemon SPECIES_LUCARIO, 100, gender=MON_MALE;); }
STORE_IN_DAYCARE_AND_GET_EGG();

EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), offspring);
}

TEST("(Daycare) Pokémon can breed with Ditto if they don't belong to the Ditto or No Eggs Discovered group")
{
u32 j = 0;
u32 parentSpecies = 0;

ZeroPlayerPartyMons();
for (j = 1; j < NUM_SPECIES; j++)
PARAMETRIZE { parentSpecies = j; }
VarSet(VAR_TEMP_C, parentSpecies);
RUN_OVERWORLD_SCRIPT(
givemon SPECIES_DITTO, 100; givemon VAR_TEMP_C, 100;
);
STORE_IN_DAYCARE_AND_GET_EGG();

if (gSpeciesInfo[parentSpecies].eggGroups[0] != EGG_GROUP_NO_EGGS_DISCOVERED
&& gSpeciesInfo[parentSpecies].eggGroups[0] != EGG_GROUP_DITTO)
EXPECT_NE(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_NONE);
else
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_NONE);
}

TEST("(Daycare) Shellos' form is always based on the mother's form")
{
u32 offspring = 0;
ASSUME(P_FAMILY_MEOWTH == TRUE);
ASSUME(P_ALOLAN_FORMS == TRUE);
ASSUME(P_GALARIAN_FORMS == TRUE);

ZeroPlayerPartyMons();
PARAMETRIZE { offspring = SPECIES_SHELLOS_WEST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_EAST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_WEST, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_SHELLOS_WEST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_EAST, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_SHELLOS_WEST, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_SHELLOS_WEST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_EAST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_WEST, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_SHELLOS_EAST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_WEST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_EAST, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_SHELLOS_EAST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_WEST, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_SHELLOS_EAST, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_SHELLOS_EAST; RUN_OVERWORLD_SCRIPT(givemon SPECIES_SHELLOS_WEST, 1, gender=MON_MALE; givemon SPECIES_SHELLOS_EAST, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
STORE_IN_DAYCARE_AND_GET_EGG();

EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), offspring);
}

TEST("(Daycare) Pokémon with regional forms give the correct offspring")
{
u32 offspring = 0, region = 0;
ASSUME(P_FAMILY_MEOWTH == TRUE);
ASSUME(P_ALOLAN_FORMS == TRUE);
ASSUME(P_GALARIAN_FORMS == TRUE);

ZeroPlayerPartyMons();

region = GetCurrentRegion();
if (region == REGION_ALOLA) {
PARAMETRIZE { offspring = SPECIES_MEOWTH_ALOLA; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_ALOLA, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_ALOLA; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_ALOLA, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_ALOLA; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_ALOLA; RUN_OVERWORLD_SCRIPT(givemon SPECIES_DIGLETT, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_DIGLETT, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PERRSERKER, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_PERSIAN, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PERRSERKER, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_PERSIAN, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PERSIAN_ALOLA, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_PERSIAN, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
} else if (region == REGION_GALAR) {
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_ALOLA, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_ALOLA; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_ALOLA, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_DIGLETT, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_DIGLETT, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PERRSERKER, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_PERSIAN, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PERRSERKER, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_PERSIAN, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PERSIAN_ALOLA, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_PERSIAN, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
} else {
PARAMETRIZE { offspring = SPECIES_MEOWTH; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_ALOLA, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_ALOLA; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_ALOLA, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_MEOWTH, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH; RUN_OVERWORLD_SCRIPT(givemon SPECIES_DIGLETT, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_DIGLETT, 1, gender=MON_MALE; givemon SPECIES_MEOWTH_GALAR, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH_GALAR; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PERRSERKER, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_PERSIAN, 1, gender=MON_FEMALE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PERRSERKER, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_PERSIAN, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
PARAMETRIZE { offspring = SPECIES_MEOWTH; RUN_OVERWORLD_SCRIPT(givemon SPECIES_PERSIAN_ALOLA, 1, gender=MON_MALE, item=ITEM_EVERSTONE; givemon SPECIES_PERSIAN, 1, gender=MON_FEMALE, item=ITEM_EVERSTONE;); }
}
STORE_IN_DAYCARE_AND_GET_EGG();

EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), offspring);
}
Loading