The Big Bang

pull/1/head
Yong Zhu 6 years ago
parent 1d9dd6ebd9
commit b4abaeaf83

@ -0,0 +1 @@
mvn eclipse:clean

@ -0,0 +1,2 @@
call mvn eclipse:eclipse
call pause

@ -27,10 +27,12 @@ import com.github.drinkjava2.frog.egg.Egg;
import com.github.drinkjava2.frog.egg.Zone; import com.github.drinkjava2.frog.egg.Zone;
import com.github.drinkjava2.frog.env.Application; import com.github.drinkjava2.frog.env.Application;
import com.github.drinkjava2.frog.env.Env; import com.github.drinkjava2.frog.env.Env;
import com.github.drinkjava2.frog.env.Food;
/** /**
* Frog = brain + body(mouth, eye, leg) * Frog = brain + body(mouth, eye, leg), but now let's focus on brain, ignore
* body
*
*
* *
* @author Yong Zhu * @author Yong Zhu
* @since 1.0.0 * @since 1.0.0
@ -47,15 +49,18 @@ public class Frog {
public static Zone eye = new Zone(0, 0, 300); public static Zone eye = new Zone(0, 0, 300);
/** 运动细胞的输入区在脑中的坐标,先随便取就可以了,以后再考虑放到蛋里去进化 */ /** 运动细胞的输入区在脑中的坐标,先随便取就可以了,以后再考虑放到蛋里去进化 */
public static Zone moveUp = new Zone(500, 100, 10); public static Zone moveUp = new Zone(500, 50, 10);
public static Zone moveDown = new Zone(500, 200, 10); public static Zone moveDown = new Zone(500, 100, 10);
public static Zone moveLeft = new Zone(500, 300, 10); public static Zone moveLeft = new Zone(500, 150, 10);
public static Zone moveRight = new Zone(500, 400, 10); public static Zone moveRight = new Zone(500, 200, 10);
public static Zone moveRandom = new Zone(500, 300, 10);
public int x; public int x;
public int y; public int y;
public long energy = 10000; public long energy = 10000;
public Egg egg; public Egg egg;
public boolean alive = true; // if dead set to false
public int moveCount = 0; // how many times moved
static final Random r = new Random(); static final Random r = new Random();
static Image frogImg; static Image frogImg;
@ -80,12 +85,14 @@ public class Frog {
c.inputs = new Input[g.inputQtyPerCell]; c.inputs = new Input[g.inputQtyPerCell];
for (int j = 0; j < g.inputQtyPerCell; j++) { for (int j = 0; j < g.inputQtyPerCell; j++) {
c.inputs[j] = new Input(); c.inputs[j] = new Input();
c.inputs[j].cell = c;
Zone.copyXY(randomPosInZone(g.groupInputZone), c.inputs[j]); Zone.copyXY(randomPosInZone(g.groupInputZone), c.inputs[j]);
c.inputs[j].radius = g.cellInputRadius; c.inputs[j].radius = g.cellInputRadius;
} }
c.outputs = new Output[g.outputQtyPerCell]; c.outputs = new Output[g.outputQtyPerCell];
for (int j = 0; j < g.outputQtyPerCell; j++) { for (int j = 0; j < g.outputQtyPerCell; j++) {
c.outputs[j] = new Output(); c.outputs[j] = new Output();
c.outputs[j].cell = c;
Zone.copyXY(randomPosInZone(g.groupInputZone), c.outputs[j]); Zone.copyXY(randomPosInZone(g.groupInputZone), c.outputs[j]);
c.outputs[j].radius = g.cellOutputRadius; c.outputs[j].radius = g.cellOutputRadius;
} }
@ -95,45 +102,95 @@ public class Frog {
this.egg = egg;// 保留一份蛋,如果没被淘汰掉,将来下蛋时要用这个蛋来下新蛋 this.egg = egg;// 保留一份蛋,如果没被淘汰掉,将来下蛋时要用这个蛋来下新蛋
} }
public void active(Env env) { /** Active a frog, if frog is dead return false */
// this.x = this.x - 1 + r.nextInt(3); public boolean active(Env env) {
// this.y = this.y - 1 + r.nextInt(3); if (!alive)
// eat food return false;
if (x < 0 || x >= env.ENV_XSIZE || y < 0 || y >= env.ENV_YSIZE) {// 越界者死!
alive = false;
return false;
}
// move
for (Cell cell : cells) {
for (Output output : cell.outputs) {
if (moveUp.nearby(output))
moveUp(env);
if (moveDown.nearby(output))
moveDown(env);
if (moveLeft.nearby(output))
moveLeft(env);
if (moveRight.nearby(output))
moveRight(env);
if (moveRandom.nearby(output))
moveRandom(env);
}
}
return true;
}
/** 如果青蛙位置与food重合吃掉它 */
private void checkFoodAndEat(Env env) {
boolean eatedFood = false; boolean eatedFood = false;
int j = env.foods.size() - 1; if (x >= 0 && x < env.ENV_XSIZE && y > 0 && y < env.ENV_YSIZE)
for (int i = j; i >= 0; i--) { if (env.foods[x][y] > 0) {
Food food = env.foods.get(i); env.foods[x][y] = 0;
if (x == food.x && y == food.y) { energy = energy + 1000;// 吃掉food能量境加
energy = energy + food.energy;
env.foods.remove(i);
eatedFood = true; eatedFood = true;
break;
} }
}
// 奖励 // 奖励
if (eatedFood) { if (eatedFood) {
} }
}
// move private void moveRandom(Env env) {
for (Cell cell : cells) { int ran = r.nextInt(4);
for (Output output : cell.outputs) { if (ran == 0)
if (Zone.nearby(moveUp, output)) { moveUp(env);
y += 1; if (ran == 1)
break; moveDown(env);
} else if (Zone.nearby(moveDown, output)) { if (ran == 2)
y -= 1; moveLeft(env);
break; if (ran == 3)
} else if (Zone.nearby(moveLeft, output)) { moveRight(env);
x -= 1; }
break;
} else if (Zone.nearby(moveRight, output)) { private void moveUp(Env env) {
x += 1; y += 1;
break; if (y < 0 || y >= env.ENV_YSIZE) {
} alive = false;
} return;
}
checkFoodAndEat(env);
}
private void moveDown(Env env) {
y -= 1;
if (y < 0 || y >= env.ENV_YSIZE) {
alive = false;
return;
}
checkFoodAndEat(env);
}
private void moveLeft(Env env) {
x -= 1;
if (x < 0 || x >= env.ENV_XSIZE) {
alive = false;
return;
}
checkFoodAndEat(env);
}
private void moveRight(Env env) {
x += 1;
if (x < 0 || x >= env.ENV_XSIZE) {
alive = false;
return;
} }
checkFoodAndEat(env);
} }
private boolean allowVariation = false; private boolean allowVariation = false;
@ -182,6 +239,8 @@ public class Frog {
} }
public void show(Graphics g) { public void show(Graphics g) {
if (!alive)
return;
g.drawImage(frogImg, x - 8, y - 8, 16, 16, null); g.drawImage(frogImg, x - 8, y - 8, 16, 16, null);
} }

@ -20,15 +20,12 @@ public class Cell {
public int group; // this cell belong to which group? public int group; // this cell belong to which group?
public Input[] inputs; // inputs of cell, float array format like {x1,y1, x2, y2...} public Input[] inputs; // inputs of cell, float array format like {x1,y1, x2, y2...}
public Output[] outputs; // outputs of cell, float array format like {x1,y1, x2, y2...} public Output[] outputs; // outputs of cell, float array format like {x1,y1, x2, y2...}
public boolean used = false;
public void activate() { public void activate() {
used = true;
for (Input xy : inputs) { for (Input xy : inputs) {
} }
} }
} }

@ -20,4 +20,5 @@ import com.github.drinkjava2.frog.egg.Zone;
*/ */
public class Input extends Zone{ public class Input extends Zone{
public float energy; public float energy;
public Cell cell;
} }

@ -20,4 +20,5 @@ import com.github.drinkjava2.frog.egg.Zone;
*/ */
public class Output extends Zone { public class Output extends Zone {
public float energy; public float energy;
public Cell cell;
} }

@ -34,13 +34,21 @@ public class Zone implements Serializable {
this.radius = radius; this.radius = radius;
} }
public static boolean nearby(Zone z1, Zone z2) { public boolean nearby(Zone z) {
float dist = z1.radius + z2.radius; float dist = radius + z.radius;
if (Math.abs(z1.x - z2.x) < dist && Math.abs(z1.y - z2.y) < dist) if (Math.abs(x - z.x) < dist && Math.abs(y - z.y) < dist)
return true; return true;
return false; return false;
} }
public int roundX() {
return Math.round(x);
}
public int roundY() {
return Math.round(y);
}
public static void copyXY(Zone from, Zone to) { public static void copyXY(Zone from, Zone to) {
to.x = from.x; to.x = from.x;
to.y = from.y; to.y = from.y;

@ -1,5 +1,6 @@
package com.github.drinkjava2.frog.env; package com.github.drinkjava2.frog.env;
import java.awt.Color;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Image; import java.awt.Image;
import java.util.ArrayList; import java.util.ArrayList;
@ -18,10 +19,10 @@ import com.github.drinkjava2.frog.util.EggTool;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class Env extends JPanel { public class Env extends JPanel {
/** Speed of test */ /** Speed of test */
public static int SHOW_SPEED = 10; public static int SHOW_SPEED =1;
/** Steps of one test round */ /** Steps of one test round */
public static int STEPS_PER_ROUND = 1000; public static int STEPS_PER_ROUND = 3000;
/** Virtual environment x size is 500 pixels */ /** Virtual environment x size is 500 pixels */
public int ENV_XSIZE = 300; public int ENV_XSIZE = 300;
@ -29,12 +30,13 @@ public class Env extends JPanel {
/** Virtual environment y size is 500 pixels */ /** Virtual environment y size is 500 pixels */
public int ENV_YSIZE = 300; public int ENV_YSIZE = 300;
public int FOOD_QTY = 2500; // as name public byte[][] foods = new byte[ENV_XSIZE][ENV_YSIZE];
public int EGG_QTY = 10; // as name public int FOOD_QTY = 2000; // as name
public int EGG_QTY =80; // as name
public List<Frog> frogs = new ArrayList<Frog>(); public List<Frog> frogs = new ArrayList<Frog>();
public List<Food> foods = new ArrayList<Food>();
public List<Egg> eggs; public List<Egg> eggs;
public Env() { public Env() {
@ -45,40 +47,68 @@ public class Env extends JPanel {
private void rebuildFrogAndFood() { private void rebuildFrogAndFood() {
frogs.clear(); frogs.clear();
foods.clear(); for (int i = 0; i < ENV_XSIZE; i++) {// clear foods
for (int j = 0; j < ENV_YSIZE; j++) {
foods[i][j] = 0;
}
}
Random rand = new Random(); Random rand = new Random();
for (int i = 0; i < eggs.size(); i++) { // 1个Egg生出4个Frog for (int i = 0; i < eggs.size(); i++) { // 1个Egg生出4个Frog
frogs.add(new Frog(rand.nextInt(ENV_XSIZE - 3), rand.nextInt(ENV_YSIZE - 3), eggs.get(i))); for (int j = 0; j < 4; j++) {
frogs.add(new Frog(rand.nextInt(ENV_XSIZE - 3), rand.nextInt(ENV_YSIZE - 3), eggs.get(i))); frogs.add(new Frog(ENV_XSIZE / 2 + rand.nextInt(90), ENV_YSIZE / 2 + rand.nextInt(90), eggs.get(i)));
frogs.add(new Frog(rand.nextInt(ENV_XSIZE - 3), rand.nextInt(ENV_YSIZE - 3), eggs.get(i))); }
frogs.add(new Frog(rand.nextInt(ENV_XSIZE - 3), rand.nextInt(ENV_YSIZE - 3), eggs.get(i)));
} }
System.out.println("Created "+4*eggs.size() +" frogs");
for (int i = 0; i < FOOD_QTY; i++) for (int i = 0; i < FOOD_QTY; i++)
foods.add(new Food(rand.nextInt(ENV_XSIZE - 3), rand.nextInt(ENV_YSIZE - 3))); foods[rand.nextInt(ENV_XSIZE - 3)][rand.nextInt(ENV_YSIZE - 3)] = 1;
}
private void drawFood(Graphics g) {
for (int x = 0; x < ENV_XSIZE; x++)
for (int y = 0; y < ENV_YSIZE; y++)
if (foods[x][y] > 0) {
g.fillOval(x, y, 4, 4);
}
} }
public void run() throws InterruptedException { public void run() throws InterruptedException {
EggTool.loadEggs(this); // 从磁盘加载egg或新建一批egg EggTool.loadEggs(this); // 从磁盘加载egg或新建一批egg
int round = 1; int round = 1;
Image buffImg = createImage(this.getWidth(), this.getHeight());
Graphics g = buffImg.getGraphics();
long t1, t2;
do { do {
Application.mainFrame.setTitle("Frog test round: " + round++); t1 = System.currentTimeMillis();
rebuildFrogAndFood(); rebuildFrogAndFood();
boolean allDead = false;
for (int i = 0; i < STEPS_PER_ROUND; i++) { for (int i = 0; i < STEPS_PER_ROUND; i++) {
for (Frog frog : frogs) if (allDead)
frog.active(this); break;
if (i % SHOW_SPEED != 0) // 显示会拖慢速度 allDead = true;
for (Frog frog : frogs) {
if (frog.active(this))
allDead = false;
if (frog.alive && frog.moveCount == 0 && i > 100) {// 如果不移动就死!
frog.alive = false;
}
}
if (i % SHOW_SPEED != 0) // 画青蛙会拖慢速度
continue; continue;
Image buffImg = createImage(this.getWidth(), this.getHeight()); // 开始画青蛙
Graphics g = buffImg.getGraphics(); g.setColor(Color.white);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.BLACK);
for (Frog frog : frogs) for (Frog frog : frogs)
frog.show(g); frog.show(g);
for (Food food : foods)
food.show(g); drawFood(g);
Graphics g2 = this.getGraphics(); Graphics g2 = this.getGraphics();
g2.drawImage(buffImg, 0, 0, this); g2.drawImage(buffImg, 0, 0, this);
Thread.sleep(10); Thread.sleep(10);
} }
EggTool.layEggs(this); EggTool.layEggs(this);
t2 = System.currentTimeMillis();
Application.mainFrame.setTitle("Frog test round: " + round++ + ", time used: " + (t2 - t1) + " ms");
} while (true); } while (true);
} }
} }

@ -1,23 +0,0 @@
package com.github.drinkjava2.frog.env;
import java.awt.Graphics;
/**
* Food is food for frogs, one food = 500 unit energy
*/
public class Food {
public int energy = 500;
public int x;
public int y;
public Food(int x, int y) {
this.x = x;
this.y = y;
}
public void show(Graphics g) {
g.fillOval(x, y, 4, 4);
}
}

@ -35,35 +35,31 @@ public class EggTool {
public static final boolean JSON_FILE_FORMAT = false; // JSON is slow but easier to debug public static final boolean JSON_FILE_FORMAT = false; // JSON is slow but easier to debug
public static void layEggs(Env env) {
if (JSON_FILE_FORMAT)
layJsonEggs(env);
else
laySerializedEggs(env);
}
public static void loadEggs(Env env) {
if (JSON_FILE_FORMAT)
loadJsonEggs(env);
else
loadSerializedEggs(env);
}
/** /**
* Java (fat)Frog, Frog * Java (fat)Frog, Frog
*/ */
public static void laySerializedEggs(Env env) { public static void layEggs(Env env) {
sortFrogsOrderByEnergyDesc(env); sortFrogsOrderByEnergyDesc(env);
System.out.print("First frog energy=" + env.frogs.get(0).energy); System.out.print("First frog energy=" + env.frogs.get(0).energy);
System.out.print(", Last frog energy=" + env.frogs.get(env.frogs.size() - 1).energy + ", "); System.out.print(", Last frog energy=" + env.frogs.get(env.frogs.size() - 1).energy + ", ");
for (Frog frog : env.frogs) {
System.out.print(frog.energy + ",");
}
System.out.println();
try { try {
List<Egg> newEggs = new ArrayList<Egg>(); List<Egg> newEggs = new ArrayList<Egg>();
for (int i = 0; i < env.frogs.size() / 4; i++) for (int i = 0; i < env.EGG_QTY; i++)
newEggs.add(env.frogs.get(i).layEgg()); newEggs.add(env.frogs.get(i).layEgg());
FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs.ser");
ObjectOutputStream so = new ObjectOutputStream(fo); if (JSON_FILE_FORMAT) {
so.writeObject(newEggs); String newEggsString = JSON.toJSONString(newEggs);
so.close(); FrogFileUtils.writeFile(Application.CLASSPATH + "eggs.json", newEggsString, "utf-8");
} else {
FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs.ser");
ObjectOutputStream so = new ObjectOutputStream(fo);
so.writeObject(newEggs);
so.close();
}
env.eggs = newEggs; env.eggs = newEggs;
System.out System.out
.println("Saved " + env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs.ser" + "'"); .println("Saved " + env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs.ser" + "'");
@ -72,20 +68,6 @@ public class EggTool {
} }
} }
/** 类似laySerializedEggs方法但是存为JSON格式 ,以方便调试 */
public static void layJsonEggs(Env env) {
sortFrogsOrderByEnergyDesc(env);
System.out.print("First frog energy=" + env.frogs.get(0).energy);
System.out.print(", Last frog energy=" + env.frogs.get(env.frogs.size() - 1).energy + ", ");
List<Egg> newEggs = new ArrayList<Egg>();
for (int i = 0; i < env.frogs.size() / 4; i++)
newEggs.add(env.frogs.get(i).layEgg());
String newEggsString = JSON.toJSONString(newEggs);
FrogFileUtils.writeFile(Application.CLASSPATH + "eggs.json", newEggsString, "utf-8");
env.eggs = newEggs;
System.out.println("Saved " + env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs.json" + "'");
}
private static void sortFrogsOrderByEnergyDesc(Env env) { private static void sortFrogsOrderByEnergyDesc(Env env) {
Collections.sort(env.frogs, new Comparator<Frog>() { Collections.sort(env.frogs, new Comparator<Frog>() {
public int compare(Frog a, Frog b) { public int compare(Frog a, Frog b) {
@ -103,44 +85,40 @@ public class EggTool {
* Egg * Egg
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void loadSerializedEggs(Env env) { public static void loadEggs(Env env) {
try { boolean errorfound = false;
FileInputStream eggsFile = new FileInputStream(Application.CLASSPATH + "eggs.ser"); if (JSON_FILE_FORMAT) {
ObjectInputStream eggsInputStream = new ObjectInputStream(eggsFile); String eggsString = FrogFileUtils.readFile(Application.CLASSPATH + "eggs.json", "utf-8");
env.eggs = (List<Egg>) eggsInputStream.readObject(); if (eggsString != null) {
System.out.println( List<JSONObject> jsonEggs = (List<JSONObject>) JSON.parse(eggsString);
"Loaded " + env.eggs.size() + " eggs from file '" + Application.CLASSPATH + "eggs.ser" + "'."); env.eggs = new ArrayList<Egg>();
eggsInputStream.close(); for (JSONObject json : jsonEggs) {
} catch (Exception e) { Egg egg = json.toJavaObject(Egg.class);
System.out.println("No eggs files ' " + Application.CLASSPATH + "eggs.ser" + "' found, created " env.eggs.add(egg);
+ env.EGG_QTY + " new eggs to do test."); }
env.eggs = new ArrayList<Egg>(); System.out.println(
for (int i = 0; i < env.EGG_QTY; i++) "Loaded " + env.eggs.size() + " eggs from file '" + Application.CLASSPATH + "eggs.json" + "'.");
env.eggs.add(Egg.createBrandNewEgg()); } else
} errorfound = true;
}
/** 类似loadSerializedEggs方法但是读取的是JSON格式以方便调试 */
@SuppressWarnings("unchecked")
public static void loadJsonEggs(Env env) {
String eggsString = FrogFileUtils.readFile(Application.CLASSPATH + "eggs.json", "utf-8");
if (eggsString != null) {
List<JSONObject> jsonEggs = (List<JSONObject>) JSON.parse(eggsString);
env.eggs = new ArrayList<Egg>();
for (JSONObject json : jsonEggs) {
Egg egg = json.toJavaObject(Egg.class);
env.eggs.add(egg);
}
System.out.println(
"Loaded " + env.eggs.size() + " eggs from file '" + Application.CLASSPATH + "eggs.json" + "'.");
} else { } else {
System.out.println("No eggs files ' " + Application.CLASSPATH + "eggs.json" + "' found, created " try {
+ env.EGG_QTY + " new eggs to do test."); FileInputStream eggsFile = new FileInputStream(Application.CLASSPATH + "eggs.ser");
ObjectInputStream eggsInputStream = new ObjectInputStream(eggsFile);
env.eggs = (List<Egg>) eggsInputStream.readObject();
System.out.println(
"Loaded " + env.eggs.size() + " eggs from file '" + Application.CLASSPATH + "eggs.ser" + "'.");
eggsInputStream.close();
} catch (Exception e) {
errorfound = true;
}
}
if (errorfound) {
System.out.println("No eggs files ' " + Application.CLASSPATH + " found, created " + env.EGG_QTY
+ " new eggs to do test.");
env.eggs = new ArrayList<Egg>(); env.eggs = new ArrayList<Egg>();
for (int i = 0; i < env.EGG_QTY; i++) for (int i = 0; i < env.EGG_QTY; i++)
env.eggs.add(Egg.createBrandNewEgg()); env.eggs.add(Egg.createBrandNewEgg());
} }
} }
} }

Loading…
Cancel
Save