import java.applet.Applet; import java.awt.Color; import java.awt.Graphics; import java.awt.Font; import java.awt.FontMetrics; import java.awt.*; import java.util.Date; import java.lang.Math; import java.lang.*; import java.*; // Modified on Sept 25 1997 for java virtual machine jdk.1.0.2 // use System.exit(return-code); to halt program public class terri extends java.applet.Applet implements Runnable { int Ix, Iy; double vx = 80.0, vy = 60.0, vz = 70.0, xhome = 200.0, yhome = 200.0, theta = -.5, PI = 3.1415926, omega = 1.3, alpha = -0.9; double box[][] = new double[8][3]; Image image1=null; Thread runner; public static final int max_random_dir = 100, // max_random_dir MUST be multiple of 4 (ie. 16 24 256) left = 0, right = 1, up = 2, down = 3; int random_dir[] = new int[max_random_dir]; int current_generation = 0; // 0=left 1=right 2=up 3=down as per above constants int cur_random_index = 0; /* legend for array pop 0 x 1 y 2 species 0 fish 1 shark 999 vacant 3 age 4 hunger 0 --> infinite - pertains to shark only - fish remain 0 */ /* legend for array grid <--- MUST check value of species FIRST - species = vacant nullifies values of vitality/number (x) (y) (0 vitality 0 alive 1 dead 1 number whichAnimal 2 species 0 fish 1 shark 999 vacant */ static final int vacant = 999, x = 0, y = 1, species = 2, age = 3, hunger = 4, fish = 0, shark = 1, vitality = 0, alive = 0, dead = 0, number=1, undefined = -1; int curAnimal = 0, cur_fish = 0, cur_shark = 0, curDead = 0, sharkStarveAge = 6, fishSexMaturity = 2, sharkSexMaturity = 8, oceanx = 60, oceany = 60, init_fish = 280, init_shark = 122, MaxAnimals = oceanx * oceany, animalSize = 5; boolean debugMode = false , continue_looping = true; static final boolean no = false, yes = true; int pop[][] = new int [oceanx * oceany][5]; // 0=x 1=y 2=species 3=age 4=hunger int grid[][][] = new int [oceanx][oceany][3]; // 0=vitality (0 alive 1 dead) // 1=number(whichAnimal) 2=species(0/1/999) int cur_pop[] = new int [2]; // 0=fish 1=shark int birthAge[] = new int [2]; // age respective species gives birth int deathRow[] = new int [oceanx * oceany]; // list of dead animals as index into pop curAnimals int locx[] = new int [oceanx]; int locy[] = new int [oceany]; Color animalColor[] = new Color[2]; // .... private boolean doubleBuffer=true; // or false of course private Image buf; // bitmap for double buffering private Graphics gBuf; // gc to draw on bitmap public void init() { double xoff = 0.0, yoff = 0.0, zoff = 0.0, xfactor = 80.5, yfactor = 80.5, zfactor = 80.5; image1 = getImage(getDocumentBase(), "/ms/user/s/stens/gif/kidney_pie.gif"); // .... birthAge[fish] = fishSexMaturity; birthAge[shark] = sharkSexMaturity; animalColor[fish] = Color.green; animalColor[shark] = Color.red; box[0][0] = (-1.0 + xoff) * xfactor; box[0][1] = (-1.0 + yoff) * yfactor; box[0][2] = (-1.0 + zoff) * zfactor; box[1][0] = (-1.0 + xoff) * xfactor; box[1][1] = (1.0 + yoff) * yfactor; box[1][2] = (-1.0 + zoff) * zfactor; box[2][0] = (1.0 + xoff) * xfactor; box[2][1] = (1.0 + yoff) * yfactor; box[2][2] = (-1.0 + zoff) * zfactor; box[3][0] = (1.0 + xoff) * xfactor; box[3][1] = (-1.0 + yoff) * yfactor; box[3][2] = (-1.0 + zoff) * zfactor; box[4][0] = (-1.0 + xoff) * xfactor; box[4][1] = (-1.0 + yoff) * yfactor; box[4][2] = (1.0 + zoff) * zfactor; box[5][0] = (-1.0 + xoff) * xfactor; box[5][1] = (1.0 + yoff) * yfactor; box[5][2] = (1.0 + zoff) * zfactor; box[6][0] = (1.0 + xoff) * xfactor; box[6][1] = (1.0 + yoff) * yfactor; box[6][2] = (1.0 + zoff) * zfactor; box[7][0] = (1.0 + xoff) * xfactor; box[7][1] = (-1.0 + yoff) * yfactor; box[7][2] = (1.0 + zoff) * zfactor; // initialize pop of animals int tempc = 0; for (int i = 0; i < oceanx; i++) { locx[i] = i * animalSize; for (int ii = 0; ii < oceany; ii++) { // initialize to blank grid/pop locy[ii] = ii * animalSize; grid[i][ii][vitality] = vacant; grid[i][ii][number] = undefined; grid[i][ii][species] = vacant; pop[tempc][species] = vacant; tempc++; } } int possx, possy; curAnimal = 0; cur_pop[fish] = 0; for (int i = 0; i < init_fish;) { possx = Randomize(oceanx); possy = Randomize(oceany); if (grid[possx][possy][species] == vacant) { birthAnimal(possx, possy, fish); i++; } } if (debugMode) { System.out.println("init_fish = " + init_fish + " and cur_pop[fish] = " + cur_pop[fish]); } cur_pop[shark] = 0; for (int i = 0; i < init_shark;) { possx = Randomize(oceanx); possy = Randomize(oceany); if (grid[possx][possy][species] == vacant) { birthAnimal(possx, possy, shark); i++; } } if (debugMode) { System.out.println("init_shark = " + init_shark + " and cur_pop[shark] = " + cur_pop[shark]); System.out.println("curAnimal = " + curAnimal); } // initializes array with random sequence of the 4 directions 0 -> 3 storeRandom(); // buffer image for smooth animation if (doubleBuffer) { // Dimension d = size(); // buf = createImage(d.width, d.height); buf = createImage(400, 500); gBuf = buf.getGraphics(); } } public void birthAnimal(int newx, int newy, int whichSpecies) { pop[curAnimal][x] = newx; pop[curAnimal][y] = newy; pop[curAnimal][species] = whichSpecies; pop[curAnimal][age] = 0; pop[curAnimal][hunger] = 0; grid[newx][newy][vitality] = alive; grid[newx][newy][number] = curAnimal; grid[newx][newy][species] = whichSpecies; curAnimal++; cur_pop[whichSpecies] += 1; if (curAnimal >= MaxAnimals) { System.out.println("Error - attempt to birth too many animals. "); System.out.println("Reduce init animal count if this has happened during init"); System.exit(103); } } public void storeRandom() { int i; if (max_random_dir < 50) { System.out.println("Increase size of max_random_dir"); System.exit(104); } random_dir[0] = 0; random_dir[1] = 3; random_dir[2] = 1; random_dir[3] = 2; for (i = 7; i < max_random_dir; i += 4) { random_dir[i] = Randomize(4); random_dir[i - 1] = Randomize(4); while (random_dir[i - 1] == random_dir[i]) { random_dir[i - 1] = Randomize(4); } random_dir[i - 2] = Randomize(4); while (random_dir[i - 2] == random_dir[i] || random_dir[i - 2] == random_dir[i - 1]) { random_dir[i - 2] = Randomize(4); } random_dir[i - 3] = Randomize(4); while (random_dir[i - 3] == random_dir[i] || random_dir[i - 3] == random_dir[i - 1] || random_dir[i - 3] == random_dir[i - 2]) { random_dir[i - 3] = Randomize(4); } } if (i - 3 != max_random_dir) { System.out.println("max_random_dir must be Multiple of 4"); System.exit(105); } } public int getNextx(int now_animal, int dir) { /* IMPROVEMENT need to determine poss dir without mindlessly trying successive list of random directions - repeating past directions */ int tempx = pop[now_animal][x]; if (dir == left) { tempx -= 1; if (tempx < 0) tempx = oceanx - 1; } else if (dir == right) { tempx += 1; if (tempx == oceanx) tempx = 0; } return tempx; } public int getNexty(int now_animal, int dir) { int tempy = pop[now_animal][y]; if (dir == up) { tempy -= 1; if (tempy < 0) tempy = oceany - 1; } else if (dir == down) { tempy += 1; if (tempy == oceany) tempy = 0; } return tempy; } public boolean isStarved(int whichAnimal) { if (pop[whichAnimal][species] == fish) return no; if (pop[whichAnimal][hunger] > sharkStarveAge) { if (debugMode) { System.out.println(" --------> Shark starved."); } return yes; } return no; } public void doMate(int whichAnimal) { } public void chronos() { int tempf=0, temps=0 ; if (debugMode) { System.out.println("chronos begins anew"); referentialIntegrity("chronos begins anew"); System.out.print("fish = " + cur_pop[fish] + " shark = " + cur_pop[shark] + " curAnimal = " + curAnimal); for (int i = 0; i < curAnimal; i++) { if (pop[i][species] == fish) tempf++; if (pop[i][species] == shark) temps++; } System.out.println(" countfish= " + tempf + " countshark= " + temps); System.out.println(" generation= " + current_generation ); if ((cur_pop[fish] != tempf) || (cur_pop[shark] != temps)) { System.out.println("Error - top of chronos athena"); System.exit(100); continue_looping = false; } } boolean sharkEatsFish, found_good_dir = false, triedDir [] = new boolean [4]; int cur_dir, possx, possy, origCurAnimal = curAnimal, xcanDoDir, ycanDoDir, indeterminant = -1; // showGridText(); if (debugMode) { System.out.println("Total Animal Count = " + curAnimal); showGridText(); System.out.println(" -------- " ); } for (int i = 0; i < origCurAnimal; i++) { sharkEatsFish = false; if (pop[i][species] == vacant) continue; // found dead fish - bypass this index i if (grid[pop[i][x]][pop[i][y]][species] == vacant) { continue_looping = false; System.out.println("Error in Chronos - dead according to grid, but pop says alive for species = " + pop[i][species]); System.out.println("dump of pop --> animal=" + i + " x=" + pop[i][x] + " y=" + pop[i][y] + " species=" + pop[i][species] + " age=" + pop[i][age] + " hunger=" + pop[i][hunger]); System.out.println("dump of grid -> vitality=" + grid[pop[i][x]][pop[i][y]][vitality] + " number=" + grid[pop[i][x]][pop[i][y]][number] + " species=" + grid[pop[i][x]][pop[i][y]][species]); System.exit(101); } if (debugMode) { System.out.println(" "); System.out.print("chronos of animal " + i + " is at xy of " + pop[i][x] + ", " + pop[i][y]); System.out.print(" species = " + pop[i][species] + " age = " + pop[i][age] + " hunger=" + pop[i][hunger]); } pop[i][age] += 1; if (pop[i][species] == shark) pop[i][hunger]++; if (isStarved(i)) { if (debugMode) { System.out.print(" pre-burying animal " + i); showGridText(); } killAnimal(i); if (debugMode) { System.out.print(" post burial animal " + i); showGridText(); System.out.print(" done burying animal " + i); } } else { triedDir[up] = triedDir[down] = triedDir[left] = triedDir[right] = false; found_good_dir = false; xcanDoDir = ycanDoDir = indeterminant; do { // move animal cur_dir = getRandomDir(); // above randomly directs animal to any direction, parameter for // intelligence should alter above to be non-random possx = getNextx(i, cur_dir); possy = getNexty(i, cur_dir); if (debugMode) { System.out.println("possible xy are " + possx + ", " + possy); } if ((pop[i][species] == shark) && (grid[possx][possy][species] == fish)) { found_good_dir = true; xcanDoDir = ycanDoDir = indeterminant; if (debugMode) { System.out.println("animal " + i + " is shark eating FISH " + grid[possx][possy][number] + " at location xy of " + possx + ", " + possy); } killAnimal(grid[possx][possy][number]); // shark eats fish moveAnimal(i, possx, possy); pop[i][hunger] = 0; } else { if (grid[possx][possy][species] == vacant) { xcanDoDir = possx; ycanDoDir = possy; if (pop[i][species] == fish) { found_good_dir = true; moveAnimal(i, possx, possy); } } } triedDir[cur_dir] = true; if (debugMode) { System.out.println("just tried dir of " + cur_dir); } } while ((found_good_dir != true) && (triedDir[up]==false || triedDir[down]==false || triedDir[left]==false || triedDir[right]==false)) ; if ((found_good_dir != true) && (xcanDoDir != indeterminant)) { moveAnimal(i, xcanDoDir, ycanDoDir); } } if (debugMode) { System.out.println(" "); } } buryDead(); if (debugMode) { referentialIntegrity("end of chronos"); } } public void referentialIntegrity(String called_from_here) { int totalFishp = 0, totalSharkp = 0, totalFishg = 0, totalSharkg = 0; for (int xx = 0; xx < oceanx; xx++) { for (int yy = 0; yy < oceany; yy++) { if (grid[xx][yy][species] == fish) { totalFishg++; } else if (grid[xx][yy][species] == shark) { totalSharkg++; } } } for (int i = 0; i < curAnimal; i++) { if (pop[i][species] == fish) totalFishp++; else if (pop[i][species] == shark) totalSharkp++; } System.out.println("inside - ref integ fault - " + called_from_here); System.out.println("totalfish pop= " + totalFishp + " totalShark pop = " + totalSharkp); System.out.println("totalfish grid= " + totalFishg + " totalShark grid = " + totalSharkg); if ((totalFishp != totalFishg) || (totalSharkp != totalSharkg)) { System.out.println("Error - ref integ fault - " + called_from_here); showGridText(); System.exit(102); continue_looping = false; } } public void showGridText() { int whichAnimal = 0; boolean foundAnimal = false; System.out.println("show grid with total fish=" + cur_pop[fish] + " and shark=" +cur_pop[shark]); for (int i = 0; i < curAnimal; i++) { System.out.print("animal = " + i + " x= " + pop[i][x] + " y= " + pop[i][y]); System.out.println(" species= " + pop[i][species] + " age= " + pop[i][age] + " hunger=" + pop[i][hunger]); } for (int xx = 0; xx < oceanx; xx++) { System.out.println(" "); for (int yy = 0; yy < oceany; yy++) { if (grid[xx][yy][species] == vacant) { System.out.print("_"); } else { System.out.print(grid[xx][yy][species]); } } } System.out.println("\nNow displaying grid[x][y][number]"); for (int xx = 0; xx < oceanx; xx++) { System.out.println(" "); for (int yy = 0; yy < oceany; yy++) { if (grid[xx][yy][species] == vacant) { System.out.print("_"); } else { System.out.print(grid[xx][yy][number]); } } } System.out.println("Now Displaying grid of whichAnimal"); for (int xx = 0; xx < oceanx; xx++) { System.out.println(" "); for (int yy = 0; yy < oceany; yy++) { if (grid[xx][yy][species] == vacant) { System.out.print("_"); } else { foundAnimal = false; whichAnimal = 0; do { if ((pop[whichAnimal][x] == xx) && (pop[whichAnimal][y] == yy)) { System.out.print(whichAnimal); foundAnimal = true; } whichAnimal++; } while ((whichAnimal < curAnimal) && (foundAnimal == false)); } } } } public void storeDeathRow(int killThisAnimal) { int index = curDead, tempSlot; boolean stillSearchingPosition = true; deathRow[curDead] = killThisAnimal; curDead++; while (index - 1 >= 0 && stillSearchingPosition == true) { stillSearchingPosition = false; if (deathRow[index - 1] > killThisAnimal) { stillSearchingPosition = true; tempSlot = deathRow[index - 1]; deathRow[index - 1] = killThisAnimal; deathRow[index] = tempSlot; } index--; } } // pussy public void killAnimal(int killThisAnimal) { int xx = pop[killThisAnimal][x], yy = pop[killThisAnimal][y];; if (debugMode) { System.out.println("inside killAnimal with death of " + killThisAnimal + " x=" + xx + " y=" + yy + " species=" + pop[killThisAnimal][species] + " at age=" + pop[killThisAnimal][age] + " cur_pop=" + cur_pop[fish] + ", " + cur_pop[shark]); } if (grid[xx][yy][species] == vacant) { continue_looping = false; System.out.println("Error in killAnimal - attempting to kill dead animal"); } storeDeathRow(killThisAnimal); // deathRow[curDead] = killThisAnimal; // curDead++; cur_pop[pop[killThisAnimal][species]] -= 1; grid[xx][yy][vitality] = dead; grid[xx][yy][number] = undefined; grid[xx][yy][species] = vacant; pop[killThisAnimal][species] = vacant; // able to use pop[][species] == vacant to mean dead } public boolean mateSuccess(int whichAnimal) { if ((curAnimal + 1) < (oceanx * oceany) && pop[whichAnimal] [age] >= birthAge[pop[whichAnimal][species]]) { return true; } return false; } public void moveAnimal(int now_animal, int newx, int newy) { if (debugMode) { System.out.println("inside moveAnimal moving animal " + now_animal + " to xy of " + newx + ", " + newy); referentialIntegrity("calling referential Integrity at TOP of moveAnimal"); } if (grid[newx][newy][species] != vacant) { // throw exception } else { if (mateSuccess(now_animal)) { pop[now_animal][age] = 0; if ((pop[now_animal][species] != fish) && (pop[now_animal][species] != shark)) { continue_looping = false; System.out.println("Error in moveAnimal - birthing unknown species = " + pop[now_animal][species]); } birthAnimal(newx, newy, pop[now_animal][species]); } else { grid[newx][newy][vitality] = alive; grid[newx][newy][number] = now_animal; grid[newx][newy][species] = pop[now_animal][species]; grid[pop[now_animal][x]][pop[now_animal][y]][vitality] = vacant; grid[pop[now_animal][x]][pop[now_animal][y]][number] = undefined; grid[pop[now_animal][x]][pop[now_animal][y]][species] = vacant; pop[now_animal][x] = newx; pop[now_animal][y] = newy; } } if (debugMode) { referentialIntegrity("calling referential Integrity at BOTTOM of moveAnimal"); } } public int getRandomDir() { int next_dir; next_dir = random_dir[cur_random_index++]; if (cur_random_index >= max_random_dir) { cur_random_index = 0; // storeRandom(); } return next_dir; } public int Randomize( int range ) { double rawResult; rawResult = Math.random(); return (int) (rawResult * range); } public void destroy() { // .... if (doubleBuffer) gBuf.dispose(); } public void showPop(Graphics g) { g.setColor(Color.blue); g.drawString ("generation = " + Integer.toString(current_generation), 410, 10) ; g.drawString ("curDead = " + Integer.toString(curDead), 410, 20) ; g.drawString ("fish coun t = " + Integer.toString(cur_pop[fish]), 410, 30) ; g.drawString ("shark count = " + Integer.toString(cur_pop[shark]), 410, 40) ; // System.out.println(" just refreshed appletviewer of cur_pop stats"); g.setColor(getBackground()); /* for (int i = 0; i < curDead; i++) { g.fillRect(locx[pop[deathRow[i]][x]], locy[pop[deathRow[i]][y]], animalSize - 1, animalSize - 1); if (debugMode) { System.out.println("paintover dead animal " + deathRow[i] + " at position " + pop[deathRow[i]][x] + ", " + pop[deathRow[i]][y]); } } */ for (int i = 0; i < curAnimal; i++) { if (pop[i][species] != vacant) { g.setColor(animalColor[pop[i][species]]); g.fillRect(locx[pop[i][x]], locy[pop[i][y]], animalSize, animalSize); // System.out.println("animal " + i + " is at xy of " + pop[i][x] + ", " + pop[i][y]); } } } public int getTopAliveAnimal() { for (int i = (curAnimal - 1); i >= 0; i--) { if (pop[i][species] != vacant) return i; } return 0; } public int getNextDead() { int highestDead = deathRow[0], indexHighestDead = 0; /* for (int i = 1; i < curDead; i++) { if (highestDead < deathRow[i] && deathRow[i] != undefined) { highestDead = deathRow[i]; indexHighestDead = i; } System.out.println("highest Dead is " + highestDead + " viewing cur deathRow of " + deathRow[i]); } System.out.println("Found highest Dead which is " + highestDead); deathRow[indexHighestDead] = undefined; */ curDead--; return deathRow[curDead]; } public void buryDead() { if (debugMode) { referentialIntegrity("top of buryDead"); showGridText(); for (int i = 0; i < curDead; i++) System.out.println("displaying deathRow = " + deathRow[i]); } int origDead = curDead - 1, whichDead, topAliveAnimal; if (curDead == 0) return; for (int i = origDead; i >= 0; i--) { // whichDead = deathRow[i]; whichDead = getNextDead(); if (debugMode) { System.out.println("inside buryDead - burying animal " + whichDead + " pop x=" + pop[whichDead][x] + " y=" + pop[whichDead][y] + " species=" + pop[whichDead][species]); } topAliveAnimal = getTopAliveAnimal(); // was topAliveAnimal = curAnimal - 1; if (debugMode) { System.out.println("top animal number is " + topAliveAnimal); } if (whichDead < topAliveAnimal) { if (debugMode) { System.out.println("Moving top animal of " + topAliveAnimal + " into dead slot of " + whichDead); } pop[whichDead][x] = pop[topAliveAnimal][x]; pop[whichDead][y] = pop[topAliveAnimal][y]; pop[whichDead][species] = pop[topAliveAnimal][species]; pop[whichDead][age] = pop[topAliveAnimal][age]; pop[whichDead][hunger] = pop[topAliveAnimal][hunger]; grid[pop[topAliveAnimal][x]] [pop[topAliveAnimal][y]] [number] = whichDead; } else { if (debugMode) { System.out.println("dead NOT moved - just buried in spot for animal " + whichDead); } pop[whichDead][species] = vacant; // grid[pop[whichDead][x]][pop[whichDead][y]][vitality] = vacant; // grid[pop[whichDead][x]][pop[whichDead][y]][number] = undefined; // grid[pop[whichDead][x]][pop[whichDead][y]][species] = vacant; } curAnimal -= 1; } if (curAnimal == 0 || cur_pop[shark] == 0 || cur_pop[fish] == 0) { System.out.println("Game Over"); init(); // continue_looping = false; } if (debugMode) { referentialIntegrity("bottom of buryDead"); } curDead = 0; } protected void paintApplet(Graphics g) { double rx, ry, rz, tx, ty, tz, zcos, zsin, ysin, ycos, xsin, xcos; // pre-clear the bitmap or the applet // remove this if you paint the entire area anyway // Dimension d = size(); g.setColor(getBackground()); // g.fillRect(0, 0, d.width, d.height); g.fillRect(0, 0, 400, 500); // ....code that was originally in paint()... /* if(image1 != null) g.drawImage(image1, Ix, Iy, this); g.setColor(Color.blue); g.drawString (Integer.toString(Ix), 210, 50) ; g.drawString (Integer.toString(Iy), 240, 50) ; getAppletContext().showStatus("hello terri - hope your are feeling better"); zsin = Math.sin(theta); zcos = Math.cos(theta); ysin = Math.sin(omega); ycos = Math.cos(omega); xsin = Math.sin(alpha); xcos = Math.cos(alpha); for (int i = 0; i < box.length; i++) { // twist object about z axis tx = box[i][0] * zcos - box[i][1] * zsin; ty = box[i][0] * zsin + box[i][1] * zcos; tz = box[i][2]; // twist object about y axis rx = tx * ycos + tz * ysin; ry = ty; rz = -1.0 * tx * ysin + tz * ycos; // twist object about x axis tx = rx; ty = ry * xcos - rz * xsin; tz = ry * xsin + rz * xcos; g.fillRect((int) (tx + xhome), (int) (ty + yhome), 15, 15); } alpha -= 0.173; if (alpha <= 0.0) { alpha += (2.0 * PI); } theta -= 0.02; if (theta <= 0.0) { theta += (2.0 * PI); } omega += 0.0; if (omega >= (2.0 * PI)) { omega -= (2.0 * PI); } */ // show population of fish & sharks showPop(g); } public void paint(Graphics g) { if (doubleBuffer) { paintApplet(gBuf); g.drawImage(buf, 0, 0, this); } else { paintApplet(g); } } public void update(Graphics g) { // override this because the default implementation always // calls clearRect first, causing unwanted flicker paint(g); } public void run () { while (continue_looping) { repaint(); chronos(); current_generation++ ; try { Thread.sleep(100); } catch (InterruptedException e) { } } } public void start () { if (runner == null) ; { runner = new Thread (this) ; runner.start() ; } } public void stop () { if (runner != null) { runner.stop() ; runner = null ; } } }