diff --git a/README.md b/README.md index 44e95ca..86934b6 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,8 @@ Frog: 这是人工生命的主体,目前起名叫青蛙(Frog),其实叫什 * 移殖到超级电脑上,由人来同它交流,输入新的图形和汉字,纠正它说的错误的话 * 移殖到并行芯片硬件上 -## 目前进展和成绩 -2018.10.21 开始编码。 -2019.03.11 虚拟环境已建好,可以模拟低等生命的遗传、繁殖、变异、进化现象,但目前只能往一个方向运动,相当于一个最简单的单细胞生物,还不具备视觉能力,不具备主动找食能力。 +## 目前进展和成绩 +2019.03.11 虚拟环境已建好,可以模拟低等生命的遗传、繁殖、变异、进化现象,但目前只能往一个方向运动,相当于一个最简单的单细胞生物,还不具备视觉能力,不具备主动找食能力。 运行run.bat可以查看演示。Env.java中的几个重要参数说明: * SHOW_SPEED: 调整实验的速度(1~1000),值越小则越慢。 * EGG_QTY: 每次允许Frog下多少个蛋,每个蛋可以孵出4个青蛙。通常下蛋取值在10~1000之间。蛋保存着我们测试的结果。实验的最终目标就是获得一个蛋。 @@ -68,7 +67,8 @@ Frog: 这是人工生命的主体,目前起名叫青蛙(Frog),其实叫什 下面是这个测试的动画截图,有兴趣的可以试着自己运行一下: ![截图](https://gitee.com/drinkjava2/frog/raw/master/result.gif) 另外每步演示的结果(egg)会存盘在根目根目录下,名为egg.ser,可以删除这个文件以从头开始新的测试。目前万里长征刚踏上第一步,因为还没涉及脑模型的搭建。可以看到有些青蛙跑得飞快,这是自然选择的结果,因为跑在最前面的吃得多。以后会改正这个bug,要让最聪明的、会抢食的Frog胜出,而不是让跑得快的胜出。 -2019.03.21 添加了脑图,改进随机运动模式为Hungry区驱动。从脑图上可以直观地观察脑结构,方便调试。 +2019.03.21 添加了脑图,改进随机运动模式为Hungry区驱动。从脑图上可以直观地观察脑结构,方便调试。 +2019.04.01 改进脑图的显示bug, 每一次生成Frog时添加随机神经元,并简单实现"卵+精子->受精卵"算法,以促进种群多样性。 ## 版权 | License [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) 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 97fca1b..5320846 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/Frog.java +++ b/core/src/main/java/com/github/drinkjava2/frog/Frog.java @@ -29,8 +29,7 @@ import com.github.drinkjava2.frog.env.Application; import com.github.drinkjava2.frog.env.Env; /** - * Frog = brain + body(mouth, eye, leg), but now let's focus on brain, ignore - * body + * Frog = brain + body, but now let's only focus on brain, ignore body * * 为了简化模型,这个类里出现多个固定数值的编码,以后要改进成可以可以放在蛋里遗传进化的动态数值,先让生命延生是第一步,优化是以后的事 * @@ -39,6 +38,8 @@ import com.github.drinkjava2.frog.env.Env; */ public class Frog { + public CellGroup[] cellGroups; + /** brain cells */ public List cells = new ArrayList(); @@ -59,8 +60,7 @@ public class Frog { public int x; public int y; - public long energy = 10000; - public Egg egg; // 青蛙是从哪个egg孵出来的,如果青蛙生存下来,将用这个egg来下蛋 + public long energy = 10000; public boolean alive = true; // 设为false表示青蛙死掉了,将不参与任何计算,以节省时间 static final Random r = new Random(); @@ -76,12 +76,16 @@ public class Frog { public Frog(int x, int y, Egg egg) { this.x = x; this.y = y; - if (egg.cellgroups == null) - throw new IllegalArgumentException("Illegal egg cellgroups argument:" + egg.cellgroups); - for (int k = 0; k < egg.cellgroups.length; k++) { - CellGroup g = egg.cellgroups[k]; + if (egg.cellGroups == null) + throw new IllegalArgumentException("Illegal egg cellgroups argument:" + egg.cellGroups); + + cellGroups = new CellGroup[egg.cellGroups.length]; + for (int k = 0; k < egg.cellGroups.length; k++) { + CellGroup g = egg.cellGroups[k]; + cellGroups[k] = new CellGroup(g); for (int i = 0; i < g.cellQty; i++) {// 开始根据蛋来创建脑细胞 Cell c = new Cell(); + c.group = k; int cellQTY = Math.round(g.inputQtyPerCell); c.inputs = new Input[cellQTY]; for (int j = 0; j < cellQTY; j++) { @@ -100,8 +104,7 @@ public class Frog { } cells.add(c); } - } - this.egg = new Egg(egg);// 克隆一份蛋,如果没被淘汰掉,将来下蛋时要用这个蛋来下变异蛋 + } } private int goUp = 0; @@ -122,38 +125,40 @@ public class Frog { for (Cell cell : cells) { if (energy < 10000) // in hungry for (Input input : cell.inputs) { - if (input.nearby(hungry)) { - if (cell.energy < 100) { + if (input.nearby(hungry)) { + if (cell.energy < 100) cell.energy++; - egg.cellgroups[cell.group].activeTimes++; - } } } for (Output output : cell.outputs) { // hungry drive moves if (goUp < 1 && cell.energy > 10 && moveUp.nearby(output)) { + cellGroups[cell.group].fat++; goUp++; if (cell.energy > 0) cell.energy--; } if (goDown < 1 && cell.energy > 10 && moveDown.nearby(output)) { + cellGroups[cell.group].fat++; goDown++; if (cell.energy > 0) cell.energy--; } if (goLeft < 1 && cell.energy > 10 && moveLeft.nearby(output)) { + cellGroups[cell.group].fat++; goLeft++; if (cell.energy > 0) cell.energy--; } if (goRight < 1 && cell.energy > 10 && moveRight.nearby(output)) { + cellGroups[cell.group].fat++; goRight++; if (cell.energy > 0) cell.energy--; } } - moveAndEat(env); } + moveAndEat(env); return alive; } @@ -185,58 +190,11 @@ public class Frog { } } - private boolean allowVariation = false; - - private float percet1(float f) { - if (!allowVariation) - return f; - return (float) (f * (0.99f + r.nextFloat() * 0.02)); - } - - private static boolean percent70() { - return r.nextInt(10) > 2; - } - - private float percet2(float f) { - if (!allowVariation) - return f; - return (float) (f * (0.98f + r.nextFloat() * 0.04)); - } - private static Zone randomPosInZone(Zone z) { return new Zone(z.x - z.radius + z.radius * 2 * r.nextFloat(), z.y - z.radius + z.radius * 2 * r.nextFloat(), 0); } - public Egg layEgg() { - if (r.nextInt(100) > 25) // 变异率先固定在25% - allowVariation = false;// 如果不允许变异,下的蛋就相当于克隆原来的蛋 - else - allowVariation = true; - Egg newEgg = new Egg(); - - List gpList = new ArrayList<>(); - for (int i = 0; i < egg.cellgroups.length; i++) { - if (egg.cellgroups[i].activeTimes == 0 && percent70()) - // if (egg.cellgroups[i].activeTimes == 0) - continue;// 从未激活过的神经元有70%的概率被丢弃掉 - CellGroup cellGroup = new CellGroup(); - CellGroup oldGp = egg.cellgroups[i]; - cellGroup.groupInputZone = new Zone(percet2(oldGp.groupInputZone.x), percet2(oldGp.groupInputZone.y), - percet2(oldGp.groupInputZone.radius)); - cellGroup.groupOutputZone = new Zone(percet2(oldGp.groupOutputZone.x), percet2(oldGp.groupOutputZone.y), - percet2(oldGp.groupOutputZone.radius)); - cellGroup.cellQty = Math.round(percet2(oldGp.cellQty)); - cellGroup.cellInputRadius = percet1(oldGp.cellInputRadius); - cellGroup.cellOutputRadius = percet1(oldGp.cellOutputRadius); - cellGroup.inputQtyPerCell = Math.round(percet2(oldGp.inputQtyPerCell)); - cellGroup.outputQtyPerCell = Math.round(percet2(oldGp.outputQtyPerCell)); - gpList.add(cellGroup); - } - newEgg.cellgroups = gpList.toArray(new CellGroup[gpList.size()]); - return newEgg; - } - public void show(Graphics g) { if (!alive) return; diff --git a/core/src/main/java/com/github/drinkjava2/frog/egg/CellGroup.java b/core/src/main/java/com/github/drinkjava2/frog/egg/CellGroup.java index 9628861..2e57fef 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/egg/CellGroup.java +++ b/core/src/main/java/com/github/drinkjava2/frog/egg/CellGroup.java @@ -11,6 +11,7 @@ package com.github.drinkjava2.frog.egg; import java.io.Serializable; +import java.util.Random; /** * CellGroup represents a bunch of similar nerve cells
@@ -38,5 +39,38 @@ public class CellGroup implements Serializable { public float inputQtyPerCell; // input qty per cell public float outputQtyPerCell; // output qty per cell - public long activeTimes = 0; // if activate times=0 ,this cellgroup may be ignored in egg + public long fat = 0; // if activate times=0 ,this cellgroup may be ignored in egg + public boolean inherit = false; // set to true if is inherited from egg, not by random + + private static final Random r = new Random(); + + public CellGroup() { + + } + + public CellGroup(CellGroup g) {// clone old CellGroup + groupInputZone = new Zone(g.groupInputZone); + groupOutputZone = new Zone(g.groupOutputZone); + cellInputRadius = g.cellInputRadius; + cellOutputRadius = g.cellOutputRadius; + cellQty = g.cellQty; + inputQtyPerCell = g.inputQtyPerCell; + outputQtyPerCell = g.outputQtyPerCell; + fat = g.fat; + inherit = g.inherit; + } + + public CellGroup(int brainWidth, int randomCellQtyPerGroup, int randomInputQtyPerCell, int randomOutQtyPerCell) { + inherit = false; + groupInputZone = new Zone(r.nextFloat() * brainWidth, r.nextFloat() * brainWidth, + (float) (r.nextFloat() * brainWidth * .01)); + groupOutputZone = new Zone(r.nextFloat() * brainWidth, r.nextFloat() * brainWidth, + (float) (r.nextFloat() * brainWidth * .01)); + cellQty = 1 + r.nextInt(randomCellQtyPerGroup); + cellInputRadius = (float) (0.001 + r.nextFloat() * 2); + cellOutputRadius = (float) (0.001 + r.nextFloat() * 2); + inputQtyPerCell = 1 + r.nextInt(randomInputQtyPerCell); + outputQtyPerCell = 1 + r.nextInt(randomOutQtyPerCell); + } + } diff --git a/core/src/main/java/com/github/drinkjava2/frog/egg/Egg.java b/core/src/main/java/com/github/drinkjava2/frog/egg/Egg.java index 6b37ccc..026c274 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/egg/Egg.java +++ b/core/src/main/java/com/github/drinkjava2/frog/egg/Egg.java @@ -11,8 +11,12 @@ package com.github.drinkjava2.frog.egg; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import java.util.Random; +import com.github.drinkjava2.frog.Frog; + /** * Egg is the static structure description of frog, can save as text file, to * build a frog, first need build a egg.
@@ -24,45 +28,28 @@ import java.util.Random; public class Egg implements Serializable { private static final long serialVersionUID = 2L; public static final int BRAIN_WIDTH = 800; - public int randomCellGroupQty = 100; - public int randomCellQtyPerGroup = 5; - public int randomInputQtyPerCell = 10; - public int randomOutQtyPerCell = 5; - - - - public CellGroup[] cellgroups; - public int realCellGroupQty=0; //z + public int randomCellGroupQty = 100; // 随机生成多少个组 + public int randomCellQtyPerGroup = 3; // 每个组有多少个脑细胞 + public int randomInputQtyPerCell = 3;// 每个脑细胞有多少个输入触突 + public int randomOutQtyPerCell = 2; // 每个脑细胞有多少个输出触突 + + public CellGroup[] cellGroups; public Egg() { // default constructor } private static Random r = new Random(); - - public Egg(Egg e) {// clone the old egg - cellgroups = new CellGroup[e.cellgroups.length]; - for (int i = 0; i < e.cellgroups.length; i++) { - CellGroup oldCellGroup = e.cellgroups[i]; - CellGroup cellGroup = new CellGroup(); - cellgroups[i] = cellGroup; - cellGroup.groupInputZone = new Zone(oldCellGroup.groupInputZone); - cellGroup.groupOutputZone = new Zone(oldCellGroup.groupOutputZone); - cellGroup.cellQty = oldCellGroup.cellQty; - cellGroup.cellInputRadius = oldCellGroup.cellInputRadius; - cellGroup.cellOutputRadius = oldCellGroup.cellOutputRadius; - cellGroup.inputQtyPerCell = oldCellGroup.inputQtyPerCell; - cellGroup.outputQtyPerCell = oldCellGroup.outputQtyPerCell; - } - realCellGroupQty=e.realCellGroupQty; - } + // 我靠,两个蛋怎么合成一个蛋?看来要模拟XY染色体了,不能做加法,会撑暴内存的,但现在,每次只随机加一个 public Egg(Egg x, Egg y) { // use 2 eggs to create a zygote - cellgroups = new CellGroup[x.cellgroups.length + y.cellgroups.length+ randomCellGroupQty/5]; - for (int i = 0; i < x.cellgroups.length; i++) { - CellGroup oldCellGroup = x.cellgroups[i]; + // x里原来的CellGroup + cellGroups = new CellGroup[x.cellGroups.length + 1 + randomCellGroupQty / 3]; + for (int i = 0; i < x.cellGroups.length; i++) { + CellGroup oldCellGroup = x.cellGroups[i]; CellGroup cellGroup = new CellGroup(); - cellgroups[i] = cellGroup; + cellGroups[i] = cellGroup; + cellGroup.inherit = true; cellGroup.groupInputZone = new Zone(oldCellGroup.groupInputZone); cellGroup.groupOutputZone = new Zone(oldCellGroup.groupOutputZone); cellGroup.cellQty = oldCellGroup.cellQty; @@ -71,55 +58,70 @@ public class Egg implements Serializable { cellGroup.inputQtyPerCell = oldCellGroup.inputQtyPerCell; cellGroup.outputQtyPerCell = oldCellGroup.outputQtyPerCell; } - int xLength = x.cellgroups.length; - for (int i = 0; i < y.cellgroups.length; i++) { - CellGroup oldCellGroup = y.cellgroups[i]; - CellGroup cellGroup = new CellGroup(); - cellgroups[xLength + i] = cellGroup; - cellGroup.groupInputZone = new Zone(oldCellGroup.groupInputZone); - cellGroup.groupOutputZone = new Zone(oldCellGroup.groupOutputZone); - cellGroup.cellQty = oldCellGroup.cellQty; - cellGroup.cellInputRadius = oldCellGroup.cellInputRadius; - cellGroup.cellOutputRadius = oldCellGroup.cellOutputRadius; - cellGroup.inputQtyPerCell = oldCellGroup.inputQtyPerCell; - cellGroup.outputQtyPerCell = oldCellGroup.outputQtyPerCell; - } - int yLength=y.cellgroups.length; - realCellGroupQty=xLength+yLength; - for (int i = 0; i < randomCellGroupQty/5; i++) { - CellGroup cellGroup = new CellGroup(); - cellgroups[i+xLength+yLength] = cellGroup; - cellGroup.groupInputZone = new Zone(r.nextFloat() * BRAIN_WIDTH, r.nextFloat() * BRAIN_WIDTH, - (float) (r.nextFloat() * BRAIN_WIDTH * .01)); - cellGroup.groupOutputZone = new Zone(r.nextFloat() * BRAIN_WIDTH, r.nextFloat() * BRAIN_WIDTH, - (float) (r.nextFloat() * BRAIN_WIDTH * .01)); - cellGroup.cellQty = r.nextInt(x.randomCellQtyPerGroup); - cellGroup.cellInputRadius = (float) (r.nextFloat() * 0.001); - cellGroup.cellOutputRadius = (float) (r.nextFloat() * 0.001); - cellGroup.inputQtyPerCell = r.nextInt(x.randomInputQtyPerCell); - cellGroup.outputQtyPerCell = r.nextInt(x.randomOutQtyPerCell); - } - + + // 从y里借一个CellGroup + CellGroup randomY = y.cellGroups[r.nextInt(y.cellGroups.length)]; + CellGroup cellGroup = new CellGroup(randomY); + cellGroups[x.cellGroups.length ] = cellGroup; + + //随机生成一批CellGroup + for (int i = 0; i < randomCellGroupQty / 3; i++) + cellGroups[i + x.cellGroups.length + 1] = new CellGroup(Egg.BRAIN_WIDTH, x.randomCellQtyPerGroup, + x.randomInputQtyPerCell, x.randomOutQtyPerCell); } public static Egg createBrandNewEgg() { // create a brand new Egg - Egg egg = new Egg(); - egg.cellgroups = new CellGroup[egg.randomCellGroupQty]; - for (int i = 0; i < egg.randomCellGroupQty; i++) { + Egg egg = new Egg(); + egg.cellGroups = new CellGroup[egg.randomCellGroupQty]; + for (int i = 0; i < egg.randomCellGroupQty; i++) + egg.cellGroups[i] = new CellGroup(Egg.BRAIN_WIDTH, egg.randomCellQtyPerGroup, egg.randomInputQtyPerCell, + egg.randomOutQtyPerCell); + return egg; + } + + private static boolean allowVariation = false; + + private static float percet1(float f) { + if (!allowVariation) + return f; + return (float) (f * (0.99f + r.nextFloat() * 0.02)); + } + + private static boolean percent(int percent) { + return r.nextInt(100) < percent; + } + + private static float percet2(float f) { + if (!allowVariation) + return f; + return (float) (f * (0.98f + r.nextFloat() * 0.04)); + } + + public Egg(Frog frog, boolean allowVariate) { // create a brand new Egg + allowVariation = allowVariate; + List gpList = new ArrayList<>(); + for (int i = 0; i < frog.cellGroups.length; i++) { + if (frog.cellGroups[i].fat <= 0) { + if (! frog.cellGroups[i].inherit) + continue;// 从未激活过的神经元,并且就是本轮随机生成的,丢弃之 + if (percent(10)) + continue;// 继承下来的神经元,但是本轮并没用到, 扔掉又可惜,可以小概率丢掉 + } CellGroup cellGroup = new CellGroup(); - egg.cellgroups[i] = cellGroup; - cellGroup.groupInputZone = new Zone(r.nextFloat() * BRAIN_WIDTH, r.nextFloat() * BRAIN_WIDTH, - (float) (r.nextFloat() * BRAIN_WIDTH * .01)); - cellGroup.groupOutputZone = new Zone(r.nextFloat() * BRAIN_WIDTH, r.nextFloat() * BRAIN_WIDTH, - (float) (r.nextFloat() * BRAIN_WIDTH * .01)); - cellGroup.cellQty = r.nextInt(egg.randomCellQtyPerGroup); - cellGroup.cellInputRadius = (float) (r.nextFloat() * 0.001); - cellGroup.cellOutputRadius = (float) (r.nextFloat() * 0.001); - cellGroup.inputQtyPerCell = r.nextInt(egg.randomInputQtyPerCell); - cellGroup.outputQtyPerCell = r.nextInt(egg.randomOutQtyPerCell); + CellGroup oldGp = frog.cellGroups[i]; + cellGroup.groupInputZone = new Zone(percet2(oldGp.groupInputZone.x), percet2(oldGp.groupInputZone.y), + percet2(oldGp.groupInputZone.radius)); + cellGroup.groupOutputZone = new Zone(percet2(oldGp.groupOutputZone.x), percet2(oldGp.groupOutputZone.y), + percet2(oldGp.groupOutputZone.radius)); + cellGroup.cellQty = Math.round(percet2(oldGp.cellQty)); + cellGroup.cellInputRadius = percet1(oldGp.cellInputRadius); + cellGroup.cellOutputRadius = percet1(oldGp.cellOutputRadius); + cellGroup.inputQtyPerCell = Math.round(percet2(oldGp.inputQtyPerCell)); + cellGroup.outputQtyPerCell = Math.round(percet2(oldGp.outputQtyPerCell)); + cellGroup.inherit = true; + gpList.add(cellGroup); } - egg.realCellGroupQty=egg.cellgroups.length; - return egg; + cellGroups = gpList.toArray(new CellGroup[gpList.size()]); } } diff --git a/core/src/main/java/com/github/drinkjava2/frog/env/Application.java b/core/src/main/java/com/github/drinkjava2/frog/env/Application.java index d022802..c1f0a56 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/env/Application.java +++ b/core/src/main/java/com/github/drinkjava2/frog/env/Application.java @@ -29,7 +29,7 @@ public class Application { if (SHOW_FIRST_FROG_BRAIN) mainFrame.setSize(1320, 840); // 窗口大小 else - mainFrame.setSize(550, 550); // 窗口大小 + mainFrame.setSize(550, 570); // 窗口大小 mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭时退出程序 mainFrame.add(env); @@ -48,14 +48,31 @@ public class Application { mainFrame.setSize(1320, 840); } else { button.setText("Show first frog's brain"); - mainFrame.setSize(550, 550); + mainFrame.setSize(550, 570); } } }; button.addActionListener(al); - mainFrame.add(button); + JButton stopButton = new JButton("Pause"); + stopButton.setVisible(true); + stopButton.setLayout(null);// 空布局 + stopButton.setBounds(150, 490, 180, 30); + ActionListener a2 = new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + Env.pause = !Env.pause; + if (Env.pause) { + stopButton.setText("Resume"); + } else { + stopButton.setText("Pause"); + } + } + }; + stopButton.addActionListener(a2); + mainFrame.add(stopButton); + mainFrame.setVisible(true); env.run(); diff --git a/core/src/main/java/com/github/drinkjava2/frog/env/BrainStructure.java b/core/src/main/java/com/github/drinkjava2/frog/env/BrainStructure.java index 48c0792..3965b9a 100644 --- a/core/src/main/java/com/github/drinkjava2/frog/env/BrainStructure.java +++ b/core/src/main/java/com/github/drinkjava2/frog/env/BrainStructure.java @@ -27,13 +27,17 @@ public class BrainStructure extends JPanel { g.drawRect(round(z.x - z.radius), round(z.y - z.radius), round(z.radius * 2), round(z.radius * 2)); } + void drawZoneCircle(Graphics g, Zone z) { + g.drawArc(round(z.x - 8), round(z.y - 8), 16, 16, 0, 360); + } + void fillZone(Graphics g, Zone z) { g.fillRect(round(z.x - z.radius), round(z.y - z.radius), round(z.radius * 2), round(z.radius * 2)); } private static Color color(float i) { if (i <= 1) - return Color.GRAY; + return Color.RED; if (i <= 3) return Color.ORANGE; if (i <= 10) @@ -50,36 +54,41 @@ public class BrainStructure extends JPanel { public void drawBrain(Frog frog) { if (!Application.SHOW_FIRST_FROG_BRAIN) return; - Graphics g = this.getGraphics(); + Graphics g = this.getGraphics();// border g.setColor(Color.WHITE); g.fillRect(0, 0, 800, 800); g.setColor(Color.black); g.drawRect(0, 0, 800, 800); g.setColor(Color.red); - drawZone(g, frog.eye); + drawZone(g, frog.eye); // eye g.setColor(Color.green); - drawZone(g, frog.happy); + drawZone(g, frog.happy); // happy g.setColor(Color.yellow); - drawZone(g, frog.hungry); + drawZone(g, frog.hungry); // hungry g.setColor(Color.gray); - drawZone(g, frog.moveUp); + drawZone(g, frog.moveUp); // moves drawZone(g, frog.moveDown); drawZone(g, frog.moveLeft); drawZone(g, frog.moveRight); - g.setColor(Color.black); - - for (int j = 0; j < frog.egg.realCellGroupQty; j++) { - CellGroup group = frog.egg.cellgroups[j]; - g.setColor(color(group.cellQty));// 取随机色 + for (CellGroup group : frog.cellGroups) { + if (!group.inherit) + g.setColor(Color.lightGray); // 如果是本轮随机生成的,灰色表示 + else + g.setColor(color(group.cellQty)); // 如果是继承的,彩虹色表示,颜色数越往后表示数量越多 g.drawLine(round(group.groupInputZone.x), round(group.groupInputZone.y), round(group.groupOutputZone.x), round(group.groupOutputZone.y)); drawZone(g, group.groupInputZone); + fillZone(g, group.groupOutputZone); + if (group.fat > 0) { + g.setColor(Color.BLACK); + drawZoneCircle(g, group.groupOutputZone); // 如果胖了,表示激活过了,下次下蛋少不了这一组 + } } } 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 596555e..1870986 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 @@ -32,6 +32,8 @@ public class Env extends JPanel { EggTool.deleteEggs(); } + public static boolean pause = false; + private static final Random r = new Random(); /** Virtual environment x size is 500 pixels */ @@ -42,7 +44,7 @@ public class Env extends JPanel { public byte[][] foods = new byte[ENV_XSIZE][ENV_YSIZE]; - public int FOOD_QTY =800; // as name + public int FOOD_QTY = 1800; // as name public int EGG_QTY = 50; // as name @@ -87,6 +89,15 @@ public class Env extends JPanel { } } + private static void sleep() { + try { + Thread.sleep(300); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + public void run() throws InterruptedException { EggTool.loadEggs(this); // 从磁盘加载egg,或新建一批egg int round = 1; @@ -94,6 +105,10 @@ public class Env extends JPanel { Graphics g = buffImg.getGraphics(); long t1, t2; do { + if (pause) { + sleep(); + continue; + } t1 = System.currentTimeMillis(); rebuildFrogAndFood(); boolean allDead = false; @@ -119,10 +134,12 @@ public class Env extends JPanel { Graphics g2 = this.getGraphics(); g2.drawImage(buffImg, 0, 0, this); } + EggTool.layEggs(this); Application.brainStructure.drawBrain(frogs.get(0)); t2 = System.currentTimeMillis(); - Application.mainFrame.setTitle("Frog test round: " + round++ + ", time used: " + (t2 - t1) + " ms"); + Application.mainFrame.setTitle("Frog test round: " + round++ + ", time used: " + (t2 - t1) + " ms, x=" + + frogs.get(0).x + ", y=" + frogs.get(0).y); } while (true); } } 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 4aa1949..66b1ba3 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 @@ -40,14 +40,15 @@ public class EggTool { */ public static void layEggs(Env env) { sortFrogsOrderByEnergyDesc(env); - System.out.print("First frog has " + env.frogs.get(0).egg.cellgroups.length + " cellgroups, energy=" + System.out.print("First frog has " + env.frogs.get(0).cellGroups.length + " cellgroups, energy=" + env.frogs.get(0).energy); System.out.print(", Last frog energy=" + env.frogs.get(env.frogs.size() - 1).energy + ", "); try { List newEggs = new ArrayList(); for (int i = 0; i < env.EGG_QTY; i++) - newEggs.add(env.frogs.get(i).layEgg()); - + newEggs.add( new Egg(env.frogs.get(i), true)); + System.out.print(", EggCellGroups="+newEggs.get(0).cellGroups.length); + if (JSON_FILE_FORMAT) { String newEggsString = JSON.toJSONString(newEggs); FrogFileUtils.writeFile(Application.CLASSPATH + "eggs.json", newEggsString, "utf-8"); @@ -59,7 +60,7 @@ public class EggTool { } env.eggs = newEggs; 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" + "'"); } catch (IOException e) { System.out.println(e); } diff --git a/20190311.gif b/result.gif similarity index 100% rename from 20190311.gif rename to result.gif diff --git a/版本提交记录.md b/版本提交记录.md index 71691fc..fc82cea 100644 --- a/版本提交记录.md +++ b/版本提交记录.md @@ -18,8 +18,10 @@ 在脑区添加Hungry,删除随机运动的硬编码,改成由Hungry区来驱动,一旦frog能量小于10000,hungry区的所有脑神经元的input区激活,如果这些神经元的输出区位于move区,则作相应的移动。这是一个更随机一点的运动,不再总是固定向一个方向。 ### 2019-03-27, 1.0.3版, Commit:Shrink & Sperm -添加了"蛋+精子->受精蛋"的模拟,这是为了实现生物多样性。添加了每次添加一批随机神经元,但是只保留激活过的,如果某组神经元从没被用到(激活过),则有很大的可能不会将这组神经元添加到蛋中(用进废退规则)。 +添加了"卵+精子->受精卵"的模拟,这是为了实现生物多样性。添加了每次添加一批随机神经元,但是只保留激活过的,如果某组神经元从没被用到(激活过),则有很大的可能不会将这组神经元添加到蛋中(用进废退规则)。 ### 2019-03-29, Commit:Rainbow 更正一个小Bug,BrainStructure的zone显示的半径是实际的一半,用彩虹色而不是随机数来表示CellGroup的细胞数量,色彩越靠后表示细胞数越多。 +### 2019-04-01, Commit:Cleanup +做一些debug清理,每个Frog不再保留egg的副本,“卵+精子->受精卵”算法改进一下,不能简单两两相加,而是随机取一个精子的cellgroup。