diff --git a/core/maven_clean.bat b/core/maven_clean.bat new file mode 100644 index 0000000..2f3d3e5 --- /dev/null +++ b/core/maven_clean.bat @@ -0,0 +1 @@ +mvn clean \ No newline at end of file diff --git a/core/maven_eclipse_clean.bat b/core/maven_eclipse_clean.bat new file mode 100644 index 0000000..a427bd7 --- /dev/null +++ b/core/maven_eclipse_clean.bat @@ -0,0 +1 @@ +mvn eclipse:clean \ No newline at end of file diff --git a/core/maven_eclipse_eclipse.bat b/core/maven_eclipse_eclipse.bat new file mode 100644 index 0000000..99fa0b2 --- /dev/null +++ b/core/maven_eclipse_eclipse.bat @@ -0,0 +1,2 @@ +call mvn eclipse:eclipse +call pause \ No newline at end of file diff --git a/core/src/main/java/com/github/drinkjava2/frog/Frog.java b/core/src/main/java/com/github/drinkjava2/frog/Frog.java index ecfaa8a..708a9a6 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/Frog.java +++ b/core/src/main/java/com/github/drinkjava2/frog/Frog.java @@ -27,10 +27,12 @@ import com.github.drinkjava2.frog.egg.Egg; import com.github.drinkjava2.frog.egg.Zone; import com.github.drinkjava2.frog.env.Application; 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 * @since 1.0.0 @@ -47,15 +49,18 @@ public class Frog { public static Zone eye = new Zone(0, 0, 300); /** 运动细胞的输入区在脑中的坐标,先随便取就可以了,以后再考虑放到蛋里去进化 */ - public static Zone moveUp = new Zone(500, 100, 10); - public static Zone moveDown = new Zone(500, 200, 10); - public static Zone moveLeft = new Zone(500, 300, 10); - public static Zone moveRight = new Zone(500, 400, 10); + public static Zone moveUp = new Zone(500, 50, 10); + public static Zone moveDown = new Zone(500, 100, 10); + public static Zone moveLeft = new Zone(500, 150, 10); + public static Zone moveRight = new Zone(500, 200, 10); + public static Zone moveRandom = new Zone(500, 300, 10); public int x; public int y; public long energy = 10000; 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 Image frogImg; @@ -80,12 +85,14 @@ public class Frog { c.inputs = new Input[g.inputQtyPerCell]; for (int j = 0; j < g.inputQtyPerCell; j++) { c.inputs[j] = new Input(); + c.inputs[j].cell = c; Zone.copyXY(randomPosInZone(g.groupInputZone), c.inputs[j]); c.inputs[j].radius = g.cellInputRadius; } c.outputs = new Output[g.outputQtyPerCell]; for (int j = 0; j < g.outputQtyPerCell; j++) { c.outputs[j] = new Output(); + c.outputs[j].cell = c; Zone.copyXY(randomPosInZone(g.groupInputZone), c.outputs[j]); c.outputs[j].radius = g.cellOutputRadius; } @@ -95,45 +102,95 @@ public class Frog { this.egg = egg;// 保留一份蛋,如果没被淘汰掉,将来下蛋时要用这个蛋来下新蛋 } - public void active(Env env) { -// this.x = this.x - 1 + r.nextInt(3); -// this.y = this.y - 1 + r.nextInt(3); - // eat food + /** Active a frog, if frog is dead return false */ + public boolean active(Env env) { + if (!alive) + 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; - int j = env.foods.size() - 1; - for (int i = j; i >= 0; i--) { - Food food = env.foods.get(i); - if (x == food.x && y == food.y) { - energy = energy + food.energy; - env.foods.remove(i); + if (x >= 0 && x < env.ENV_XSIZE && y > 0 && y < env.ENV_YSIZE) + if (env.foods[x][y] > 0) { + env.foods[x][y] = 0; + energy = energy + 1000;// 吃掉food,能量境加 eatedFood = true; - break; } - } // 奖励 if (eatedFood) { } + } - // move - for (Cell cell : cells) { - for (Output output : cell.outputs) { - if (Zone.nearby(moveUp, output)) { - y += 1; - break; - } else if (Zone.nearby(moveDown, output)) { - y -= 1; - break; - } else if (Zone.nearby(moveLeft, output)) { - x -= 1; - break; - } else if (Zone.nearby(moveRight, output)) { - x += 1; - break; - } - } + private void moveRandom(Env env) { + int ran = r.nextInt(4); + if (ran == 0) + moveUp(env); + if (ran == 1) + moveDown(env); + if (ran == 2) + moveLeft(env); + if (ran == 3) + moveRight(env); + } + + private void moveUp(Env env) { + y += 1; + 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; @@ -182,6 +239,8 @@ public class Frog { } public void show(Graphics g) { + if (!alive) + return; g.drawImage(frogImg, x - 8, y - 8, 16, 16, null); } diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/Cell.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Cell.java index 0197dfc..f97eb2d 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/Cell.java +++ b/core/src/main/java/com/github/drinkjava2/frog/brain/Cell.java @@ -20,15 +20,12 @@ public class Cell { public int group; // this cell belong to which group? 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 boolean used = false; + public void activate() { - used = true; for (Input xy : inputs) { } } - - - + } diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/Input.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Input.java index 29944ac..984acf2 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/Input.java +++ b/core/src/main/java/com/github/drinkjava2/frog/brain/Input.java @@ -20,4 +20,5 @@ import com.github.drinkjava2.frog.egg.Zone; */ public class Input extends Zone{ public float energy; + public Cell cell; } diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/Output.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Output.java index 0766777..f28d8e4 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/brain/Output.java +++ b/core/src/main/java/com/github/drinkjava2/frog/brain/Output.java @@ -20,4 +20,5 @@ import com.github.drinkjava2.frog.egg.Zone; */ public class Output extends Zone { public float energy; + public Cell cell; } diff --git a/core/src/main/java/com/github/drinkjava2/frog/egg/Zone.java b/core/src/main/java/com/github/drinkjava2/frog/egg/Zone.java index 87be952..848059a 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/egg/Zone.java +++ b/core/src/main/java/com/github/drinkjava2/frog/egg/Zone.java @@ -34,13 +34,21 @@ public class Zone implements Serializable { this.radius = radius; } - public static boolean nearby(Zone z1, Zone z2) { - float dist = z1.radius + z2.radius; - if (Math.abs(z1.x - z2.x) < dist && Math.abs(z1.y - z2.y) < dist) + public boolean nearby(Zone z) { + float dist = radius + z.radius; + if (Math.abs(x - z.x) < dist && Math.abs(y - z.y) < dist) return true; return false; } + public int roundX() { + return Math.round(x); + } + + public int roundY() { + return Math.round(y); + } + public static void copyXY(Zone from, Zone to) { to.x = from.x; to.y = from.y; diff --git a/core/src/main/java/com/github/drinkjava2/frog/env/Env.java b/core/src/main/java/com/github/drinkjava2/frog/env/Env.java index 299aeb6..a3c0bfb 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/env/Env.java +++ b/core/src/main/java/com/github/drinkjava2/frog/env/Env.java @@ -1,5 +1,6 @@ package com.github.drinkjava2.frog.env; +import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.util.ArrayList; @@ -18,10 +19,10 @@ import com.github.drinkjava2.frog.util.EggTool; @SuppressWarnings("serial") public class Env extends JPanel { /** Speed of test */ - public static int SHOW_SPEED = 10; + public static int SHOW_SPEED =1; /** 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 */ public int ENV_XSIZE = 300; @@ -29,12 +30,13 @@ public class Env extends JPanel { /** Virtual environment y size is 500 pixels */ 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 frogs = new ArrayList(); - public List foods = new ArrayList(); public List eggs; public Env() { @@ -45,40 +47,68 @@ public class Env extends JPanel { private void rebuildFrogAndFood() { 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(); 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))); - 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))); - 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(ENV_XSIZE / 2 + rand.nextInt(90), ENV_YSIZE / 2 + rand.nextInt(90), eggs.get(i))); + } } + System.out.println("Created "+4*eggs.size() +" frogs"); 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 { EggTool.loadEggs(this); // 从磁盘加载egg,或新建一批egg int round = 1; + Image buffImg = createImage(this.getWidth(), this.getHeight()); + Graphics g = buffImg.getGraphics(); + long t1, t2; do { - Application.mainFrame.setTitle("Frog test round: " + round++); + t1 = System.currentTimeMillis(); rebuildFrogAndFood(); + boolean allDead = false; for (int i = 0; i < STEPS_PER_ROUND; i++) { - for (Frog frog : frogs) - frog.active(this); - if (i % SHOW_SPEED != 0) // 显示会拖慢速度 + if (allDead) + break; + 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; - 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) frog.show(g); - for (Food food : foods) - food.show(g); + + drawFood(g); Graphics g2 = this.getGraphics(); g2.drawImage(buffImg, 0, 0, this); Thread.sleep(10); } EggTool.layEggs(this); + t2 = System.currentTimeMillis(); + Application.mainFrame.setTitle("Frog test round: " + round++ + ", time used: " + (t2 - t1) + " ms"); } while (true); } } diff --git a/core/src/main/java/com/github/drinkjava2/frog/env/Food.java b/core/src/main/java/com/github/drinkjava2/frog/env/Food.java deleted file mode 100644 index fd51dcc..0000000 --- a/core/src/main/java/com/github/drinkjava2/frog/env/Food.java +++ /dev/null @@ -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); - } -} diff --git a/core/src/main/java/com/github/drinkjava2/frog/util/EggTool.java b/core/src/main/java/com/github/drinkjava2/frog/util/EggTool.java index 65c6881..00f0a95 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/util/EggTool.java +++ b/core/src/main/java/com/github/drinkjava2/frog/util/EggTool.java @@ -35,35 +35,31 @@ public class EggTool { 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被淘汰,没有下蛋的资格。 */ - public static void laySerializedEggs(Env env) { + public static void layEggs(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 + ", "); + for (Frog frog : env.frogs) { + System.out.print(frog.energy + ","); + } + System.out.println(); try { List newEggs = new ArrayList(); - 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()); - FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs.ser"); - ObjectOutputStream so = new ObjectOutputStream(fo); - so.writeObject(newEggs); - so.close(); + + if (JSON_FILE_FORMAT) { + String newEggsString = JSON.toJSONString(newEggs); + 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; System.out .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 newEggs = new ArrayList(); - 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) { Collections.sort(env.frogs, new Comparator() { public int compare(Frog a, Frog b) { @@ -103,44 +85,40 @@ public class EggTool { * 从磁盘读入一批Egg */ @SuppressWarnings("unchecked") - public static void loadSerializedEggs(Env env) { - try { - FileInputStream eggsFile = new FileInputStream(Application.CLASSPATH + "eggs.ser"); - ObjectInputStream eggsInputStream = new ObjectInputStream(eggsFile); - env.eggs = (List) eggsInputStream.readObject(); - System.out.println( - "Loaded " + env.eggs.size() + " eggs from file '" + Application.CLASSPATH + "eggs.ser" + "'."); - eggsInputStream.close(); - } catch (Exception e) { - System.out.println("No eggs files ' " + Application.CLASSPATH + "eggs.ser" + "' found, created " - + env.EGG_QTY + " new eggs to do test."); - env.eggs = new ArrayList(); - for (int i = 0; i < env.EGG_QTY; i++) - env.eggs.add(Egg.createBrandNewEgg()); - } - } - - /** 类似loadSerializedEggs方法,但是读取的是JSON格式,以方便调试 */ - @SuppressWarnings("unchecked") - public static void loadJsonEggs(Env env) { - String eggsString = FrogFileUtils.readFile(Application.CLASSPATH + "eggs.json", "utf-8"); - if (eggsString != null) { - List jsonEggs = (List) JSON.parse(eggsString); - env.eggs = new ArrayList(); - 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" + "'."); + public static void loadEggs(Env env) { + boolean errorfound = false; + if (JSON_FILE_FORMAT) { + String eggsString = FrogFileUtils.readFile(Application.CLASSPATH + "eggs.json", "utf-8"); + if (eggsString != null) { + List jsonEggs = (List) JSON.parse(eggsString); + env.eggs = new ArrayList(); + 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 + errorfound = true; } else { - System.out.println("No eggs files ' " + Application.CLASSPATH + "eggs.json" + "' found, created " - + env.EGG_QTY + " new eggs to do test."); + try { + FileInputStream eggsFile = new FileInputStream(Application.CLASSPATH + "eggs.ser"); + ObjectInputStream eggsInputStream = new ObjectInputStream(eggsFile); + env.eggs = (List) 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(); for (int i = 0; i < env.EGG_QTY; i++) env.eggs.add(Egg.createBrandNewEgg()); } - } }