/* 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 "glife.h" #include "data.h" #include "simulation.h" #include "move.h" /* Prototypes */ gboolean move_animal (AnimalType *, gint, gint); static void move_direction (AnimalType *, MoveDirection); void random_movement (AnimalType *); static void choose_direction_and_move (AnimalType *, MoveChoices); gboolean move_animal (AnimalType *anim, gint x2, gint y2) { gint x1, y1; g_assert (anim != NULL); x1 = anim->posx; y1 = anim->posy; g_assert ((x2>0) && (x2<=MAXCOL+1)); g_assert ((y2>0) && (y2<=MAXROW+1)); if (animal_exists (x2, y2)) return FALSE; /* Spot Occupied */ if (!animal_exists (x1, y1)) return FALSE; /* Initial animal does not exist */ /* Code to move Mr. Animal */ terrain[anim->posx-1][anim->posy-1].occupied = FALSE; terrain[anim->posx-1][anim->posy-1].anim = NULL; terrain[x2-1][y2-1].occupied = TRUE; terrain[x2-1][y2-1].anim = anim; anim->posx = x2; anim->posy = y2; return TRUE; } static void move_direction (AnimalType *animal, MoveDirection heading) { gboolean value; gint x, y; x = animal->posx; y = animal->posy; #if 0 g_assert ((x>0) && (x<=MAXCOL+1)); g_assert ((y>0) && (y<=MAXROW+1)); #endif /* Assertions unecessary since the animal MUST be on the terrain */ if (heading == UP) { value = move_animal (animal, x, y-1); /* g_print ("Up\n"); */ } else if (heading == DOWN) { value = move_animal (animal, x, y+1); /* g_print ("Down\n"); */ } else if (heading == RIGHT) { value = move_animal (animal, x+1, y); /* g_print ("Right\n"); */ } else if (heading == LEFT) { value = move_animal (animal, x-1, y); /* g_print ("Left\n"); */ } else g_assert_not_reached (); if (value == FALSE) /* g_warning ("Movement of animal at %d,%d did not take place",x,y); */ /* This will only occur if the place is occupied */ ; } static void choose_direction_and_move (AnimalType *animal, MoveChoices move) { gint randval; /* We have 2^4 possible configurations for MoveChoices: * TTTT TTTF TTFT TFTT TTFF TFTF TFFT TFFF * FFFF FFFT FFTF FTFF FFTT FTFT FTTF FTTT */ /* randval = 1 + (gint) (100.0*rand()/(RAND_MAX+1.0)); */ randval = RAND (1,100); if (move.up && move.down && move.left && move.right) /* TTTT */ if (randval > 75) move_direction (animal, UP); else if (randval > 50) move_direction (animal, DOWN); else if (randval > 25) move_direction (animal, LEFT); else move_direction (animal, RIGHT); else if (move.up && move.down && move.left) /* TTTF */ if (randval > 67) move_direction (animal, UP); else if (randval > 33) move_direction (animal, DOWN); else move_direction (animal, LEFT); else if (move.up && move.down && move.right) /* TTFT */ if (randval > 67) move_direction (animal, UP); else if (randval > 33) move_direction (animal, DOWN); else move_direction (animal, RIGHT); else if (move.up && move.down) /* TTFF */ if (randval > 50) move_direction (animal, UP); else move_direction (animal, DOWN); else if (move.up && move.left && move.right) /* TFTT */ if (randval > 67) move_direction (animal, UP); else if (randval > 33) move_direction (animal, LEFT); else move_direction (animal, RIGHT); else if (move.up && move.left) /* TFTF */ if (randval > 50) move_direction (animal, UP); else move_direction (animal, LEFT); else if (move.up && move.right) /* TFFT */ if (randval > 50) move_direction (animal, UP); else move_direction (animal, RIGHT); else if (move.up) /* TFFF */ move_direction (animal, UP); else if (move.down && move.left && move.right) /* FTTT */ if (randval > 67) move_direction (animal, DOWN); else if (randval > 33) move_direction (animal, LEFT); else move_direction (animal, RIGHT); else if (move.down && move.right) /* FTFT */ if (randval > 50) move_direction (animal, DOWN); else move_direction (animal, RIGHT); else if (move.down && move.left) /* FTTF */ if (randval > 50) move_direction (animal, DOWN); else move_direction (animal, LEFT); else if (move.down) /* FTFF */ move_direction (animal, DOWN); else if (move.left && move.right) /* FFTT */ if (randval > 50) move_direction (animal, LEFT); else move_direction (animal, RIGHT); else if (move.left) /* FFTF */ move_direction (animal, LEFT); else if (move.right) /* FFFT */ move_direction (animal, RIGHT); else /* No movement */; } void random_movement(AnimalType *anim) { static guint updateblock = 0; /* Assume we can move anywhere */ MoveChoices directions = { TRUE, TRUE, TRUE, TRUE }; #if 1 if (updateblock >= 1) { updateblock = 0; while (gtk_events_pending()) gtk_main_iteration(); } #endif if (anim->posx == 1) { directions.left = FALSE; /* somewhere on left column */ if (anim->posy == 1) { /* Top Left Corner */ directions.up = FALSE; } else if (anim->posy == MAXROW+1) { /* Bottom Left corner */ directions.down = FALSE; } } else if (anim->posx == MAXCOL+1) { directions.right = FALSE; /* somewhere on right column */ if (anim->posy == 1) { /* Top right corner */ directions.up = FALSE; } else if (anim->posy == MAXCOL+1) { /* Bottom right corner */ directions.down = FALSE; } } else if (anim->posy == 1) { /* Top row */ directions.up = FALSE; } else if (anim->posy == MAXROW+1) { /* Bottom row */ directions.down = FALSE; } /* If an animal exists then we can't move there !!! */ if (directions.up) if (animal_exists (anim->posx, anim->posy-1)) directions.up = FALSE; if (directions.down) if (animal_exists (anim->posx, anim->posy+1)) directions.down = FALSE; if (directions.left) if (animal_exists (anim->posx-1, anim->posy)) directions.left = FALSE; if (directions.right) if (animal_exists (anim->posx+1, anim->posy)) directions.right = FALSE; choose_direction_and_move (anim, directions); updateblock++; }