diff --git a/README.md b/README.md index 4066f40..9ec92fc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Frog | 人工生命 +## Frog | 人工生命 这是一个人工生命试验项目,最终目标是创建“有自我意识表现”的模拟生命体,技术架构基于02年提出的 [一个人工脑模型](一个人工脑模型.md)。 这个项目永远没有结束的时候,开始于模拟一个简单的生命体,然后是青蛙、狗......, 结束于有“自我意识表现”的人工脑,或者说,结束于被机器人代替人类的那一天。 @@ -82,7 +82,7 @@ Frog: 这是人工生命的主体,目前起名叫青蛙(Frog),其实叫什 git reset --hard ae34b07e 可以转回到上一个分组测试的找食版本。 2019-09-09 开始3D脑的构建,任务又回到原点:找食,从静止的青蛙要能进化到吃光所有食物。目前只是搭建空的3D框架,还未涉及3D脑模型编程。新的工作存放在core3d目录,原有的旧core目录保留,相应地批处理文件也分为普通版run.bat和3d版run3d.bat,蛋文件也分为普通版eggs.ser和3d版eggs3d.ser。 脑的3D版要引入模式识别功能,第一个编程任务是要用这个3D脑模拟出体全息存贮现象,也就等价于模式识别功能,用字母的点阵图像激活它的视觉区,并同时激活一个随意指定的脑区作为字母识别区,然后只激活视觉区的图像,再检查这个随意指定的字母区是否会被激活,而其它字母区基本不激活,例如同时训练字母A、B、C、D一段时间,然后只激活字母A的图像区(即在视网膜区产生光子),其它三个BCD字母区应该没有A字母区活跃(即其它字母区收到的光子数或总能量少于A字母区),这是从从二维图像识别出对应的文字,比较好检测并利用检测结果来进行生存竟争,从大量随机生成的脑细胞播种器官中挑选出有用的器官,注意在同一个脑空间(cube),可以同时存在多个不同器官播种出来的脑细胞(cell)。体全息存贮在物理上很难实现,因为光和材料受物理特性制约,但在虚拟脑中不存在这个物理限制,让虚拟的光子反射、拐弯、增强、拆分都可轻易模拟出。 -反之,如果对应A字母的脑区兴奋,也要能激活一个模糊的A的像素点阵图像脑内某个区(与视网膜重合或下层),这不好检测,但可以变通一下,比如同时训练C和O两个字母,然后只激活C字母区,并检测O字母区是否有较强的信号,也就是说C字母区会在脑内成像区生成一个C的像素点阵,然后这个像素点阵又会倒过来激活与C图像相似的O字母区(以及所有类似C图像的其它脑区),这是第二步的编程任务,它反映了脑的联想机制。如果说第一步是信息的存贮,是体全息存贮原理的简单实现,这第二步就是信息的检索和联想,相比与普通的体全息存贮,它多了一个联想功能,这个联想功能以后会用到,由痛苦、愉快等奖惩机制来调节这个联想过程一直永无止歇地进行下去。 +反之,如果对应A字母的脑区兴奋,也要能激活一个模糊的A的像素点阵图像脑内某个区(与视网膜重合或下层),这不好检测,但可以变通一下,比如同时训练C和O两个字母,然后只激活C字母区,并检测O字母区是否有较强的信号,也就是说C字母区会在脑内成像区生成一个C的像素点阵,然后这个像素点阵又会倒过来激活与C图像相似的O字母区(以及所有类似C图像的其它脑区),这是第二步的编程任务,它反映了脑的联想机制。如果说第一步是信息的存贮,是体全息存贮原理的简单实现,这第二步就是信息的检索和联想,相比与普通的体全息存贮,它多了一个联想功能,这个联想功能以后会用到,由痛苦、愉快等奖惩机制来调节这个联想过程一直永无止歇地进行下去。 ## 重要参数 | Parameters 在Env.java类中以下有以下可调整参数,请手工修改这些参数进行不同的测试,前5个参数很重要: diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/Application.java b/core3d/src/main/java/com/github/drinkjava2/frog/Application.java index e27fb30..ade67cf 100644 --- a/core3d/src/main/java/com/github/drinkjava2/frog/Application.java +++ b/core3d/src/main/java/com/github/drinkjava2/frog/Application.java @@ -16,8 +16,7 @@ import com.github.drinkjava2.frog.brain.BrainPicture; * @since 1.0 */ public class Application { - /** SHOW first frog's brain structure */ - public static boolean SHOW_FIRST_FROG_BRAIN = false; + public static final String CLASSPATH; static { @@ -30,6 +29,19 @@ public class Application { public static BrainPicture brainPic = new BrainPicture(Env.ENV_WIDTH + 5, 0, Env.FROG_BRAIN_XSIZE, Env.FROG_BRAIN_DISP_WIDTH); + static private void checkIfShowBrainPicture(JButton button) { + if (Env.SHOW_FIRST_FROG_BRAIN) { + button.setText("Hide brain"); + int y = Env.ENV_HEIGHT + 100; + if (Env.FROG_BRAIN_DISP_WIDTH + 41 > y) + y = Env.FROG_BRAIN_DISP_WIDTH + 41; + mainFrame.setSize(Env.ENV_WIDTH + Env.FROG_BRAIN_DISP_WIDTH + 25, y); + } else { + button.setText("Show brain"); + mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 100); + } + } + public static void main(String[] args) throws InterruptedException { mainFrame.setLayout(null); mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 100); // 窗口大小 @@ -39,26 +51,20 @@ public class Application { mainFrame.add(brainPic); JButton button = new JButton("Show brain"); - int buttonWidth =100; + int buttonWidth = 100; int buttonHeight = 22; int buttonXpos = Env.ENV_WIDTH / 2 - buttonWidth / 2; button.setBounds(buttonXpos, Env.ENV_HEIGHT + 8, buttonWidth, buttonHeight); + ActionListener al = new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { - SHOW_FIRST_FROG_BRAIN = !SHOW_FIRST_FROG_BRAIN; - if (SHOW_FIRST_FROG_BRAIN) { - button.setText("Hide brain"); - int y = Env.ENV_HEIGHT + 100; - if (Env.FROG_BRAIN_DISP_WIDTH + 41 > y) - y = Env.FROG_BRAIN_DISP_WIDTH + 41; - mainFrame.setSize(Env.ENV_WIDTH + Env.FROG_BRAIN_DISP_WIDTH + 25, y); - } else { - button.setText("Show brain"); - mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 100); - } + Env.SHOW_FIRST_FROG_BRAIN = !Env.SHOW_FIRST_FROG_BRAIN; + checkIfShowBrainPicture(button); } + }; + checkIfShowBrainPicture(button); button.addActionListener(al); mainFrame.add(button); diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/Env.java b/core3d/src/main/java/com/github/drinkjava2/frog/Env.java index 3c08ec9..9e06491 100644 --- a/core3d/src/main/java/com/github/drinkjava2/frog/Env.java +++ b/core3d/src/main/java/com/github/drinkjava2/frog/Env.java @@ -11,6 +11,7 @@ import javax.swing.JPanel; import com.github.drinkjava2.frog.egg.Egg; import com.github.drinkjava2.frog.egg.EggTool; +import com.github.drinkjava2.frog.objects.LetterTester; import com.github.drinkjava2.frog.objects.Material; import com.github.drinkjava2.frog.objects.Object; import com.github.drinkjava2.frog.util.RandomUtils; @@ -37,6 +38,9 @@ public class Env extends JPanel { public static final int FROG_PER_SCREEN = EGG_QTY * FROG_PER_EGG / SCREEN; // 每屏上显示几个青蛙,这个数值由上面三个参数计算得来 + /** SHOW first frog's brain structure */ + public static boolean SHOW_FIRST_FROG_BRAIN = true; // 是否显示脑图在Env区的右侧 + /** Draw first frog's brain after some steps */ public static int DRAW_BRAIN_AFTER_STEPS = 20; // 以此值为间隔动态画出脑图,设为0则关闭这个动态脑图功能,只显示一个静态、不闪烁的脑图 @@ -47,10 +51,11 @@ public class Env extends JPanel { public static final int ENV_HEIGHT = ENV_WIDTH; // 虚拟环境高度, 可调,通常取正方形 /** Frog's brain display width on screen, not important */ - public static final int FROG_BRAIN_DISP_WIDTH = 400; // Frog的脑图在屏幕上的显示大小,可调 + public static final int FROG_BRAIN_DISP_WIDTH = 600; // Frog的脑图在屏幕上的显示大小,可调 /** Steps of one test round */ - public static final int STEPS_PER_ROUND = 50000;// 每轮测试步数,可调 + public static final int STEPS_PER_ROUND = 3000;// 每轮测试步数,可调 + public static int step;// 当前测试步数 /** Frog's x radius, brain volume = XSIZE * YSIZE * ZSIZE */ public static final int FROG_BRAIN_XSIZE = 50; // frog的脑在X方向长度 @@ -59,6 +64,7 @@ public class Env extends JPanel { public static final int FOOD_QTY = 100; // 食物数量, 可调 + // 以下是程序内部变量,不要手工修改它们 public static boolean pause = false; // 暂停按钮按下将暂停测试 public static byte[][] bricks = new byte[ENV_WIDTH][ENV_HEIGHT];// 组成环境的材料,0=无, 1=食, 其它=其它... @@ -67,7 +73,7 @@ public class Env extends JPanel { public static List eggs = new ArrayList<>(); // 这里存放从磁盘载入或上轮下的蛋,每个蛋可能生成1~n个青蛙, - public static Object[] things = new Object[] {}; + public static Object[] things = new Object[] { new LetterTester() };// 所有外界物体,如食物、字母测试工具都放在这个things里面 static { System.out.println("唵缚悉波罗摩尼莎诃!"); // 杀生前先打印往生咒,见码云issue#IW4H8 @@ -190,9 +196,9 @@ public class Env extends JPanel { Frog firstFrog = frogs.get(screen * FROG_PER_SCREEN); for (int j = 0; j < FROG_PER_SCREEN; j++) { Frog f = frogs.get(screen * FROG_PER_SCREEN + j); - f.initOrgans(); + f.initOrgans(); // 初始化器官延迟到这一步,是因为脑细胞太占内存,而且测完后会清空 } - for (int i = 0; i < STEPS_PER_ROUND; i++) { + for (step = 0; step < STEPS_PER_ROUND; step++) { for (Object thing : things)// 调用食物、陷阱等物体的动作 thing.active(screen); if (allDead) @@ -204,7 +210,7 @@ public class Env extends JPanel { allDead = false; } - if (SHOW_SPEED > 0 && i % SHOW_SPEED != 0) // 用画青蛙的方式来拖慢速度 + if (SHOW_SPEED > 0 && step % SHOW_SPEED != 0) // 用画青蛙的方式来拖慢速度 continue; if (SHOW_SPEED < 0) // 如果speed小于0,人为加入延迟 @@ -221,22 +227,22 @@ public class Env extends JPanel { } if (firstFrog.alive) { // 开始显示第一个Frog的动态脑图 - if (Application.SHOW_FIRST_FROG_BRAIN) { + if (SHOW_FIRST_FROG_BRAIN) { g.setColor(Color.red); g.drawArc(firstFrog.x - 15, firstFrog.y - 15, 30, 30, 0, 360); g.setColor(Color.BLACK); } - if (DRAW_BRAIN_AFTER_STEPS > 0 && i % DRAW_BRAIN_AFTER_STEPS == 0) + if (DRAW_BRAIN_AFTER_STEPS > 0 && step % DRAW_BRAIN_AFTER_STEPS == 0) Application.brainPic.drawBrainPicture(firstFrog); } Graphics g2 = this.getGraphics(); g2.drawImage(buffImg, 0, 0, this); } + Application.brainPic.drawBrainPicture(firstFrog); for (int j = 0; j < FROG_PER_SCREEN; j++) { Frog f = frogs.get(screen * FROG_PER_SCREEN + j); - f.cubes = new Object[1][1][1]; + f.cubes = null; // 清空frog脑细胞所占用的内存 } - Application.brainPic.drawBrainPicture(firstFrog); Application.mainFrame.setTitle(new StringBuilder("Round: ").append(round).append(", screen:") .append(screen).append(", ").append(foodFoundCountText()).append(", 用时: ") .append(System.currentTimeMillis() - time0).append("ms").toString()); diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/Frog.java b/core3d/src/main/java/com/github/drinkjava2/frog/Frog.java index 0afa4c6..8409122 100644 --- a/core3d/src/main/java/com/github/drinkjava2/frog/Frog.java +++ b/core3d/src/main/java/com/github/drinkjava2/frog/Frog.java @@ -18,14 +18,16 @@ import java.util.List; import javax.imageio.ImageIO; +import com.github.drinkjava2.frog.brain.Cube; import com.github.drinkjava2.frog.brain.Organ; import com.github.drinkjava2.frog.egg.Egg; import com.github.drinkjava2.frog.objects.Material; /** - * Frog = organs + brain cells + * Frog = organs + cubes
+ * cubes = brain cells + photon * - * 青蛙由器官组成,器官中的Group类会生成各种脑细胞 + * 青蛙由器官组成,器官中的Group类会播种出各种脑细胞填充在一个cubes三维数组代表的空间中,每个cube里可以存在多个脑细胞和光子,光子是信息的载体,永远不停留。 * * @author Yong Zhu * @since 1.0 @@ -33,7 +35,7 @@ import com.github.drinkjava2.frog.objects.Material; public class Frog { /** brain cells */ - public Object[][][] cubes; + public Cube[][][] cubes; /** organs */ public List organs = new ArrayList<>(); @@ -54,19 +56,62 @@ public class Frog { } public Frog(int x, int y, Egg egg) { - this.x = x; + initCubes(); + this.x = x; // x, y 是虑拟环境的坐标 this.y = y; for (Organ org : egg.organs) organs.add(org); } - public void initOrgans() { + public void initCubes() { + cubes = new Cube[Env.FROG_BRAIN_XSIZE][Env.FROG_BRAIN_YSIZE][Env.FROG_BRAIN_ZSIZE]; + for (int a = 0; a < Env.FROG_BRAIN_XSIZE; a++) + for (int b = 0; b < Env.FROG_BRAIN_YSIZE; b++) + for (int c = 0; c < Env.FROG_BRAIN_ZSIZE; c++) + cubes[a][b][c] = new Cube(); + } + + public void initOrgans() {// 调用每个器官的init方法,通常用于脑细胞的播种 for (Organ org : organs) - org.init(this);// 每个新器官初始化,如果是Group类,它们会生成许多脑细胞 + org.init(this); + } + + /** Find a organ in frog by organ's name */ + public Organ findOrganByName(String organName) {// 根据器官名寻找器官 + for (Organ o : organs) + if (organName.equalsIgnoreCase(o.getClass().getSimpleName())) + return o; + return null; + } + + /** Active all cubes in organ with given activeValue */ + public void activeOrgan(Organ o, float activeValue) {// 激活与器官重合的所有脑区 + for (int x = o.x; x < o.x + o.xe; x++) + for (int y = o.y; y < o.y + o.ye; y++) + for (int z = o.z; z < o.z + o.ze; z++) + cubes[x][y][z].active = activeValue; + } + + /** Deactivate all cubes in organ with given activeValue */ + public void deactivateOrgan(Organ o) {// 激活与器官重合的所有脑区 + for (int x = o.x; x < o.x + o.xe; x++) + for (int y = o.y; y < o.y + o.ye; y++) + for (int z = o.z; z < o.z + o.ze; z++) + cubes[x][y][z].active = 0; + } + + /** Calculate organ activity by add all organ cubes' active value together */ + public float getOrganActivity(Organ o) {// 遍历所有器官所在cube,将它们的激活值汇总返回 + float activity = 0; + for (int x = o.x; x < o.x + o.xe; x++) + for (int y = o.y; y < o.y + o.ye; y++) + for (int z = o.z; z < o.z + o.ze; z++) + activity += this.cubes[x][y][z].active; + return activity; } - public boolean active(Env v) { - // 如果能量小于0则死、出界、与非食物的点重合则判死 + public boolean active(Env v) {// 这个active方法在每一步循环都会被调用,是脑思考的最小帧 + // 如果能量小于0、出界、与非食物的点重合则判死 if (!alive || energy < 0 || Env.outsideEnv(x, y) || Env.bricks[x][y] >= Material.KILLFROG) { energy -= 100; // 死掉的青蛙也要消耗能量,确保淘汰出局 alive = false; @@ -74,7 +119,7 @@ public class Frog { } energy -= 20; for (Organ o : organs) { - o.active(this); + o.active(this); // 调用每个器官的active方法,如果重写了的话 } return alive; } diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java b/core3d/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java index a88a4b9..d8b3ea8 100644 --- a/core3d/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java +++ b/core3d/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java @@ -16,7 +16,6 @@ import java.awt.Graphics; import javax.swing.JPanel; -import com.github.drinkjava2.frog.Application; import com.github.drinkjava2.frog.Env; import com.github.drinkjava2.frog.Frog; @@ -33,6 +32,7 @@ public class BrainPicture extends JPanel { Color color = Color.red; int brainDispWidth; // screen display piexls width float scale; // brain scale + int pointDia; // point size int xOffset = 0; // brain display x offset compare to screen int yOffset = 0; // brain display y offset compare to screen float xAngle = (float) (Math.PI / 2.5); // brain rotate on x axis @@ -44,6 +44,7 @@ public class BrainPicture extends JPanel { this.setLayout(null);// 空布局 this.brainDispWidth = brainDispWidth; scale = 0.7f * brainDispWidth / brainWidth; + pointDia = Math.max(Math.round(scale), 1); this.setBounds(x, y, brainDispWidth + 1, brainDispWidth + 1); MouseAction act = new MouseAction(this); this.addMouseListener(act); @@ -51,7 +52,7 @@ public class BrainPicture extends JPanel { this.addMouseMotionListener(act); } - public void drawCube(Cuboid c) { + public void drawCuboid(Cuboid c) {// 在脑图上画一个长立方体框架,视角是TopView float x = c.x; float y = c.y; float z = c.z; @@ -59,20 +60,20 @@ public class BrainPicture extends JPanel { float ye = c.ye; float ze = c.ze; - drawTopViewLine(x, y, z, x + xe, y, z);// 画立方体的下面边 - drawTopViewLine(x + xe, y, z, x + xe, y + ye, z); - drawTopViewLine(x + xe, y + ye, z, x, y + ye, z); - drawTopViewLine(x, y + ye, z, x, y, z); + drawLine(x, y, z, x + xe, y, z);// 画立方体的下面边 + drawLine(x + xe, y, z, x + xe, y + ye, z); + drawLine(x + xe, y + ye, z, x, y + ye, z); + drawLine(x, y + ye, z, x, y, z); - drawTopViewLine(x, y, z, x, y, z + ze);// 画立方体的中间边 - drawTopViewLine(x + xe, y, z, x + xe, y, z + ze); - drawTopViewLine(x + xe, y + ye, z, x + xe, y + ye, z + ze); - drawTopViewLine(x, y + ye, z, x, y + ye, z + ze); + drawLine(x, y, z, x, y, z + ze);// 画立方体的中间边 + drawLine(x + xe, y, z, x + xe, y, z + ze); + drawLine(x + xe, y + ye, z, x + xe, y + ye, z + ze); + drawLine(x, y + ye, z, x, y + ye, z + ze); - drawTopViewLine(x, y, z + ze, x + xe, y, z + ze);// 画立方体的上面边 - drawTopViewLine(x + xe, y, z + ze, x + xe, y + ye, z + ze); - drawTopViewLine(x + xe, y + ye, z + ze, x, y + ye, z + ze); - drawTopViewLine(x, y + ye, z + ze, x, y, z + ze); + drawLine(x, y, z + ze, x + xe, y, z + ze);// 画立方体的上面边 + drawLine(x + xe, y, z + ze, x + xe, y + ye, z + ze); + drawLine(x + xe, y + ye, z + ze, x, y + ye, z + ze); + drawLine(x, y + ye, z + ze, x, y, z + ze); } /*- @@ -86,7 +87,7 @@ public class BrainPicture extends JPanel { 绕 z 轴旋转 θ x.cosθ-y.sinθ, x.sinθ+y.consθ, z -*/ - private void drawTopViewLine(float px1, float py1, float pz1, float px2, float py2, float pz2) { + public void drawLine(float px1, float py1, float pz1, float px2, float py2, float pz2) { double x1 = px1 - Env.FROG_BRAIN_XSIZE / 2; double y1 = -py1 + Env.FROG_BRAIN_YSIZE / 2;// 屏幕的y坐标是反的,显示时要正过来 double z1 = pz1 - Env.FROG_BRAIN_ZSIZE / 2; @@ -138,6 +139,41 @@ public class BrainPicture extends JPanel { (int) round(y2) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset); } + /** 画点,固定以top视角的角度,所以只需要在x1,y1位置画一个点 */ + public void drawCubeCenter(float x, float y, float z) { + drawPoint(x+0.5f, y+0.5f, z+0.5f, pointDia); + } + + /** 画点,固定以top视角的角度,所以只需要在x1,y1位置画一个点 */ + public void drawPoint(float px1, float py1, float pz1, int diameter) { + double x1 = px1 - Env.FROG_BRAIN_XSIZE / 2; + double y1 = -py1 + Env.FROG_BRAIN_YSIZE / 2;// 屏幕的y坐标是反的,显示时要正过来 + double z1 = pz1 - Env.FROG_BRAIN_ZSIZE / 2; + x1 = x1 * scale; + y1 = y1 * scale; + z1 = z1 * scale; + double x, y, z; + y = y1 * cos(xAngle) - z1 * sin(xAngle);// 绕x轴转 + z = y1 * sin(xAngle) + z1 * cos(xAngle); + y1 = y; + z1 = z; + + x = z1 * sin(yAngle) + x1 * cos(yAngle);// 绕y轴转 + z = z1 * cos(yAngle) - x1 * sin(yAngle); + x1 = x; + z1 = z; + + x = x1 * cos(zAngle) - y1 * sin(zAngle);// 绕z轴转 + y = x1 * sin(zAngle) + y1 * cos(zAngle); + x1 = x; + y1 = y; + + Graphics g = this.getGraphics(); + g.setColor(color); + g.fillOval((int) round(x1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset, + (int) round(y1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset - diameter/2, diameter, diameter); + } + private static final Color[] rainbow = new Color[] { RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA }; private static int nextColor = 0; @@ -147,8 +183,26 @@ public class BrainPicture extends JPanel { return rainbow[nextColor++]; } + public static Color rainboColor(float i) { + if (i == 0) + return Color.black; + if (i == 1) + return Color.RED; + if (i <= 3) + return Color.ORANGE; + if (i <= 10) + return Color.YELLOW; + if (i <= 20) + return Color.GREEN; + if (i <= 50) + return Color.CYAN; + if (i <= 100) + return Color.BLUE; + return Color.MAGENTA; + } + public void drawBrainPicture(Frog frog) { - if (!Application.SHOW_FIRST_FROG_BRAIN) + if (!Env.SHOW_FIRST_FROG_BRAIN) return; Graphics g = this.getGraphics(); g.setColor(Color.WHITE);// 先清空旧图 @@ -158,6 +212,22 @@ public class BrainPicture extends JPanel { for (Organ organ : frog.organs)// 每个器官负责画出自已在脑图中的位置和形状 organ.drawOnBrainPicture(frog, this); // each organ draw itself + this.setColor(Color.RED); + drawLine(0, 0, 0, 1, 0, 0); + drawLine(0, 0, 0, 0, 1, 0); + drawLine(0, 0, 0, 0, 0, 1); + + for (int x = 0; x < Env.FROG_BRAIN_XSIZE; x++) { + for (int y = 0; y < Env.FROG_BRAIN_YSIZE; y++) { + for (int z = 0; z < Env.FROG_BRAIN_ZSIZE; z++) { + if (frog.cubes[x][y][z].active > 0) { + setColor(rainboColor(frog.cubes[x][y][z].active)); + drawCubeCenter(x, y, z); + } + } + } + + } } // getters & setters diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Cube.java b/core3d/src/main/java/com/github/drinkjava2/frog/brain/Cube.java index 218e353..5702916 100644 --- a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Cube.java +++ b/core3d/src/main/java/com/github/drinkjava2/frog/brain/Cube.java @@ -15,13 +15,26 @@ import java.util.Arrays; /** * Cube include 0~n cells and 0~n photons * + * Cube是脑的空间单位,是一个正立方体,里面可以存放多个脑细胞(Cell)和光子(Photon) + * Cube和Cuboid的区别是,Cube是脑的最小空间单元,作为脑细胞存放和光子传播的介质,简化计算,而Cuboid通常是一个长方体,用来描述器官的大小和位置, + * 器官的大小和位置是可以变异的 + * * @author Yong Zhu * @since 1.0 */ public class Cube { - Cell[] cells = new Cell[] {}; + /** Activity of current cube */ + public float active = 0; // 这个立方体的激活程度,允许是负值,它反映了在这个小立方体里所有光子的能量汇总值 + + /** + * Fat of brain nerve cell
+ * 处理的光子信号越多,这个立方体会越肥,肥度大有两个作用:它对信号的处理会有增强效应 2.它会使脑细胞播种器官产生更多的变异,如数量、分布范围增加。 + */ + public float fat = 0; + + public Cell[] cells = new Cell[] {}; - Photon[] photons = new Photon[] {}; + public Photon[] photons = new Photon[] {}; public void addCell(Cell cell) {// 每个方格空间可以存在多个脑细胞 cells = Arrays.copyOf(cells, cells.length + 1); diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Organ.java b/core3d/src/main/java/com/github/drinkjava2/frog/brain/Organ.java index c7b058b..973fc17 100644 --- a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Organ.java +++ b/core3d/src/main/java/com/github/drinkjava2/frog/brain/Organ.java @@ -12,7 +12,7 @@ package com.github.drinkjava2.frog.brain; import java.awt.Color; -import com.github.drinkjava2.frog.Application; +import com.github.drinkjava2.frog.Env; import com.github.drinkjava2.frog.Frog; /** @@ -42,10 +42,10 @@ public class Organ extends Cuboid { /** Child class can override this method to drawing picture */ public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来,子类可以重写这个方法 - if (!Application.SHOW_FIRST_FROG_BRAIN) + if (!Env.SHOW_FIRST_FROG_BRAIN) return; pic.setColor(Color.BLACK); // 缺省是黑色 - pic.drawCube(this); + pic.drawCuboid(this); } /** Only call once after organ be created by new() method */ diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Brain.java b/core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Brain.java index 94df6e8..8af00ff 100644 --- a/core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Brain.java +++ b/core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Brain.java @@ -11,8 +11,6 @@ package com.github.drinkjava2.frog.brain.organ; import com.github.drinkjava2.frog.Env; -import com.github.drinkjava2.frog.Frog; -import com.github.drinkjava2.frog.brain.Cube; import com.github.drinkjava2.frog.brain.Organ; /** @@ -43,9 +41,4 @@ public class Brain extends Organ { ze = Env.FROG_BRAIN_ZSIZE; } - @Override - public void init(Frog f) { - f.cubes = new Cube[Env.FROG_BRAIN_XSIZE][Env.FROG_BRAIN_YSIZE][Env.FROG_BRAIN_ZSIZE]; - } - } diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java b/core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java index 01188d5..af8900b 100644 --- a/core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java +++ b/core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java @@ -21,7 +21,7 @@ import com.github.drinkjava2.frog.brain.Organ; */ public class Eye extends Organ {//这个眼睛有nxn个感光细胞,可以看到青蛙周围nxn网络内有没有食物 private static final long serialVersionUID = 1L; - public int n = 13; // 眼睛有n x n个感光细胞, 用随机试错算法自动变异(加1或减1,最小是3x3) + public int n = 18; // 眼睛有n x n个感光细胞, 用随机试错算法自动变异(加1或减1,最小是3x3) @Override public void init(Frog f) { // 仅在Frog生成时这个方法会调用一次,缺省啥也不干,通常用于Organ类的初始化 @@ -33,7 +33,7 @@ public class Eye extends Organ {//这个眼睛有nxn个感光细胞,可以看 public Eye() { x = 10; y = 10; - z = Env.FROG_BRAIN_ZSIZE - 1; + z = Env.FROG_BRAIN_ZSIZE-1; xe = 10; ye = xe; ze = 1; diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/egg/Egg.java b/core3d/src/main/java/com/github/drinkjava2/frog/egg/Egg.java index 7b66dd1..2b1b9c1 100644 --- a/core3d/src/main/java/com/github/drinkjava2/frog/egg/Egg.java +++ b/core3d/src/main/java/com/github/drinkjava2/frog/egg/Egg.java @@ -48,7 +48,6 @@ public class Egg implements Serializable { organs.add(new B()); organs.add(new C()); organs.add(new D()); - } /** Create egg from frog */ diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java b/core3d/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java index f23e8f5..d4c694e 100644 --- a/core3d/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java +++ b/core3d/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java @@ -10,17 +10,26 @@ */ package com.github.drinkjava2.frog.objects; +import com.github.drinkjava2.frog.Env; +import com.github.drinkjava2.frog.Frog; +import com.github.drinkjava2.frog.brain.Organ; +import com.github.drinkjava2.frog.util.RandomUtils; +import com.github.drinkjava2.frog.util.StringPixelUtils; + /** * LetterTester used to test A, B , C, D letter recognition * * 这是一个临时类,用来测试青蛙的视觉模式识别功能。 在测试的前半段,它在青蛙视觉区激活一个字母的图像并同时激活对应这个字母的区(如A的图像对应A区, - * B的图像对应B区...), 然后仅仅激活图像,检测是否对应字母的区能被图像激活, 有就增加青蛙的能量,让它在生存竟争中胜出 + * B的图像对应B区...), 然后在下半段仅仅激活图像,检测是否对应字母的区能被图像激活, 有就增加青蛙的能量,让它在生存竟争中胜出 * * * @author Yong Zhu * @since 1.0 */ public class LetterTester implements Object { + private static final String STR = "ABCD"; + boolean[][] pixels; + String letter; @Override public void build() { // do nothing @@ -32,7 +41,29 @@ public class LetterTester implements Object { @Override public void active(int screen) { + if (Env.step == 0) { // 每当开始新一屏测试时,重选一个随机字符 + letter = String.valueOf(STR.charAt(RandomUtils.nextInt(4))); + pixels = StringPixelUtils.getSanserif12Pixels(letter); + } + Frog f = Env.frogs.get(screen * Env.FROG_PER_SCREEN); + Organ eye = f.findOrganByName("eye"); + int w = pixels.length; + int h = pixels[0].length; + + // 在视网膜上产生字母像素点阵,即激活这个脑视网膜所在的cubes区,然后由器官播种出的脑细胞负责将激活能量转为光子输送、存贮到其它位置 + for (int x = 0; x < w; x++) + for (int y = 0; y < h; y++) + if (pixels[x][y]) + f.cubes[x + eye.x][y + eye.y][eye.z].active = 20; + if (Env.step < Env.STEPS_PER_ROUND / 2) {// 前半段同时还要激活与这个字母对应脑区 + f.activeOrgan(f.findOrganByName(letter), 20); + } else if (Env.step == Env.STEPS_PER_ROUND / 2) {// 在中段取消字母对应脑区的激活 + f.deactivateOrgan(f.findOrganByName(letter)); + } else if (Env.step > Env.STEPS_PER_ROUND / 2) {// 后半段要检测这个字母区是否能收到光子信号 + if (f.getOrganActivity(f.findOrganByName(letter)) > 0) + f.energy += 100; + } } } diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/util/StringPixelUtils.java b/core3d/src/main/java/com/github/drinkjava2/frog/util/StringPixelUtils.java index ba7d919..6602ef3 100644 --- a/core3d/src/main/java/com/github/drinkjava2/frog/util/StringPixelUtils.java +++ b/core3d/src/main/java/com/github/drinkjava2/frog/util/StringPixelUtils.java @@ -21,7 +21,7 @@ import java.util.Map; /** * StringPixelUtils used to get pixel array from a given string * - * 根据给定的字体和字符串,返回它的像素点阵,返回结果是boolean[][]二维数组 + * 根据给定的字体和字符串,返回它的像素点阵,lettersMap[0][0]是左下角素 * * @author Yong Zhu * @since 2.0.2 @@ -47,28 +47,31 @@ public class StringPixelUtils { g2d.setFont(font); FontMetrics fm = g2d.getFontMetrics(); int strHeight = fm.getAscent() + fm.getDescent() - 3; - int strWidth = fm.stringWidth(s); - g2d.drawString(s, 0, fm.getAscent() - fm.getLeading() - 1); - boolean[][] b = new boolean[strHeight][strWidth]; + int strWidth = fm.stringWidth(s); + g2d.drawString(s, 0, fm.getAscent() - fm.getLeading() - 1); + boolean[][] b = new boolean[strWidth][strHeight]; for (int y = 0; y < strHeight; y++) for (int x = 0; x < strWidth; x++) if (bi.getRGB(x, y) == -1) - b[y][x] = true; + b[x][strHeight-y-1] = true; else - b[y][x] = false; + b[x][strHeight-y-1] = false; lettersMap.put(key, b); return b; } public static void main(String[] args) { - boolean[][] c = getStringPixels(Font.SANS_SERIF, Font.PLAIN, 10, "∮ABCD中国人"); - for (int y = 0; y < c.length; y++) { - boolean[] line = c[y]; - for (int x = 0; x < line.length; x++) - if (c[y][x]) + boolean[][] c = getStringPixels(Font.SANS_SERIF, Font.PLAIN, 12, "Test点阵输出"); + int w = c.length; + int h = c[0].length; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + if (c[x][h-y-1]) System.out.print("*"); else System.out.print(" "); + } System.out.println(); } } diff --git a/捐款记录.md b/捐款记录.md index 628713b..457b824 100644 --- a/捐款记录.md +++ b/捐款记录.md @@ -1,10 +1,10 @@ ¼ĿΪ֧͸һĿˣյƽ̨ľҲ¼¼ʱ˳¼˺͵ǰܶǾ˲ʱȡԸԭҲͨʷ¼ѯÿʵľڴĵظлÿһλޡעĿͬѧ -(ʱ˳): +(ʱ˳): wangtao dotao LongFer +ʪ - -Ŀǰܶ:48.88Ԫ -Ŀǰ֧ܶ:0Ԫ \ No newline at end of file +Ŀǰܶ:98.88Ԫ +Ŀǰ֧ܶ:0Ԫ \ No newline at end of file