/* gLife - An Artificial Life implementation using GNOME * * Copyright (C) 1999 Ali Abdin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "simulation.h" #include "data.h" #include "glife.h" #include "reproduction.h" #include "move.h" void reproduce (AnimalType *); gboolean is_fertile (AnimalType *); gboolean find_empty (gint, gint, gint *, gint *); gboolean is_fertile (AnimalType *anim) { if ((anim->age >= ruleset.minrepage) && (anim->storefood >= ruleset.minfoodtorep)) return TRUE; return FALSE; g_assert_not_reached(); } static void mendel_select (guint biga, guint bigb, guint smalla, guint smallb, guint *result1, guint *result2) { gint randval; randval = RAND (0, 100); if (randval < 25) { *result1 = smalla; *result2 = smallb; } else if ((randval >= 25) && (randval < 50)) { *result1 = smalla; *result2 = bigb; } else if ((randval >= 50) && (randval < 75)) { *result1 = biga; *result2 = smallb; } else { *result1 = biga; *result2 = bigb; } } static void have_sex (AnimalType *anim, AnimalType *partner, gint emptyx, gint emptyy) { guint foodtochild; gint randval; gchar sex; guint vision, metafood, speed, maxage; foodtochild = (guint) (anim->storefood * (ruleset.percenttochild / 100.0)) + (partner->storefood * (ruleset.percenttochild / 100.0)); /* g_print ("Foodtochild is: %d\n",foodtochild); g_print ("Old anim->storefood %d\n",anim->storefood); */ anim->storefood = anim->storefood - (guint)(anim->storefood * (ruleset.percenttochild/100.0)); /* g_print ("New anim->storefood %d\nOld partner->storefood: %d\n",anim->storefood, partner->storefood); */ partner->storefood = partner->storefood - (guint)(partner->storefood * (ruleset.percenttochild/100.0)); /* g_print ("New parnter->storefood: %d\n",partner->storefood); */ randval = RAND (0, 100); if (randval < 50) sex = 'M'; else sex = 'F'; mendel_select (anim->vision, anim->metafood, partner->vision, partner->metafood, &vision, &metafood); mendel_select (anim->speed, anim->maxage, partner->speed, partner->maxage, &speed, &maxage); add_animal (sex, 1, vision, metafood, speed, foodtochild, maxage, emptyx, emptyy); } gboolean find_empty (gint x, gint y, gint *emptyx, gint *emptyy) { /* Big bad function that given x,y coordinates - it searches the * surrounding area and finds and returns an empty spot, if available */ if (x == 1) { /* On left column - always check right */ if (!animal_exists (x+1, y)) { *emptyx = x+1; *emptyy = y; return TRUE; } if (y == 1) { /* Top-left corner */ if (!animal_exists (x, y+1)) { *emptyx = x; *emptyy = y+1; return TRUE; } } else if (y == MAXROW+1) { /* Bottom-Left corner */ if (!animal_exists (x, y-1)) { *emptyx = x; *emptyy = y-1; return TRUE; } } else { /* Left column */ if (!animal_exists (x, y+1)) { *emptyx = x; *emptyy = y+1; return TRUE; } if (!animal_exists (x, y-1)) { *emptyx = x; *emptyy = y-1; return TRUE; } } } else if (x == MAXCOL+1) { /* On right column, always check left */ if (!animal_exists (x-1, y)) { *emptyx = x-1; *emptyy = y; return TRUE; } if (y == 1) { /* Top-Right */ if (!animal_exists (x, y+1)) { *emptyx = x; *emptyy = y+1; return TRUE; } } else if (y == MAXROW+1) { /* Bottom-right */ if (!animal_exists (x, y-1)) { *emptyx = x; *emptyy = y-1; return TRUE; } } else { /* Right column */ if (!animal_exists (x, y+1)) { *emptyx = x; *emptyy = y+1; return TRUE; } if (!animal_exists (x, y-1)) { *emptyx = x; *emptyy = y-1; return TRUE; } } } else if (y == 1) { /* Top row - not corners */ if (!animal_exists (x, y+1)) { *emptyx = x; *emptyy = y+1; return TRUE; } if (!animal_exists (x+1, y)) { *emptyx = x+1; *emptyy = y; return TRUE; } if (!animal_exists (x-1, y)) { *emptyx = x-1; *emptyy = y; return TRUE; } } else if (y == MAXROW+1) { if (!animal_exists (x, y-1)) { *emptyx = x; *emptyy = y-1; return TRUE; } if (!animal_exists (x+1, y)) { *emptyx = x+1; *emptyy = y; return TRUE; } if (!animal_exists (x-1, y)) { *emptyx = x-1; *emptyy = y; return TRUE; } } else { if (!animal_exists (x, y-1)) { *emptyx = x; *emptyy = y-1; return TRUE; } if (!animal_exists (x+1, y)) { *emptyx = x+1; *emptyy = y; return TRUE; } if (!animal_exists (x, y+1)) { *emptyx = x; *emptyy = y+1; return TRUE; } if (!animal_exists (x-1, y)) { *emptyx = x-1; *emptyy = y; return TRUE; } } return FALSE; g_assert_not_reached(); } void reproduce (AnimalType *anim) { /* Assume we have potential partners surrounding us */ MoveChoices partners = { TRUE, TRUE, TRUE, TRUE }; if (anim->posx == 1) { partners.left = FALSE; /* anim on left column */ if (anim->posy == 1) { /* Top Left Corner */ partners.up = FALSE; } else if (anim->posy == MAXROW+1) { /* Bottom Left corner */ partners.down = FALSE; } } else if (anim->posx == MAXCOL+1) { partners.right = FALSE; /* anim on right column */ if (anim->posy == 1) { /* Top right corner */ partners.up = FALSE; } else if (anim->posy == MAXCOL+1) { /* Bottom right corner */ partners.down = FALSE; } } else if (anim->posy == 1) { /* Top row */ partners.up = FALSE; } else if (anim->posy == MAXROW+1) { /* Bottom row */ partners.down = FALSE; } /* if (partners.up) g_print ("Up is okay\n"); if (partners.down) g_print ("down is okay\n"); if (partners.left) g_print ("left is okay\n"); if (partners.right) g_print ("right is okay\n"); */ /* Reproduction rules - both must be fertile (old enough, have enough food), * must be of different sex, and there must be an availble spot */ if (partners.up) { AnimalType *partner = NULL; gboolean available_spot; gint emptyx,emptyy; /* Co-ords for empty spot */ partner = animal_at (anim->posx, anim->posy-1); if ((partner != NULL) && (is_fertile(anim))) { available_spot = find_empty (anim->posx, anim->posy, &emptyx, &emptyy); if (!available_spot) /* No spot next to the original animal */ available_spot = find_empty (partner->posx, partner->posy, &emptyx, &emptyy); if ((is_fertile (partner)) && (partner->sex != anim->sex) && available_spot) have_sex (anim, partner, emptyx, emptyy); } } if (partners.down) { AnimalType *partner = NULL; gboolean available_spot; gint emptyx, emptyy; partner = animal_at (anim->posx, anim->posy+1); if ((partner != NULL) && (is_fertile (anim))) { available_spot = find_empty (anim->posx, anim->posy, &emptyx, &emptyy); if (!available_spot) /* No spot next to the original animal */ available_spot = find_empty (partner->posx, partner->posy, &emptyx, &emptyy); if ((is_fertile (partner)) && (partner->sex != anim->sex) && available_spot) have_sex (anim, partner, emptyx, emptyy); } } if (partners.left) { AnimalType *partner = NULL; gboolean available_spot; gint emptyx, emptyy; partner = animal_at (anim->posx-1, anim->posy); if ((partner != NULL) && (is_fertile (anim))) { available_spot = find_empty (anim->posx, anim->posy, &emptyx, &emptyy); if (!available_spot) /* No spot next to the original animal */ available_spot = find_empty (partner->posx, partner->posy, &emptyx, &emptyy); if ((is_fertile (partner)) && (partner->sex != anim->sex) && available_spot) have_sex (anim, partner, emptyx, emptyy); } } if (partners.right) { AnimalType *partner = NULL; gboolean available_spot; gint emptyx, emptyy; partner = animal_at (anim->posx-1, anim->posy); if ((partner != NULL) && (is_fertile(anim))) { available_spot = find_empty (anim->posx, anim->posy, &emptyx, &emptyy); if (!available_spot) /* No spot next to the original animal */ available_spot = find_empty (partner->posx, partner->posy, &emptyx, &emptyy); if ((is_fertile (partner)) && (is_fertile (anim)) && (partner->sex != anim->sex) && available_spot) have_sex (anim, partner, emptyx, emptyy); } } }