Work on 3d brain, Line will change to organ

pull/2/head
drinkjava2 5 years ago
parent 6be80b30f2
commit 10c0193411

@ -1,4 +1,5 @@
## Frog | 人工生命
(Engish instruction see README_EN.md)
这是一个人工生命试验项目最终目标是创建“有自我意识表现”的模拟生命体技术架构基于02年提出的 [一个人工脑模型](一个人工脑模型.md)。
这个项目永远没有结束的时候,开始于模拟一个简单的生命体,然后是青蛙、狗......, 结束于有“自我意识表现”的人工脑,或者说,结束于被机器人代替人类的那一天。

File diff suppressed because one or more lines are too long

@ -6,6 +6,10 @@ import java.io.File;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import com.github.drinkjava2.frog.brain.BrainPicture;
@ -37,14 +41,14 @@ public class Application {
static private void checkIfShowBrainPicture(JButton button) {
if (Env.SHOW_FIRST_FROG_BRAIN) {
button.setText("Hide brain");
int y = Env.ENV_HEIGHT + 100;
int y = Env.ENV_HEIGHT + 120;
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);
brainPic.requestFocus();
} else {
button.setText("Show brain");
mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 100);
mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 120);
}
}
@ -52,11 +56,10 @@ public class Application {
mainFrame.setLayout(null);
mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 100); // 窗口大小
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭时退出程序
mainFrame.add(env);
mainFrame.add(env); // 添加虚拟环境Panel
mainFrame.add(brainPic); // 添加脑图Panel
mainFrame.add(brainPic);
JButton button = new JButton("Show brain");
JButton button = new JButton("Show brain");// 按钮,显示或隐藏脑图
int buttonWidth = 100;
int buttonHeight = 22;
int buttonXpos = Env.ENV_WIDTH / 2 - buttonWidth / 2;
@ -74,7 +77,7 @@ public class Application {
button.addActionListener(al);
mainFrame.add(button);
JButton stopButton = new JButton("Pause");
JButton stopButton = new JButton("Pause");// 按钮,暂停或继续
stopButton.setBounds(buttonXpos, Env.ENV_HEIGHT + 35, buttonWidth, buttonHeight);
pauseAction = new ActionListener() {
@Override
@ -91,6 +94,20 @@ public class Application {
stopButton.addActionListener(pauseAction);
mainFrame.add(stopButton);
final JSlider speedSlider = new JSlider(1, 10, (int) Math.round(Math.sqrt(Env.SHOW_SPEED))); // 速度条
speedSlider.setBounds(buttonXpos - 50, stopButton.getY() + 25, buttonWidth + 100, buttonHeight);
ChangeListener slideAction = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
Env.SHOW_SPEED = speedSlider.getValue() * speedSlider.getValue() * speedSlider.getValue();
}
};
speedSlider.addChangeListener(slideAction);
mainFrame.add(speedSlider);
final JLabel label = new JLabel("Speed:");
label.setBounds(buttonXpos - 90, stopButton.getY() + 23, 100, buttonHeight);
mainFrame.add(label);
mainFrame.setVisible(true);
env.run();
}

@ -25,16 +25,16 @@ import com.github.drinkjava2.frog.util.RandomUtils;
@SuppressWarnings("all")
public class Env extends JPanel {
/** Speed of test */
public static final int SHOW_SPEED = 10; // 测试速度,-1000~1000,可调, 数值越小,速度越慢
public static int SHOW_SPEED = 10; // 测试速度,-1000~1000,可调, 数值越小,速度越慢
/** Delete eggs at beginning of each run */
public static final boolean DELETE_EGGS = true;// 每次运行是否先删除保存的蛋
public static final int EGG_QTY = 10; // 每轮下n个蛋可调只有最优秀的前n个青蛙们才允许下蛋
public static final int EGG_QTY = 50; // 每轮下n个蛋可调只有最优秀的前n个青蛙们才允许下蛋
public static final int FROG_PER_EGG = 4; // 每个蛋可以孵出几个青蛙
public static final int SCREEN = 1; // 分几屏测完
public static final int SCREEN = 4; // 分几屏测完
public static final int FROG_PER_SCREEN = EGG_QTY * FROG_PER_EGG / SCREEN; // 每屏上显示几个青蛙,这个数值由上面三个参数计算得来
@ -59,10 +59,10 @@ public class Env extends JPanel {
public static final int FROG_BRAIN_DISP_WIDTH = 600; // Frog的脑图在屏幕上的显示大小,可调
/** Steps of one test round */
public static final int STEPS_PER_ROUND = 1000;// 每轮测试步数,可调
public static final int STEPS_PER_ROUND = 2000;// 每轮测试步数,可调
public static int step;// 当前测试步数
public static final int FOOD_QTY = 3000; // 食物数量, 可调
public static final int FOOD_QTY = 2000; // 食物数量, 可调
// 以下是程序内部变量,不要手工修改它们
public static boolean pause = false; // 暂停按钮按下将暂停测试
@ -73,7 +73,7 @@ public class Env extends JPanel {
public static List<Egg> eggs = new ArrayList<>(); // 这里存放新建或从磁盘载入上轮下的蛋,每个蛋可能生成几个青蛙,
public static EnvObject[] things = new EnvObject[] {new Food()};// 所有外界物体如食物、字母测试工具都放在这个things里面
public static EnvObject[] things = new EnvObject[] { new Food() };// 所有外界物体如食物、字母测试工具都放在这个things里面
static {
System.out.println("唵缚悉波罗摩尼莎诃!"); // 杀生前先打印往生咒见码云issue#IW4H8
@ -203,7 +203,6 @@ public class Env extends JPanel {
thing.build();
boolean allDead = false;
Frog firstFrog = frogs.get(screen * FROG_PER_SCREEN);
checkIfPause(firstFrog);
for (int j = 0; j < FROG_PER_SCREEN; j++) {
Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
f.initFrog(); // 初始化器官延迟到这一步,是因为脑细胞太占内存,而且当前屏测完后会清空
@ -217,7 +216,7 @@ public class Env extends JPanel {
allDead = true;
for (int j = 0; j < FROG_PER_SCREEN; j++) {
Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
if (f.active(this))
if (f.active(this))// 调用青蛙的Active方法并返回是否还活着
allDead = false;
}
@ -250,13 +249,15 @@ public class Env extends JPanel {
g2.drawImage(buffImg, 0, 0, this);
}
Application.brainPic.drawBrainPicture(firstFrog);
checkIfPause(firstFrog);
for (int j = 0; j < FROG_PER_SCREEN; j++) {
Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
f.cells = null; // 清空frog脑细胞所占用的内存
}
Application.mainFrame.setTitle(new StringBuilder("Round: ").append(round).append(", screen:")
.append(screen).append(", ").append(foodFoundCountText()).append(", 用时: ")
.append(System.currentTimeMillis() - time0).append("ms").toString());
Application.mainFrame
.setTitle(new StringBuilder("Round: ").append(round).append(", screen:").append(screen)
.append(", speed:").append(Env.SHOW_SPEED).append(", ").append(foodFoundCountText())
.append(", 用时: ").append(System.currentTimeMillis() - time0).append("ms").toString());
for (EnvObject thing : things)// 去除食物、陷阱等物体
thing.destory();
}

@ -21,7 +21,7 @@ import javax.imageio.ImageIO;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Cuboid;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.brain.Shape;
import com.github.drinkjava2.frog.brain.organ.Line;
import com.github.drinkjava2.frog.egg.Egg;
import com.github.drinkjava2.frog.objects.Material;
@ -45,7 +45,7 @@ public class Frog {// 这个程序大量用到public变量而不是getter/setter
public int x; // frog在Env中的x坐标
public int y; // frog在Env中的y坐标
public long energy = 10000000; // 青蛙的能量为0则死掉
public long energy = 1000000; // 青蛙的能量为0则死掉
public boolean alive = true; // 设为false表示青蛙死掉了将不参与计算和显示以节省时间
public int ateFood = 0; // 青蛙曾吃过的食物总数,下蛋时如果两个青蛙能量相等,可以比数量
@ -65,60 +65,23 @@ public class Frog {// 这个程序大量用到public变量而不是getter/setter
organs.add(org);
}
public void initFrog() {// 仅在测试之前调用这个方法初始化frog以节约内存测试完成后要清空units释放内存
try {
cells = new Cell[Env.FROG_BRAIN_XSIZE][][]; // 为了节约内存先只初始化三维数组的x维另两维用到时再分配
} catch (OutOfMemoryError e) {
System.out.println("OutOfMemoryError found for frog, force it die.");
this.alive = false;
return;
}
public void initFrog() {
for (int orgNo = 0; orgNo < organs.size(); orgNo++) {
organs.get(orgNo).init(this, orgNo);
}
}
/** Find a organ in frog by organ's name */
@SuppressWarnings("unchecked")
public <T extends Organ> T findOrganByName(String organName) {// 根据器官名寻找器官,但不是每个器官都有名字
for (Organ o : organs)
if (o.organName != null && organName.equalsIgnoreCase(o.organName))
return (T) o;
return null;
}
/** Set with given activeValue */
public void activeCellsInShape(Shape sp) {// 激活长方体区域内的所有脑区
if (!alive)
return;
if (sp instanceof Cuboid) {
Cuboid o = (Cuboid) sp;
for (int x = o.x; x < o.x + o.xe; x++)
if (cells[x] != null)
for (int y = o.y; y < o.y + o.ye; y++)
if (cells[x][y] != null)
for (int z = o.z; z < o.z + o.ze; z++)
if (cells[x][y][z] != null) {
getOrCreateCell(x, y, z).active();
}
}
}
public boolean active(Env v) {// 这个active方法在每一步循环都会被调用是脑思考的最小帧
// 如果能量小于0、出界、与非食物的点重合则判死
if (!alive || energy < 0 || Env.outsideEnv(x, y) || Env.bricks[x][y] >= Material.KILLFROG) {
energy -= 100; // 死掉的青蛙也要消耗能量,确保淘汰出局
energy -= 1000; // 死掉的青蛙也要消耗能量,确保淘汰出局
alive = false;
return false;
}
energy -= 20;
for (Organ o : organs)
o.active(this); // 调用每个器官的active方法 通常只用于执行器官的外界信息输入、动作输出,脑细胞的遍历不是在这一步
// 这里是最关键的脑细胞主循环依次调用每个器官的active方法每个器官各自负责调用各自区域通常是Cuboid)内的细胞的行为
// 依次调用每个器官的active方法每个器官各自负责调用各自区域通常是Cuboid)内的细胞的行为
for (Organ o : organs)
o.active(this);
return alive;
}
@ -128,17 +91,41 @@ public class Frog {// 这个程序大量用到public变量而不是getter/setter
g.drawImage(frogImg, x - 8, y - 8, 16, 16, null);
}
@SuppressWarnings("unchecked")
public <T extends Organ> T findOrganByClass(Class<?> claz) {// 根据器官名寻找器官,但不是每个器官都有名字
for (Organ o : organs)
if (o != null && o.getClass() == claz)
return (T) o;
return null;
}
public Cell findFirstCellByClass(Class<?> claz) {// 根据器官名寻找器官,但不是每个器官都有名字
Organ o = findOrganByClass(claz);
Cuboid c = (Cuboid) o.shape;
return this.getCell(c.x, c.y, c.z);
}
/** Check if cell exist */
public Cell getCell(int x, int y, int z) {// 返回指定脑ssf坐标的cell 如果不存在返回null
if (cells[x] == null || cells[x][y] == null)
if (cells == null || cells[x] == null || cells[x][y] == null)
return null;
return cells[x][y][z];
}
public Cell getCell1(Line l) {
return cells[l.x1][l.y1][l.z1];
}
public Cell getCell2(Line l) {
return cells[l.x2][l.y2][l.z2];
}
/** Get a cell in position (x,y,z), if not exist, create a new one */
public Cell getOrCreateCell(int x, int y, int z) {// 获取指定坐标的Cell如果为空则在指定位置新建Cell
if (outBrainRange(x, y, z))
return null;
throw new IllegalArgumentException("x,y,z postion out of range, x=" + x + ", y=" + y + ", z=" + z);
if (cells == null)
cells = new Cell[Env.FROG_BRAIN_XSIZE][][];
if (cells[x] == null)
cells[x] = new Cell[Env.FROG_BRAIN_YSIZE][];
if (cells[x][y] == null)

@ -9,17 +9,18 @@ import static java.lang.Math.round;
import static java.lang.Math.sin;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.plaf.ColorUIResource;
import com.github.drinkjava2.frog.Application;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.organ.Line;
import com.github.drinkjava2.frog.util.ColorUtils;
/**
@ -152,6 +153,18 @@ public class BrainPicture extends JPanel {
// TODO 画出锥体的上下面
}
/**
* cell c1线cell c2
*/
public void drawLine(Cell c1, Cell c2) {
drawLine(c1.x + .5f, c1.y + .5f, c1.z + .5f, c2.x + .5f, c2.y + .5f, c2.z + .5f);
}
/** 将Line对象在pic上画一条线 */
public void drawLine(Line l) {
drawLine(l.x1 + .5f, l.y1 + .5f, l.z1 + .5f, l.x2 + .5f, l.y2 + .5f, l.z2 + .5f);
}
/*-
线topx1,y1x2,y2线
x θ
@ -250,6 +263,35 @@ public class BrainPicture extends JPanel {
(int) round(y1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset - diameter / 2, diameter, diameter);
}
public void drawText(float px1, float py1, float pz1, String text) {
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;
g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, (int) round(scale * .3)));
g.drawString(text, (int) round(x1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset,
(int) round(y1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset);
}
private static Cuboid brain = new Cuboid(0, 0, 0, Env.FROG_BRAIN_XSIZE, Env.FROG_BRAIN_YSIZE, Env.FROG_BRAIN_ZSIZE);
public void drawBrainPicture(Frog f) {// 在这个方法里进行青蛙三维脑结构的绘制
@ -263,6 +305,9 @@ public class BrainPicture extends JPanel {
g.drawRect(0, 0, brainDispWidth, brainDispWidth);
setPicColor(BLACK);
drawCuboid(brain);// 先把脑的框架画出来
drawText(1, 0, 0, "x");
drawText(0, 1, 0, "y");
drawText(0, 0, 1, "z");
for (Organ organ : f.organs)// 每个器官负责画出自已在脑图中的位置和形状
organ.drawOnBrainPicture(f, this); // each organ draw itself
@ -271,25 +316,24 @@ public class BrainPicture extends JPanel {
drawLine(0, 0, 0, 0, 1, 0);
drawLine(0, 0, 0, 0, 0, 1);
for (int x = 0; x < Env.FROG_BRAIN_XSIZE; x++) {// 开始画整个脑空间的光子和激活点阵
if (f.cells[x] != null)
for (int x = 0; x < Env.FROG_BRAIN_XSIZE; x++) {// 开始画整个脑空间的细胞活跃分布
if (f.cells != null && f.cells[x] != null)
for (int y = 0; y < Env.FROG_BRAIN_YSIZE; y++) {
if (f.cells[x][y] != null)
for (int z = 0; z < Env.FROG_BRAIN_ZSIZE; z++) {
Cell cell = f.getCell(x, y, z);
if (cell != null && cell.energy>10) {
setPicColor(ColorUtils.rainbowColor(cell.energy));
if (cell != null && cell.energy > 20) {
setPicColor(ColorUtils.grayColor(cell.energy));// 用灰度表示活跃度
drawCellCenter(x, y, z, 0.6f);
}
}
}
}
g.setColor(Color.black);
if (note != null)
if (note != null) // 全局注释
g.drawString(note, 30, 55);
Graphics g2 = this.getGraphics(); // 这两行是将缓存中的图像写到屏幕上
g2.drawImage(buffImg, 0, 0, this);
Graphics g2 = this.getGraphics();
g2.drawImage(buffImg, 0, 0, this);// 利用缓存避免画面闪烁,这里输出缓存图片
}
public static void setNote(String note) {

@ -10,6 +10,7 @@
*/
package com.github.drinkjava2.frog.brain;
import java.io.Serializable;
import java.util.Arrays;
/**
@ -33,11 +34,12 @@ import java.util.Arrays;
* @author Yong Zhu
* @since 1.0
*/
public class Cell {
public class Cell implements Serializable {
private static final long serialVersionUID = 1L;
public int x;
public int y;
public int z;
public float energy;
public float energy=0;
public Cell(int x, int y, int z) {
this.x = x;
@ -49,24 +51,23 @@ public class Cell {
public Hole[] holes = null;// 洞(即动态突触),洞由光子产生,洞由时间抹平,洞的角度本身就是关联关系,角度越大,关联关系越大
/** Active this cell, increase its energy value */
public void active() {// 激活这个细胞也就是说增加它的能量值最大到10000饱和
energy += 100;
if (energy > 10000)
energy = 10000;
}
public void deActive() {// 抑制这个细胞也就是说减小它的能量值最小到0
energy -= 300;
if (energy < 0)
energy = 0;
}
public void regOrgan(int orgNo) {// 每个Cell可以被多个Organ登记通常只在青蛙初始化器官时调用这个方法
if (organs == null)
organs = new int[] {};
organs = Arrays.copyOf(organs, organs.length + 1);
organs = new int[1];
else
organs = Arrays.copyOf(organs, organs.length + 1);
organs[organs.length - 1] = orgNo;
}
public void addEnergy(float e) {
energy += e;
if (energy > 100)
energy = 100;
}
public void subEnergy(float e) {
energy -= e;
if (energy < 0)
energy = 0;
}
}

@ -15,6 +15,8 @@ import java.io.Serializable;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.organ.Line;
import com.github.drinkjava2.frog.brain.organ.Lines;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
@ -44,32 +46,18 @@ public class Organ implements Serializable, Cloneable {// 因为要保存在蛋
private static final long serialVersionUID = 1L;
// 以下是各种器官类型每个神经元都属于一个器官每个器官都有一个type类型参数
private static int organNoIndex = 1;
public int organNo = organNoIndex++; // 每个器官都有一个唯一的编号,作用是同一个编号的光子间将不产生绑定
public int color = 1;// 这个不重要表示它生成的光子的显示在脑图中的颜色号见ColorUtils
public float fat = 0;// 细胞活跃多则fat值大如果fat值很低则这个器官被丢弃的可能性加大这个值很重要它使得孤岛器官被淘汰
public boolean allowVary;// 是否允许变异,有一些器官是手工创建的,在项目初级阶段禁止它们参与变异和生存竟争。
public boolean allowBorrow;// 是否允许在精子中将这个器官借出,有一些器官是手工创建的,在项目初级阶段禁止它们借出
public String organName;// 器官的名字通常只有手工创建的器官才有名字可以用frog.findOrganByName来查找到这个器官
public String organName = this.getClass().getSimpleName();;// 器官的名字通常只有手工创建的器官才有名字可以用frog.findOrganByName来查找到这个器官
public Shape shape; // 器官的形状,不同的形状要写出不同的播种行为
// =====注意以下三个字段可以让细胞具备一些固定角度的洞这个不占内存但缺点是不灵活不智能详见与Cell类中动态洞的对比 =====
public Hole[] holes; // 输出洞
public Organ() {// 缺省构造器,生成具有缺省参数但没有形状的器官
allowVary = true;
allowBorrow = true;
holes = null;
}
/** Only call once after organ be created */
public Organ[] vary(Frog f) { // 器官变异仅会在青蛙下蛋时即new Egg(frog)中被调用一次,返回本身或变异后的一个或一组类似器官返回
if (!allowVary)
return new Organ[] { this };// 如果不允许变异,器官就把自身返回,存放在蛋里
// 各参数 随机有大概率小变异,小概率大变异,极小概率极大变异
shape = RandomUtils.vary(shape);
holes = RandomUtils.vary(holes);
return new Organ[] { this };
}
@ -82,13 +70,15 @@ public class Organ implements Serializable, Cloneable {// 因为要保存在蛋
/** each step will call Organ's active methodd */
public void active(Frog f) {// 每一步测试都会调用active方法它通常遍历每个细胞调用它们的cellAct方法
if (!f.alive)
// 这里是缺省的方法体,子类可以重写这个方法
if (!f.alive || shape == null)
return;
Cuboid c = (Cuboid) shape;
for (int px = 0; px < c.xe; px++)
for (int py = 0; py < c.ye; py++) {// 要做到近处的分辨率高,远处的分辨率低
cellAct(f, f.getOrCreateCell(c.x + px, c.y + py, c.z));
}
for (int py = 0; py < c.ye; py++)
for (int pz = 0; pz < c.ze; pz++) {
cellAct(f, f.getCell(c.x + px, c.y + py, c.z + pz));
}
}
/** each step will call Organ's active methodd */
@ -96,13 +86,40 @@ public class Organ implements Serializable, Cloneable {// 因为要保存在蛋
}
/** Child class can override this method to drawing picture */
public void drawOnBrainPicture(Frog f, BrainPicture pic) { // 把器官的轮廓显示在脑图上
if (shape == null)
return;// 如果没有形状,就不画
if (!Env.SHOW_FIRST_FROG_BRAIN || !f.alive) // 如果不允许画或青蛙死了,就直接返回
public void drawOnBrainPicture(Frog f, BrainPicture pic) { // 把器官的轮廓显示在脑图上,子类可以重写这个方法
if (!Env.SHOW_FIRST_FROG_BRAIN || !f.alive || shape == null) // 如果不允许画或青蛙死了或没形状,就直接返回
return;
pic.setPicColor(Color.LIGHT_GRAY); // 缺省是灰色
shape.drawOnBrainPicture(pic);
pic.setPicColor(Color.RED); // 缺省是灰色
if (this.organName != null && this.shape.getClass() == Cuboid.class) {
int x = ((Cuboid) shape).x;
int y = ((Cuboid) shape).y;
int z = ((Cuboid) shape).z;
pic.drawText(x, y, z, this.organName);
}
}
public boolean getLineEnergy(Frog f, Cell c) {
Lines ls = f.findOrganByClass(Lines.class);
for (Line l : ls.lines) {
if (l == null || l.energy < 30)
continue;
if (l.x2 == c.x && l.y2 == c.y && l.z2 == c.z) {
l.energy -= 30;
return true;
}
}
return false;
}
public static void addLineEnergy(Frog f, Cell c, float energy) {
Lines ls = f.findOrganByClass(Lines.class);
for (Line l : ls.lines) {
if (l == null || l.energy > 100)
continue;
if (l.x1 == c.x && l.y1 == c.y && l.z1 == c.z) // 如果线的输入端位于视网膜上,增加线的能量
l.energy += energy;
}
}
}

@ -28,4 +28,5 @@ public interface Shape extends Serializable {
/* Organ will call this method to create cells or register organ in cells */
public void createCellsRegOrgan(Frog f, int orgNo); // 在Shape所代表的脑区内找到或创建Cell对象并将器官号orgNo登记在cell里
}

@ -0,0 +1,43 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.brain.organ;
import static com.github.drinkjava2.frog.Env.FROG_BRAIN_ZSIZE;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Cuboid;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
* Active always active
*
* @author Yong Zhu
*/
public class Active extends Organ {// 这个器官的作用总是激活一个固定区,它有可能会被自然选择选中
private static final long serialVersionUID = 1L;
public int actEngery = 5;
public Active() {
this.shape = new Cuboid(15, 10, FROG_BRAIN_ZSIZE / 2 + 3, 1, 1, 1);
}
public Organ[] vary(Frog f) {// 重写器官的very方法
actEngery = RandomUtils.varyInLimit(actEngery, 1, 500);
return new Organ[] { this };
}
@Override
public void cellAct(Frog f, Cell c) {
addLineEnergy(f, c, actEngery);
}
}

@ -0,0 +1,51 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.brain.organ;
import static com.github.drinkjava2.frog.Env.FROG_BRAIN_XSIZE;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Cuboid;
import com.github.drinkjava2.frog.brain.Organ;
/**
* BigEye can see 8x8 square around of current frog
*
* @author Yong Zhu
*/
public class BigEye extends Organ {// 这个大眼睛是青蛙从上帝视角来观察产生一个8x8的图像区用来作为模式识别功能的输入区
private static final int EYE_RADIUS = 4;
private static final int cx = 6; // 中心点
private static final int cy = 6;
private static final int cz = FROG_BRAIN_XSIZE / 2; // 中层
private static final long serialVersionUID = 1L;
public BigEye() {
// 大眼晴位于脑的中部,模仿视神经通到脑的中部,而不是通到脑的皮层。视信号从脑的中部传到脑皮层的过程就是模式识别的筛选过程,筛选结果记录在脑皮层里。
// 模式识别的基本原理是反复发生的信号会到达并存贮在脑皮层(挖洞),不常发生的信号不会在脑皮层留下印象(或洞很快就自愈了)。
// 脑皮层的回忆原理是B角度入射的信号会触发脑皮层细胞原存有的A角度的洞信号从A洞开始沿A信号曾经射入的方向反射回去
this.shape = new Cuboid(cx - EYE_RADIUS, cy - EYE_RADIUS, cz, EYE_RADIUS * 2, EYE_RADIUS * 2, 1);
}
@Override
public void cellAct(Frog f, Cell c) {// 大眼睛根据虚拟环境是否有物体,激活视网膜细胞, 以及与它底层相邻的脑细胞(待加)
// 根据距中心点(cx,cy)的偏移,来映射虚拟环境的物体到视网膜上
if (Env.foundAnyThing(f.x + c.x - cx, f.y - c.y + cy))
c.addEnergy(30);
else
c.subEnergy(30);
// TODO激活眼下细胞让信号进入模式识别之旅并最终存贮在脑皮层细胞里,即金字塔的底部。
}
}

@ -0,0 +1,45 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.brain.organ;
import static com.github.drinkjava2.frog.Env.FROG_BRAIN_ZSIZE;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Cuboid;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
* Happy active after ate food
*/
public class Eat extends Organ { // Eat器官的作用就是如果位置与食物重合增加frog的能量
private static final long serialVersionUID = 1L;
public int actEngery = 1000;
public Eat() {
this.shape = new Cuboid(15, 13, FROG_BRAIN_ZSIZE / 2 + 3, 1, 1, 1);
}
public Organ[] vary(Frog f) {// 重写器官的very方法
actEngery = RandomUtils.varyInLimit(actEngery, 1, 5000);
return new Organ[] { this };
}
@Override
public void active(Frog f) {
if (Env.foundAndAteFood(f.x, f.y)) {
f.energy += actEngery;
}
}
}

@ -10,45 +10,94 @@
*/
package com.github.drinkjava2.frog.brain.organ;
import static com.github.drinkjava2.frog.Env.FROG_BRAIN_ZSIZE;
import static com.github.drinkjava2.frog.Env.FROG_BRAIN_XSIZE;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Cuboid;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.objects.Material;
import com.github.drinkjava2.frog.util.ColorUtils;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
* Eye can only see env material
*
* Eye便
*
* @author Yong Zhu
*/
public class Eye extends Organ {// 眼睛是长方体
private static final int EYE_SIZE = 6;
public class Eye {// 这个眼睛是从青蛙视角来观察因为青蛙生活在二次元空间所以它只能观察上下左右4个方向有无食物
// 视距
private static final int cx = 5; // 中心点
private static final int cy = 15;
private static final int cz = FROG_BRAIN_XSIZE / 2; // 中层
public static class SeeUp extends Organ {// 这个感光细胞只能看到上方有没有物体
private static final long serialVersionUID = 1L;
public int seeDistance = 10;
public int addEyeEnergy = 6;
public Organ[] vary(Frog f) {// 重写器官的very方法允许眼睛看到的距离随机进化
seeDistance = RandomUtils.varyInLimit(seeDistance, 1, 50);
addEyeEnergy = RandomUtils.varyInLimit(addEyeEnergy, 1, 200);
return new Organ[] { this };
}
public SeeUp() {
shape = new Cuboid(cx, cy + 2, cz, 1, 1, 1);
}
public void cellAct(Frog f, Cell c) {// 如果上方有物体就激活视网膜细胞
for (int i = 1; i <= seeDistance; i++)
if (Env.foundAnyThing(f.x, f.y - i)) {
addLineEnergy(f, c, addEyeEnergy);
}
}
}
public static class SeeDown extends SeeUp {// 这个感光细胞只能看到下方有没有物体
private static final long serialVersionUID = 1L;
public SeeDown() {
shape = new Cuboid(cx, cy - 2, cz, 1, 1, 1);
}
public void cellAct(Frog f, Cell c) {// 如果上方有物体就激活视网膜细胞
for (int i = 1; i <= seeDistance; i++)
if (Env.foundAnyThing(f.x, f.y + i)) {
addLineEnergy(f, c, addEyeEnergy);
}
}
}
public static class SeeLeft extends SeeUp {// 这个感光细胞只能看到左边有没有物体
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
public SeeLeft() {
shape = new Cuboid(cx - 2, cy, cz, 1, 1, 1);
}
public Eye() {
this.shape = new Cuboid(3, 3, FROG_BRAIN_ZSIZE / 2, EYE_SIZE, EYE_SIZE, 1);// 眼晴位于脑的中部
this.organName = "Eye";
this.allowVary = false;// 不允许变异
this.allowBorrow = false;// 不允许借出
this.color = ColorUtils.GRAY;
public void cellAct(Frog f, Cell c) {// 如果上方有物体就激活视网膜细胞
for (int i = 1; i <= seeDistance; i++)
if (Env.foundAnyThing(f.x - i, f.y)) {
addLineEnergy(f, c, addEyeEnergy);
}
}
}
public void cellAct(Frog f, Cell c) {// 眼细胞的作用是根据食物激活视网膜和眼下皮层
f.x=0;f.y=0;
for (int i = 0; i < 2; i++) {
Env.bricks[i][0]=Material.FOOD;
Env.bricks[i][1]=Material.FOOD;
Env.bricks[i][32]=Material.FOOD;
}
if (Env.foundAnyThing(f.x - EYE_SIZE / 2 + c.x, f.y - EYE_SIZE / 2 + c.y))
c.active();
else
c.deActive();
public static class SeeRight extends SeeUp {// 这个感光细胞只能看到右边有没有物体
private static final long serialVersionUID = 1L;
public SeeRight() {
shape = new Cuboid(cx + 2, cy, cz, 1, 1, 1);
}
public void cellAct(Frog f, Cell c) {// 如果上方有物体就激活视网膜细胞
for (int i = 1; i <= seeDistance; i++)
if (Env.foundAnyThing(f.x + i, f.y)) {
addLineEnergy(f, c, addEyeEnergy);
}
}
}
}

@ -0,0 +1,42 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.brain.organ;
import java.io.Serializable;
import com.github.drinkjava2.frog.brain.Cell;
/**
* Line is a line from cell1 to cell2
*
* @author Yong Zhu
* @since 2020-04-18
*/
public class Line implements Serializable {// Line代表一个从cell1到cell2的神经元连接,energy表示连接能量
private static final long serialVersionUID = 1L;
public float energy;
public int fat = 0;
public int x1, y1, z1, x2, y2, z2;
public Line() {
// 缺省构造器必有, 因为从磁盘上反序列化要先调用这个构造器
}
public Line(Cell c1, Cell c2) {
this.x1 = c1.x;
this.y1 = c1.y;
this.z1 = c1.z;
this.x2 = c2.x;
this.y2 = c2.y;
this.z2 = c2.z;
}
}

@ -0,0 +1,96 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.brain.organ;
import java.awt.Color;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.BrainPicture;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
* If move cell active, frog will move
*
* Move便
*
* @author Yong Zhu
*/
public class Lines extends Organ {// Lines器官很重要它是神经元之间的连线由随机生成由生存竟争淘汰
private static final long serialVersionUID = 1L;
private static final int LINE_QTY = 100;// 总共允许最多有多少根线条
public Line[] lines;
public Lines() {
shape = null;
organName = null;
if (lines == null)
lines = new Line[LINE_QTY];
}
public void init(Frog f, int orgNo) { // 在青蛙生成时会调用这个方法,进行一些初始化
if (RandomUtils.percent(3f)) // 生成线
addLine(f);
if (RandomUtils.percent(3f)) // 丢弃线
discardLine(f);
}
/**
* 1.线 2.线
*/
public void active(Frog f) {
for (Line line : lines) {
if (line == null)
continue;
f.energy -= 1; //线不是越多越好,线越多,所需能量越多
}
}
public void addLine(Frog f) {// 随机生成线
Cell c1 = RandomUtils.getRandomCell(f);
if (c1 == null)
return;
Cell c2 = RandomUtils.getRandomCell(f);
if (c2 == null)
return;
for (int i = 0; i < lines.length; i++) {// 找空位插入新的线
if (lines[i] == null) {
lines[i] = new Line(c1, c2);
return;
}
}
// 没找到? 随便找个位置顶替原来的线
lines[RandomUtils.nextInt(LINE_QTY)] = new Line(c1, c2);
}
public void discardLine(Frog f) {// 随机丢弃线
lines[RandomUtils.nextInt(LINE_QTY)] = null;
}
/** Child class can override this method to drawing picture */
public void drawOnBrainPicture(Frog f, BrainPicture pic) { // 把器官的轮廓显示在脑图上
if (!Env.SHOW_FIRST_FROG_BRAIN || !f.alive) // 如果不允许画或青蛙死了,就直接返回
return;
for (Line line : lines) {
if (line == null)
continue;
if (line.energy > 0) // 正值用兰色,负值用红色表示
pic.setPicColor(Color.RED);
else
pic.setPicColor(Color.GRAY);
pic.drawLine(line);
pic.drawPoint(line.x2 + .5f, line.y2 + .5f, line.z2 + .5f, 10);
}
}
}

@ -0,0 +1,89 @@
/*
* Copyright 2018 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
* applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package com.github.drinkjava2.frog.brain.organ;
import static com.github.drinkjava2.frog.Env.FROG_BRAIN_ZSIZE;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Cuboid;
import com.github.drinkjava2.frog.brain.Organ;
/**
* If move cell active, frog will move
*
* Move便
*
* @author Yong Zhu
*/
public class Move {// 因为青蛙生活在二次元所以只有上下左右4个运动方向
private static final int cx = 5;
private static final int cy = 15;
private static final int cz = FROG_BRAIN_ZSIZE / 2 + 3;
public static class MoveUp extends Organ {// 这个运动细胞激活,青蛙将向上移动
private static final long serialVersionUID = 1L;
public MoveUp() {
shape = new Cuboid(cx, cy + 2, cz, 1, 1, 1);
}
@Override
public void cellAct(Frog f, Cell c) {
if (getLineEnergy(f, c))
f.y--;
}
}
public static class MoveDown extends Organ {// 这个运动细胞激活,青蛙将向下移动
private static final long serialVersionUID = 1L;
public MoveDown() {
shape = new Cuboid(cx, cy - 2, cz, 1, 1, 1);
}
@Override
public void cellAct(Frog f, Cell c) {
if (getLineEnergy(f, c))
f.y++;
}
}
public static class MoveLeft extends Organ {// 这个运动细胞激活,青蛙将向左移动
private static final long serialVersionUID = 1L;
public MoveLeft() {
shape = new Cuboid(cx - 2, cy, cz, 1, 1, 1);
}
@Override
public void cellAct(Frog f, Cell c) {
if (getLineEnergy(f, c))
f.x--;
}
}
public static class MoveRight extends Organ {// 这个运动细胞激活,青蛙将向右移动
private static final long serialVersionUID = 1L;
public MoveRight() {
shape = new Cuboid(cx + 2, cy, cz, 1, 1, 1);
}
@Override
public void cellAct(Frog f, Cell c) {
if (getLineEnergy(f, c))
f.x++;
}
}
}

@ -16,7 +16,11 @@ import java.util.List;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.brain.organ.Active;
import com.github.drinkjava2.frog.brain.organ.Eye;
import com.github.drinkjava2.frog.brain.organ.Eat;
import com.github.drinkjava2.frog.brain.organ.Lines;
import com.github.drinkjava2.frog.brain.organ.Move;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
@ -35,8 +39,18 @@ public class Egg implements Serializable {
public List<Organ> organs = new ArrayList<>();// NOSONAR
public Egg() {// 无中生有,创建一个蛋,先有蛋,后有蛙
//organs.add(new MoveJelly()); // MoveJelly即移动光子也是果冻记忆细胞本来可以分成两个器官的图省事
organs.add(new Eye()); // 眼是手工创建的,必有
organs.add(new Eye.SeeUp()); // 添加眼睛的四个感光细胞器官
organs.add(new Eye.SeeDown());
organs.add(new Eye.SeeLeft());
organs.add(new Eye.SeeRight());
// organs.add(new BigEye()); // 添加大眼睛
organs.add(new Move.MoveUp()); // 添加四个运动输出细胞
organs.add(new Move.MoveDown());
organs.add(new Move.MoveLeft());
organs.add(new Move.MoveRight());
organs.add(new Active()); // 始终激活
organs.add(new Eat()); // 没有什么比吃到东西更愉快的了
organs.add(new Lines()); // 连线
}
/** Create egg from frog */

@ -39,11 +39,14 @@ public class EggTool {
* EGG_QTY
*/
public static void layEggs() {
sortFrogsOrderByEnergyDesc();
// for (Frog frog : Env.frogs) {
// Lines LINES=(Lines) frog.organs.get(10);
// System.out.println(frog.energy+":"+LINES.lines[0]);
// }
Frog first = Env.frogs.get(0);
Frog last = Env.frogs.get(Env.frogs.size() - 1);
try {
Env.eggs.clear();
for (int i = 0; i < Env.EGG_QTY; i++)

@ -59,4 +59,13 @@ public class ColorUtils {
return Color.RED;
return Color.MAGENTA;
}
public static Color grayColor(float f) { // 根据数值大小范围0~1000返回一个灰度色越大越黑
if (f > 1000)
f = 1000;
int i1 = 255 - (int) Math.round(f * .255);
int i2 = 200 - (int) Math.round(f * .200);
int i3 = 150 - (int) Math.round(f * .150);
return new Color(i1, i2, i3);
}
}

@ -17,9 +17,12 @@ import static com.github.drinkjava2.frog.Env.FROG_BRAIN_ZSIZE;
import java.util.Random;
import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Cell;
import com.github.drinkjava2.frog.brain.Cone;
import com.github.drinkjava2.frog.brain.Cuboid;
import com.github.drinkjava2.frog.brain.Hole;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.brain.Shape;
/**
@ -44,7 +47,22 @@ public class RandomUtils {
}
public static boolean percent(float percent) {// 有百分这percent的机率为true
return rand.nextInt(100) < percent;
return rand.nextFloat() * 100 < percent;
}
public static Cell getRandomCell(Frog f) {// 在随机一个器官里取一个随机Cell
int r = rand.nextInt(f.organs.size());
Organ o = f.organs.get(r);
if (o.shape == null)
return null;
if (o.shape instanceof Cuboid) {
Cuboid c = (Cuboid) o.shape;
int x = c.x + rand.nextInt(c.xe);
int y = c.y + rand.nextInt(c.ye);
int z = c.z + rand.nextInt(c.ze);
return f.getCell(x, y, z);
}
return null;
}
/** Randomly create a Cuboid inside of brain space */
@ -103,6 +121,15 @@ public class RandomUtils {
return v;
}
public static int varyInLimit(int v, int from, int to) {// 让返回值在from和to之间随机变异
int i = vary(v);
if (i < from)
i = from;
if (i > to)
i = to;
return i;
}
public static float vary(float v, int percet) {
if (percent(percet))
return vary(v);

@ -14,10 +14,11 @@ chanvictoire
Ad
涤青
张四峰
目前收入总额:288.77元
这家伙太懒了
目前收入总额:308.57元
支出(按时间顺序)
目前支出总额:0元
目前余额:288.77元
目前余额:308.57元

Loading…
Cancel
Save