/* * BUGS in 3D Version 2.0 Alpha * * by David Barberi 3/6/92 * * An Experiment in Artificial Life and Darwinian Evolution * * Bugs and Predators live, die and evolve inside a 3d World. * * Written on a Silicon Graphics Personal Iris 4D/25 * at the Syracuse University Virtual Reality Lab * * Send any Comments, Patches, Additions to: * dbarberi AT ibiblio DOT org * * Copyright (c) 1992 by David Barberi * Permission to Copy and Modify for non-commerical use * is granted as long as this notice is not removed. * * What's New in Version 2.0: * x PowerGlove support added * x Bugs and Predators are now in seperate structures * x Zbuffering, Lighting and Materials added * x New style polygon commands used * x Help screen added * x Additional navigation commands added * x Bugs and predators redrawn * x Replaced God with Genetics * x Predators cannot eat more then their stomach size * x When STARVING, Predators will eat kin * * * compile me with: ccc bugs2.c -lgl_s */ char copyright_notice[]=" (c) 1991 by David Barberi "; #include #include #include #include "colors.h" #define MAX 500 #define CHAR 20 #define WORLD_X 500 #define WORLD_Y 500 #define WORLD_Z 500 #define X 0 #define Y 1 #define Z 2 #define BUG 0 #define PRED 1 #define CONTENT 0 /* For pred.hungry */ #define HUNGRY 2 #define STARVING 4 #define MAX_BUG_SIZE 80 #define MIN_BUG_SIZE 4 #define MAX_BUG_SPEED 15 #define MIN_BUG_SPEED 0 #define MAX_PRED_SIZE 80 #define MIN_PRED_SIZE 8 #define MAX_PRED_SPEED 16 #define MIN_PRED_SPEED 3 typedef struct { float center[3], /* 3d center of creature in the World */ slope[3], /* X slope, Y slope, Z slope */ size; /* Current size of bounding cube */ int rotation[3]; /* Current rotation factor */ /****** The Global Genes ******/ float aura, /* The creatures event horizon */ birth_size, /* newborn size */ birth_speed, /* newborn speed */ int duration, /* the momentum, how long we plan to */ /* keep on going in the current direction */ bolt, /* tendency for short bursts in speed */ reverse, /* tendency to switch course backwards */ dependecy, /* how dependent on the mother? */ old_age, /* how many clicks until old age starts */ /**** Bug Only Genes ****/ int flock, /* a tendency to gather in groups */ /* if another bugs crosses our event horizon, then */ /* attempt to take that bugs direction and speed */ freeze_or_flee /* 100 = freeze, 0 = flee */ /**** Predator Only Genes ****/ int hunger, /* How hungry are we? */ float stomach_size, /* We can only eat as much as we can hold */ } Creature_Structure; Creature_Structure bug[MAX]; Creature_Structure pred[MAX]; int global_rot_x, global_rot_y, global_rot_z, global_tran_x, global_tran_y, global_tran_z, total_bugs, total_predators, click, bug_birth_count, pred_birth_count, bug_death_count, pred_death_count, v0[3]={-WORLD_X, -WORLD_Y, -WORLD_Z}, v1[3]={-WORLD_X, -WORLD_Y, WORLD_X}, v2[3]={-WORLD_X, WORLD_Y, WORLD_X}, v3[3]={-WORLD_X, WORLD_Y, -WORLD_Z}, v4[3]={ WORLD_X, -WORLD_Y, -WORLD_Z}, v5[3]={ WORLD_X, -WORLD_Y, WORLD_X}, v6[3]={ WORLD_X, WORLD_Y, WORLD_X}, v7[3]={ WORLD_X, WORLD_Y, -WORLD_Z}; char char_clicks[CHAR], char_bug_death_count[CHAR], char_bug_birth_count[CHAR], char_bug[CHAR], char_population[CHAR], char_total_pred[CHAR]; /***************************************************************/ /*** The Main Loop ***/ /***************************************************************/ main() { initialize(); while(!getbutton(ESCKEY)) { /* c3i(backbround); */ /* the background shall be variable */ /* clear(); zclear(); */ a_click_in_time(); /* calculate the next move */ /* pushmatrix(); translate( global_tran_x, global_tran_y, global_tran_z ); rot( global_rot_x, 'x' ); rot( global_rot_y, 'y' ); rot( global_rot_z, 'z' ); */ draw_world(); /* draw the World of the Creatures */ draw_bugs(); /* draw the bugs inside the world */ draw_predators(); /* and draw thee ole Hungry ones */ /* popmatrix(); */ do_data(); /* do the Data Window */ /* swapbuffers(); */ } printf("\n\n Long live the Bugs! \n\n"); } /**************************************************************/ /*** Calculate everyones next move ***/ /**************************************************************/ a_click_in_time() { register int i; click++; global_navigation(); /* rot, translate, basic navigation */ for(i=0; i < total_bugs; i++) { /* loop through all the bugs */ bug[i].center[X] += bug[i].slope[X]; bug[i].center[Y] += bug[i].slope[Y]; bug[i].center[Z] += bug[i].slope[Z]; } for(i=0; i < total_preds; i++) { /* loop through all the predators */ pred[i].center[X] += pred[i].slope[X]; pred[i].center[Y] += pred[i].slope[Y]; pred[i].center[Z] += pred[i].slope[Z]; } } /***********************************************************/ /**** draw_world() ***/ /***********************************************************/ draw_world() { /* c3i(255, 97, 217); linewidth(3); bgnline(); v3i(v0); v3i(v1); v3i(v2); v3i(v3); v3i(v0); v3i(v4); v3i(v5); v3i(v6); v3i(v7); v3i(v4); v3i(v5); v3i(v1); v3i(v2); v3i(v6); v3i(v7); v3i(v3); endline(); */ } /*****************************************************************/ /*** The Miracle of Birth.... ***/ /*****************************************************************/ birth( int bugorpred, parent ) { register int newborn; switch( bugorpred ) { case BUG: ++number_of_bugs; ++bug_birth_count; newborn = number_of_bugs; bug[newborn].center[X] = bug[parent].center[X]; bug[newborn].center[Y] = bug[parent].center[Y]; bug[newborn].center[Z] = bug[parent].center[Z]; bug[newborn].slope[X] = bug[parent].slope[X]; bug[newborn].slope[Y] = bug[parent].slope[Y]; bug[newborn].slope[Z] = bug[parent].slope[Z]; bug[newborn].size = bug[parent].birth_size; bug[newborn].speed = bug[parent].speed; break; case PRED: ++number_of_preds; ++pred_birth_count; newborn = number_of_preds; pred[newborn].center[X] = pred[parent].center[X]; pred[newborn].center[Y] = pred[parent].center[Y]; pred[newborn].center[Z] = pred[parent].center[Z]; pred[newborn].slope[X] = pred[parent].slope[X]; pred[newborn].slope[Y] = pred[parent].slope[Y]; pred[newborn].slope[Z] = pred[parent].slope[Z]; pred[newborn].size = pred[parent].birth_size; pred[newborn].speed = pred[parent].speed; pred[newborn].hunger = pred[parent.speed; pred[newborn].bolt = pred[parent].bolt; break; default: return(0); } return(1); } /********************** pred_die() ********************************/ /******************************************************************/ pred_die( int pred ) { if(pred==total_pred) { total_pred--; get_correct_pred_count(); return(0); } bug_x[pred] = bug_x[total_pred]; bug_y[pred] = bug_y[total_pred]; bug_z[pred] = bug_z[total_pred]; bug_size[pred] = bug_size[total_pred]; bug_speed[pred] = bug_speed[total_pred]; direction[pred] = direction[total_pred]; duration[pred] = duration[total_pred]; countdown[pred] = countdown[total_pred]; total_pred--; } /*************************** input() *****************************/ /*** Get input from the Keyboard to change view, pause, etc. ***/ /*******************************************************************/ global_navigation() { if(getbutton(MKEY)) { /* Press M to create another Predator */ create_new_pred(); } if(getbutton(F1KEY) || getbutton(HKEY)) { show_help_screen(); } if(getbutton(F2KEY)) /* Press F2 to pause */ while(!getbutton(F3KEY)); ; /* Press F3 to unpause */ if(getbutton(RKEY)) { if(rotate_mode==TRUE) rotate_mode = FALSE; else rotate_mode = TRUE; } if(getbutton(ONEKEY)) ispeed = 1; /* Number keys */ if(getbutton(TWOKEY)) ispeed = 2; /* control the speed */ if(getbutton(THREEKEY)) ispeed = 3; /* of movement */ if(getbutton(FOURKEY)) ispeed = 4; if(getbutton(FIVEKEY)) ispeed = 5; if(getbutton(SIXKEY)) ispeed = 6; if(getbutton(SEVENKEY)) ispeed = 7; if(getbutton(EIGHTKEY)) ispeed = 8; if(getbutton(NINEKEY)) ispeed = 9; if(getbutton(ZEROKEY)) ispeed = 15; if (getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY)) { if (getbutton(XKEY)) global_rot_x -= ispeed; if (getbutton(YKEY)) global_rot_y -= ispeed; if (getbutton(ZKEY)) global_rot_z -= ispeed; } else { if (getbutton(XKEY)) global_rot_x += ispeed; if (getbutton(YKEY)) global_rot_y += ispeed; if (getbutton(ZKEY)) global_rot_z += ispeed; if (getbutton(IKEY)) global_tran_z += ispeed; if (getbutton(OKEY)) global_tran_z -= ispeed; if (getbutton(UPARROWKEY)) global_tran_y += ispeed; if (getbutton(DOWNARROWKEY)) global_tran_y -= ispeed; if (getbutton(LEFTARROWKEY)) global_tran_x += ispeed; if (getbutton(RIGHTARROWKEY)) global_tran_x -= ispeed; } } /******************** game_over() ******************************/ /*****************************************************************/ game_over() { /* draw_world(); writenote(); swapbuffers(); */ while(!getbutton(ESCKEY)) { c3i(15,15,15); clear(); draw_world(); writenote(); pushmatrix(); ortho2(0.0,1024.0,0.0,768.0); cmov2(90.0, 200.0); c3i(255, 255, 0); charstr(" GAME OVER.. ALL BUGS HAVE DIED.. ALL HAIL THE BUGS!"); cmov2(90.0, 150.0); charstr(" type ESC to end "); popmatrix(); swapbuffers(); } gexit(); exit(); } /********************* draw_creatures() ****************************/ /*** ***/ /***********************************************************************/ draw_creatures() { register int i; for(i=0; i < total_bugs; i++) { } for(i=0; i < total_preds; i++) { } } for(pred=pred_start; pred < pred_end; pred++) { eat_anything(pred); if(bug_size[pred] > MAX_PRED_SIZE) bug_size[pred] = MAX_PRED_SIZE; if(bug_size[pred] < MIN_PRED_SIZE) bug_size[pred] = MIN_PRED_SIZE; if(bug_speed[pred] > MAX_PRED_SPEED) bug_speed[pred] = MAX_PRED_SPEED; if(bug_speed[pred] < MIN_PRED_SPEED) bug_speed[pred] = MIN_PRED_SPEED; countdown[pred]++; if(countdown[pred] > duration[pred]) get_new_direction(pred); get_direction(pred); splat_check(pred); if(pred_mode[pred] == CONTENT) { happy++; if((rand()%9)==2) bug_speed[pred] -= (rand()%4); if(happy >= 60) { pred_mode[pred] = HUNGRY; happy=0; } } if(pred_mode[pred] == HUNGRY) { hunger++; if((rand()%3)==1) bug_speed[pred] += (rand()%4); if(hunger >= 70) { pred_mode[pred] = STARVING; hunger=0; } } if(pred_mode[pred] == STARVING) { starve++; bug_speed[pred] += (rand()%2); if(starve >= 150) pred_die(pred); } /** Draw an outline of the predator **/ if(pred_mode[pred]==CONTENT) c3i(pred_content); /* c3i(255, 109, 113); */ else if(pred_mode[pred]==HUNGRY) c3i(pred_hungry); /* c3i(255,0,130); */ else c3i(pred_starving); /* c3i(255,0,0); */ aura_xf = bug_x[pred] + bug_size[pred] + AURA; aura_xb = bug_x[pred] - bug_size[pred] - AURA; aura_yf = bug_y[pred] + bug_size[pred] + AURA; aura_yb = bug_y[pred] - bug_size[pred] - AURA; aura_zf = bug_z[pred] + bug_size[pred] + AURA; aura_zb = bug_z[pred] - bug_size[pred] - AURA; } /*********************** eat_anything() ************************/ /*** Predator looks around for a bug ***/ /*** and eats it if it's close enough ***/ /****************************************************************/ eat_anything( int pred) { /* printf(" eat_anything pred=%i clicks=%i ", pred, clicks); */ for(food=0; food < total_bugs; food++) { if( (bug_x[food] < aura_xf) && (bug_x[food] > aura_xb) && (bug_y[food] < aura_yf) && (bug_y[food] > aura_yb) && (bug_z[food] < aura_zf) && (bug_z[food] > aura_zb) ) { pred_mode[pred] = CONTENT; bug_size[pred] += ((bug_size[food]*0.4)+(rand()%3)); bug_speed[pred] -= (rand()%3); duration[pred] += ((rand()%5) +10); die(food); /* printf(" *******eating bug %i \n", food); */ return(0); /* so you only eat one bug at a time */ } } /* printf(" END \n", pred, clicks); */ } /********************** splat_check() *******************************/ /*** Teleportation, Splatting ***/ /**********************************************************************/ splat_check( int bug) { xfront = (bug_x[bug] + bug_size[bug]); yfront = (bug_y[bug] + bug_size[bug]); zfront = (bug_z[bug] + bug_size[bug]); xback = (bug_x[bug] - bug_size[bug]); yback = (bug_y[bug] - bug_size[bug]); zback = (bug_z[bug] - bug_size[bug]); xfsplat = xfront + 30; yfsplat = yfront + 30; zfsplat = zfront + 30; xbsplat = xback - 30; ybsplat = yback - 30; zbsplat = zback -30; /* if((bug_x[bug] > WORLD_SIZE_X) || (bug_x[bug] < -WORLD_SIZE_X) || (bug_y[bug] < -WORLD_SIZE_Y) || (bug_y[bug] > WORLD_SIZE_Y) || (bug_z[bug] < -WORLD_SIZE_Z) || (bug_z[bug] > WORLD_SIZE_Z) ) get_new_direction(bug); this will cause bugs to sometimes get caught outside box and flounder */ /* Teleport the bugs to the other side of the world and make a big Splat on the wall they teleported through */ if(bug_x[bug] > WORLD_SIZE_X ) { bug_x[bug] = (-WORLD_SIZE_X); bgnpolygon(); c3i(248, 0, 121); v3f(WORLD_SIZE_X, yfsplat, zfsplat); v3f(WORLD_SIZE_X, yfsplat, zbsplat); v3f(WORLD_SIZE_X, ybsplat, zbsplat); v3f(WORLD_SIZE_X, ybsplat, zfsplat); endpolygon(); } if(bug_x[bug] < (-WORLD_SIZE_X) ) { bug_x[bug] = WORLD_SIZE_X; c3i(248, 0, 121); v3f(-WORLD_SIZE_X, yfsplat, zfsplat); v3f(-WORLD_SIZE_X, yfsplat, zbsplat); v3f(-WORLD_SIZE_X, ybsplat, zbsplat); v3f(-WORLD_SIZE_X, ybsplat, zfsplat); pclos(); } if(bug_y[bug] < (-WORLD_SIZE_Y)) { bug_y[bug] = WORLD_SIZE_Y; c3i(248, 0, 121); v3f( xfsplat, -WORLD_SIZE_Y, zfsplat); v3f( xfsplat, -WORLD_SIZE_Y, zbsplat); v3f( xbsplat, -WORLD_SIZE_Y, zbsplat); v3f( xbsplat, -WORLD_SIZE_Y, zfsplat); pclos(); } if(bug_y[bug] > WORLD_SIZE_Y) { bug_y[bug] = (-WORLD_SIZE_Y); c3i(248, 0, 121); v3f( xfsplat, WORLD_SIZE_Y, zfsplat); v3f( xfsplat, WORLD_SIZE_Y, zbsplat); v3f( xbsplat, WORLD_SIZE_Y, zbsplat); v3f( xbsplat, WORLD_SIZE_Y, zfsplat); } if(bug_z[bug] < (-WORLD_SIZE_Z) ) { bug_z[bug] = WORLD_SIZE_Z; c3i(248, 0, 121); v3f( xfsplat, yfsplat, -WORLD_SIZE_Z); v3f( xfsplat, ybsplat, -WORLD_SIZE_Z); v3f( xbsplat, ybsplat, -WORLD_SIZE_Z); v3f( xbsplat, yfsplat, -WORLD_SIZE_Z); } if(bug_z[bug] > WORLD_SIZE_Z) { bug_z[bug] = (-WORLD_SIZE_Z); c3i(248, 0, 121); v3f( xfsplat, yfsplat, WORLD_SIZE_Z); v3f( xfsplat, ybsplat, WORLD_SIZE_Z); v3f( xbsplat, ybsplat, WORLD_SIZE_Z); v3f( xbsplat, yfsplat, WORLD_SIZE_Z); } } /************************** get_direction() ***************************/ /*** move in one of 25 x,y,z directions ***/ /***********************************************************************/ get_direction( int bug) { if(direction[bug]==0) { bug_x[bug] += bug_speed[bug]; } if(direction[bug]==1) { bug_x[bug] -= bug_speed[bug]; } if(direction[bug]==2) { bug_y[bug] += bug_speed[bug]; } if(direction[bug]==3) { bug_y[bug] -= bug_speed[bug]; } if(direction[bug]==4) { bug_z[bug] += bug_speed[bug]; } if(direction[bug]==5) { bug_z[bug] -= bug_speed[bug]; } if(direction[bug]==6) { bug_x[bug] += bug_speed[bug]; bug_y[bug] += bug_speed[bug]; } if(direction[bug]==7) { bug_x[bug] += bug_speed[bug]; bug_z[bug] += bug_speed[bug]; } if(direction[bug]==8) { bug_x[bug] += bug_speed[bug]; bug_y[bug] -= bug_speed[bug]; } if(direction[bug]==9) { bug_x[bug] += bug_speed[bug]; bug_z[bug] -= bug_speed[bug]; } if(direction[bug]==10) { bug_x[bug] -= bug_speed[bug]; bug_y[bug] += bug_speed[bug]; } if(direction[bug]==11) { bug_x[bug] -= bug_speed[bug]; bug_z[bug] += bug_speed[bug]; } if(direction[bug]==12) { bug_x[bug] -= bug_speed[bug]; bug_y[bug] -= bug_speed[bug]; } if(direction[bug]==13) { bug_x[bug] -= bug_speed[bug]; bug_z[bug] -= bug_speed[bug]; } if(direction[bug]==14) { bug_y[bug] += bug_speed[bug]; bug_z[bug] += bug_speed[bug]; } if(direction[bug]==15) { bug_y[bug] += bug_speed[bug]; bug_z[bug] -= bug_speed[bug]; } if(direction[bug]==16) { bug_y[bug] -= bug_speed[bug]; bug_z[bug] += bug_speed[bug]; } if(direction[bug]==17) { bug_y[bug] -= bug_speed[bug]; bug_z[bug] -= bug_speed[bug]; } if(direction[bug]==18) { bug_x[bug] += bug_speed[bug]; bug_y[bug] += bug_speed[bug]; bug_z[bug] += bug_speed[bug]; } if(direction[bug]==19) { bug_x[bug] += bug_speed[bug]; bug_y[bug] += bug_speed[bug]; bug_z[bug] -= bug_speed[bug]; } if(direction[bug]==20) { bug_x[bug] += bug_speed[bug]; bug_y[bug] -= bug_speed[bug]; bug_z[bug] += bug_speed[bug]; } if(direction[bug]==21) { bug_x[bug] += bug_speed[bug]; bug_y[bug] -= bug_speed[bug]; bug_z[bug] -= bug_speed[bug]; } if(direction[bug]==22) { bug_x[bug] -= bug_speed[bug]; bug_y[bug] += bug_speed[bug]; bug_z[bug] += bug_speed[bug]; } if(direction[bug]==23) { bug_x[bug] -= bug_speed[bug]; bug_y[bug] += bug_speed[bug]; bug_z[bug] -= bug_speed[bug]; } if(direction[bug]==24) { bug_x[bug] -= bug_speed[bug]; bug_y[bug] -= bug_speed[bug]; bug_z[bug] += bug_speed[bug]; } if(direction[bug]==25) { bug_x[bug] -= bug_speed[bug]; bug_y[bug] -= bug_speed[bug]; bug_z[bug] -= bug_speed[bug]; } } /******************* get_new_direction() ***************************/ /*******************************************************************/ get_new_direction( int bug) { duration[bug]=( (rand()%30) + 30 ); direction[bug]=( rand()%26 ); countdown[bug]=0; } /******************** get_new_location() ***************************/ /*******************************************************************/ get_new_location( int bug) { bug_x[bug] = ((rand()%(WORLD_SIZE_X *2)) - WORLD_SIZE_X); bug_y[bug] = ((rand()%(WORLD_SIZE_Y *2)) - WORLD_SIZE_Y); bug_z[bug] = ((rand()%(WORLD_SIZE_Z *2)) - WORLD_SIZE_Z); } /*****/ cls( int lines ); { register int i; for(i=0; i= MAXPREDATORS) total_pred = MAXPREDATORS; /** Predators are saved in the bug..[] hierarchy **/ get_correct_pred_count(); for(pred=pred_start; pred <= pred_end; pred++) { get_new_direction(pred); get_new_location(pred); bug_size[pred] = PRED_BIRTH_SIZE; bug_speed[pred] = PRED_BIRTH_SPEED; pred_mode[pred] = HUNGRY; } /*** Initialize graphics ****/ keepaspect(1,1); prefposition(20, 990, 20, 990); winopen("Bugs"); doublebuffer(); RGBmode(); gconfig(); /* zbuffer(TRUE); mmode(MVIEWING); */ perspective(300.0, 1.0, 0.000001, 600.0); polarview(100.0, 0.0, 0.0, 0.0); translate(0.0, 0.0, -2700.0); } /****************************************************************/ /* Place stationary text on the screen */ /****************************************************************/ writenote() { sprintf(char_clicks, "%d", clicks); sprintf(char_bug_deaths, "%d", deaths); sprintf(char_bug_birth_count, "%d", bug_birth_count); sprintf(char_population, "%d", total_bugs); sprintf(char_total_pred, "%d", total_pred); pushmatrix(); ortho2(0.0,1024.0,0.0,768.0); cmov2(10.0,30.0); c3i(255,255,255); charstr(" BUGS -- By David Barberi "); charstr(" Type 'Esc' to quit"); cmov2(35.0, 60.0); charstr(" clicks ="); c3i(255,255,0); charstr(char_clicks); c3i(255,255,255); charstr(" # of bugs ="); c3i(255,255,0); charstr(char_population); c3i(255,255,255); charstr(" # of bug_birth_count ="); c3i(255,255,0); charstr(char_bug_birth_count); c3i(255,255,255); charstr(" # of deaths ="); c3i(255,255,0); charstr(char_deaths); c3i(255,255,255); charstr(" # of Predators ="); c3i(255,255,0); charstr(char_total_pred); if(god==TRUE) charstr(" Playing GOD"); popmatrix(); } /*** finis ***/