diff --git a/README.md b/README.md
index ce4f32f..b134175 100644
--- a/README.md
+++ b/README.md
@@ -91,7 +91,9 @@ Frog: 这是人工生命的主体,目前起名叫青蛙(Frog),其实叫什
![result6](https://gitee.com/drinkjava2/frog/raw/master/result6_letter.gif)
2019-11-26 优化了一下程序,用8个汉字来进行模式识别原理演示,但容错性依然没有,变形、变位后的文字识别率很差。以后要考虑借签算法中的侧抑制、卷积、分层等原理来提高它的容错性,这方面算法已经很成熟了,目前只需要拿来主义,用图形化模拟的方式来实现。但总体上算法和图形化模拟是两条路,算法通常可以用模拟的方式来表达,但不是所有模拟都可以归纳成算法,因为模拟(或者说软件本身)有时会非常复杂,不容易总结出规律。也就是说模拟的表现力比算法更强,但模拟的缺点是资源消耗大。
-注意:如果想要运行这个项目的以前码云版本,可以结合gitk命令和参考"版本提交记录.md"的介绍,用git reset命令回复到以前任一个版本,例如用:
+## 运行方式 | Run
+运行core或history各个子目录下的run.bat批处理文件即可启动运行,history下有多个子目录,按时间顺序按列,存放着这个项目演化过程中的主要历史版本供演示。
+另外如果想要研究这个项目的任一旧版本,可以结合gitk命令和参考"版本提交记录.md"的介绍,用git reset命令回复到以前任一个版本,例如用:
git reset --hard ae34b07e 可以转回到以前一个分组测试的找食版本。
## 重要参数 | Parameters
diff --git a/core/pom.xml b/core/pom.xml
index 4f24670..c0b7163 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -4,7 +4,7 @@
com.gitee.drinkjava2frogjar
- 2.0.1
+ 1.0frogAn artificial life test project
@@ -99,4 +99,4 @@
-
+
\ No newline at end of file
diff --git a/core/src/main/java/com/github/drinkjava2/frog/Application.java b/core/src/main/java/com/github/drinkjava2/frog/Application.java
index d1b0d0a..8d96ff0 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/Application.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/Application.java
@@ -16,19 +16,36 @@ 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 {
String classpath = new File("").getAbsolutePath();
- int core = classpath.indexOf("core");
- CLASSPATH = classpath.substring(0, core);
+ int core = classpath.indexOf("\\frog\\");
+ if (core > 0)
+ CLASSPATH = classpath.substring(0, core) + "\\frog\\";
+ else
+ CLASSPATH = classpath.substring(0, core) + "/frog/"; // UNIX
}
public static JFrame mainFrame = new JFrame();
public static Env env = new Env();
- public static BrainPicture brainPic = new BrainPicture(Env.ENV_WIDTH + 5, 0, Env.FROG_BRAIN_WIDTH,
+ public static BrainPicture brainPic = new BrainPicture(Env.ENV_WIDTH + 5, 0, Env.FROG_BRAIN_XSIZE,
Env.FROG_BRAIN_DISP_WIDTH);
+ public static ActionListener pauseAction;
+
+ 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);
+ brainPic.requestFocus();
+ } 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);
@@ -38,33 +55,27 @@ public class Application {
mainFrame.add(brainPic);
- JButton button = new JButton("Show first frog's brain");
- int buttonWidth = 180;
+ JButton button = new JButton("Show brain");
+ 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 first frog's 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 first frog's 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);
JButton stopButton = new JButton("Pause");
stopButton.setBounds(buttonXpos, Env.ENV_HEIGHT + 35, buttonWidth, buttonHeight);
- ActionListener a2 = new ActionListener() {
+ pauseAction = new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Env.pause = !Env.pause;
@@ -72,10 +83,11 @@ public class Application {
stopButton.setText("Resume");
} else {
stopButton.setText("Pause");
+ brainPic.requestFocus();
}
}
};
- stopButton.addActionListener(a2);
+ stopButton.addActionListener(pauseAction);
mainFrame.add(stopButton);
mainFrame.setVisible(true);
diff --git a/core/src/main/java/com/github/drinkjava2/frog/Env.java b/core/src/main/java/com/github/drinkjava2/frog/Env.java
index 9869499..878f3be 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/Env.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/Env.java
@@ -9,13 +9,11 @@ import java.util.List;
import javax.swing.JPanel;
-import com.github.drinkjava2.frog.brain.group.RandomConnectGroup;
import com.github.drinkjava2.frog.egg.Egg;
import com.github.drinkjava2.frog.egg.EggTool;
-import com.github.drinkjava2.frog.objects.Food;
+import com.github.drinkjava2.frog.objects.LetterTester;
+import com.github.drinkjava2.frog.objects.EnvObject;
import com.github.drinkjava2.frog.objects.Material;
-import com.github.drinkjava2.frog.objects.Object;
-import com.github.drinkjava2.frog.objects.SeeSaw;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
@@ -27,21 +25,29 @@ import com.github.drinkjava2.frog.util.RandomUtils;
@SuppressWarnings("all")
public class Env extends JPanel {
/** Speed of test */
- public static final int SHOW_SPEED = 500; // 测试速度,-1000~1000,可调, 数值越小,速度越慢
+ public static final int SHOW_SPEED = 1; // 测试速度,-1000~1000,可调, 数值越小,速度越慢
/** Delete eggs at beginning of each run */
- public static final boolean DELETE_EGGS = false;// 每次运行是否先删除保存的蛋
+ public static final boolean DELETE_EGGS = true;// 每次运行是否先删除保存的蛋
- public static final int EGG_QTY = 25; // 每轮下n个蛋,可调,只有最优秀的前n个青蛙们才允许下蛋
+ public static final int EGG_QTY = 10; // 每轮下n个蛋,可调,只有最优秀的前n个青蛙们才允许下蛋
public static final int FROG_PER_EGG = 4; // 每个蛋可以孵出几个青蛙
- public static final int SCREEN = 100; // 分几屏测完
+ public static final int SCREEN = 1; // 分几屏测完
public static final int FROG_PER_SCREEN = EGG_QTY * FROG_PER_EGG / SCREEN; // 每屏上显示几个青蛙,这个数值由上面三个参数计算得来
+ /** Frog's brain size is a 3D array of Cell */ // 脑空间是个三维Cell数组,为节约内存,仅在用到数组元素时才去初始化这维,按需分配内存
+ public static final int FROG_BRAIN_XSIZE = 30; // frog的脑在X方向长度
+ public static final int FROG_BRAIN_YSIZE = 20; // frog的脑在Y方向长度
+ public static final int FROG_BRAIN_ZSIZE = 20; // frog的脑在Z方向长度
+
+ /** 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 = 50; // 以此值为间隔动态画出脑图,设为0则关闭这个动态脑图功能,只显示一个静态、不闪烁的脑图
+ public static int DRAW_BRAIN_AFTER_STEPS = 1; // 以此值为间隔动态画出脑图,设为0则关闭这个动态脑图功能,只显示一个静态、不闪烁的脑图
/** Environment x width, unit: pixels */
public static final int ENV_WIDTH = 400; // 虚拟环境的宽度, 可调
@@ -50,30 +56,31 @@ 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 = 2000;// 每轮测试步数,可调
-
- /** Frog's brain width, fixed to 1000 unit */
- public static final float FROG_BRAIN_WIDTH = 1000; // frog的脑宽度固定为1000,不要随便调整,因为器官的相对位置和大小是按脑大小设定的
+ public static final int STEPS_PER_ROUND = LetterTester.STR.length() * 2 * LetterTester.TIME;// 每轮测试步数,可调
+ public static int step;// 当前测试步数
- public static final int FOOD_QTY = 1500; // 食物数量, 可调
+ public static final int FOOD_QTY = 100; // 食物数量, 可调
+ // 以下是程序内部变量,不要手工修改它们
public static boolean pause = false; // 暂停按钮按下将暂停测试
- public static byte[][] bricks = new byte[ENV_WIDTH][ENV_HEIGHT];// 组成环境的材料,0=无, 1=食, 其它=其它...
+ public static byte[][] bricks = new byte[ENV_WIDTH][ENV_HEIGHT];// 组成环境的材料,见Material.java
public static List frogs = new ArrayList<>(); // 这里存放所有待测的青蛙,可能分几次测完,由FROG_PER_SCREEN大小来决定
- public static List eggs = new ArrayList<>(); // 这里存放从磁盘载入或上轮下的蛋,每个蛋可能生成1~n个青蛙,
+ public static List eggs = new ArrayList<>(); // 这里存放新建或从磁盘载入上轮下的蛋,每个蛋可能生成几个青蛙,
- public static Object[] things = new Object[] { new SeeSaw() };
+ public static EnvObject[] things = new EnvObject[] {};// 所有外界物体,如食物、字母测试工具都放在这个things里面
static {
System.out.println("唵缚悉波罗摩尼莎诃!"); // 杀生前先打印往生咒,见码云issue#IW4H8
+ System.out.println("脑图快捷键: T:顶视 F:前视 L:左视 R:右视 X:斜视 方向键:剖视 空格:暂停 鼠标:缩放旋转平移");
if (DELETE_EGGS)
EggTool.deleteEggs();
+
}
public Env() {
@@ -148,7 +155,7 @@ public class Env extends JPanel {
int leftfood = 0;
for (int x = 0; x < ENV_WIDTH; x++)
for (int y = 0; y < ENV_HEIGHT; y++)
- if (bricks[x][y] == 1)
+ if (bricks[x][y] == Material.FOOD)
leftfood++;
return FOOD_QTY - leftfood;
}
@@ -163,7 +170,18 @@ public class Env extends JPanel {
.append(foodFound * 1.0f / FROG_PER_SCREEN).append(",最多:").append(maxFound).toString();
}
- private static void sleep(long millis) {
+ public static void checkIfPause(Frog f) {
+ if (pause)
+ do {
+ if (f != null) {
+ Application.brainPic.drawBrainPicture(f);
+ Application.brainPic.requestFocus();
+ }
+ sleep(100);
+ } while (pause);
+ }
+
+ public static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
@@ -181,16 +199,18 @@ public class Env extends JPanel {
rebuildFrogs();
for (int screen = 0; screen < SCREEN; screen++) {// 分屏测试,每屏FROG_PER_SCREEN个蛙
time0 = System.currentTimeMillis();
- if (pause)
- do {
- sleep(300);
- } while (pause);
- for (Object thing : things) // 创建食物、陷阱等物体
+ for (EnvObject thing : things) // 创建食物、陷阱等物体
thing.build();
boolean allDead = false;
Frog firstFrog = frogs.get(screen * FROG_PER_SCREEN);
- for (int i = 0; i < STEPS_PER_ROUND; i++) {
- for (Object thing : things)// 调用食物、陷阱等物体的动作
+ checkIfPause(firstFrog);
+ for (int j = 0; j < FROG_PER_SCREEN; j++) {
+ Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
+ f.initFrog(); // 初始化器官延迟到这一步,是因为脑细胞太占内存,而且当前屏测完后会清空
+ }
+
+ for (step = 0; step < STEPS_PER_ROUND; step++) {
+ for (EnvObject thing : things)// 调用食物、陷阱等物体的动作
thing.active(screen);
if (allDead)
break; // 青蛙全死光了就直接跳到下一轮,以节省时间
@@ -199,14 +219,9 @@ public class Env extends JPanel {
Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
if (f.active(this))
allDead = false;
- if (f.alive && RandomUtils.percent(0.5f)) {// 有很小的机率在青蛙活着时就创建新的器官
- RandomConnectGroup newConGrp = new RandomConnectGroup();
- newConGrp.initFrog(f);
- f.organs.add(newConGrp);
- }
}
- if (SHOW_SPEED > 0 && i % SHOW_SPEED != 0) // 用画青蛙的方式来拖慢速度
+ if (SHOW_SPEED > 0 && step % SHOW_SPEED != 0) // 用画青蛙的方式来拖慢速度
continue;
if (SHOW_SPEED < 0) // 如果speed小于0,人为加入延迟
@@ -223,23 +238,26 @@ 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.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").append(", energy:")
- .append(firstFrog.energy).toString());
- for (Object thing : things)// 去除食物、陷阱等物体
+ .append(System.currentTimeMillis() - time0).append("ms").toString());
+ for (EnvObject thing : things)// 去除食物、陷阱等物体
thing.destory();
}
round++;
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 5f1af0c..c2efea6 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/Frog.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/Frog.java
@@ -19,29 +19,35 @@ import java.util.List;
import javax.imageio.ImageIO;
import com.github.drinkjava2.frog.brain.Cell;
+import com.github.drinkjava2.frog.brain.CellActions;
+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.Photon;
import com.github.drinkjava2.frog.egg.Egg;
import com.github.drinkjava2.frog.objects.Material;
/**
- * Frog = organs + brain cells
+ * Frog = cells
+ * cells = actions + photons
*
- * 青蛙由器官组成,器官中的Group类会生成各种脑细胞
+ * Frog's name is Sam.
+ *
+ * 青蛙脑由一个cells三维数组组成,每个cell里可以存在多个行为,行为是由器官决定,同一个细胞可以存在多种行为。光子是信息的载体,永远不停留。
*
* @author Yong Zhu
* @since 1.0
*/
-public class Frog {
-
+public class Frog {// 这个程序大量用到public变量而不是getter/setter,主要是为了编程方便和简洁,但缺点是编程者需要小心维护各个变量
/** brain cells */
- public List cells = new ArrayList<>();
+ public Cell[][][] cells;// 一开始不要初始化,只在调用getOrCreateCell方法时才初始化相关维以节约内存
/** organs */
public List organs = new ArrayList<>();
public int x; // frog在Env中的x坐标
public int y; // frog在Env中的y坐标
- public long energy = 100000; // 青蛙的能量为0则死掉
+ public long energy = 10000000; // 青蛙的能量为0则死掉
public boolean alive = true; // 设为false表示青蛙死掉了,将不参与计算和显示,以节省时间
public int ateFood = 0;
@@ -54,25 +60,73 @@ public class Frog {
}
}
- public Frog(int x, int y, Egg egg) {
+ public Frog(int x, int y, Egg egg) {// x, y 是虑拟环境的坐标
this.x = x;
this.y = y;
- for (Organ org : egg.organs) {
+ for (Organ org : egg.organs)
organs.add(org);
- org.initFrog(this);// 每个新器官初始化,如果是Group类,它们会生成许多脑细胞
+ }
+
+ 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;
+ }
+ for (int orgNo = 0; orgNo < organs.size(); orgNo++) {
+ organs.get(orgNo).init(this, orgNo);
}
}
- public boolean active(Env v) {
- // 如果能量小于0则死、出界、与非食物的点重合则判死
+ /** Find a organ in frog by organ's name */
+ @SuppressWarnings("unchecked")
+ public 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 setCuboidVales(Cuboid o, boolean active) {// 激活长方体区域内的所有脑区
+ if (!alive)
+ return;
+ 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).hasInput = active;
+ }
+
+ private int activeNo = 0;// 每一帧光子只能走一步,用这个来作标记
+
+ public boolean active(Env v) {// 这个active方法在每一步循环都会被调用,是脑思考的最小帧
+ activeNo++;
+ // 如果能量小于0、出界、与非食物的点重合则判死
if (!alive || energy < 0 || Env.outsideEnv(x, y) || Env.bricks[x][y] >= Material.KILLFROG) {
energy -= 100; // 死掉的青蛙也要消耗能量,确保淘汰出局
alive = false;
return false;
}
energy -= 20;
- for (Organ o : organs) {
- o.active(this);
+ for (Organ o : organs)
+ o.active(this); // 调用每个器官的active方法, 通常只用于执行器官的外界信息输入、动作输出,脑细胞的遍历不是在这一步
+
+ // 这里是最关键的脑细胞主循环,脑细胞负责捕获和发送光子,光子则沿它的矢量方向每次自动走一格,如果下一格是真空(即cell未初始化)会继续走下去并衰减直到为0(为减少运算)
+ for (int i = 0; i < Env.FROG_BRAIN_XSIZE; i++) {
+ Env.checkIfPause(this);
+ if (cells[i] != null)
+ for (int j = 0; j < Env.FROG_BRAIN_YSIZE; j++)
+ if (cells[i][j] != null)
+ for (int k = 0; k < Env.FROG_BRAIN_ZSIZE; k++) {
+ Cell cell = cells[i][j][k];
+ if (cell != null)
+ CellActions.act(this, activeNo, cell); // 调用每个细胞的act方法
+ }
}
return alive;
}
@@ -83,4 +137,86 @@ public class Frog {
g.drawImage(frogImg, x - 8, y - 8, 16, 16, null);
}
+ /** Check if cell exist */
+ public Cell getCell(int x, int y, int z) {// 返回指定脑ssf坐标的cell ,如果不存在,返回null
+ if (cells[x] == null || cells[x][y] == null)
+ return null;
+ return cells[x][y][z];
+ }
+
+ /** 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 (outBrainBound(x, y, z))
+ return null;
+ if (cells[x] == null)
+ cells[x] = new Cell[Env.FROG_BRAIN_YSIZE][];
+ if (cells[x][y] == null)
+ cells[x][y] = new Cell[Env.FROG_BRAIN_ZSIZE];
+ Cell cell = cells[x][y][z];
+ if (cell == null) {
+ cell = new Cell(x, y, z);
+ cells[x][y][z] = cell;
+ }
+ return cell;
+ }
+
+ /** Check if x,y,z out of frog's brain bound */
+ public static boolean outBrainBound(int x, int y, int z) {// 检查指定坐标是否超出frog脑空间界限
+ return x < 0 || x >= Env.FROG_BRAIN_XSIZE || y < 0 || y >= Env.FROG_BRAIN_YSIZE || z < 0
+ || z >= Env.FROG_BRAIN_ZSIZE;
+ }
+
+ /** Photon always walk */
+ public void addAndWalk(Photon p) { // 添加光子的同时让它沿光子方向自动走一格
+ p.x += p.mx;
+ p.y += p.my;
+ p.z += p.mz;
+ int rx = Math.round(p.x);
+ int ry = Math.round(p.y);
+ int rz = Math.round(p.z);
+ if (Frog.outBrainBound(rx, ry, rz))
+ return;// 出界直接扔掉
+ Cell cell = getCell(rx, ry, rz);
+ if (cell != null)
+ cell.addPhoton(p);
+ }
+
+ /** Photon always walk */
+ public void addAndWalkAndDig(Photon p) { // 添加光子的同时让它沿光子方向自动走一格
+ p.x += p.mx;
+ p.y += p.my;
+ p.z += p.mz;
+ int rx = Math.round(p.x);
+ int ry = Math.round(p.y);
+ int rz = Math.round(p.z);
+ if (Frog.outBrainBound(rx, ry, rz))
+ return;// 出界直接扔掉
+ Cell cell = getCell(rx, ry, rz);
+ if (cell != null) {
+ cell.addPhoton(p);
+ cell.digHole(p);
+ }
+ }
+
+ // for test purpose, reset some values for prepare next training.
+ public void prepareNewTraining() {
+ for (int i = 0; i < Env.FROG_BRAIN_XSIZE; i++) {
+ if (cells[i] != null)
+ for (int j = 0; j < Env.FROG_BRAIN_YSIZE; j++)
+ if (cells[i][j] != null)
+ for (int k = 0; k < Env.FROG_BRAIN_ZSIZE; k++) {
+ Cell cell = cells[i][j][k];
+ if (cell != null) {
+ cell.deleteAllPhotons();
+ cell.hasInput = false;
+ cell.photonSum = 0;
+ if (cell.holes != null)
+ for (Hole h : cell.holes) {
+ h.age += 100;// 强迫洞的年龄增加,用这个方法来区分开不同批次的训练
+ }
+ }
+ }
+ }
+ }
+
}
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java b/core/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java
index 44de23f..87ad70a 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java
@@ -1,128 +1,366 @@
package com.github.drinkjava2.frog.brain;
-import static java.awt.Color.BLUE;
-import static java.awt.Color.CYAN;
-import static java.awt.Color.GREEN;
-import static java.awt.Color.MAGENTA;
-import static java.awt.Color.ORANGE;
+import static java.awt.Color.BLACK;
import static java.awt.Color.RED;
-import static java.awt.Color.YELLOW;
+import static java.awt.Color.WHITE;
+//import static java.awt.BLUE;
+import static java.lang.Math.cos;
+import static java.lang.Math.round;
+import static java.lang.Math.sin;
import java.awt.Color;
import java.awt.Graphics;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import com.github.drinkjava2.frog.Application;
+import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.util.ColorUtils;
/**
* BrainPicture show first frog's brain structure, for debug purpose only
*
+ * 这个类用来画出脑图,这不是一个关键类,对脑的运行逻辑无影响,但有了脑图后可以直观地看出脑的3维结构,进行有针对性的改进
+ * 可以用鼠标进行平移、缩放、旋转,以及t、f、l、r,x五个键来选择顶视、前视、左视、右视、斜视这5个方向的视图,以及空格暂停、方向键调整切面
+ * 鼠标的动作定义在MouseAction类中。
+ *
* @author Yong Zhu
* @since 1.0
*/
-@SuppressWarnings("serial")
+@SuppressWarnings("all")
public class BrainPicture extends JPanel {
- private float brainWidth; // real brain width
- private int brainDispWidth; // screen display width
- private Color color = Color.BLACK;
+ private static final float d90 = (float) (Math.PI / 2);
- public void setColor(Color c) {
- color = c;
- }
+ Color picColor = RED;
+ int brainDispWidth; // screen display piexls width
+ float scale; // brain scale
+ int xOffset = 0; // brain display x offset compare to screen
+ int yOffset = 0; // brain display y offset compare to screen
+ float xAngle = d90 * .8f; // brain rotate on x axis
+ float yAngle = d90 / 4; // brain rotate on y axis
+ float zAngle = 0;// brain rotate on z axis
+ int xMask = -1;// x Mask
+ int yMask = -1;// y Mask
+ BufferedImage buffImg;
+ Graphics g;
+ String note;
+ public KeyAdapter keyAdapter;
public BrainPicture(int x, int y, float brainWidth, int brainDispWidth) {
super();
this.setLayout(null);// 空布局
this.brainDispWidth = brainDispWidth;
- this.brainWidth = brainWidth;
+ scale = 0.7f * brainDispWidth / brainWidth;
this.setBounds(x, y, brainDispWidth + 1, brainDispWidth + 1);
+ buffImg = new BufferedImage(Env.FROG_BRAIN_DISP_WIDTH, Env.FROG_BRAIN_DISP_WIDTH, BufferedImage.TYPE_INT_RGB);
+ g = buffImg.getGraphics();
+ MouseAction act = new MouseAction(this);
+ this.addMouseListener(act); // 添加鼠标动作监听
+ this.addMouseWheelListener(act);// 添加鼠标滚轮动作监听
+ this.addMouseMotionListener(act);// 添加鼠标移动动作监听
+
+ keyAdapter = new KeyAdapter() {// 处理t,f,l,r,x键盘命令
+ public void keyPressed(KeyEvent e) {
+ switch (e.getKeyCode()) {
+ case KeyEvent.VK_UP:// Y切面向上
+ yMask++;
+ if (yMask > Env.FROG_BRAIN_YSIZE)
+ yMask = Env.FROG_BRAIN_YSIZE;
+ break;
+ case KeyEvent.VK_DOWN:// Y切面向下
+ yMask--;
+ if (yMask < 0)
+ yMask = 0;
+ break;
+ case KeyEvent.VK_LEFT:// x切面向左
+ xMask--;
+ if (xMask < 0)
+ xMask = 0;
+ break;
+ case KeyEvent.VK_RIGHT:// x切面向右
+ xMask++;
+ if (xMask > Env.FROG_BRAIN_XSIZE)
+ xMask = Env.FROG_BRAIN_XSIZE;
+ break;
+ case ' ':// 暂停及继续
+ Application.pauseAction.actionPerformed(null);
+ break;
+ case 'T':// 顶视
+ xAngle = 0;
+ yAngle = 0;
+ zAngle = 0;
+ break;
+ case 'F':// 前视
+ xAngle = d90;
+ yAngle = 0;
+ zAngle = 0;
+ break;
+ case 'L':// 左视
+ xAngle = d90;
+ yAngle = d90;
+ zAngle = 0;
+ break;
+ case 'R':// 右视
+ xAngle = d90;
+ yAngle = -d90;
+ zAngle = 0;
+ break;
+ case 'X':// 斜视
+ xAngle = d90 * .8f;
+ yAngle = d90 / 4;
+ zAngle = 0;
+ break;
+ default:
+ }
+ }
+ };
+ addKeyListener(keyAdapter);
+ this.setFocusable(true);
+ }
+
+ public void drawCuboid(Cuboid c) {// 在脑图上画一个长立方体框架,视角是TopView
+ float x = c.x;
+ float y = c.y;
+ float z = c.z;
+ float xe = c.xe;
+ float ye = c.ye;
+ float ze = c.ze;
+
+ 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);
+
+ 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);
+
+ 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);
}
- public void drawZone( Zone z) {Graphics g = this.getGraphics();
- g.setColor(color);
- float rate = brainDispWidth / brainWidth;
- int x = Math.round(z.x * rate);
- int y = Math.round(z.y * rate);
- int radius = Math.round(z.r * rate);
- g.drawRect(x - radius, y - radius, radius * 2, radius * 2);
- }
-
- public void drawCircle( Zone z) {Graphics g = this.getGraphics();
- g.setColor(color);
- float rate = brainDispWidth / brainWidth;
- int x = Math.round(z.x * rate);
- int y = Math.round(z.y * rate);
- g.drawArc(x - 5, y - 5, 10, 10, 0, 360);
- }
-
- public void fillZone( Zone z) {Graphics g = this.getGraphics();
- g.setColor(color);
- float rate = brainDispWidth / brainWidth;
- int x = Math.round(z.x * rate);
- int y = Math.round(z.y * rate);
- int radius = Math.round(z.r * rate);
- g.fillRect(x - radius, y - radius, radius * 2, radius * 2);
- }
-
- public void drawLine(Zone z1, Zone z2) {
- Graphics g = this.getGraphics();
- g.setColor(color);
- float rate = brainDispWidth / brainWidth;
- int x1 = Math.round(z1.x * rate);
- int y1 = Math.round(z1.y * rate);
- int x2 = Math.round(z2.x * rate);
- int y2 = Math.round(z2.y * rate);
- g.drawLine(x1, y1, x2, y2);
- }
-
- public void drawText( Zone z, String text) {Graphics g = this.getGraphics();
- g.setColor(color);
- float rate = brainDispWidth / brainWidth;
- int x = Math.round(z.x * rate);
- int y = Math.round(z.y * rate);
- g.drawString(text, x - text.length() * 3 - 2, y);
- }
-
- private static final Color[] rainbow = new Color[] { RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA };
- private static int nextColor = 0;
-
- public static Color nextRainbowColor() {
- if (nextColor == rainbow.length)
- nextColor = 0;
- return rainbow[nextColor++];
- }
-
- public static Color color(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)
+ public void drawCone(Cone c) {// 在脑图上画一个锥体,视角是TopView
+ drawLine(c.x1, c.y1, c.z1, c.x2, c.y2, c.z2);// 画锥体的中心线
+ // TODO 画出锥体的上下面
+ }
+
+ /*-
+ 画线,固定以top视角的角度,所以只需要从x1,y1画一条到x2,y2的直线
+ 绕 x 轴旋转 θ
+ x, y.cosθ-zsinθ, y.sinθ+z.cosθ
+
+ 绕 y 轴旋转 θ
+ z.sinθ+x.cosθ, y, z.cosθ-x.sinθ
+
+ 绕 z 轴旋转 θ
+ x.cosθ-y.sinθ, x.sinθ+y.consθ, z
+ -*/
+ 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;
+ double x2 = px2 - Env.FROG_BRAIN_XSIZE / 2;
+ double y2 = -py2 + Env.FROG_BRAIN_YSIZE / 2;// 屏幕的y坐标是反的,显示时要正过来
+ double z2 = pz2 - Env.FROG_BRAIN_ZSIZE / 2;
+ x1 = x1 * scale;
+ y1 = y1 * scale;
+ z1 = z1 * scale;
+ x2 = x2 * scale;
+ y2 = y2 * scale;
+ z2 = z2 * 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;
+
+ y = y2 * cos(xAngle) - z2 * sin(xAngle);// 绕x轴转
+ z = y2 * sin(xAngle) + z2 * cos(xAngle);
+ y2 = y;
+ z2 = z;
+
+ x = z2 * sin(yAngle) + x2 * cos(yAngle);// 绕y轴转
+ z = z2 * cos(yAngle) - x2 * sin(yAngle);
+ x2 = x;
+ z2 = z;
+
+ x = x2 * cos(zAngle) - y2 * sin(zAngle);// 绕z轴转
+ y = x2 * sin(zAngle) + y2 * cos(zAngle);
+ x2 = x;
+ y2 = y;
+
+ g.setColor(picColor);
+ g.drawLine((int) round(x1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset,
+ (int) round(y1) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset,
+ (int) round(x2) + Env.FROG_BRAIN_DISP_WIDTH / 2 + xOffset,
+ (int) round(y2) + Env.FROG_BRAIN_DISP_WIDTH / 2 + yOffset);
+ }
+
+ /** 画出cell的中心点 */
+ public void drawCellCenter(float x, float y, float z, float diameter) {
+ if (x > 0 && (x < xMask || y < yMask))
return;
- Graphics g = this.getGraphics();// border
- g.setColor(Color.WHITE);
+ drawPoint(x + 0.5f, y + 0.5f, z + 0.5f, (int) Math.max(2, Math.round(scale * diameter)));
+ }
+
+ /** 画点,固定以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;
+
+ g.setColor(picColor);
+ 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 Cuboid brain = new Cuboid(0, 0, 0, Env.FROG_BRAIN_XSIZE, Env.FROG_BRAIN_YSIZE, Env.FROG_BRAIN_ZSIZE);
+
+ public void drawBrainPicture(Frog f) {// 在这个方法里进行青蛙三维脑结构的绘制
+ if (!f.alive)
+ return;
+ if (!Env.SHOW_FIRST_FROG_BRAIN)
+ return;
+ g.setColor(WHITE);// 先清空旧图
g.fillRect(0, 0, brainDispWidth, brainDispWidth);
- g.setColor(Color.black);
+ g.setColor(BLACK); // 画边框
g.drawRect(0, 0, brainDispWidth, brainDispWidth);
+ setPicColor(BLACK);
+ drawCuboid(brain);// 先把脑的框架画出来
+
+ for (Organ organ : f.organs)// 每个器官负责画出自已在脑图中的位置和形状
+ organ.drawOnBrainPicture(f, this); // each organ draw itself
+ setPicColor(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++) {// 开始画整个脑空间的光子和激活点阵图
+ if (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) {// 只显示激活点
+ if (cell.hasInput && x == 0) {// 如果在左边,显示黑色大圆
+ setPicColor(Color.BLACK);
+ drawCellCenter(x, y, z, 0.6f);
+ } else if (z == Env.FROG_BRAIN_ZSIZE - 1 && cell.hasInput) {// 如果在顶上边,显示兰色大圆
+ setPicColor(Color.BLUE);
+ drawCellCenter(x, y, z, 0.6f);
+ }
+
+ if (cell.photonQty > 0) {// 如果在内部,只显示有光子的cell
+ setPicColor(ColorUtils.colorByCode(cell.color));
+ float dia = 0.2f;
+ if (cell.color == 0)
+ dia = 0.3f;
+ if (x == xMask || y == yMask)
+ dia = 0.5f;
+ drawCellCenter(x, y, z, dia);
+ }
+ }
+ }
+ }
+ }
+ g.setColor(Color.black);
+ if (note != null)
+ g.drawString(note, 30, 55);
+ Graphics g2 = this.getGraphics(); // 这两行是将缓存中的图像写到屏幕上
+ g2.drawImage(buffImg, 0, 0, this);
+
+ }
+
+ public static void setNote(String note) {
+ Application.brainPic.note = note;
+ }
+
+ // getters & setters
+ public float getScale() {
+ return scale;
+ }
+
+ public void setScale(float scale) {
+ this.scale = scale;
+ }
+
+ public float getxAngle() {
+ return xAngle;
+ }
+
+ public void setxAngle(float xAngle) {
+ this.xAngle = xAngle;
+ }
+
+ public float getyAngle() {
+ return yAngle;
+ }
+
+ public void setyAngle(float yAngle) {
+ this.yAngle = yAngle;
+ }
+
+ public float getzAngle() {
+ return zAngle;
+ }
+
+ public void setzAngle(float zAngle) {
+ this.zAngle = zAngle;
+ }
+
+ public void setPicColor(Color color) {
+ this.picColor = color;
+ }
+
+ public int getxOffset() {
+ return xOffset;
+ }
+
+ public void setxOffset(int xOffset) {
+ this.xOffset = xOffset;
+ }
+
+ public int getyOffset() {
+ return yOffset;
+ }
- for (Organ organ : frog.organs)
- organ.drawOnBrainPicture(frog, this); // each organ draw itself
+ public void setyOffset(int yOffset) {
+ this.yOffset = yOffset;
}
}
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 fdae751..7dcb8ba 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
@@ -10,25 +10,179 @@
*/
package com.github.drinkjava2.frog.brain;
+import java.util.Arrays;
+
+import com.github.drinkjava2.frog.util.ColorUtils;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
/**
- * Cell is the basic unit of frog's brain
+ * Cell is the smallest unit of brain space, a Cell can have many actions and
+ * photons and holes and relations
+ *
+ * Cell是脑的最小空间单元,可以存在多个行为(由organs中的器官代号来表示)和光子(Photon)和洞(Hole)和关联(Relation),脑是由frog中的cells三维数组组
+ * 成,但不是每一维都初始化过。
+ *
+ * Cell原则上只有数据,应该把所有方法移出去,放到具体的器官行为中,见CellActions类,但暂时图省事,在Cell里放一些常用方法
+ *
+ * Jelly或MoveJelly器官有一种特殊行为,它可以产生动态触突效果,可以把具备动态触突的神经元比作一个果冻,光子来了,在上面撞了一个坑(hole)并损失能量,
+ * 如果来的多,或者速度快(能量大),一部分的光子就被从果冻的另一头撞出去了(光直线传播,寻找下一个神经元,增加信息存储单元,实现体全息存贮)。如果在另一个角度又
+ * 来了新的光子,同样的过程在发生,只不过在撞击的过程中,以前被撞出的坑里有可能被撞出光子来,沿着撞击坑的路径直线逆向返回(即波的逆向成像,两个撞击事件,如果
+ * 在短期内同时发生,或长期反复发生,就形成比较稳定的关联,这个与神经网络的hebb规则相符合,以后在这个基础上,看看能不能将深度学习的分层结构借签进来,用图形化
+ * 表示,并有可能是无级分层的,层与层之前没有明显界限。
*
* @author Yong Zhu
* @since 1.0
*/
public class Cell {
- public static final float MAX_ENERGY_LIMIT = 100.0f;
+ public int x;
+ public int y;
+ public int z;
+
+ public Cell(int x, int y, int z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ /** Active of current cell */
+ public boolean hasInput = false; // 这个细胞是否有外界信号(如光、声音)输入
+
+ public int[] organs = null; //// 每个Cell可以被多个Organ登记,这里保存organ在蛋里的序号
+
+ public Photon[] photons = null;// 光子
+
+ public Hole[] holes = null;// 洞(即动态突触),洞由光子产生,洞由时间抹平
+
+ public Relation[] relations = null;// 洞的关联关系
+
+ public int color;// Cell的颜色取最后一次被添加的光子的颜色,颜色不重要,但能方便观察
+
+ public int photonQty = 0; // 这个细胞里当前包含的光子总数
+
+ public int photonSum = 0; // 这个细胞里曾经收到的光子总数
+
+ public void regOrgan(int orgNo) {// 每个Cell可以被多个Organ登记,通常只在青蛙初始化器官时调用这个方法
+ if (organs == null)
+ organs = new int[] {};
+ organs = Arrays.copyOf(organs, organs.length + 1);
+ organs[organs.length - 1] = orgNo;
+ }
+
+ public void addPhoton(Photon p) {// 每个cell可以存在多个光子
+ if (p == null)
+ return;
+ photonQty++;
+ photonSum++;
+ color = p.color; // Cell的颜色取最后一次被添加的光子的颜色
+ if (photons == null) {
+ photons = new Photon[] { p };// 创建数组
+ return;
+ } else
+ for (int i = 0; i < photons.length; i++) { // 找空位插入,尽量重复利用内存
+ if (photons[i] == null) {
+ photons[i] = p;
+ return; // 如找到就插入,返回
+ }
+ }
+ photons = Arrays.copyOf(photons, photons.length + 1);// 否则追加新光子到未尾
+ photons[photons.length - 1] = p;
+ }
+
+ public void digHole(Photon p) {// 根据光子来把洞挖大一点,同时,如果有洞和它年龄相近,将把它们绑定起来,如果已有绑定的洞,有可能在绑定的洞里撞出光子来
+ if (p == null || p.isBackway())// 反向的光子不参与挖坑
+ return;
+ if (holes == null) {// 如果没有坑,就新挖一个
+ holes = new Hole[] { new Hole(p) }; // 新挖的坑不参与绑定
+ return;
+ }
+
+ if (RandomUtils.percent(10)) // 这个机率纯粹是为了减少光子数,增加运行速度
+ for (int i = 0; i < holes.length; i++) { // 这部分很关键,光子如果与坑同向或角度相近,会在与坑绑定的坑上撞出新的光子反向飞回,注意只针对绑定的坑
+ Hole h = holes[i];
+ if (h != null) {
+ float r = h.angleCompare(p);
+ if (r < 0.05) {
+ if (RandomUtils.percent(h.size))
+ createBackPhoton(h); // 产生光子的机率与洞的大小有关
+ } else if (r > 0.1 && r < 0.5) { // 这个叫侧抑制,角度不等但相近的光子射过来会使洞变小
+ h.size -= 10;
+ if (h.size < 10)
+ h.size = 10;
+ }
+ }
+ }
+
+ Hole found = null;
+ for (int i = 0; i < holes.length; i++) { // 先看看已存在的洞是不是与光子同向,是的话就把洞挖大一点
+ Hole h = holes[i];
+ if (h != null && h.ifSimilarWay(p)) { // 找到了与入射光子同向的洞,实际上就是同一个波源发来的
+ found = h;
+ h.size += 10;
+ h.age = 0; // 为0表示这个洞被重新激活,可以参与绑定
+ if (h.size > 100)
+ h.size = 100;
+ break;
+ }
+ }
+
+ if (found != null) { // 如果第二次扩洞,且光子和洞不是同一个器官产生的,这时可以把这个洞和其它洞关联起来了
+ for (Hole hole : holes) {
+ if (hole != found && found.organNo != hole.organNo && (Math.abs(found.age - hole.age) < 80)) {// TODO:不应用固定值
+ bind(found, hole);
+ }
+ }
+ }
+
+ if (found == null) {// 如果还没有找到旧坑,只好挖一个新坑到未尾
+ holes = Arrays.copyOf(holes, holes.length + 1);
+ holes[holes.length - 1] = new Hole(p);
+ }
+ }
- // this cell belong to frog's which organ
- public Organ organ;
+ private void createBackPhoton(Hole h) { // 根据给定的洞,把所有与它绑定的洞上撞出光子来
+ if (relations == null)
+ return;
+ for (Relation r : relations) {
+ Hole f = null;
+ if (h.equals(r.h1))
+ f = r.h2;// h2与h是一对绑定的
+ else if (h.equals(r.h2))
+ f = r.h1; // h1与h是一对绑定的
+ if (f != null) {
+ Photon back = new Photon(-1, ColorUtils.RED, f.x, f.y, f.z, -f.mx, -f.my, -f.mz);// 生成反向的光子
+ addPhoton(back);
+ // energy -= 90;
+ }
+ }
+ }
- // inputs of cell
- public Input[] inputs; // 每个细胞有一组输入触突
+ public void bind(Hole a, Hole b) {// 将两个坑绑定,以后只要有一个坑激活,另一个坑也会产生出光子
+ if (relations == null) {
+ relations = new Relation[] { new Relation(a, b) };
+ return;
+ }
+ for (Relation r : relations) {// 先看看是不是已绑过,绑过就把强度乘1.5
+ if ((r.h1 == a && r.h2 == b) || (r.h2 == a && r.h1 == b)) {
+ r.strength *= 1.5;
+ if (r.strength > 100000) // TODO: strength要有遗忘机制
+ r.strength = 100000;
+ return;
+ }
+ }
+ relations = Arrays.copyOf(relations, relations.length + 1);
+ relations[relations.length - 1] = new Relation(a, b);
+ }
- // outputs of cell
- public Output[] outputs; // 每个细胞有一组输出触突
+ public void removePhoton(int i) {// 删第几个光子
+ if (photons[i] != null) {
+ photons[i] = null;
+ photonQty--;
+ }
+ }
- // energy of cell, energy got from food
- public float energy; // 每个细胞当前的能量值
+ public void deleteAllPhotons() {
+ photons = null;
+ photonQty = 0;
+ }
}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/CellActions.java b/core/src/main/java/com/github/drinkjava2/frog/brain/CellActions.java
similarity index 90%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/CellActions.java
rename to core/src/main/java/com/github/drinkjava2/frog/brain/CellActions.java
index 8e4960d..9251262 100644
--- a/core3d/src/main/java/com/github/drinkjava2/frog/brain/CellActions.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/brain/CellActions.java
@@ -29,14 +29,16 @@ public class CellActions {
*
* 在每个测试步长中act方法都会被调用一次,这个方法针对不同的细胞类型有不同的行为逻辑,这是硬
* 编码,所以要准备多套不同的行为(可以参考动物脑细胞的活动逻辑),然后抛给电脑去随机筛选,不怕多。
+ * 同一个细胞可能有多个action,由organs数组中登记的器官号决定,调用顺序也是按器官号顺序
+ *
*
* 举例来说,以下是一些假想中的脑细胞行为:
- * 一对一,穿透,光子会穿过细胞,细胞起到中继站的作用,如果没有细胞中继,光子在真空中传播(即三维数组的当前坐标没有初始化)会迅速衰减
+ * 一对一,穿透,光子会穿过细胞,细胞起到中继站的作用,如果没有细胞中继,光子在真空中不能传播
* 一对一,转向,光子传播角度被改变成另一个绝对角度发出
* 一对一,转向,光子传播角度被改变成与器官有关的角度发出,可以模拟光线的发散(如视网膜细胞)和聚焦(如脑内成像,即沿光线发散的逆路径)
* 一对多,拆分,入射光子被拆分成多个光子,以一定的发散角发出,通常发散光子的总能量小于入射+细胞输出能量之和
* 一对多,拆分,入射光子被拆分成多个光子,发散角与器官相关
- * 多对一,聚合,入射光子被触突捕获
+ * 多对一,聚合,入射光子被细胞捕获
*/
public static void act(Frog frog, int activeNo, Cell c) {
if (c.holes != null)
@@ -62,7 +64,7 @@ public class CellActions {
continue;
p.activeNo = activeNo;
c.removePhoton(ii);
- frog.addAndWalk(p); // 让光子自已往下走,并且还挖洞
+ frog.addAndWalk(p); // 让光子自已往下走,走到哪就停到哪个细胞里
}
}
break;
@@ -81,15 +83,15 @@ public class CellActions {
continue;
p.activeNo = activeNo;
c.removePhoton(ii);
- frog.addAndWalkAndDig(p); // 让光子自已往下走,并且还挖洞
+ frog.addAndWalkAndDig(p); // 让光子自已往下走,走到哪就停到哪个细胞里,并且还在细胞上挖洞
}
}
break;
- case Organ.EYE: // 如果是视网膜细胞,它的行为是将只要Cell有输入信号,就产生向右的多个光子发散出去,模拟波源
+ case Organ.EYE: // 如果是视网膜细胞,它的行为是只要Cell有输入信号,就产生向右的多个光子发散出去,模拟波源
if (c.hasInput && RandomUtils.percent(40)) {// 随机数的作用是减少光子数,加快速度
for (float yy = -0.1f; yy <= 0.1f; yy += 0.03) {// 形成一个扇面向右发送
for (float zz = -0.1f; zz <= 0.1f; zz += 0.03) {
- Photon p = new Photon(orgNo, o.color, c.x, c.y, c.z, 1.0f, yy, zz, 100f);
+ Photon p = new Photon(orgNo, o.color, c.x, c.y, c.z, 1.0f, yy, zz);
p.activeNo = activeNo; // 用这个activeNo防止一直被赶着走
frog.addAndWalk(p);// 光子不是直接添加,而是走一格后添加在相邻的细胞上
}
@@ -100,7 +102,7 @@ public class CellActions {
if (c.hasInput && RandomUtils.percent(40)) {// 随机数的作用是减少光子数,加快速度
for (float xx = -0.3f; xx <= 0.3f; xx += 0.15) {// 形成一个扇面向下发送
for (float yy = -1f; yy <= 1f; yy += 0.06) {
- Photon p = new Photon(o.organNo, o.color, c.x, c.y, c.z, xx, yy, -1, 100f);
+ Photon p = new Photon(o.organNo, o.color, c.x, c.y, c.z, xx, yy, -1);
p.activeNo = activeNo;
frog.addAndWalk(p);// 光子不是直接添加,而是走一格后添加在相邻的细胞上
}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Cone.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Cone.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/Cone.java
rename to core/src/main/java/com/github/drinkjava2/frog/brain/Cone.java
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Cuboid.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Cuboid.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/Cuboid.java
rename to core/src/main/java/com/github/drinkjava2/frog/brain/Cuboid.java
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Hole.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Hole.java
similarity index 87%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/Hole.java
rename to core/src/main/java/com/github/drinkjava2/frog/brain/Hole.java
index 4eb77b3..c4d53a5 100644
--- a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Hole.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/brain/Hole.java
@@ -11,7 +11,7 @@
package com.github.drinkjava2.frog.brain;
/**
- * Hole can be input, output, side synapse
+ * Hole is a hole on jelly cell, it works like synapse on nerve cell
*
* 以前叫突触,现在改名叫洞,更形象一点,每个光子传来就好象在果冻上砸出个洞。管它符不符合生物脑突触这个形象,张牙舞爪的神经元变成了千创百孔的果冻,先乱试一通再说。
*
@@ -25,8 +25,8 @@ public class Hole {
public float mx; // mx,my,mz分别是光子砸出这个洞时的光子每单元移动方向在三个轴上的投影
public float my;
public float mz;
- public float size = 1;// 洞的大小,同一个方向砸来的光子越多, 洞就越大
- public int age;// 洞的年龄,一直在增长,但当洞光子砸进来或被激活产生光子时,洞的年龄就归0
+ public int size = 50;// 洞的大小1~100,这个size会按记忆曲线慢慢回复到0,接近0后这个洞就被删除回收内存,
+ public int age;// 洞的年龄,一直在增长,但一个洞有完全同向的光子再次砸进来,洞的年龄就归0
public int organNo;// 这里记录第一个撞出来这个洞的产子是由哪个器官产生出来的
public Hole(Photon p) {
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/MouseAction.java b/core/src/main/java/com/github/drinkjava2/frog/brain/MouseAction.java
similarity index 95%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/MouseAction.java
rename to core/src/main/java/com/github/drinkjava2/frog/brain/MouseAction.java
index 73d8ead..de5b59f 100644
--- a/core3d/src/main/java/com/github/drinkjava2/frog/brain/MouseAction.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/brain/MouseAction.java
@@ -9,7 +9,7 @@ import java.awt.event.MouseWheelListener;
/**
* MouseAction
*
- * 这个类用来处理脑图上的鼠标动作,有平移、旋转、缩放三种
+ * 这个类用来处理脑图BrainPicture上的鼠标动作,有平移、旋转、缩放三种
*
* @author Yong Zhu
* @since 2.0.2
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/Organ.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
index c26da8f..d2ce3ff 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
@@ -11,84 +11,166 @@
package com.github.drinkjava2.frog.brain;
import java.awt.Color;
+import java.io.Serializable;
-import com.github.drinkjava2.frog.Application;
+import com.github.drinkjava2.frog.Env;
import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.util.RandomUtils;
/**
- * Organ is a part of frog, organ can be saved in egg
+ * Organ is a cone-cylinder shape zone inside of brain,, organ can be saved in
+ * egg, organ will create cells in brain. Most organ's size, angle, location and
+ * cell parameters are randomly created
*
- * 器官是脑的一部分,多个器官在脑内可以允许重叠出现在同一位置。
+ * 器官是脑的一部分,多个器官在脑内可以允许部分或完全重叠出现在同一脑内位置,器官都是可以变异的,所有器官都会保存在蛋里面。
+ *
+ * 器官是一种外形为锥圆柱体或长方体的脑内区,它的作用是在它的形状范围内在脑细胞内登记行为,当然如果脑细胞不存在它首先会新建一个脑细胞。
+ * 器官的数量、形状、大小、角度、位置、神经元分布方式,以及神经元的内部参数可以随机生成和变异, 并由生存竟争来淘汰筛选。
+ *
+ * 器官可以组合成复杂的网络结构或曲折的信号传导路径,例如一个圆柱形神经传导器官,可以变异为由两个圆柱状传导器官首尾相接,然后这两个器官各
+ * 自变异,就有可能形成弯的传导路径或更复杂的网络结构。看起来复杂,但大自然可以做到比这更复杂的进化逻辑,先假设大自然是万能的,只要是有用的
+ * 变异逻辑,就有可能出现。
+ *
+ * 器官描述细胞的行为,其中洞数量和参数是有可能随机变异的。行为则是硬编码不可以变异,模拟单个神经元的逻辑,不同的细胞可以登记属于多个不同的
+ * 器官,虽然器官行为不可以变异,但是可以写出尽可能多种不同的行为(貌似神经元的活动也只有有限的几种),由生存竟争来筛选。
+ *
+ * 器官通常是单例,每个脑细胞都指向一些器官单例,器官这个单例参与神经活动时是无状态的,有状态的神经元的参数是保存在Cell中而不是器官中,这种设计是为了减少
+ * Cell的内存占用
+ *
+ * 信息(光子)的逻辑:
+ * 能量上限很低的细胞,相当于信息的中转站,来多少光子就转发多少光子;能量上限高的细胞,可以起到记忆作用,它的原理是多个洞、反复累集的光子能量,
+ * 可以在收到某个方向光子的信号后短暂释放,以这个细胞中为心形成一个新的波源,波的发散方向就是洞的分布方向,只有位于波的驻点位置的细胞才会吸收和释放更多
+ * 能量,光子总是直线传播,不在合适交点(波的驻点)位置的细胞吸收不到能量。
+ *
+ * 光子自带传播方向,并在每个测试步长中自动走一格,为什么还需要脑细胞的静态洞和动态洞?
+ * 因为光子只能直线传播,而洞具有分发、收集、改变光子方向等作用,能增加脑的复杂,cell中根据光子的方向动态生成的洞是智能的基石,它能将有关联关系的
+ * 重复光子信号从海量的自然界噪声信号中抽取出来产生关联。
*
* @author Yong Zhu
* @since 1.0.4
*/
-public class Organ extends Zone {
+public class Organ implements Serializable, Cloneable {// 因为要保存在蛋文件里,所以必须支持串行化
private static final long serialVersionUID = 1L;
- public String name; // 显示在脑图上的器官名称,可选
- public long fat = 0; // 如果活跃多,fat值高,则保留(及变异)的可能性大,反之则很可能丢弃掉
- // public float organWasteEnergy = 0.05f; //
- // 器官在每个测试循环中需要消耗青蛙多少能量,可以通过调节这个参数抑制器官数量无限增长
- public float organActiveEnergy = 1; // 输出器官激活需要消耗每个脑细胞多少能量
- public float organOutputEnergy = 2; // 感觉器官激活会给每个脑细胞增加多少能量
- public boolean initilized; // 通过这个标记判断是否需要手工给定它的参数初值
-
- public boolean allowBorrow() { // 是否允许在精子中将这个器官借出
- return false;
+
+ // 以下是各种器官类型,每个神经元都属于一个器官,每个器官都有一个type类型参数
+ public static final int EMPTY = 0;// 空细胞,不处理光子
+ public static final int MOVE = 1;// 会让光子沿直线走一格
+ public static final int MOVE_JELLY = 2;// 会让光子沿直线走一格,并在下一个细胞上打洞
+ public static final int EYE = 3;// 眼细胞,会根据cell激活度产生发散到各个方向的光子
+ public static final int EAR = 4;// 耳细胞,类似眼细胞,不同点是为了简化,脑内听觉区和输入区混用一个区,所以它也可吸收光子,倒过来激活cell
+ public static final int JELLY = 5; // 光子在当前细胞上可以打出洞来
+ public static final int STATIC = 6; // 只有静态洞的细胞,它忽略动态洞参数
+ public static final int MIX = 7; // 同时具有静态和动态洞的细胞
+
+ public static final int TYPE_QTY = 8;// 所有的type都是预先写好在这里的,自动生成的type也只能在写好的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 int type; // 器官类型,见上面的常量定义,这个字段通常很稳定。一旦变异,将从根本上改变器官的播种行为和神经元的行为
+
+ public Shape shape; // 器官的形状,不同的形状要写出不同的播种行为
+
+ public float cellDistance; // 细胞播种间隔,每隔多少个cell进行器官行为的播种
+
+ public float centerDensityRate; // 中心相对于边沿的播种密度比,为1时为均匀分布
+
+ public int holeLimit;// 细胞允许创建动态洞的数量上限,详见Cell类的holes.字段
+
+ public float energyLimit;// 细胞能量上限,当能量超过能存贮的上限,多余的光子能量将不被细胞吸收,直接煙灭或以光子的形式转发出去
+
+ public float outputRate;// 细胞激活后,一次脉冲会释放出细胞存贮的能量比率(或释放出一个固定值), 根据能量守恒,这个值通常小于1
+
+ public float outputDoor;// 输出阀值,细胞当前能量小于这个阀值时,细胞不会产生输出
+
+ public float inputRate;// 能量接收率,细胞存贮的能量占输入能量的比率(或吸收一个固定值), 根据能量守恒,这个值通常小于1
+
+ public float inputDoor;// 接收阀值,接收的能量小于这个阀值时,细胞不会吸收这份能量,直接煙灭或以光子的形式转发出去
+
+ public float radius;// 细胞即使没有洞,也可以处理光子,这个radius是细胞的管辖半径,但处理信号角度只限于穿透和反射或6个正方向
+
+ public float dropRate;// 是一个介于0~1的值,反映了细胞存贮能量的下降速率,在每一步长中细胞能量都以这个速率损失,可以参考遗忘曲线
+
+ // =====注意以下三个字段可以让细胞具备一些固定角度的洞,这个不占内存,但缺点是不灵活,不智能,详见与Cell类中动态洞的对比 =====
+ public Hole[] holes; // 输出洞
+
+ public Organ() {// 缺省构造器,生成具有缺省参数但没有形状的器官
+ allowVary = true;
+ allowBorrow = true;
+ type = 0;
+ cellDistance = 1;
+ centerDensityRate = 1;
+ holeLimit = 10;
+ energyLimit = 100;
+ outputRate = 30;
+ outputDoor = 30;
+ inputRate = 100;
+ inputDoor = 5;
+ radius = 1;
+ dropRate = 95;
+ holes = null;
}
- /** Each loop step call active method, Child class can override this method */
- public void active(Frog f) { // 每一步都会调用器官的active方法 ,缺省啥也不干
+ /** Only call once after organ be created */
+ public Organ[] vary(Frog f) { // 器官变异,仅会在青蛙下蛋时即new Egg(frog)中被调用一次,返回本身或变异后的一个或一组类似器官返回
+ if (!allowVary)
+ return new Organ[] { this };// 如果不允许变异,器官就把自身返回,存放在蛋里
+ // 各参数 随机有大概率小变异,小概率大变异,极小概率极大变异
+ type = RandomUtils.vary(type, 10);// 这个type通常不允许变,所以只给它10%的机率去变, 也就是说在正常变异概率上再乘以10%的变异可能性
+ shape = RandomUtils.vary(shape);
+ cellDistance = RandomUtils.vary(cellDistance);
+ centerDensityRate = RandomUtils.vary(centerDensityRate);
+ holeLimit = RandomUtils.vary(holeLimit);
+ energyLimit = RandomUtils.vary(energyLimit);
+ outputRate = RandomUtils.vary(outputRate);
+ outputDoor = RandomUtils.vary(outputDoor);
+ inputRate = RandomUtils.vary(inputRate);
+ inputDoor = RandomUtils.vary(inputDoor);
+ radius = RandomUtils.vary(radius);
+ dropRate = RandomUtils.vary(dropRate);
+ holes = RandomUtils.vary(holes);
+ return new Organ[] { this };
}
- /** If active in this organ's zone? */
- public boolean outputActive(Frog f) { // 如果一个细胞能量>10,且它的输出触突位于这个器官内,则器官被激活
- for (Cell cell : f.cells) {
- if (cell.energy > organActiveEnergy)
- for (Output output : cell.outputs) { //
- if (this.nearby(output)) {
- cell.organ.fat++;
- cell.energy -= 30;//
- return true;
- }
- }
- }
- return false;
+ /** Only call once when frog created , Child class can override this method */
+ public void init(Frog f, int orgNo) { // 在青蛙生成时会调用这个方法,进行一些初始化,通常是根据参数来播种脑细胞
+ // 里是器官播种脑细胞的具体代码,对于手工生成的器官,也可以重写这个方法,对于自动生成的器官,必须根据type和shape等来播种,要写死在这里
+ if (shape != null)
+ shape.createCellsRegOrgan(f, orgNo); // 先均匀播种脑细胞试试
}
- /** Set X, Y, Radius, name of current Organ */
- public Organ setXYRN(float x, float y, float r, String name) {
- this.setXYR(x, y, r);
- this.name = name;
- return this;
+ /** each step will call Organ's active methodd */
+ public void active(Frog f) { // 每一步测试都会调用active方法,通常用于手动生成的器官,自动生成的器官其行为仅由脑细胞来决定
+ // do nothing
}
/** Child class can override this method to drawing picture */
- public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来,子类可以重写这个方法
- if (!Application.SHOW_FIRST_FROG_BRAIN)
+ public void drawOnBrainPicture(Frog f, BrainPicture pic) { // 把器官的轮廓显示在脑图上
+ if (shape == null)
+ return;// 如果没有形状,就不画
+ if (!Env.SHOW_FIRST_FROG_BRAIN || !f.alive) // 如果不允许画或青蛙死了,就直接返回
return;
- pic.setColor(Color.BLACK); // 缺省是黑色
- pic.drawZone(this);
- if (this.name != null)
- pic.drawText(this, String.valueOf(this.name));
+ pic.setPicColor(Color.LIGHT_GRAY); // 缺省是灰色
+ shape.drawOnBrainPicture(pic);
}
- /** Only call once when frog created , Child class can override this method */
- public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次,缺省啥也不干,通常用于Group子类的初始化
+ public static Organ randomCuboidOrgan() {
+ Organ o = new Organ();
+ o.shape = RandomUtils.randomCuboid();
+ return o;
}
- /** Only call once after organ be created by new() method */
- public Organ[] vary() { // 在下蛋时每个器官会调用这个方法,缺省返回一个类似自已的副本,子类通常要覆盖这个方法
- Organ newOrgan = null;
- try {
- newOrgan = this.getClass().newInstance();
- } catch (Exception e) {
- throw new UnknownError("Can not make new Organ copy for " + this);
- }
- copyXYR(this, newOrgan);
- newOrgan.name = this.name;
- newOrgan.fat = this.fat;
- return new Organ[] { newOrgan };
+ public static Organ randomConeOrgan() {
+ Organ o = new Organ();
+ o.shape = RandomUtils.randomCone();
+ return o;
}
}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Photon.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Photon.java
similarity index 97%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/Photon.java
rename to core/src/main/java/com/github/drinkjava2/frog/brain/Photon.java
index 9b0c541..b8e9db6 100644
--- a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Photon.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/brain/Photon.java
@@ -31,11 +31,12 @@ public class Photon {
public int organNo;// 每个光子是由哪个器官产生的,为-1表示它不是器官产生而是由细胞动态生成的反向光子信号
public int color;// 每个光子都有自已的颜色,由产生光子的器官的颜色来决定,颜色不重要,但能方便观察
public int activeNo;// 每一轮循环都有一个编号,光子走一格后就加上这个编号,同一个循环如果遇到相同编号的光子就跳过,防止光子被一直赶着走
+ public int energy;
public Photon() { // 缺省构造器
}
- public Photon(int organNo, int color, float x, float y, float z, float mx, float my, float mz, float energy) {
+ public Photon(int organNo, int color, float x, float y, float z, float mx, float my, float mz) {
this.x = x;
this.y = y;
this.z = z;
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Relation.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Relation.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/Relation.java
rename to core/src/main/java/com/github/drinkjava2/frog/brain/Relation.java
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Shape.java b/core/src/main/java/com/github/drinkjava2/frog/brain/Shape.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/Shape.java
rename to core/src/main/java/com/github/drinkjava2/frog/brain/Shape.java
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Ear.java b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Ear.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Ear.java
rename to core/src/main/java/com/github/drinkjava2/frog/brain/organ/Ear.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
index 29d9686..a9c06f2 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
@@ -10,129 +10,55 @@
*/
package com.github.drinkjava2.frog.brain.organ;
-import com.github.drinkjava2.frog.Application;
-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.Input;
+import com.github.drinkjava2.frog.brain.Cuboid;
import com.github.drinkjava2.frog.brain.Organ;
-import com.github.drinkjava2.frog.brain.Zone;
-import com.github.drinkjava2.frog.util.RandomUtils;
+import com.github.drinkjava2.frog.util.ColorUtils;
+import com.github.drinkjava2.frog.util.PixelsUtils;
/**
- * Eye can only see 4 direction
+ * Eye can only see env material
*
* @author Yong Zhu
- * @since 1.0
*/
-public class Eye extends Organ {// 这个Eye是老版的眼睛,只能看到四个方向,但它的调节距离会自动随机调整到一个最佳值,这就是随机试错算法的一个应用
+public class Eye extends Organ {// 眼睛是长方体
private static final long serialVersionUID = 1L;
- public int seeDistance; // 眼睛能看到的距离
- @Override
- public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次
- if (!initilized) {
- initilized = true;
- organOutputEnergy = 30;
- seeDistance = 8;
- }
+ public Eye() {
+ this.shape = new Cuboid(0, 3, 2, 1, 13, 13);
+ this.type = Organ.EYE;
+ this.organName = "Eye";
+ this.allowVary = false;// 不允许变异
+ this.allowBorrow = false;// 不允许借出
+ this.color = ColorUtils.GRAY;
}
- @Override
- public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
- if (!Application.SHOW_FIRST_FROG_BRAIN)
- return;
- super.drawOnBrainPicture(f, pic);
- float qRadius = r / 4;
- float q3Radius = (float) (r * .75);
- Zone seeUp = new Zone(x, y + q3Radius, qRadius);
- Zone seeDown = new Zone(x, y - q3Radius, qRadius);
- Zone seeLeft = new Zone(x - q3Radius, y, qRadius);
- Zone seeRight = new Zone(x + q3Radius, y, qRadius);
- pic.drawZone(seeUp);
- pic.drawZone(seeDown);
- pic.drawZone(seeLeft);
- pic.drawZone(seeRight);
- }
-
- @Override
- public Organ[] vary() {
- if (RandomUtils.percent(5)) { // 可视距离有5%的机率变异
- seeDistance = seeDistance + 1 - 2 * RandomUtils.nextInt(2);
- if (seeDistance < 1)
- seeDistance = 1;
- if (seeDistance > 50)
- seeDistance = 50;
- }
- return new Organ[] { this };
+ /** Clear image on retina */
+ public void seeNothing(Frog f) {// 外界可以直接调用这个方法,清除视网膜图像
+ f.setCuboidVales((Cuboid) shape, false);
}
- @Override
- public void active(Frog f) {
- // 第一个眼睛只能观察上、下、左、右四个方向有没有食物
- float qRadius = r / 4;
- float q3Radius = (float) (r * .75);
- Zone seeUp = new Zone(x, y + q3Radius, qRadius);
- Zone seeDown = new Zone(x, y - q3Radius, qRadius);
- Zone seeLeft = new Zone(x - q3Radius, y, qRadius);
- Zone seeRight = new Zone(x + q3Radius, y, qRadius);
-
- boolean seeSomething = false;
- boolean atUp = false;
- boolean atDown = false;
- boolean atLeft = false;
- boolean atRight = false;
-
- for (int i = 1; i < seeDistance; i++)
- if (Env.foundAnyThing(f.x, f.y + i)) {
- seeSomething = true;
- atUp = true;
- break;
- }
-
- for (int i = 1; i < seeDistance; i++)
- if (Env.foundAnyThing(f.x, f.y - i)) {
- seeSomething = true;
- atDown = true;
- break;
- }
-
- for (int i = 1; i < seeDistance; i++)
- if (Env.foundAnyThing(f.x - i, f.y)) {
- seeSomething = true;
- atLeft = true;
- break;
- }
-
- for (int i = 1; i < seeDistance; i++)
- if (Env.foundAnyThing(f.x + i, f.y)) {
- seeSomething = true;
- atRight = true;
- break;
- }
-
- if (seeSomething)
- for (Cell cell : f.cells) {
- if (cell.energy < 100)
- for (Input input : cell.inputs) {
- if (input.nearby(this)) {
- if (atUp && input.nearby(seeUp)) {
- input.cell.energy += organOutputEnergy;
- }
- if (atDown && input.nearby(seeDown)) {
- input.cell.energy += organOutputEnergy;
- }
- if (atLeft && input.nearby(seeLeft)) {
- input.cell.energy += organOutputEnergy;
- }
- if (atRight && input.nearby(seeRight)) {
- input.cell.energy += organOutputEnergy;
- }
- }
- }
- }
+ /**
+ * Accept a byte[x][y] array, active tubes located on eye's retina
+ *
+ * 接收一个二维数组,激活它视网膜所在的脑空间
+ */
+ public void seeImage(Frog f, byte[][] pixels) {// 外界可以直接调用这个方法,硬塞一个象素图到视网膜上
+ if (!f.alive)
+ return;
+ int w = pixels.length;
+ int h = pixels[0].length;
+ Cuboid c = (Cuboid) shape;
+ // 在视网膜上产生字母像素点阵,即激活这个脑视网膜所在的cells区,然后由器官播种出的脑细胞负责将激活能量转为光子输送、存贮到其它位置
+ for (int px = 0; px < w; px++)
+ for (int py = 0; py < h; py++)
+ if (pixels[px][py] > 0)
+ f.getOrCreateCell(0, c.y + c.ye - px - 1, c.z + py).hasInput = true;
}
+ public void seeImageWithOffset(Frog f, byte[][] pixels, int xOff, int yOff) {// 外界硬塞一个象素图到视网膜上,并给出偏移量
+ byte[][] newPixels = PixelsUtils.offset(pixels, xOff, yOff);
+ seeImage(f, newPixels);
+ }
}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveJelly.java b/core/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveJelly.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveJelly.java
rename to core/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveJelly.java
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 ac5128c..a641e30 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
@@ -16,24 +16,14 @@ import java.util.List;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Organ;
-import com.github.drinkjava2.frog.brain.group.Group;
-import com.github.drinkjava2.frog.brain.organ.Active;
-import com.github.drinkjava2.frog.brain.organ.Chance;
-import com.github.drinkjava2.frog.brain.organ.Eat;
+import com.github.drinkjava2.frog.brain.organ.Ear;
import com.github.drinkjava2.frog.brain.organ.Eye;
-import com.github.drinkjava2.frog.brain.organ.Happy;
-import com.github.drinkjava2.frog.brain.organ.Hungry;
-import com.github.drinkjava2.frog.brain.organ.MoveDown;
-import com.github.drinkjava2.frog.brain.organ.MoveLeft;
-import com.github.drinkjava2.frog.brain.organ.MoveRight;
-import com.github.drinkjava2.frog.brain.organ.MoveUp;
-import com.github.drinkjava2.frog.brain.organ.NewEye;
-import com.github.drinkjava2.frog.brain.organ.Pain;
+import com.github.drinkjava2.frog.brain.organ.MoveJelly;
import com.github.drinkjava2.frog.util.RandomUtils;
/**
- * Egg is the static structure description of frog, can save as text file, to
- * build a frog, first need build a egg.
+ * Egg is the static structure description of frog, can save as file, to build a
+ * frog, first need build a egg.
*
* 蛋存在的目的是为了以最小的字节数串行化存储Frog,它是Frog的生成算法描述,而不是Frog本身,这样一来Frog就不能"永生"了,因为每一个egg都不等同于
* 它的母体, 而且每一次测试,大部分条件反射的建立都必须从头开始训练,类似于人类,无论人类社会有多聪明, 婴儿始终是一张白纸,需要花大量的时间从头学习。
@@ -42,59 +32,51 @@ import com.github.drinkjava2.frog.util.RandomUtils;
* @since 1.0
*/
public class Egg implements Serializable {
- // 为了缩短时间,这个程序随机生成的联结将只落在固定的器官上而不是漫天撒网(见4.12提交),这是程序的优化,实现的逻辑和随机漫天撒网定是相同的。
- // 但是这个优化带来的问题是这是一个硬编码逻辑,不利于器官的优胜劣汰, 而且下面这个 FIXED_ORGAN_QTY必须每次手工设定,以后需要重构这块的代码
- public static int FIXED_ORGAN_QTY = 11;
-
private static final long serialVersionUID = 1L;
- public List organs = new ArrayList<>();
-
- public List groups = new ArrayList<>();
+ public List organs = new ArrayList<>();// NOSONAR
public Egg() {// 无中生有,创建一个蛋,先有蛋,后有蛙
- organs.add(new Happy().setXYRN(600, 700, 60, "Happy")); // Happy必须第一个加入
- organs.add(new Hungry().setXYRN(300, 100, 60, "Hungry"));
- organs.add(new MoveUp().setXYRN(800, 100, 60, "Up"));
- organs.add(new MoveDown().setXYRN(800, 400, 60, "Down"));
- organs.add(new MoveLeft().setXYRN(700, 250, 60, "Left"));
- organs.add(new MoveRight().setXYRN(900, 250, 60, "Right"));
- organs.add(new Eye().setXYRN(100, 300, 100, "Eye"));
- organs.add(new NewEye().setXYRN(200, 700, 200, "NewEye"));
- organs.add(new Pain().setXYRN(800, 700, 60, "Pain")); // 痛苦在靠近边界时触发
- organs.add(new Active().setXYRN(500, 100, 60, "Active")); // 永远激活
- organs.add(new Chance().setXYRN(650, 100, 60, "Chance")); // 永远激活
-
- // 以上为11个, 就是FIXED_ORGAN_QTY值
-
- organs.add(new Eat().setXYRN(0, 0, 0, "Eat")); // EAT不是感觉或输出器官,没有位置和大小
-
+ organs.add(new MoveJelly()); // MoveJelly即移动光子,也是果冻记忆细胞,本来可以分成两个器官的,图省事
+ organs.add(new Eye()); // 眼是手工创建的,必有
+ organs.add(new Ear()); // 耳是手工创建的,这个是用来测试ABCD字母识别的
}
/** Create egg from frog */
public Egg(Frog frog) { // 青蛙下蛋,每个青蛙的器官会创建自已的副本或变异,可以是0或多个
for (Organ organ : frog.organs)
- for (Organ newOrgan : organ.vary())
+ for (Organ newOrgan : organ.vary(frog))
organs.add(newOrgan);
}
/**
- * Create a egg by join 2 eggs, x+y=zygote 模拟X、Y 染色体合并,两个蛋生成一个新的蛋, X从Y里借一个器官,
- * 不用担心器官会越来越多,因为通过用进废退原则来筛选,没用到的器官会在几代之后被自然淘汰掉
- * 器官不是越多越好,因为器官需要消耗能量,器官数量多了,在生存竞争中也是劣势
- *
+ * Create a egg by join 2 eggs, x+y=zygote 模拟X、Y 染色体合并,两个蛋生成一个新的蛋,
+ * X有可能从Y里的相同位置借一个器官
*/
public Egg(Egg x, Egg y) {
+ for (Organ organ : x.organs) {
+ if (!organ.allowVary || organ.fat != 0 || RandomUtils.percent(70)) // 如果器官没用到,fat为0,增加丢弃它的机率
+ organs.add(organ);
+ }
// x里原来的organ
- for (Organ organ : x.organs)
- organs.add(organ);
-
- // 从y里借一个organ
- int yOrganSize = y.organs.size();
- if (yOrganSize > 0) {
- Organ o = y.organs.get(RandomUtils.nextInt(yOrganSize));
- if (o.allowBorrow())
- organs.add(o);
+ if (RandomUtils.percent(70)) // 70%的情况下不作为, x就是受精卵
+ return;
+ // 从y里借一个organ,替换掉原来位置的organ,相当于DNA级别的片段切换,它要求一个随机位置的Organ都允许替换allowBorrow
+ // int yOrganSize = y.organs.size();
+ // if (yOrganSize > 0) {
+ // int i = RandomUtils.nextInt(yOrganSize);
+ // Organ o = y.organs.get(i);
+ // if (o.allowBorrow) {
+ // if (organs.size() > i && organs.get(i).allowBorrow)
+ // organs.set(i, o);// 用y里的organ替换掉x里的organ,模拟受精
+ // }
+ // }
+ // if (RandomUtils.percent(50))// 有50%的机率随机会产生新的器官
+ // organs.add(Organ.randomCuboidOrgan());
+ if (RandomUtils.percent(organs.size())) {// 器官会随机丢失,并且机率与器官数量成正比,防止器官无限增长
+ int i = RandomUtils.nextInt(organs.size());
+ if (organs.get(i).allowBorrow)
+ organs.remove(i);
}
}
diff --git a/core/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java b/core/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
index 4e36670..54de0a4 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
@@ -22,8 +22,6 @@ import java.util.List;
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.Chance;
-import com.github.drinkjava2.frog.brain.organ.Eye;
import com.github.drinkjava2.frog.util.FrogFileUtils;
/**
@@ -54,10 +52,9 @@ public class EggTool {
ObjectOutputStream so = new ObjectOutputStream(fo);
so.writeObject(Env.eggs);
so.close();
- System.out.print("\r1st frog has " + first.organs.size() + " organs, energy=" + first.energy + ", seeDist="
- + ((Eye) first.organs.get(6)).seeDistance + ", chance=" + ((Chance) first.organs.get(10)).percent);
+ System.out.print("Fist frog has " + first.organs.size() + " organs, energy=" + first.energy);
System.out.println(", Last frog has " + last.organs.size() + " organs, energy=" + last.energy);
- System.out.println("Saved "+Env.eggs.size() +" eggs to file '" + Application.CLASSPATH + "eggs.ser'");
+ System.out.println("Saved " + Env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs.ser'");
} catch (IOException e) {
System.out.println(e);
}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/objects/EnvObject.java b/core/src/main/java/com/github/drinkjava2/frog/objects/EnvObject.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/objects/EnvObject.java
rename to core/src/main/java/com/github/drinkjava2/frog/objects/EnvObject.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/objects/Food.java b/core/src/main/java/com/github/drinkjava2/frog/objects/Food.java
index ea03051..7489171 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/objects/Food.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/objects/Food.java
@@ -23,7 +23,7 @@ import com.github.drinkjava2.frog.util.RandomUtils;
* @author Yong Zhu
* @since 1.0
*/
-public class Food implements Object {
+public class Food implements EnvObject {
@Override
public void build() {
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java b/core/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java
similarity index 95%
rename from core3d/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java
rename to core/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java
index 056f109..dd0531c 100644
--- a/core3d/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java
@@ -26,7 +26,7 @@ import com.github.drinkjava2.frog.util.StringPixelUtils;
* @since 1.0
*/
public class LetterTester implements EnvObject {
- public static final String STR = "对酒当歌人生几何";
+ public static final String STR = "一二三";
public static final int TIME = 120;
@Override
@@ -54,7 +54,7 @@ public class LetterTester implements EnvObject {
} else {
int index2 = index % STR.length();
BrainPicture.setNote("第" + (index2 + 1) + "个字识别");
- eye.seeImageWithOffset(frog, StringPixelUtils.getSanserif12Pixels(STR.substring(index2, index2 + 1)),0,0);
+ eye.seeImageWithOffset(frog, StringPixelUtils.getSanserif12Pixels(STR.substring(index2, index2 + 1)),1,1);
if (Env.step % TIME > (TIME - 2)) {
int result = ear.readcode(frog);
System.out.println("Max=" + result+", 即 '"+STR.substring(result, result+1)+"'");
diff --git a/core/src/main/java/com/github/drinkjava2/frog/objects/Material.java b/core/src/main/java/com/github/drinkjava2/frog/objects/Material.java
index ca66cc7..584361f 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/objects/Material.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/objects/Material.java
@@ -15,21 +15,22 @@ import java.awt.Color;
/**
* Object means some thing in Env
*
+ * 用不同的数字常量代表虚拟环境中不同的组成材料,0为空,小于10的不可见,大于20的将杀死在同一位置出现的青蛙,例如砖头和青蛙不可以重叠出现在同一位置
+ *
* @author Yong Zhu
* @since 1.0
*/
public class Material {
- public static final byte VISIBLE = 10; // if>=10 will visible to frog
- public static final byte KILLFROG = 20; // if>=20 will kill frog
-
- public static final byte NO = 0;
+ public static final byte NO = 0; // nothing
public static final byte SEESAW_BASE = 1; // 1~9 is invisible to frog
+ public static final byte VISIBLE = 10; // if>=10 will visible to frog
public static final byte FOOD = VISIBLE + 1;
- public static final byte SEESAW = VISIBLE + 2; // if <0 will not cause frog die
+ public static final byte SEESAW = VISIBLE + 2;
- public static final byte BRICK = KILLFROG + 1;
- public static final byte TRAP = KILLFROG + 2;
+ public static final byte KILLFROG = 20; // if>=20 will kill frog
+ public static final byte BRICK = KILLFROG + 1;// brick will kill frog
+ public static final byte TRAP = KILLFROG + 2; // trap will kill frog
public static Color color(byte material) {
if (material == TRAP)
diff --git a/core/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java b/core/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java
index 5f220ae..ca1f212 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java
@@ -24,7 +24,7 @@ import com.github.drinkjava2.frog.util.RandomUtils;
* @author Yong Zhu
* @since 2.0.1
*/
-public class SeeSaw implements Object {
+public class SeeSaw implements EnvObject {
private static final int LEGNTH = 300;
private static final int CENTER_X = Env.ENV_WIDTH / 2;
private static final int CENTER_Y = Env.ENV_HEIGHT / 2;
@@ -40,7 +40,7 @@ public class SeeSaw implements Object {
@Override
public void destory() {
-
+ // do nothing
}
@Override
diff --git a/core/src/main/java/com/github/drinkjava2/frog/objects/Trap.java b/core/src/main/java/com/github/drinkjava2/frog/objects/Trap.java
index 0b7fc68..ff89086 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/objects/Trap.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/objects/Trap.java
@@ -24,7 +24,7 @@ import com.github.drinkjava2.frog.Frog;
* @since 2019-08-05
*/
@SuppressWarnings("all")
-public class Trap implements Object {
+public class Trap implements EnvObject {
private static final int X1 = ENV_WIDTH / 2 - 350 / 2; // 陷阱左上角
private static final int Y1 = ENV_HEIGHT / 2 - 20 / 2; // 陷阱左上角
private static final int X2 = ENV_WIDTH / 2 + 350 / 2; // 陷阱右下角
@@ -49,8 +49,4 @@ public class Trap implements Object {
}
- public static boolean inTrap(Frog f) {
- return f.x >= X1 && f.x <= X2 && f.y >= Y1 && f.y <= Y2;
- }
-
}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/util/ColorUtils.java b/core/src/main/java/com/github/drinkjava2/frog/util/ColorUtils.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/util/ColorUtils.java
rename to core/src/main/java/com/github/drinkjava2/frog/util/ColorUtils.java
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/util/PixelsUtils.java b/core/src/main/java/com/github/drinkjava2/frog/util/PixelsUtils.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/util/PixelsUtils.java
rename to core/src/main/java/com/github/drinkjava2/frog/util/PixelsUtils.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java b/core/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java
index b7827bc..efca33c 100644
--- a/core/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java
+++ b/core/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java
@@ -10,11 +10,17 @@
*/
package com.github.drinkjava2.frog.util;
+import static com.github.drinkjava2.frog.Env.FROG_BRAIN_XSIZE;
+import static com.github.drinkjava2.frog.Env.FROG_BRAIN_YSIZE;
+import static com.github.drinkjava2.frog.Env.FROG_BRAIN_ZSIZE;
+
import java.util.Random;
-import com.github.drinkjava2.frog.Frog;
-import com.github.drinkjava2.frog.brain.Zone;
-import com.github.drinkjava2.frog.egg.Egg;
+import com.github.drinkjava2.frog.Env;
+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.Shape;
/**
* Random Utilities used in this project
@@ -23,6 +29,10 @@ import com.github.drinkjava2.frog.egg.Egg;
* @since 1.0
*/
public class RandomUtils {
+
+ private RandomUtils() {
+ }
+
private static final Random rand = new Random();
public static int nextInt(int i) {
@@ -33,83 +43,90 @@ public class RandomUtils {
return rand.nextFloat();
}
- /** Return a random zone inside of a zone */
- public static Zone randomZoneInZone(Zone z) { // 在一个区内随机取一个小小区
- return new Zone(z.x - z.r + z.r * 2 * rand.nextFloat(), z.y - z.r + z.r * 2 * rand.nextFloat(),
- z.r * rand.nextFloat() * .04f);
+ public static boolean percent(float percent) {// 有百分这percent的机率为true
+ return rand.nextInt(100) < percent;
}
- /** Return a random zone inside of frog's random organ */
- public static Zone randomPosInAnyFrogOrgan(Frog f) {
- if (f.organs == null || f.organs.size() == 0)
- throw new IllegalArgumentException("Can not call randomPosInRandomOrgan method when frog has no organ");
- return randomZoneInZone(f.organs.get(RandomUtils.nextInt(Egg.FIXED_ORGAN_QTY)));
+ /** Randomly create a Cuboid inside of brain space */
+ public static Cuboid randomCuboid() {// 随机生成一个位于脑空间内的立方体
+ Cuboid c = new Cuboid();
+ c.x = nextInt(FROG_BRAIN_XSIZE) - FROG_BRAIN_XSIZE / 4;// 为了多产生贴边的立方体,超出边界的被裁切
+ if (c.x < 0)
+ c.x = 0;
+ c.y = nextInt(FROG_BRAIN_YSIZE) - FROG_BRAIN_YSIZE / 4;
+ if (c.y < 0)
+ c.y = 0;
+ c.z = nextInt(FROG_BRAIN_ZSIZE) - FROG_BRAIN_ZSIZE / 4;
+ if (c.z < 0)
+ c.z = 0;
+ c.xe = 1 + nextInt(FROG_BRAIN_XSIZE); // 立方体任一个边长至少是1
+ if (c.xe > (FROG_BRAIN_XSIZE - c.x))// 超出边界的被裁切
+ c.xe = FROG_BRAIN_XSIZE - c.x;
+ c.ye = 1 + nextInt(FROG_BRAIN_YSIZE);
+ if (c.ye > (FROG_BRAIN_YSIZE - c.y))
+ c.ye = FROG_BRAIN_YSIZE - c.y;
+ c.ze = 1 + nextInt(FROG_BRAIN_ZSIZE);
+ if (c.ze > (FROG_BRAIN_ZSIZE - c.z))
+ c.ze = FROG_BRAIN_ZSIZE - c.z;
+ return c;
}
- /** Return a random zone inside of frog's random organ */
- public static Zone randomPosMostInNewEye(Frog f) {
- if (f.organs == null || f.organs.size() == 0)
- throw new IllegalArgumentException("Can not call randomPosInRandomOrgan method when frog has no organ");
- if (RandomUtils.percent(95))
- return randomZoneInZone(f.organs.get(7));// 这是一个硬编码,大部分新联接建立在newEye中
- return randomZoneInZone(f.organs.get(RandomUtils.nextInt(Egg.FIXED_ORGAN_QTY)));
+ /** Randomly create a Cone inside of brain space */
+ public static Cone randomCone() {// 随机生成一个位于脑空间内的锥体
+ Cone c = new Cone();
+ c.x1 = nextInt(Env.FROG_BRAIN_XSIZE);
+ c.y1 = nextInt(Env.FROG_BRAIN_YSIZE);
+ c.z1 = nextInt(Env.FROG_BRAIN_ZSIZE);
+ c.x2 = nextInt(Env.FROG_BRAIN_XSIZE);
+ c.y2 = nextInt(Env.FROG_BRAIN_YSIZE);
+ c.z2 = nextInt(Env.FROG_BRAIN_ZSIZE);
+ c.r1 = nextInt(Env.FROG_BRAIN_ZSIZE / 2);// 暂时以z边长的一半取随机数
+ c.r2 = nextInt(Env.FROG_BRAIN_ZSIZE / 2);
+ return c;
}
- public static boolean percent(float percent) {
- return rand.nextFloat() * 100 < percent;
+ public static int vary(int v, int percet) {
+ if (percent(percet))
+ return vary(v);
+ return v;
}
- // /** vary a zone position, size a little bit */
- // public static void varyZone(Zone z) {
- // int i = rand.nextInt(100);
- // if (i < 95) // 有95的机率不变异
- // return;
- // z.x = varyByRate(z.x, 0.01f);
- // z.y = varyByRate(z.y, 0.01f);
- // z.r = varyByRate(z.r, 0.03f);
- // }
-
- // public static float varyByRate(float f, float rate) { // 用指定的机率变异
- // boolean bigger = rand.nextInt(2) > 0;
- // if (bigger)
- // f = f + f * rate * rand.nextFloat() + .001f;
- // else
- // f = f - f * rate * rand.nextFloat() - .001f;
- // if (Float.isNaN(f))
- // f = 0f;
- // if (f > 1000000f)
- // f = 1000000f;
- // else if (f < -1000000f)
- // f = -1000000f;
- // return f;
- // }
-
- // public static float vary(float f) { // 大部分时候不变,有极小机会变异,有极极小机会大变异,有极极极小机会大大大变异
- // int i = rand.nextInt(100);
- // if (i < 50) // 有50的机率不变异
- // return f;
- // float rate = 0.2f; // 50%机率在0.2倍范围变异
- // if (i > 80)
- // rate = 1f; // 有20%的机率在1倍的范围变异
- // if (i > 90)
- // rate = 10f; // 有10%的机率在10倍的范围变异
- // if (i > 95)
- // rate = 100f; // 有5%的机率在100倍的范围变异
- // if (i > 98)
- // rate = 1000f; // 有1%的机率在1000倍的范围变异
- //
- // boolean bigger = rand.nextInt(2) > 0;
- // if (bigger)
- // f = f + f * rate * rand.nextFloat() + .001f;
- // else
- // f = f - f * rate * rand.nextFloat() - .001f;
- // if (Float.isNaN(f))
- // f = 0f;
- // if (f > 1000000f)
- // f = 1000000f;
- // else if (f < -1000000f)
- // f = -1000000f;
- // return f;
- // }
+ public static int vary(int v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异
+ if (percent(40))
+ v *= .98 + .04 * nextFloat(); // 0.98~1.02
+ if (percent(10))
+ v *= .95 + .103 * nextFloat(); // 0.95~1.053
+ else if (percent(5))
+ v *= .08 + 0.45 * nextFloat(); // 0.8~1.25
+ else if (percent(1))
+ v *= .05 + 1.5 * nextFloat(); // 0.5~2
+ return v;
+ }
+
+ public static float vary(float v, int percet) {
+ if (percent(percet))
+ return vary(v);
+ return v;
+ }
+
+ public static float vary(float v) {// 随机有大概率小变异,小概率大变异,极小概率极大变异
+ if (percent(40))
+ v *= .98 + .04 * nextFloat(); // 0.98~1.02
+ if (percent(10))
+ v *= .95 + .103 * nextFloat(); // 0.95~1.053
+ else if (percent(5))
+ v *= .08 + 0.45 * nextFloat(); // 0.8~1.25
+ else if (percent(1))
+ v *= .05 + 1.5 * nextFloat(); // 0.5~2
+ return v;
+ }
+
+ public static Shape vary(Shape shape) {// 随机有大概率小变异,小概率大变异,极小概率极大变异
+ return shape; // TODO shape的变异
+ }
+
+ public static Hole[] vary(Hole[] holes) {// 随机有大概率小变异,小概率大变异,极小概率极大变异
+ return holes; // TODO holes的变异
+ }
}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/util/StringPixelUtils.java b/core/src/main/java/com/github/drinkjava2/frog/util/StringPixelUtils.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/util/StringPixelUtils.java
rename to core/src/main/java/com/github/drinkjava2/frog/util/StringPixelUtils.java
diff --git a/eggs.ser b/eggs.ser
new file mode 100644
index 0000000..cea85db
Binary files /dev/null and b/eggs.ser differ
diff --git a/core3d/LICENSE b/history/001_first_version/LICENSE
similarity index 100%
rename from core3d/LICENSE
rename to history/001_first_version/LICENSE
diff --git a/core3d/maven_clean.bat b/history/001_first_version/maven_clean.bat
similarity index 100%
rename from core3d/maven_clean.bat
rename to history/001_first_version/maven_clean.bat
diff --git a/core3d/maven_eclipse_clean.bat b/history/001_first_version/maven_eclipse_clean.bat
similarity index 100%
rename from core3d/maven_eclipse_clean.bat
rename to history/001_first_version/maven_eclipse_clean.bat
diff --git a/core3d/maven_eclipse_eclipse.bat b/history/001_first_version/maven_eclipse_eclipse.bat
similarity index 100%
rename from core3d/maven_eclipse_eclipse.bat
rename to history/001_first_version/maven_eclipse_eclipse.bat
diff --git a/history/001_first_version/pom.xml b/history/001_first_version/pom.xml
new file mode 100644
index 0000000..ccec02b
--- /dev/null
+++ b/history/001_first_version/pom.xml
@@ -0,0 +1,110 @@
+
+ 4.0.0
+ com.gitee.drinkjava2
+ frog001
+ jar
+ 1.0
+
+ frog
+ An artificial life test project
+ https://gitee.com/drinkjava2/jsqlbox/frog
+
+
+ gitee Issue
+ https://gitee.com/drinkjava2/jsqlbox/frog/issues
+
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+
+ Yong Zhu
+ yong9981@gmail.com
+ https://gitee.com/drinkjava2/
+
+
+
+
+ scm:git@gitee.com:drinkjava2/frog.git
+ scm:git@gitee.com:drinkjava2/frog.git
+ git@gitee.com:drinkjava2/frog.git
+
+
+
+ UTF-8
+ UTF-8
+ UTF-8
+
+ 1.8
+ 6
+ 3.3
+ 2.6
+ 3.0.0
+ 2.7
+ 2.19
+ 2.6
+ 2.4
+ 2.10.3
+ 1.6
+
+
+
+
+
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.54
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${version.compiler-plugin}
+
+ ${version.java}
+ ${version.java}
+ UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.2
+
+
+
+ true
+ false
+ lib/
+ com.github.drinkjava2.frog.Application
+
+
+
+
+
+
+
+
+
+
+
diff --git a/history/001_first_version/run.bat b/history/001_first_version/run.bat
new file mode 100644
index 0000000..fa4fed9
--- /dev/null
+++ b/history/001_first_version/run.bat
@@ -0,0 +1,4 @@
+call mvn clean compile
+cd target\classes
+java -classpath ".;*" com.github.drinkjava2.frog.env.Application
+@pause
\ No newline at end of file
diff --git a/core3d/run.sh b/history/001_first_version/run.sh
similarity index 100%
rename from core3d/run.sh
rename to history/001_first_version/run.sh
diff --git a/history/001_first_version/src/main/java/com/github/drinkjava2/frog/Frog.java b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/Frog.java
new file mode 100644
index 0000000..708a9a6
--- /dev/null
+++ b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/Frog.java
@@ -0,0 +1,247 @@
+/*
+ * 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;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import javax.imageio.ImageIO;
+
+import com.github.drinkjava2.frog.brain.Cell;
+import com.github.drinkjava2.frog.brain.Input;
+import com.github.drinkjava2.frog.brain.Output;
+import com.github.drinkjava2.frog.egg.CellGroup;
+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;
+
+/**
+ * Frog = brain + body(mouth, eye, leg), but now let's focus on brain, ignore
+ * body
+ *
+ * 为了简化模型,这个类里出现多个固定数值的编码,以后要改进成可以可以放在蛋里遗传进化的动态数值,先让生命延生是第一步,优化是以后的事
+ *
+ * @author Yong Zhu
+ * @since 1.0.0
+ */
+public class Frog {
+
+ /** brain radius virtual unit */
+ public float brainRadius;
+
+ /** brain cells */
+ List cells = new ArrayList();
+
+ /** 视觉细胞的输入区在脑中的坐标,先随便取 在原点附件就可以了,以后再考虑放到蛋里去进化 */
+ public static Zone eye = new Zone(0, 0, 300);
+
+ /** 运动细胞的输入区在脑中的坐标,先随便取就可以了,以后再考虑放到蛋里去进化 */
+ 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;
+ static {
+ try {
+ frogImg = ImageIO.read(new FileInputStream(Application.CLASSPATH + "frog.png"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ 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);
+ this.brainRadius = egg.brainRadius;
+ for (int k = 0; k < egg.cellgroups.length; k++) {
+ CellGroup g = egg.cellgroups[k];
+ for (int i = 0; i < g.cellQty; i++) {// 开始根据蛋来创建脑细胞
+ Cell c = new Cell();
+ 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;
+ }
+ cells.add(c);
+ }
+ }
+ this.egg = egg;// 保留一份蛋,如果没被淘汰掉,将来下蛋时要用这个蛋来下新蛋
+ }
+
+ /** 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;
+ 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;
+ }
+
+ // 奖励
+ if (eatedFood) {
+
+ }
+ }
+
+ 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;
+
+ private float percet1(float f) {
+ if (!allowVariation)
+ return f;
+ return (float) (f * (0.99f + r.nextFloat() * 0.02));
+ }
+
+ private float percet5(float f) {
+ if (!allowVariation)
+ return f;
+ return (float) (f * (0.95f + r.nextFloat() * 0.10));
+ }
+
+ 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();
+ newEgg.brainRadius = percet5(egg.brainRadius);
+ CellGroup[] cellgroups = new CellGroup[egg.cellgroups.length];
+ newEgg.cellgroups = cellgroups;
+ for (int i = 0; i < cellgroups.length; i++) {
+ CellGroup cellGroup = new CellGroup();
+ cellgroups[i] = cellGroup;
+ CellGroup oldGp = egg.cellgroups[i];
+ cellGroup.groupInputZone = new Zone(percet5(oldGp.groupInputZone.x), percet5(oldGp.groupInputZone.y),
+ percet5(oldGp.groupInputZone.radius));
+ cellGroup.groupOutputZone = new Zone(percet5(oldGp.groupOutputZone.x), percet5(oldGp.groupOutputZone.y),
+ percet5(oldGp.groupOutputZone.radius));
+ cellGroup.cellQty = Math.round(percet5(oldGp.cellQty));
+ cellGroup.cellInputRadius = percet1(oldGp.cellInputRadius);
+ cellGroup.cellOutputRadius = percet1(oldGp.cellOutputRadius);
+ cellGroup.inputQtyPerCell = Math.round(percet5(oldGp.inputQtyPerCell));
+ cellGroup.outputQtyPerCell = Math.round(percet5(oldGp.outputQtyPerCell));
+ }
+ return newEgg;
+ }
+
+ public void show(Graphics g) {
+ if (!alive)
+ return;
+ g.drawImage(frogImg, x - 8, y - 8, 16, 16, null);
+ }
+
+}
diff --git a/history/001_first_version/src/main/java/com/github/drinkjava2/frog/brain/Cell.java b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
new file mode 100644
index 0000000..f97eb2d
--- /dev/null
+++ b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+/**
+ * Cell is a brain nerve cell, this is the basic unit of frog's brain
+ *
+ * @author Yong Zhu
+ * @since 1.0.0
+ */
+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 void activate() {
+ for (Input xy : inputs) {
+ }
+
+ }
+
+}
diff --git a/history/001_first_version/src/main/java/com/github/drinkjava2/frog/brain/Input.java b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/brain/Input.java
new file mode 100644
index 0000000..984acf2
--- /dev/null
+++ b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/brain/Input.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+import com.github.drinkjava2.frog.egg.Zone;
+
+/**
+ * Input is the sensor of nerve cell
+ *
+ * @author Yong Zhu
+ * @since 1.0.0
+ */
+public class Input extends Zone{
+ public float energy;
+ public Cell cell;
+}
diff --git a/history/001_first_version/src/main/java/com/github/drinkjava2/frog/brain/Output.java b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/brain/Output.java
new file mode 100644
index 0000000..f28d8e4
--- /dev/null
+++ b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/brain/Output.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+import com.github.drinkjava2.frog.egg.Zone;
+
+/**
+ * Output can active other nerve cell's input
+ *
+ * @author Yong Zhu
+ * @since 1.0.0
+ */
+public class Output extends Zone {
+ public float energy;
+ public Cell cell;
+}
diff --git a/history/001_first_version/src/main/java/com/github/drinkjava2/frog/egg/CellGroup.java b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/egg/CellGroup.java
new file mode 100644
index 0000000..9534089
--- /dev/null
+++ b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/egg/CellGroup.java
@@ -0,0 +1,40 @@
+/*
+ * 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.egg;
+
+import java.io.Serializable;
+
+/**
+ * CellGroup represents a bunch of similar nerve cells
+ *
+ * CellGroup代表了一束相同功能和结构、分布位置相近的脑神经元,目的是为了下蛋时简化串行化海量的神经元,
+ * 只需要在egg里定义一组cellGroup就行了,不需要将海量的一个个的神经元串行化存放到egg里,这样一来Frog就不能"永生"了,因为每一个egg都不等同于
+ * 它的母体, 而且每一次测试,一些复杂的条件反射的建立都必须从头开始训练,在项目后期,有可能每个frog生命的一半时间都花在重新建立条件反射的学习过程中。
+ *
+ * 模拟一公一母两个蛋受精,CellGroup叠加也许很fun,这样可以将不同环境训练出的蛋叠加成一个。但现在暂时不考虑。
+ *
+ * @author Yong Zhu
+ * @since 1.0.0
+ */
+public class CellGroup implements Serializable {
+ private static final long serialVersionUID = 1L;
+ public Zone groupInputZone; // input distribute zone
+
+ public Zone groupOutputZone; // output distribute zone
+
+ public float cellInputRadius; // input radius of each cell
+ public float cellOutputRadius; // output radius of each cell
+
+ public int cellQty; // how many nerve cells in this CellGroup
+
+ public int inputQtyPerCell; // input qty per cell
+ public int outputQtyPerCell; // output qty per cell
+}
diff --git a/history/001_first_version/src/main/java/com/github/drinkjava2/frog/egg/Egg.java b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
new file mode 100644
index 0000000..749c017
--- /dev/null
+++ b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
@@ -0,0 +1,50 @@
+/*
+ * 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.egg;
+
+import java.io.Serializable;
+import java.util.Random;
+
+/**
+ * Egg is the static structure description of frog, can save as text file, to
+ * build a frog, first need build a egg.
+ *
+ * 蛋存在的目的是为了以最小的字节数串行化存储Frog,它是Frog的生成算法描述,而不是Frog本身,这样一来Frog就不能"永生"了,因为每一个egg都不等同于
+ * 它的母体, 而且每一次测试,大部分条件反射的建立都必须从头开始训练,类似于人类,无论人类社会有多聪明, 婴儿始终是一张白纸,需要花大量的时间从头学习。
+ *
+ */
+public class Egg implements Serializable {
+ private static final long serialVersionUID = 2L;
+ public static final int CELL_GROUP_QTY = 30;
+ public float brainRadius = 1000;
+ public CellGroup[] cellgroups;
+
+ public static Egg createBrandNewEgg() {
+ Egg egg = new Egg();
+ Random r = new Random();
+ egg.cellgroups = new CellGroup[CELL_GROUP_QTY];
+ for (int i = 0; i < CELL_GROUP_QTY; i++) {
+ CellGroup cellGroup = new CellGroup();
+ egg.cellgroups[i] = cellGroup;
+ cellGroup.groupInputZone = new Zone(r.nextFloat() * egg.brainRadius, r.nextFloat() * egg.brainRadius,
+ (float) (r.nextFloat() * egg.brainRadius * .01));
+ cellGroup.groupOutputZone = new Zone(r.nextFloat() * egg.brainRadius, r.nextFloat() * egg.brainRadius,
+ (float) (r.nextFloat() * egg.brainRadius * .01));
+ cellGroup.cellQty = r.nextInt(10);
+ cellGroup.cellInputRadius = (float) (r.nextFloat() * 0.001);
+ cellGroup.cellOutputRadius = (float) (r.nextFloat() * 0.001);
+ cellGroup.inputQtyPerCell = r.nextInt(10);
+ cellGroup.outputQtyPerCell = r.nextInt(5);
+ }
+ return egg;
+ }
+
+}
diff --git a/history/001_first_version/src/main/java/com/github/drinkjava2/frog/egg/Zone.java b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/egg/Zone.java
new file mode 100644
index 0000000..848059a
--- /dev/null
+++ b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/egg/Zone.java
@@ -0,0 +1,56 @@
+/*
+ * 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.egg;
+
+import java.io.Serializable;
+
+/**
+ * Zone represents a position in brain
+ *
+ * @author Yong Zhu
+ * @since 1.0.0
+ */
+public class Zone implements Serializable {
+ private static final long serialVersionUID = 3L;
+ public float x;
+ public float y;
+ public float radius;
+
+ public Zone() {
+ // 空构造器不能省,FastJSON实例化时要用到
+ }
+
+ public Zone(float x, float y, float radius) {
+ this.x = x;
+ this.y = y;
+ this.radius = radius;
+ }
+
+ 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/history/001_first_version/src/main/java/com/github/drinkjava2/frog/env/Application.java b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/env/Application.java
new file mode 100644
index 0000000..54aef5e
--- /dev/null
+++ b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/env/Application.java
@@ -0,0 +1,33 @@
+package com.github.drinkjava2.frog.env;
+
+import java.io.File;
+
+import javax.swing.JFrame;
+
+/**
+ * Application will build env, frogs and let them run
+ */
+public class Application {
+ public static final String CLASSPATH;
+ static {
+ String classpath = new File("").getAbsolutePath();
+ int core = classpath.indexOf("\\frog\\");
+ if (core > 0)
+ CLASSPATH = classpath.substring(0, core) + "\\frog\\";
+ else
+ CLASSPATH = classpath.substring(0, core) + "/frog/"; // UNIX
+ }
+ public static JFrame mainFrame = new JFrame();
+
+ public static void main(String[] args) throws InterruptedException {
+ mainFrame.setLayout(null);
+ mainFrame.setSize(520, 550); // 窗口大小
+ mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭时退出程序
+
+ Env env = new Env();
+ mainFrame.add(env);
+ mainFrame.setVisible(true);
+ env.run();
+ }
+
+}
diff --git a/history/001_first_version/src/main/java/com/github/drinkjava2/frog/env/Env.java b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/env/Env.java
new file mode 100644
index 0000000..089c950
--- /dev/null
+++ b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/env/Env.java
@@ -0,0 +1,123 @@
+package com.github.drinkjava2.frog.env;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import javax.swing.JPanel;
+
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.egg.Egg;
+import com.github.drinkjava2.frog.util.EggTool;
+
+/**
+ * Env is the living space of frog. draw it on JPanel
+ */
+@SuppressWarnings("serial")
+public class Env extends JPanel {
+ /** Speed of test */
+ public static int SHOW_SPEED =1;
+
+ /** Steps of one test round */
+ public static int STEPS_PER_ROUND = 3000;
+
+ /** Delete eggs at beginning of each run */
+ public static final boolean DELETE_EGGS = true;// 每次运行是否先删除保存的蛋
+
+ /** Virtual environment x size is 500 pixels */
+ public int ENV_XSIZE = 300;
+
+ /** Virtual environment y size is 500 pixels */
+ public int ENV_YSIZE = 300;
+
+ public byte[][] foods = new byte[ENV_XSIZE][ENV_YSIZE];
+
+ public int FOOD_QTY = 2000; // as name
+
+ public int EGG_QTY =80; // as name
+
+ public List frogs = new ArrayList();
+ public List eggs;
+
+ static {
+ System.out.println("唵缚悉波罗摩尼莎诃!"); // 杀生前先打印往生咒,见码云issue#IW4H8
+ if (DELETE_EGGS)
+ EggTool.deleteEggs();
+ }
+
+ public Env() {
+ super();
+ this.setLayout(null);// 空布局
+ this.setBounds(100, 100, ENV_XSIZE, ENV_YSIZE);
+ }
+
+ private void rebuildFrogAndFood() {
+ frogs.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
+ 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[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 {
+ t1 = System.currentTimeMillis();
+ rebuildFrogAndFood();
+ boolean allDead = false;
+ for (int i = 0; i < STEPS_PER_ROUND; i++) {
+ 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;
+ // 开始画青蛙
+ g.setColor(Color.white);
+ g.fillRect(0, 0, this.getWidth(), this.getHeight());
+ g.setColor(Color.BLACK);
+ for (Frog frog : frogs)
+ frog.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/history/001_first_version/src/main/java/com/github/drinkjava2/frog/util/EggTool.java b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/util/EggTool.java
new file mode 100644
index 0000000..048642f
--- /dev/null
+++ b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/util/EggTool.java
@@ -0,0 +1,129 @@
+/*
+ * 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.util;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.egg.Egg;
+import com.github.drinkjava2.frog.env.Application;
+import com.github.drinkjava2.frog.env.Env;
+
+/**
+ * Egg is the static structure description of frog, can save as text file, to
+ * build a frog, first need build a egg.
+ */
+public class EggTool {
+
+ public static final boolean JSON_FILE_FORMAT = false; // JSON is slow but easier to debug
+
+ /**
+ * 利用Java串行机制存盘。 能量多(也就是吃的更多,更fat)的Frog下蛋并存盘, 以进行下一伦测试,能量少的Frog被淘汰,没有下蛋的资格。
+ */
+ 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.EGG_QTY; i++)
+ newEggs.add(env.frogs.get(i).layEgg());
+
+ 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" + "'");
+ } catch (IOException e) {
+ System.out.println(e);
+ }
+ }
+
+ private static void sortFrogsOrderByEnergyDesc(Env env) {
+ Collections.sort(env.frogs, new Comparator() {
+ public int compare(Frog a, Frog b) {
+ if (a.energy > b.energy)
+ return -1;
+ else if (a.energy == b.energy)
+ return 0;
+ else
+ return 1;
+ }
+ });
+ }
+
+ /**
+ * 从磁盘读入一批Egg
+ */
+ @SuppressWarnings("unchecked")
+ 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 {
+ 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());
+ }
+ }
+
+ public static void deleteEggs() {
+ System.out.println("Delete exist egg file: '" + Application.CLASSPATH + "eggs.ser'");
+ FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs.ser");
+ }
+
+}
diff --git a/history/001_first_version/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java
new file mode 100644
index 0000000..32dd585
--- /dev/null
+++ b/history/001_first_version/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java
@@ -0,0 +1,141 @@
+/* Copyright 2018-2020 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.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * File Utilities usually used inside of compiler
+ *
+ * @author Yong Zhu
+ * @since 1.0.0
+ */
+public class FrogFileUtils {
+
+ private FrogFileUtils() {
+ // default constructor
+ }
+
+ public static boolean deleteFile(String fileFullPath) {
+ File file = new File(fileFullPath);
+ return file.delete(); // NOSONAR
+ }
+
+ public static void writeFile(String fileFullPath, byte[] byteArry) {
+ File file = new File(fileFullPath);
+ if (!file.getParentFile().exists())
+ file.getParentFile().mkdirs();
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ fos.write(byteArry);
+ fos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static void writeFile(String fileFullPath, String text, String encoding) {
+ File file = new File(fileFullPath);
+ if (!file.getParentFile().exists())
+ file.getParentFile().mkdirs();
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ byte[] bytes;
+ bytes = text.getBytes(encoding);
+ fos.write(bytes);
+ fos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static String readFile(String fileFullPath, String encoding) {
+ InputStream inputStream;
+ try {
+ inputStream = new FileInputStream(new File(fileFullPath));
+ } catch (FileNotFoundException e1) {
+ return null;
+ }
+ try {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = inputStream.read(buffer)) != -1)
+ result.write(buffer, 0, length);
+ String string = result.toString(encoding);
+ return string;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ } finally {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ public static void appendFile(String fileName, String content) {
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(fileName, true);
+ fos.write(content.getBytes());
+ fos.write("\r\n".getBytes());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+}
diff --git a/history/002_first_eye/LICENSE b/history/002_first_eye/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/history/002_first_eye/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ 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.
diff --git a/history/002_first_eye/maven_clean.bat b/history/002_first_eye/maven_clean.bat
new file mode 100644
index 0000000..2f3d3e5
--- /dev/null
+++ b/history/002_first_eye/maven_clean.bat
@@ -0,0 +1 @@
+mvn clean
\ No newline at end of file
diff --git a/history/002_first_eye/maven_eclipse_clean.bat b/history/002_first_eye/maven_eclipse_clean.bat
new file mode 100644
index 0000000..a427bd7
--- /dev/null
+++ b/history/002_first_eye/maven_eclipse_clean.bat
@@ -0,0 +1 @@
+mvn eclipse:clean
\ No newline at end of file
diff --git a/history/002_first_eye/maven_eclipse_eclipse.bat b/history/002_first_eye/maven_eclipse_eclipse.bat
new file mode 100644
index 0000000..99fa0b2
--- /dev/null
+++ b/history/002_first_eye/maven_eclipse_eclipse.bat
@@ -0,0 +1,2 @@
+call mvn eclipse:eclipse
+call pause
\ No newline at end of file
diff --git a/core3d/pom.xml b/history/002_first_eye/pom.xml
similarity index 98%
rename from core3d/pom.xml
rename to history/002_first_eye/pom.xml
index edda7df..3d465ac 100644
--- a/core3d/pom.xml
+++ b/history/002_first_eye/pom.xml
@@ -2,9 +2,9 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0com.gitee.drinkjava2
- frog3d
+ frog002jar
- 2.0.2
+ 1.0frogAn artificial life test project
@@ -99,4 +99,4 @@
-
\ No newline at end of file
+
diff --git a/history/002_first_eye/run.bat b/history/002_first_eye/run.bat
new file mode 100644
index 0000000..fa4fed9
--- /dev/null
+++ b/history/002_first_eye/run.bat
@@ -0,0 +1,4 @@
+call mvn clean compile
+cd target\classes
+java -classpath ".;*" com.github.drinkjava2.frog.env.Application
+@pause
\ No newline at end of file
diff --git a/history/002_first_eye/run.sh b/history/002_first_eye/run.sh
new file mode 100644
index 0000000..836c941
--- /dev/null
+++ b/history/002_first_eye/run.sh
@@ -0,0 +1,2 @@
+mvn clean package
+java -jar target/frog-*.jar
diff --git a/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/Frog.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/Frog.java
new file mode 100644
index 0000000..b2cd055
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/Frog.java
@@ -0,0 +1,144 @@
+/*
+ * 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;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import javax.imageio.ImageIO;
+
+import com.github.drinkjava2.frog.brain.Cell;
+import com.github.drinkjava2.frog.brain.Input;
+import com.github.drinkjava2.frog.brain.Organ;
+import com.github.drinkjava2.frog.brain.Output;
+import com.github.drinkjava2.frog.egg.CellGroup;
+import com.github.drinkjava2.frog.egg.Egg;
+import com.github.drinkjava2.frog.egg.OrganDesc;
+import com.github.drinkjava2.frog.egg.Zone;
+import com.github.drinkjava2.frog.env.Application;
+import com.github.drinkjava2.frog.env.Env;
+
+/**
+ * Frog = brain + organ, but now let's only focus on brain, organs are hard
+ * coded in egg
+ *
+ * 青蛙由脑细胞和器官组成,目前脑细胞可以变异、进化、遗传,以由电脑自动生成神经网络,但是器官在蛋里硬编码,不许进化,将来可以考虑器官的进化
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Frog {
+
+ public CellGroup[] cellGroups;
+
+ /** brain cells */
+ public List cells = new ArrayList<>();
+
+ /** 视觉细胞的输入区在脑中的坐标,随便取一个区就可以了,以后再考虑进化成两个眼睛 */
+ public Zone eye = new Zone(100, 400, 100);
+
+ /** 饥饿的感收区在脑中的坐标,先随便取就可以了,以后再考虑放到蛋里去进化 */
+ public Zone hungry = new Zone(300, 100, 100);
+
+ /** 运动细胞的输入区在脑中的坐标,先随便取就可以了,以后再考虑放到蛋里去进化 */
+ public Zone moveDown = new Zone(700, 100, 40); // 屏幕y坐标是向下的
+ public Zone moveUp = new Zone(700, 400, 40);
+ public Zone moveLeft = new Zone(650, 250, 40);
+ public Zone moveRight = new Zone(750, 250, 40);
+
+ public List organs = new ArrayList<>();
+
+ public int x; // frog在env中的x坐标
+ public int y; // frog在env中的y坐标
+ public long energy = 10000; // 能量为0则死掉
+ public boolean alive = true; // 设为false表示青蛙死掉了,将不参与任何计算和显示,以节省时间
+
+ static final Random r = new Random();
+ static Image frogImg;
+ static {
+ try {
+ frogImg = ImageIO.read(new FileInputStream(Application.CLASSPATH + "frog.png"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public Frog(int x, int y, Egg egg) {
+ this.x = x;
+ this.y = y;
+
+ // Brain cells
+ if (egg.cellGroups != null) {
+ 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++) {
+ c.inputs[j] = new Input();
+ c.inputs[j].cell = c;
+ Zone.copyXY(randomPosInZone(g.groupInputZone), c.inputs[j]);
+ c.inputs[j].radius = g.cellInputRadius;
+ }
+ cellQTY = Math.round(g.outputQtyPerCell);
+ c.outputs = new Output[cellQTY];
+ for (int j = 0; j < cellQTY; j++) {
+ c.outputs[j] = new Output();
+ c.outputs[j].cell = c;
+ Zone.copyXY(randomPosInZone(g.groupOutputZone), c.outputs[j]);
+ c.outputs[j].radius = g.cellOutputRadius;
+ }
+ cells.add(c);
+ }
+ }
+ }
+
+ // Create organs from egg, like eye, moves, eat...
+ if (egg.organDescs != null)
+ for (OrganDesc od : egg.organDescs)
+ organs.add(new Organ(od));
+
+ }
+
+ public boolean active(Env v) {
+ energy -= 20;
+ if (!alive)
+ return false;
+ if (energy < 0) {
+ alive = false;
+ return false;
+ }
+
+ for (Organ o : organs)
+ o.active(this);
+ return alive;
+ }
+
+ 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 void show(Graphics g) {
+ if (!alive)
+ return;
+ g.drawImage(frogImg, x - 8, y - 8, 16, 16, null);
+ }
+
+}
diff --git a/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Cell.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
new file mode 100644
index 0000000..3889841
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+/**
+ * Cell is a brain nerve cell, this is the basic unit of frog's brain
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Cell {
+ public int group; // this cell belong to which group
+ public Input[] inputs; // inputs of cell
+ public Output[] outputs; // outputs of cell
+ public long energy;
+
+}
diff --git a/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Input.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Input.java
new file mode 100644
index 0000000..dc57f26
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Input.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+import com.github.drinkjava2.frog.egg.Zone;
+
+/**
+ * Input is the sensor of nerve cell
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+@SuppressWarnings("serial")
+public class Input extends Zone {
+ public Cell cell;
+}
diff --git a/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Organ.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
new file mode 100644
index 0000000..b44e202
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
@@ -0,0 +1,151 @@
+/*
+ * 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;
+
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.organ.Eye;
+import com.github.drinkjava2.frog.egg.OrganDesc;
+import com.github.drinkjava2.frog.egg.Zone;
+import com.github.drinkjava2.frog.env.Env;
+
+/**
+ * Organ is a sensor or execute part connected to frog's brain cell, like:
+ * 器官,分为输入器官和输出器官两大类,它们在蛋里定义,数量、位置、大小可以随机变异进化,但目前在蛋里用硬编码写死,不允许器官进化,一个眼睛都没搞定,要进化出10个眼睛来会吓死人
+ *
+ *
+ *
+ * Sensors:
+ * hungry sensor, eye, ear, smell, happy sensor
+ *
+ * Executor:
+ * moves (up/down/left/right), eat ...
+ *
+ *
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Organ extends Zone {
+ private static final long serialVersionUID = 1L;
+ public static final int HUNGRY = 0;
+ public static final int UP = 1;
+ public static final int DOWN = 2;
+ public static final int LEFT = 3;
+ public static final int RIGHT = 4;
+ public static final int EAT = 5;
+ public static final int EYE = 6;
+
+ public int type;
+
+ public Organ(OrganDesc od) {
+ super(od.x, od.y, od.radius);
+ type = od.type;
+ }
+
+ public Organ(int type, float x, float y, float radius) {
+ super(x, y, radius);
+ this.type = type;
+ }
+
+ public void active(Frog f) {
+ switch (type) {
+ case HUNGRY:
+ hungry(f);
+ break;
+ case UP:
+ up(f);
+ break;
+ case DOWN:
+ down(f);
+ break;
+ case LEFT:
+ left(f);
+ break;
+ case RIGHT:
+ right(f);
+ break;
+ case EAT:
+ eat(f);
+ break;
+ case EYE:
+ eye(f);
+ break;
+ default:
+ break;
+ }
+ }
+
+ public void hungry(Frog f) {
+ for (Cell cell : f.cells) {
+ if (cell.energy > 0)
+ cell.energy--;
+
+ if (f.energy < 10000 && cell.energy < 100)
+ for (Input input : cell.inputs)
+ if (input.nearby(this)) // input zone near by hungry zone
+ cell.energy += 2;
+ }
+ }
+
+ public void up(Frog f) {
+ if (outputActive(f))
+ f.y++;
+ }
+
+ public void down(Frog f) {
+ if (outputActive(f))
+ f.y--;
+ }
+
+ public void left(Frog f) {
+ if (outputActive(f))
+ f.x--;
+ }
+
+ public void right(Frog f) {
+ if (outputActive(f))
+ f.x++;
+ }
+
+ public void eat(Frog f) {
+ int x = f.x;
+ int y = f.y;
+ if (x < 0 || x >= Env.ENV_WIDTH || y < 0 || y >= Env.ENV_HEIGHT) {// 越界者死!
+ f.alive = false;
+ return;
+ }
+
+ if (Env.foods[x][y]) {
+ Env.foods[x][y] = false;
+ f.energy = f.energy + 1000;// 吃掉food,能量境加
+ }
+ }
+
+ public void eye(Frog f) {
+ Eye.act(f, this);
+ }
+
+ // ======public methods========
+
+ public boolean outputActive(Frog f) {
+ for (Cell cell : f.cells) {
+ for (Output output : cell.outputs) { //
+ if (cell.energy > 10 && this.nearby(output)) {
+ f.cellGroups[cell.group].fat++;
+ cell.energy -= 30;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Output.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Output.java
new file mode 100644
index 0000000..18cf083
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/Output.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+import com.github.drinkjava2.frog.egg.Zone;
+
+/**
+ * Output can active other nerve cell's input
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+@SuppressWarnings("serial")
+public class Output extends Zone {
+ public Cell cell;
+}
diff --git a/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
new file mode 100644
index 0000000..043df1d
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
@@ -0,0 +1,99 @@
+/*
+ * 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 com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Cell;
+import com.github.drinkjava2.frog.brain.Input;
+import com.github.drinkjava2.frog.brain.Organ;
+import com.github.drinkjava2.frog.egg.Zone;
+import com.github.drinkjava2.frog.env.Env;
+
+/**
+ * Eye is an organ can see environment, and active brain cells which inputs are
+ * located in eye range
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Eye {
+
+ private static boolean hasFood(int x, int y) {
+ return x >= 0 && y >= 0 && x < Env.ENV_WIDTH && y < Env.ENV_HEIGHT && Env.foods[x][y];
+ }
+
+ /** First eye can only see if food nearby at 4 directions */
+ public static void act(Frog f, Organ eye) {// 第一个眼睛只能观察上、下、左、右四个方向有没有食物
+ float qRadius = eye.radius / 4;
+ float q3Radius = (float) (eye.radius * .75);
+ Zone seeUp = new Zone(eye.x, eye.y + q3Radius, qRadius);
+ Zone seeDown = new Zone(eye.x, eye.y - q3Radius, qRadius);
+ Zone seeLeft = new Zone(eye.x - q3Radius, eye.y, qRadius);
+ Zone seeRight = new Zone(eye.x + q3Radius, eye.y, qRadius);
+
+ boolean seeFood = false;
+ boolean foodAtUp = false;
+ boolean foodAtDown = false;
+ boolean foodAtLeft = false;
+ boolean foodAtRight = false;
+
+ int seeDist = 10;
+ for (int i = 1; i < seeDist; i++)
+ if (hasFood(f.x, f.y + i)) {
+ seeFood = true;
+ foodAtUp = true;
+ break;
+ }
+
+ for (int i = 1; i < seeDist; i++)
+ if (hasFood(f.x, f.y - i)) {
+ seeFood = true;
+ foodAtDown = true;
+ break;
+ }
+
+ for (int i = 1; i < seeDist; i++)
+ if (hasFood(f.x - i, f.y)) {
+ seeFood = true;
+ foodAtLeft = true;
+ break;
+ }
+
+ for (int i = 1; i < seeDist; i++)
+ if (hasFood(f.x + i, f.y)) {
+ seeFood = true;
+ foodAtRight = true;
+ break;
+ }
+
+ if (seeFood)
+ for (Cell cell : f.cells) {
+ if (cell.energy < 100)
+ for (Input input : cell.inputs) {
+ if (input.nearby(eye)) {
+ if (foodAtUp && input.nearby(seeUp)) {
+ input.cell.energy += 30;
+ }
+ if (foodAtDown && input.nearby(seeDown)) {
+ input.cell.energy += 30;
+ }
+ if (foodAtLeft && input.nearby(seeLeft)) {
+ input.cell.energy += 30;
+ }
+ if (foodAtRight && input.nearby(seeRight)) {
+ input.cell.energy += 30;
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/CellGroup.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/CellGroup.java
new file mode 100644
index 0000000..83df70e
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/CellGroup.java
@@ -0,0 +1,76 @@
+/*
+ * 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.egg;
+
+import java.io.Serializable;
+import java.util.Random;
+
+/**
+ * CellGroup represents a bunch of similar nerve cells
+ *
+ * CellGroup代表了一束相同功能和结构、分布位置相近的脑神经元,目的是为了下蛋时简化串行化海量的神经元,
+ * 只需要在egg里定义一组cellGroup就行了,不需要将海量的一个个的神经元串行化存放到egg里,这样一来Frog就不能"永生"了,因为每一个egg都不等同于
+ * 它的母体, 而且每一次测试,一些复杂的条件反射的建立都必须从头开始训练,在项目后期,有可能每个frog生命的一半时间都花在重新建立条件反射的学习过程中。
+ *
+ * 模拟一公一母两个蛋受精,CellGroup叠加也许很fun,这样可以将不同环境训练出的蛋叠加成一个。但现在暂时不考虑。
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class CellGroup implements Serializable {
+ private static final long serialVersionUID = 1L;
+ public Zone groupInputZone; // input distribute zone
+
+ public Zone groupOutputZone; // output distribute zone
+
+ public float cellInputRadius; // input radius of each cell
+ public float cellOutputRadius; // output radius of each cell
+
+ public float cellQty; // how many nerve cells in this CellGroup
+
+ public float inputQtyPerCell; // input qty per cell
+ public float outputQtyPerCell; // output qty per cell
+
+ 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(float 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/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/Egg.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
new file mode 100644
index 0000000..a46ecf9
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
@@ -0,0 +1,148 @@
+/*
+ * 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.egg;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Organ;
+import com.github.drinkjava2.frog.env.Env;
+
+/**
+ * Egg is the static structure description of frog, can save as text file, to
+ * build a frog, first need build a egg.
+ *
+ * 蛋存在的目的是为了以最小的字节数串行化存储Frog,它是Frog的生成算法描述,而不是Frog本身,这样一来Frog就不能"永生"了,因为每一个egg都不等同于
+ * 它的母体, 而且每一次测试,大部分条件反射的建立都必须从头开始训练,类似于人类,无论人类社会有多聪明, 婴儿始终是一张白纸,需要花大量的时间从头学习。
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Egg implements Serializable {
+ private static final long serialVersionUID = 1L;
+ public int randomCellGroupQty = 30; // 随机生成多少个组
+ public int randomCellQtyPerGroup = 3; // 每个组有多少个脑细胞
+ public int randomInputQtyPerCell = 3;// 每个脑细胞有多少个输入触突
+ public int randomOutQtyPerCell = 2; // 每个脑细胞有多少个输出触突
+
+ public CellGroup[] cellGroups;
+
+ public List organDescs;
+
+ public Egg() {
+ // default constructor
+ }
+
+ private static Random r = new Random();
+
+ /** Create a egg by join 2 eggs, x+y=zygote */
+ public Egg(Egg x, Egg y) {
+ // 模拟XY染色体,不能做简单加法,会撑暴内存的,现在每次只随机加一个y的cellgroup进来,这也不太好,因为基因会越加越多,只好用用进废退原则来加大淘汰率。
+
+ // x里原来的CellGroup
+ cellGroups = new CellGroup[x.cellGroups.length + 1 + randomCellGroupQty];
+ for (int i = 0; i < x.cellGroups.length; i++) {
+ CellGroup oldCellGroup = x.cellGroups[i];
+ CellGroup cellGroup = new CellGroup();
+ cellGroups[i] = cellGroup;
+ cellGroup.inherit = true;
+ 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;
+ }
+
+ // 从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; i++)
+ cellGroups[i + x.cellGroups.length + 1] = new CellGroup(Env.FROG_BRAIN_WIDTH, x.randomCellQtyPerGroup,
+ x.randomInputQtyPerCell, x.randomOutQtyPerCell);
+
+ addOrganDescs();
+ }
+
+ /** create a brand new Egg */
+ public static Egg createBrandNewEgg() { // 无中生有,创建一个蛋,先有蛋,后有鸡
+ Egg egg = new Egg();
+ egg.cellGroups = new CellGroup[egg.randomCellGroupQty];
+ for (int i = 0; i < egg.randomCellGroupQty; i++)
+ egg.cellGroups[i] = new CellGroup(Env.FROG_BRAIN_WIDTH, egg.randomCellQtyPerGroup,
+ egg.randomInputQtyPerCell, egg.randomOutQtyPerCell);
+ egg.addOrganDescs();
+ return egg;
+ }
+
+ private static boolean percent(int percent) {
+ return r.nextInt(100) < percent;
+ }
+
+ private static float vary(float f) { // 大部分时候不变,有极小机会变异,有极极小机会大变异,有极极极小机会大大大变异
+ int i=r.nextInt(100);
+ if (i<95)
+ return f;
+ float rate = .05f;
+ if(i>97)
+ rate = .1f;
+ return (float) (f * ((1 - rate) + r.nextFloat() * rate * 2));
+ }
+
+ /** Create egg from frog */
+ public Egg(Frog frog) { // 青蛙下蛋,蛋的基因生成遵循用进废退、随机变异两个原则
+ 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(5))
+ continue;// 继承下来的神经元,但是本轮并没用到, 扔掉又可惜,可以小概率丢掉
+ }
+ CellGroup cellGroup = new CellGroup();
+ CellGroup oldGp = frog.cellGroups[i];
+ cellGroup.groupInputZone = new Zone(vary(oldGp.groupInputZone.x), vary(oldGp.groupInputZone.y),
+ vary(oldGp.groupInputZone.radius));
+ cellGroup.groupOutputZone = new Zone(vary(oldGp.groupOutputZone.x), vary(oldGp.groupOutputZone.y),
+ vary(oldGp.groupOutputZone.radius));
+ cellGroup.cellQty = Math.round(vary(oldGp.cellQty));
+ cellGroup.cellInputRadius = vary(oldGp.cellInputRadius);
+ cellGroup.cellOutputRadius = vary(oldGp.cellOutputRadius);
+ cellGroup.inputQtyPerCell = Math.round(vary(oldGp.inputQtyPerCell));
+ cellGroup.outputQtyPerCell = Math.round(vary(oldGp.outputQtyPerCell));
+ cellGroup.inherit = true;
+ gpList.add(cellGroup);
+ }
+ cellGroups = gpList.toArray(new CellGroup[gpList.size()]);
+ addOrganDescs();
+ }
+
+ /** Hard code add organs */
+ public void addOrganDescs() { // 硬编码添加器官,将来考虑器官的数量、位置、大小也可以遗传、变异、进化
+ organDescs = new ArrayList<>();
+ organDescs.add(new OrganDesc(Organ.HUNGRY, 300, 100, 100));
+ organDescs.add(new OrganDesc(Organ.DOWN, 800, 100, 60));
+ organDescs.add(new OrganDesc(Organ.UP, 800, 400, 60));
+ organDescs.add(new OrganDesc(Organ.LEFT, 700, 250, 60));
+ organDescs.add(new OrganDesc(Organ.RIGHT, 900, 250, 60));
+ organDescs.add(new OrganDesc(Organ.EAT, 0, 0, 0));
+ organDescs.add(new OrganDesc(Organ.EYE, 100, 400, 100));
+ //organDescs.add(new OrganDesc(Organ.EYE, 100, 700, 100));
+ }
+
+}
diff --git a/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/OrganDesc.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/OrganDesc.java
new file mode 100644
index 0000000..892eb89
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/OrganDesc.java
@@ -0,0 +1,28 @@
+/*
+ * 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.egg;
+
+/**
+ * OrganDesc store info to create Organ
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class OrganDesc extends Zone {
+ private static final long serialVersionUID = 1L;
+ public int type;
+
+ public OrganDesc(int type, float x, float y, float radius) {
+ super(x, y, radius);
+ this.type = type;
+ }
+
+}
diff --git a/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/Zone.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/Zone.java
new file mode 100644
index 0000000..b0a2258
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/egg/Zone.java
@@ -0,0 +1,70 @@
+/*
+ * 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.egg;
+
+import java.io.Serializable;
+
+import com.github.drinkjava2.frog.env.Env;
+
+/**
+ * Zone represents a rectangle zone in brain
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Zone implements Serializable {
+ private static final long serialVersionUID = 1L;
+ public float x;
+ public float y;
+ public float radius;// so width of the zone= radius*2
+
+ public Zone() {
+ // 空构造器不能省,FastJSON实例化时要用到
+ }
+
+ public Zone(float x, float y, float radius) {
+ this.x = x;
+ this.y = y;
+ this.radius = radius;
+ if (this.x < 0)
+ this.x = 0;
+ if (this.y < 0)
+ this.y = 0;
+ if (this.x > Env.FROG_BRAIN_WIDTH)
+ this.x = Env.FROG_BRAIN_WIDTH;
+ if (this.y > Env.FROG_BRAIN_WIDTH)
+ this.y = Env.FROG_BRAIN_WIDTH;
+ }
+
+ public Zone(Zone z) {
+ this.x = z.x;
+ this.y = z.y;
+ this.radius = z.radius;
+ }
+
+ public boolean nearby(Zone z) {
+ float dist = radius + z.radius;
+ return (Math.abs(x - z.x) < dist && Math.abs(y - z.y) < dist);
+ }
+
+ 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/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/env/Application.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/env/Application.java
new file mode 100644
index 0000000..9e65b71
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/env/Application.java
@@ -0,0 +1,87 @@
+package com.github.drinkjava2.frog.env;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+
+/**
+ * Application's main method start the program
+ *
+ * @author Yong Zhu
+ * @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 {
+ String classpath = new File("").getAbsolutePath();
+ int core = classpath.indexOf("\\frog\\");
+ if (core > 0)
+ CLASSPATH = classpath.substring(0, core) + "\\frog\\";
+ else
+ CLASSPATH = classpath.substring(0, core) + "/frog/"; // UNIX
+ }
+ public static JFrame mainFrame = new JFrame();
+ public static Env env = new Env();
+ public static BrainPicture brainStructure = new BrainPicture(Env.ENV_WIDTH + 5, 0, Env.FROG_BRAIN_WIDTH,
+ Env.FROG_BRAIN_DISP_WIDTH);
+
+ public static void main(String[] args) throws InterruptedException {
+ mainFrame.setLayout(null);
+ mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 100); // 窗口大小
+ mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭时退出程序
+ mainFrame.add(env);
+
+ mainFrame.add(brainStructure);
+
+ JButton button = new JButton("Show first frog's brain");
+ int buttonWidth = 180;
+ 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 first frog's 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 first frog's brain");
+ mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 100);
+ }
+ }
+ };
+ button.addActionListener(al);
+ mainFrame.add(button);
+
+ JButton stopButton = new JButton("Pause");
+ stopButton.setBounds(buttonXpos, Env.ENV_HEIGHT + 35, buttonWidth, buttonHeight);
+ 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/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/env/BrainPicture.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/env/BrainPicture.java
new file mode 100644
index 0000000..7577d04
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/env/BrainPicture.java
@@ -0,0 +1,127 @@
+package com.github.drinkjava2.frog.env;
+
+import java.awt.Color;
+import static java.awt.Color.*;
+import java.awt.Graphics;
+
+import javax.swing.JPanel;
+
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Organ;
+import com.github.drinkjava2.frog.egg.CellGroup;
+import com.github.drinkjava2.frog.egg.Zone;
+
+/**
+ * BrainPicture show first frog's brain structure, for debug purpose only
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+@SuppressWarnings("serial")
+public class BrainPicture extends JPanel {
+ private float brainWidth; // real brain width
+ private int brainDispWidth; // screen display width
+
+ public BrainPicture(int x, int y, float brainWidth, int brainDispWidth) {
+ super();
+ this.setLayout(null);// 空布局
+ this.brainDispWidth = brainDispWidth;
+ this.brainWidth = brainWidth;
+ this.setBounds(x, y, brainDispWidth + 1, brainDispWidth + 1);
+ }
+
+ void drawZone(Graphics g, Zone z) {
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ int radius = Math.round(z.radius * rate);
+ g.drawRect(x - radius, y - radius, radius * 2, radius * 2);
+ }
+
+ void drawCircle(Graphics g, Zone z) {
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ g.drawArc(x - 5, y - 5, 10, 10, 0, 360);
+ }
+
+ void fillZone(Graphics g, Zone z) {
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ int radius = Math.round(z.radius * rate);
+ g.fillRect(x - radius, y - radius, radius * 2, radius * 2);
+ }
+
+ void drawLine(Graphics g, Zone z1, Zone z2) {
+ float rate = brainDispWidth / brainWidth;
+ int x1 = Math.round(z1.x * rate);
+ int y1 = Math.round(z1.y * rate);
+ int x2 = Math.round(z2.x * rate);
+ int y2 = Math.round(z2.y * rate);
+ g.drawLine(x1, y1, x2, y2);
+ }
+
+ void drawText(Graphics g, Zone z, String text) {
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ g.drawString(text, x, y);
+ }
+
+ private static final Color[] rainbow = new Color[] { RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA };
+ private static int nextColor = 0;
+
+ private static Color nextRainbowColor() {
+ if (nextColor == rainbow.length)
+ nextColor = 0;
+ return rainbow[nextColor++];
+ }
+
+ private static Color color(float i) {
+ 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)
+ return;
+ Graphics g = this.getGraphics();// border
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, brainDispWidth, brainDispWidth);
+ g.setColor(Color.black);
+ g.drawRect(0, 0, brainDispWidth, brainDispWidth);
+
+ for (Organ organ : frog.organs) {
+ g.setColor(nextRainbowColor());
+ drawZone(g, organ);
+ drawText(g, organ, String.valueOf(organ.type));
+ }
+
+ for (CellGroup group : frog.cellGroups) {
+ if (!group.inherit)
+ g.setColor(Color.lightGray); // 如果是本轮随机生成的,灰色表示
+ else
+ g.setColor(color(group.cellQty)); // 如果是继承的,彩虹色表示,颜色数越往后表示数量越多
+ drawLine(g, group.groupInputZone, group.groupOutputZone);
+ drawZone(g, group.groupInputZone);
+ fillZone(g, group.groupOutputZone);
+ if (group.fat > 0) {
+ g.setColor(Color.BLACK);
+ drawCircle(g, group.groupOutputZone); // 如果胖了,表示激活过了,下次下蛋少不了这一组
+ }
+ }
+
+ }
+}
diff --git a/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/env/Env.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/env/Env.java
new file mode 100644
index 0000000..fadcea1
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/env/Env.java
@@ -0,0 +1,156 @@
+package com.github.drinkjava2.frog.env;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import javax.swing.JPanel;
+
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.egg.Egg;
+import com.github.drinkjava2.frog.util.EggTool;
+
+/**
+ * Env is the living space of frog. draw it on JPanel
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+@SuppressWarnings("serial")
+public class Env extends JPanel {
+ /** Speed of test */
+ public static final int SHOW_SPEED = 1; // 测试速度,1~1000,可调, 数值越小,速度越慢
+
+ public static final int ENV_WIDTH = 400; // 虚拟环境的宽度, 可调
+
+ /** Delete eggs at beginning of each run */
+ public static final boolean DELETE_EGGS = true;// 每次运行是否先删除保存的蛋
+
+ /** Virtual environment y size pixels */
+ 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 = 300; // Frog的脑图在屏幕上的显示大小,可调
+
+ /** Steps of one test round */
+ public static final int STEPS_PER_ROUND = 3000;// 每轮测试步数,可调
+
+ /** Frog's brain width, fixed to 1000 unit */
+ public static final float FROG_BRAIN_WIDTH = 1000; // frog的脑宽度固定为1000,不要随便调整,因为器官的相对位置和大小是按脑大小设定的
+
+ static {
+ System.out.println("唵缚悉波罗摩尼莎诃!"); // 杀生前先打印往生咒,见码云issue#IW4H8
+ if (DELETE_EGGS)
+ EggTool.deleteEggs();
+ }
+
+ public static final int FOOD_QTY = 2000; // 食物数量, 可调
+
+ public static final int EGG_QTY = 50; // 每轮下n个蛋,可调,只有最优秀的前n个青蛙们才允许下蛋
+
+ private static final Random r = new Random(); // 随机数发生器
+
+ public static boolean pause = false; // 暂停按钮按下将暂停测试
+
+ public static final boolean[][] foods = new boolean[ENV_WIDTH][ENV_HEIGHT];// 食物数组定义
+
+ public List frogs = new ArrayList<>();
+
+ public List eggs;
+
+ public Env() {
+ super();
+ this.setLayout(null);// 空布局
+ this.setBounds(1, 1, ENV_WIDTH, ENV_HEIGHT);
+ }
+
+ private void rebuildFrogAndFood() {
+ frogs.clear();
+ for (int i = 0; i < ENV_WIDTH; i++) {// 清除食物
+ for (int j = 0; j < ENV_HEIGHT; j++) {
+ foods[i][j] = false;
+ }
+ }
+ Random rand = new Random();
+ for (int i = 0; i < eggs.size(); i++) {// 创建青蛙,每个蛋生成4个蛙,并随机取一个别的蛋作为精子
+ int loop = 4;
+ if (i == 0)
+ loop = 8;
+ if (i == eggs.size() - 1)
+ loop = 0;
+ for (int j = 0; j < loop; j++) {
+ Egg zygote = new Egg(eggs.get(i), eggs.get(r.nextInt(eggs.size())));
+ frogs.add(new Frog(rand.nextInt(ENV_WIDTH), rand.nextInt(ENV_HEIGHT), zygote));
+ }
+ }
+
+ System.out.println("Created " + 4 * eggs.size() + " frogs");
+ for (int i = 0; i < Env.FOOD_QTY; i++) // 生成食物
+ foods[rand.nextInt(ENV_WIDTH)][rand.nextInt(ENV_HEIGHT)] = true;
+ }
+
+ private void drawFood(Graphics g) {
+ for (int x = 0; x < ENV_WIDTH; x++)
+ for (int y = 0; y < ENV_HEIGHT; y++)
+ if (foods[x][y]) {
+ g.fillOval(x, y, 4, 4);
+ }
+ }
+
+ 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;
+ Image buffImg = createImage(this.getWidth(), this.getHeight());
+ Graphics g = buffImg.getGraphics();
+ long t1, t2;
+ do {
+ if (pause) {
+ sleep();
+ continue;
+ }
+ t1 = System.currentTimeMillis();
+ rebuildFrogAndFood();
+ boolean allDead = false;
+ for (int i = 0; i < STEPS_PER_ROUND; i++) {
+ if (allDead) {
+ System.out.println("All dead at round:" + i);
+ break; // 全死光了就直接跳到下一轮,以节省时间
+ }
+ allDead = true;
+ for (Frog frog : frogs)
+ if (frog.active(this))
+ allDead = false;
+ if (i % SHOW_SPEED != 0) // 画青蛙会拖慢速度
+ continue;
+ // 开始画青蛙
+ g.setColor(Color.white);
+ g.fillRect(0, 0, this.getWidth(), this.getHeight());
+ g.setColor(Color.BLACK);
+ for (Frog frog : frogs)
+ frog.show(g);
+
+ drawFood(g);
+ Graphics g2 = this.getGraphics();
+ g2.drawImage(buffImg, 0, 0, this);
+ }
+
+ EggTool.layEggs(this);
+ Application.brainStructure.drawBrainPicture(frogs.get(0));
+ t2 = System.currentTimeMillis();
+ 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/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/util/EggTool.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/util/EggTool.java
new file mode 100644
index 0000000..13a1df4
--- /dev/null
+++ b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/util/EggTool.java
@@ -0,0 +1,107 @@
+/*
+ * 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.util;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.egg.Egg;
+import com.github.drinkjava2.frog.env.Application;
+import com.github.drinkjava2.frog.env.Env;
+
+/**
+ * EggTool store public static methods of egg
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class EggTool {
+
+ /**
+ * 利用Java串行机制存盘。 能量多(也就是吃的更多,更fat)的Frog下蛋并存盘, 以进行下一伦测试,能量少的Frog被淘汰,没有下蛋的资格。
+ */
+ public static void layEggs(Env env) {
+ sortFrogsOrderByEnergyDesc(env);
+ 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(new Egg(env.frogs.get(i)));
+ System.out.print("EggCellGroups=" + newEggs.get(0).cellGroups.length + ", ");
+
+ 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" + "'");
+ } catch (IOException e) {
+ System.out.println(e);
+ }
+ }
+
+ private static void sortFrogsOrderByEnergyDesc(Env env) {
+ Collections.sort(env.frogs, new Comparator() {
+
+ public int compare(Frog a, Frog b) {
+ if (a.energy > b.energy)
+ return -1;
+ else if (a.energy == b.energy)
+ return 0;
+ else
+ return 1;
+ }
+ });
+ }
+
+ public static void deleteEggs() {
+ FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs.json");
+ FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs.ser");
+ }
+
+ /**
+ * 从磁盘读入一批Egg
+ */
+ @SuppressWarnings("unchecked")
+ public static void loadEggs(Env env) {
+ boolean errorfound = false;
+ 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("Fail to load egg file at path '" + Application.CLASSPATH + "', 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());
+ }
+ }
+
+}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java b/history/002_first_eye/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java
rename to history/002_first_eye/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java
diff --git a/history/003_trap/LICENSE b/history/003_trap/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/history/003_trap/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ 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.
diff --git a/history/003_trap/maven_clean.bat b/history/003_trap/maven_clean.bat
new file mode 100644
index 0000000..2f3d3e5
--- /dev/null
+++ b/history/003_trap/maven_clean.bat
@@ -0,0 +1 @@
+mvn clean
\ No newline at end of file
diff --git a/history/003_trap/maven_eclipse_clean.bat b/history/003_trap/maven_eclipse_clean.bat
new file mode 100644
index 0000000..a427bd7
--- /dev/null
+++ b/history/003_trap/maven_eclipse_clean.bat
@@ -0,0 +1 @@
+mvn eclipse:clean
\ No newline at end of file
diff --git a/history/003_trap/maven_eclipse_eclipse.bat b/history/003_trap/maven_eclipse_eclipse.bat
new file mode 100644
index 0000000..99fa0b2
--- /dev/null
+++ b/history/003_trap/maven_eclipse_eclipse.bat
@@ -0,0 +1,2 @@
+call mvn eclipse:eclipse
+call pause
\ No newline at end of file
diff --git a/history/003_trap/pom.xml b/history/003_trap/pom.xml
new file mode 100644
index 0000000..346c1b6
--- /dev/null
+++ b/history/003_trap/pom.xml
@@ -0,0 +1,102 @@
+
+ 4.0.0
+ com.gitee.drinkjava2
+ frog003
+ jar
+ 1.0
+
+ frog
+ An artificial life test project
+ https://gitee.com/drinkjava2/jsqlbox/frog
+
+
+ gitee Issue
+ https://gitee.com/drinkjava2/jsqlbox/frog/issues
+
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+
+ Yong Zhu
+ yong9981@gmail.com
+ https://gitee.com/drinkjava2/
+
+
+
+
+ scm:git@gitee.com:drinkjava2/frog.git
+ scm:git@gitee.com:drinkjava2/frog.git
+ git@gitee.com:drinkjava2/frog.git
+
+
+
+ UTF-8
+ UTF-8
+ UTF-8
+
+ 1.8
+ 6
+ 3.3
+ 2.6
+ 3.0.0
+ 2.7
+ 2.19
+ 2.6
+ 2.4
+ 2.10.3
+ 1.6
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${version.compiler-plugin}
+
+ ${version.java}
+ ${version.java}
+ UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.2
+
+
+
+ true
+ false
+ lib/
+ com.github.drinkjava2.frog.Application
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core3d/run.bat b/history/003_trap/run.bat
similarity index 100%
rename from core3d/run.bat
rename to history/003_trap/run.bat
diff --git a/history/003_trap/run.sh b/history/003_trap/run.sh
new file mode 100644
index 0000000..836c941
--- /dev/null
+++ b/history/003_trap/run.sh
@@ -0,0 +1,2 @@
+mvn clean package
+java -jar target/frog-*.jar
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/Application.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/Application.java
new file mode 100644
index 0000000..97afaea
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/Application.java
@@ -0,0 +1,88 @@
+package com.github.drinkjava2.frog;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+
+import com.github.drinkjava2.frog.brain.BrainPicture;
+
+/**
+ * Application's main method start the program
+ *
+ * @author Yong Zhu
+ * @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 {
+ String classpath = new File("").getAbsolutePath();
+ int core = classpath.indexOf("\\frog\\");
+ if (core > 0)
+ CLASSPATH = classpath.substring(0, core) + "\\frog\\";
+ else
+ CLASSPATH = classpath.substring(0, core) + "/frog/"; // UNIX
+ }
+ public static JFrame mainFrame = new JFrame();
+ public static Env env = new Env();
+ public static BrainPicture brainPic = new BrainPicture(Env.ENV_WIDTH + 5, 0, Env.FROG_BRAIN_WIDTH,
+ Env.FROG_BRAIN_DISP_WIDTH);
+
+ public static void main(String[] args) throws InterruptedException {
+ mainFrame.setLayout(null);
+ mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 100); // 窗口大小
+ mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭时退出程序
+ mainFrame.add(env);
+
+ mainFrame.add(brainPic);
+
+ JButton button = new JButton("Show first frog's brain");
+ int buttonWidth = 180;
+ 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 first frog's 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 first frog's brain");
+ mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 100);
+ }
+ }
+ };
+ button.addActionListener(al);
+ mainFrame.add(button);
+
+ JButton stopButton = new JButton("Pause");
+ stopButton.setBounds(buttonXpos, Env.ENV_HEIGHT + 35, buttonWidth, buttonHeight);
+ 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/history/003_trap/src/main/java/com/github/drinkjava2/frog/Env.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/Env.java
new file mode 100644
index 0000000..f2da41a
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/Env.java
@@ -0,0 +1,257 @@
+package com.github.drinkjava2.frog;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JPanel;
+
+import com.github.drinkjava2.frog.brain.group.RandomConnectGroup;
+import com.github.drinkjava2.frog.egg.Egg;
+import com.github.drinkjava2.frog.egg.EggTool;
+import com.github.drinkjava2.frog.objects.Food;
+import com.github.drinkjava2.frog.objects.Material;
+import com.github.drinkjava2.frog.objects.Object;
+import com.github.drinkjava2.frog.objects.Trap;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * Env is the living space of frog. draw it on JPanel
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+@SuppressWarnings("all")
+public class Env extends JPanel {
+ /** Speed of test */
+ public static final int SHOW_SPEED = 500; // 测试速度,-1000~1000,可调, 数值越小,速度越慢
+
+ /** Delete eggs at beginning of each run */
+ public static final boolean DELETE_EGGS = true;// 每次运行是否先删除保存的蛋
+
+ public static final int EGG_QTY = 25; // 每轮下n个蛋,可调,只有最优秀的前n个青蛙们才允许下蛋
+
+ public static final int FROG_PER_EGG = 4; // 每个蛋可以孵出几个青蛙
+
+ public static final int SCREEN = 1; // 分几屏测完
+
+ public static final int FROG_PER_SCREEN = EGG_QTY * FROG_PER_EGG / SCREEN; // 每屏上显示几个青蛙,这个数值由上面三个参数计算得来
+
+ /** Draw first frog's brain after some steps */
+ public static int DRAW_BRAIN_AFTER_STEPS = 50; // 以此值为间隔动态画出脑图,设为0则关闭这个动态脑图功能,只显示一个静态、不闪烁的脑图
+
+ /** Environment x width, unit: pixels */
+ public static final int ENV_WIDTH = 400; // 虚拟环境的宽度, 可调
+
+ /** Environment y height, unit: pixels */
+ 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的脑图在屏幕上的显示大小,可调
+
+ /** Steps of one test round */
+ public static final int STEPS_PER_ROUND = 2000;// 每轮测试步数,可调
+
+ /** Frog's brain width, fixed to 1000 unit */
+ public static final float FROG_BRAIN_WIDTH = 1000; // frog的脑宽度固定为1000,不要随便调整,因为器官的相对位置和大小是按脑大小设定的
+
+ public static final int FOOD_QTY = 1500; // 食物数量, 可调
+
+ public static boolean pause = false; // 暂停按钮按下将暂停测试
+
+ public static byte[][] bricks = new byte[ENV_WIDTH][ENV_HEIGHT];// 组成环境的材料,0=无, 1=食, 其它=其它...
+
+ public static List frogs = new ArrayList<>(); // 这里存放所有待测的青蛙,可能分几次测完,由FROG_PER_SCREEN大小来决定
+
+ public static List eggs = new ArrayList<>(); // 这里存放从磁盘载入或上轮下的蛋,每个蛋可能生成1~n个青蛙,
+
+ public static Object[] things = new Object[] { new Food(), new Trap() };
+
+ static {
+ System.out.println("唵缚悉波罗摩尼莎诃!"); // 杀生前先打印往生咒,见码云issue#IW4H8
+ if (DELETE_EGGS)
+ EggTool.deleteEggs();
+ }
+
+ public Env() {
+ super();
+ this.setLayout(null);// 空布局
+ this.setBounds(1, 1, ENV_WIDTH, ENV_HEIGHT);
+ }
+
+ public static boolean insideEnv(int x, int y) {// 如果指定点在边界内
+ return !(x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT);
+ }
+
+ public static boolean outsideEnv(int x, int y) {// 如果指定点超出边界
+ return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT;
+ }
+
+ public static boolean closeToEdge(Frog f) {// 青蛙靠近边界? 离死不远了
+ return f.x < 20 || f.y < 20 || f.x > (Env.ENV_WIDTH - 20) || f.y > (Env.ENV_HEIGHT - 20);
+ }
+
+ public static boolean foundAnyThing(int x, int y) {// 如果指定点看到任意东西或超出边界
+ return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT || Env.bricks[x][y] >= Material.VISIBLE;
+ }
+
+ public static boolean foundAndAteFood(int x, int y) {// 如果x,y有食物,将其清0,返回true
+ if (insideEnv(x, y) && Env.bricks[x][y] == Material.FOOD) {
+ bricks[x][y] = 0;
+ return true;
+ }
+ return false;
+ }
+
+ private void rebuildFrogs() {
+ frogs.clear();
+ for (int i = 0; i < eggs.size(); i++) {// 创建青蛙,每个蛋生成n个蛙,并随机取一个别的蛋作为精子
+ int loop = FROG_PER_EGG;
+ if (eggs.size() > 20) { // 如果数量多,进行一些优化,让排名靠前的Egg多孵出青蛙
+ if (i < FROG_PER_EGG)// 0,1,2,3
+ loop = FROG_PER_EGG + 1;
+ if (i >= (eggs.size() - FROG_PER_EGG))
+ loop = FROG_PER_EGG - 1;
+ }
+ for (int j = 0; j < loop; j++) {
+ Egg zygote = new Egg(eggs.get(i), eggs.get(RandomUtils.nextInt(eggs.size())));
+ frogs.add(new Frog(RandomUtils.nextInt(ENV_WIDTH), RandomUtils.nextInt(ENV_HEIGHT), zygote));
+ }
+ }
+ }
+
+ private void drawWorld(Graphics g) {
+ byte brick;
+ for (int x = 0; x < ENV_WIDTH; x++)
+ for (int y = 0; y < ENV_HEIGHT; y++) {
+ brick = bricks[x][y];
+ if (brick != 0) {
+ g.setColor(Material.color(brick));
+ if (brick == Material.FOOD)
+ g.fillRoundRect(x, y, 4, 4, 2, 2); // show food bigger
+ else
+ g.drawLine(x, y, x, y); // only 1 point
+ }
+ }
+ g.setColor(Color.BLACK);
+ }
+
+ static final NumberFormat format100 = NumberFormat.getPercentInstance();
+ static {
+ format100.setMaximumFractionDigits(2);
+ }
+
+ private static int foodFoundAmount() {// 统计找食数等
+ int leftfood = 0;
+ for (int x = 0; x < ENV_WIDTH; x++)
+ for (int y = 0; y < ENV_HEIGHT; y++)
+ if (bricks[x][y] == Material.FOOD)
+ leftfood++;
+ return FOOD_QTY - leftfood;
+ }
+
+ private String foodFoundCountText() {// 统计找食数等
+ int foodFound = foodFoundAmount();
+ int maxFound = 0;
+ for (Frog f : frogs)
+ if (f.ateFood > maxFound)
+ maxFound = f.ateFood;
+ return new StringBuilder("找食率:").append(format100.format(foodFound * 1.00 / FOOD_QTY)).append(", 平均: ")
+ .append(foodFound * 1.0f / FROG_PER_SCREEN).append(",最多:").append(maxFound).toString();
+ }
+
+ private static void sleep(long millis) {
+ try {
+ Thread.sleep(millis);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+ EggTool.loadEggs(); // 从磁盘加载egg,或新建一批egg
+ Image buffImg = createImage(this.getWidth(), this.getHeight());
+ Graphics g = buffImg.getGraphics();
+ long time0;// 计时用
+ int round = 1;
+ do {
+ rebuildFrogs();
+ for (int screen = 0; screen < SCREEN; screen++) {// 分屏测试,每屏FROG_PER_SCREEN个蛙
+ time0 = System.currentTimeMillis();
+ if (pause)
+ do {
+ sleep(300);
+ } while (pause);
+ for (Object thing : things) // 创建食物、陷阱等物体
+ thing.build();
+ boolean allDead = false;
+ 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();
+ }
+ for (int i = 0; i < STEPS_PER_ROUND; i++) {
+ for (Object thing : things)// 调用食物、陷阱等物体的动作
+ thing.active(screen);
+ if (allDead)
+ break; // 青蛙全死光了就直接跳到下一轮,以节省时间
+ allDead = true;
+ for (int j = 0; j < FROG_PER_SCREEN; j++) {
+ Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
+ if (f.active(this))
+ allDead = false;
+ if (f.alive && RandomUtils.percent(0.2f)) {// 有很小的机率在青蛙活着时就创建新的器官
+ RandomConnectGroup newConGrp = new RandomConnectGroup();
+ newConGrp.initFrog(f);
+ f.organs.add(newConGrp);
+ }
+ }
+
+ if (SHOW_SPEED > 0 && i % SHOW_SPEED != 0) // 用画青蛙的方式来拖慢速度
+ continue;
+
+ if (SHOW_SPEED < 0) // 如果speed小于0,人为加入延迟
+ sleep(-SHOW_SPEED);
+
+ // 开始画青蛙
+ g.setColor(Color.white);
+ g.fillRect(0, 0, this.getWidth(), this.getHeight());
+ g.setColor(Color.BLACK);
+ drawWorld(g);
+ for (int j = 0; j < FROG_PER_SCREEN; j++) {
+ Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
+ f.show(g);
+ }
+
+ if (firstFrog.alive) { // 开始显示第一个Frog的动态脑图
+ if (Application.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)
+ Application.brainPic.drawBrainPicture(firstFrog);
+ }
+ Graphics g2 = this.getGraphics();
+ g2.drawImage(buffImg, 0, 0, this);
+ }
+ for (int j = 0; j < FROG_PER_SCREEN; j++) {
+ Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
+ f.cells.clear();
+ }
+ 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());
+ for (Object thing : things)// 去除食物、陷阱等物体
+ thing.destory();
+ }
+ round++;
+ EggTool.layEggs();
+ } while (true);
+ }
+
+}
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/Frog.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/Frog.java
new file mode 100644
index 0000000..cf8be8d
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/Frog.java
@@ -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;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+
+import com.github.drinkjava2.frog.brain.Cell;
+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
+ *
+ * 青蛙由器官组成,器官中的Group类会生成各种脑细胞
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Frog {
+
+ /** brain cells */
+ public List cells = new ArrayList<>();
+
+ /** organs */
+ public List organs = new ArrayList<>();
+
+ public int x; // frog在Env中的x坐标
+ public int y; // frog在Env中的y坐标
+ public long energy = 100000; // 青蛙的能量为0则死掉
+ public boolean alive = true; // 设为false表示青蛙死掉了,将不参与计算和显示,以节省时间
+ public int ateFood = 0;
+
+ static Image frogImg;
+ static {
+ try {
+ frogImg = ImageIO.read(new FileInputStream(Application.CLASSPATH + "frog.png"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public Frog(int x, int y, Egg egg) {
+ this.x = x;
+ this.y = y;
+ for (Organ org : egg.organs)
+ organs.add(org);
+ }
+
+ public void initOrgans() {
+ for (Organ org : organs)
+ org.initFrog(this);// 每个新器官初始化,如果是Group类,它们会生成许多脑细胞
+ }
+
+ public boolean active(Env v) {
+ // 如果能量小于0则死、出界、与非食物的点重合则判死
+ if (!alive || energy < 0 || Env.outsideEnv(x, y) || Env.bricks[x][y] >= Material.KILLFROG) {
+ energy -= 100; // 死掉的青蛙也要消耗能量,确保淘汰出局
+ alive = false;
+ return false;
+ }
+ energy -= 20;
+ for (Organ o : organs) {
+ o.active(this);
+ }
+ return alive;
+ }
+
+ public void show(Graphics g) {// 显示青蛙的图象
+ if (!alive)
+ return;
+ g.drawImage(frogImg, x - 8, y - 8, 16, 16, null);
+ }
+
+}
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java
new file mode 100644
index 0000000..44de23f
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java
@@ -0,0 +1,128 @@
+package com.github.drinkjava2.frog.brain;
+
+import static java.awt.Color.BLUE;
+import static java.awt.Color.CYAN;
+import static java.awt.Color.GREEN;
+import static java.awt.Color.MAGENTA;
+import static java.awt.Color.ORANGE;
+import static java.awt.Color.RED;
+import static java.awt.Color.YELLOW;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import javax.swing.JPanel;
+
+import com.github.drinkjava2.frog.Application;
+import com.github.drinkjava2.frog.Frog;
+
+/**
+ * BrainPicture show first frog's brain structure, for debug purpose only
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+@SuppressWarnings("serial")
+public class BrainPicture extends JPanel {
+ private float brainWidth; // real brain width
+ private int brainDispWidth; // screen display width
+ private Color color = Color.BLACK;
+
+ public void setColor(Color c) {
+ color = c;
+ }
+
+ public BrainPicture(int x, int y, float brainWidth, int brainDispWidth) {
+ super();
+ this.setLayout(null);// 空布局
+ this.brainDispWidth = brainDispWidth;
+ this.brainWidth = brainWidth;
+ this.setBounds(x, y, brainDispWidth + 1, brainDispWidth + 1);
+ }
+
+ public void drawZone( Zone z) {Graphics g = this.getGraphics();
+ g.setColor(color);
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ int radius = Math.round(z.r * rate);
+ g.drawRect(x - radius, y - radius, radius * 2, radius * 2);
+ }
+
+ public void drawCircle( Zone z) {Graphics g = this.getGraphics();
+ g.setColor(color);
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ g.drawArc(x - 5, y - 5, 10, 10, 0, 360);
+ }
+
+ public void fillZone( Zone z) {Graphics g = this.getGraphics();
+ g.setColor(color);
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ int radius = Math.round(z.r * rate);
+ g.fillRect(x - radius, y - radius, radius * 2, radius * 2);
+ }
+
+ public void drawLine(Zone z1, Zone z2) {
+ Graphics g = this.getGraphics();
+ g.setColor(color);
+ float rate = brainDispWidth / brainWidth;
+ int x1 = Math.round(z1.x * rate);
+ int y1 = Math.round(z1.y * rate);
+ int x2 = Math.round(z2.x * rate);
+ int y2 = Math.round(z2.y * rate);
+ g.drawLine(x1, y1, x2, y2);
+ }
+
+ public void drawText( Zone z, String text) {Graphics g = this.getGraphics();
+ g.setColor(color);
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ g.drawString(text, x - text.length() * 3 - 2, y);
+ }
+
+ private static final Color[] rainbow = new Color[] { RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA };
+ private static int nextColor = 0;
+
+ public static Color nextRainbowColor() {
+ if (nextColor == rainbow.length)
+ nextColor = 0;
+ return rainbow[nextColor++];
+ }
+
+ public static Color color(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)
+ return;
+ Graphics g = this.getGraphics();// border
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, brainDispWidth, brainDispWidth);
+ g.setColor(Color.black);
+ g.drawRect(0, 0, brainDispWidth, brainDispWidth);
+
+ for (Organ organ : frog.organs)
+ organ.drawOnBrainPicture(frog, this); // each organ draw itself
+ }
+
+}
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Cell.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
new file mode 100644
index 0000000..fdae751
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * Cell is the basic unit of frog's brain
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Cell {
+ public static final float MAX_ENERGY_LIMIT = 100.0f;
+
+ // this cell belong to frog's which organ
+ public Organ organ;
+
+ // inputs of cell
+ public Input[] inputs; // 每个细胞有一组输入触突
+
+ // outputs of cell
+ public Output[] outputs; // 每个细胞有一组输出触突
+
+ // energy of cell, energy got from food
+ public float energy; // 每个细胞当前的能量值
+
+}
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/Input.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Input.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/Input.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Input.java
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Organ.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
new file mode 100644
index 0000000..c26da8f
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
@@ -0,0 +1,94 @@
+/*
+ * 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;
+
+import java.awt.Color;
+
+import com.github.drinkjava2.frog.Application;
+import com.github.drinkjava2.frog.Frog;
+
+/**
+ * Organ is a part of frog, organ can be saved in egg
+ *
+ * 器官是脑的一部分,多个器官在脑内可以允许重叠出现在同一位置。
+ *
+ * @author Yong Zhu
+ * @since 1.0.4
+ */
+public class Organ extends Zone {
+ private static final long serialVersionUID = 1L;
+ public String name; // 显示在脑图上的器官名称,可选
+ public long fat = 0; // 如果活跃多,fat值高,则保留(及变异)的可能性大,反之则很可能丢弃掉
+ // public float organWasteEnergy = 0.05f; //
+ // 器官在每个测试循环中需要消耗青蛙多少能量,可以通过调节这个参数抑制器官数量无限增长
+ public float organActiveEnergy = 1; // 输出器官激活需要消耗每个脑细胞多少能量
+ public float organOutputEnergy = 2; // 感觉器官激活会给每个脑细胞增加多少能量
+ public boolean initilized; // 通过这个标记判断是否需要手工给定它的参数初值
+
+ public boolean allowBorrow() { // 是否允许在精子中将这个器官借出
+ return false;
+ }
+
+ /** Each loop step call active method, Child class can override this method */
+ public void active(Frog f) { // 每一步都会调用器官的active方法 ,缺省啥也不干
+ }
+
+ /** If active in this organ's zone? */
+ public boolean outputActive(Frog f) { // 如果一个细胞能量>10,且它的输出触突位于这个器官内,则器官被激活
+ for (Cell cell : f.cells) {
+ if (cell.energy > organActiveEnergy)
+ for (Output output : cell.outputs) { //
+ if (this.nearby(output)) {
+ cell.organ.fat++;
+ cell.energy -= 30;//
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /** Set X, Y, Radius, name of current Organ */
+ public Organ setXYRN(float x, float y, float r, String name) {
+ this.setXYR(x, y, r);
+ this.name = name;
+ return this;
+ }
+
+ /** Child class can override this method to drawing picture */
+ public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来,子类可以重写这个方法
+ if (!Application.SHOW_FIRST_FROG_BRAIN)
+ return;
+ pic.setColor(Color.BLACK); // 缺省是黑色
+ pic.drawZone(this);
+ if (this.name != null)
+ pic.drawText(this, String.valueOf(this.name));
+ }
+
+ /** Only call once when frog created , Child class can override this method */
+ public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次,缺省啥也不干,通常用于Group子类的初始化
+ }
+
+ /** Only call once after organ be created by new() method */
+ public Organ[] vary() { // 在下蛋时每个器官会调用这个方法,缺省返回一个类似自已的副本,子类通常要覆盖这个方法
+ Organ newOrgan = null;
+ try {
+ newOrgan = this.getClass().newInstance();
+ } catch (Exception e) {
+ throw new UnknownError("Can not make new Organ copy for " + this);
+ }
+ copyXYR(this, newOrgan);
+ newOrgan.name = this.name;
+ newOrgan.fat = this.fat;
+ return new Organ[] { newOrgan };
+ }
+
+}
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/Output.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Output.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/Output.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Output.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/Zone.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Zone.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/Zone.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/Zone.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/group/Group.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/group/Group.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/group/Group.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/group/Group.java
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/group/RandomConnectGroup.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/group/RandomConnectGroup.java
new file mode 100644
index 0000000..ed223df
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/group/RandomConnectGroup.java
@@ -0,0 +1,100 @@
+/*
+ * 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.group;
+
+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.Input;
+import com.github.drinkjava2.frog.brain.Organ;
+import com.github.drinkjava2.frog.brain.Output;
+import com.github.drinkjava2.frog.brain.Zone;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * RandomConnectGroup
+ *
+ * 这是一个随机方式连接两端的Group,它是从旧版的CellGroup改造过来,这是一种最简单的神经元排列方式,只有一组细胞,触突输入区和输出区分别位于Zone内的任意随机两点。
+ * 至于是否合理则由frog的遗传进化来决定,不合理的RandomConnectGroup会被淘汰掉。
+ *
+ * (还没改造完成,在不破坏原有外在表现的基础上,要平滑将它改造成一个标准Group的子类,也是第一个子类 )
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class RandomConnectGroup extends Group {
+ private static final long serialVersionUID = 1L;
+
+ public Zone inputZone; // 输入触突区
+ public Zone outputZone; // 输出触突区
+
+ @Override
+ public boolean allowBorrow() { // 是否允许在精子中将这个器官借出
+ return true;
+ }
+
+ @Override
+ public void initFrog(Frog f) {
+ if (!initilized) {
+ initilized = true;
+ // organWasteEnergy=.05f;
+ x = Env.FROG_BRAIN_WIDTH / 2;
+ y = Env.FROG_BRAIN_WIDTH / 2;
+ r = Env.FROG_BRAIN_WIDTH / 2;
+ inputZone = RandomUtils.randomPosInAnyFrogOrgan(f);
+ outputZone = RandomUtils.randomPosInAnyFrogOrgan(f);
+ }
+
+ this.fat = 0;// 每次fat清0,因为遗传下来的fat不为0
+
+ Cell c = new Cell();
+ Input in = new Input(inputZone);
+ in.cell = c;
+ c.inputs = new Input[] { in };
+
+ Output out = new Output(outputZone);
+ out.cell = c;
+ c.outputs = new Output[] { out };
+
+ c.organ = this;
+ f.cells.add(c);
+ }
+
+ @Override
+ public Organ[] vary() {
+ if (fat <= 0)// 如果胖值为0,表示这个组的细胞没有用到,可以小概率丢掉它了
+ if (RandomUtils.percent(30))
+ return new Organ[] {};
+ if (RandomUtils.percent(3)) // 有3%的几率丢掉它,防止这个器官数量只增不减
+ return new Organ[] {};
+ return new Organ[] { this };
+ }
+
+ @Override
+ public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
+ if (fat <= 0)
+ pic.setColor(Color.LIGHT_GRAY); // 没用到? 灰色
+ else
+ pic.setColor(Color.red); // 用到了?红色
+ pic.drawLine(inputZone, outputZone);
+ pic.drawZone(this);
+ pic.drawZone(inputZone);
+ pic.fillZone(outputZone);
+ if (fat > 0) {
+ pic.setColor(Color.red);
+ pic.drawCircle(outputZone); // 如果胖了,表示激活过了,下次下蛋少不了这一组
+ }
+ }
+
+}
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Chance.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Chance.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/organ/Chance.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Chance.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
new file mode 100644
index 0000000..29d9686
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
@@ -0,0 +1,138 @@
+/*
+ * 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 com.github.drinkjava2.frog.Application;
+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.Input;
+import com.github.drinkjava2.frog.brain.Organ;
+import com.github.drinkjava2.frog.brain.Zone;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * Eye can only see 4 direction
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Eye extends Organ {// 这个Eye是老版的眼睛,只能看到四个方向,但它的调节距离会自动随机调整到一个最佳值,这就是随机试错算法的一个应用
+ private static final long serialVersionUID = 1L;
+ public int seeDistance; // 眼睛能看到的距离
+
+ @Override
+ public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次
+ if (!initilized) {
+ initilized = true;
+ organOutputEnergy = 30;
+ seeDistance = 8;
+ }
+ }
+
+ @Override
+ public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
+ if (!Application.SHOW_FIRST_FROG_BRAIN)
+ return;
+ super.drawOnBrainPicture(f, pic);
+ float qRadius = r / 4;
+ float q3Radius = (float) (r * .75);
+ Zone seeUp = new Zone(x, y + q3Radius, qRadius);
+ Zone seeDown = new Zone(x, y - q3Radius, qRadius);
+ Zone seeLeft = new Zone(x - q3Radius, y, qRadius);
+ Zone seeRight = new Zone(x + q3Radius, y, qRadius);
+ pic.drawZone(seeUp);
+ pic.drawZone(seeDown);
+ pic.drawZone(seeLeft);
+ pic.drawZone(seeRight);
+ }
+
+ @Override
+ public Organ[] vary() {
+ if (RandomUtils.percent(5)) { // 可视距离有5%的机率变异
+ seeDistance = seeDistance + 1 - 2 * RandomUtils.nextInt(2);
+ if (seeDistance < 1)
+ seeDistance = 1;
+ if (seeDistance > 50)
+ seeDistance = 50;
+ }
+ return new Organ[] { this };
+ }
+
+ @Override
+ public void active(Frog f) {
+ // 第一个眼睛只能观察上、下、左、右四个方向有没有食物
+ float qRadius = r / 4;
+ float q3Radius = (float) (r * .75);
+ Zone seeUp = new Zone(x, y + q3Radius, qRadius);
+ Zone seeDown = new Zone(x, y - q3Radius, qRadius);
+ Zone seeLeft = new Zone(x - q3Radius, y, qRadius);
+ Zone seeRight = new Zone(x + q3Radius, y, qRadius);
+
+ boolean seeSomething = false;
+ boolean atUp = false;
+ boolean atDown = false;
+ boolean atLeft = false;
+ boolean atRight = false;
+
+ for (int i = 1; i < seeDistance; i++)
+ if (Env.foundAnyThing(f.x, f.y + i)) {
+ seeSomething = true;
+ atUp = true;
+ break;
+ }
+
+ for (int i = 1; i < seeDistance; i++)
+ if (Env.foundAnyThing(f.x, f.y - i)) {
+ seeSomething = true;
+ atDown = true;
+ break;
+ }
+
+ for (int i = 1; i < seeDistance; i++)
+ if (Env.foundAnyThing(f.x - i, f.y)) {
+ seeSomething = true;
+ atLeft = true;
+ break;
+ }
+
+ for (int i = 1; i < seeDistance; i++)
+ if (Env.foundAnyThing(f.x + i, f.y)) {
+ seeSomething = true;
+ atRight = true;
+ break;
+ }
+
+ if (seeSomething)
+ for (Cell cell : f.cells) {
+ if (cell.energy < 100)
+ for (Input input : cell.inputs) {
+ if (input.nearby(this)) {
+ if (atUp && input.nearby(seeUp)) {
+ input.cell.energy += organOutputEnergy;
+ }
+ if (atDown && input.nearby(seeDown)) {
+ input.cell.energy += organOutputEnergy;
+ }
+ if (atLeft && input.nearby(seeLeft)) {
+ input.cell.energy += organOutputEnergy;
+ }
+ if (atRight && input.nearby(seeRight)) {
+ input.cell.energy += organOutputEnergy;
+ }
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Happy.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Happy.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/organ/Happy.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Happy.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Hungry.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Hungry.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/organ/Hungry.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Hungry.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveDown.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveDown.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveDown.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveDown.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveLeft.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveLeft.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveLeft.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveLeft.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveRight.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveRight.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveRight.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveRight.java
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveUp.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveUp.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveUp.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveUp.java
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/NewEye.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/NewEye.java
new file mode 100644
index 0000000..d9459ed
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/NewEye.java
@@ -0,0 +1,91 @@
+/*
+ * 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 com.github.drinkjava2.frog.Application;
+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.Input;
+import com.github.drinkjava2.frog.brain.Organ;
+import com.github.drinkjava2.frog.brain.Zone;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * Eye is an organ can see environment, and active brain cells which inputs are
+ * located in eye range
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class NewEye extends Organ {// 这个新版的眼睛有nxn个感光细胞,可以看到青蛙周围nxn网络内有没有食物
+ private static final long serialVersionUID = 1L;
+ public int n = 3; // 眼睛有n x n个感光细胞, 用随机试错算法自动变异(加1或减1,最小是3x3)
+
+ @Override
+ public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次,缺省啥也不干,通常用于Organ类的初始化
+ if (!initilized) {
+ initilized = true;
+ organOutputEnergy = 30;
+ }
+ }
+
+ @Override
+ public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
+ if (!Application.SHOW_FIRST_FROG_BRAIN)
+ return;
+ super.drawOnBrainPicture(f, pic);
+ float r2 = r / n; // r2是每个感光细胞的半径
+ float x0 = x - r;
+ float y0 = y - r; // x0,y0是眼睛的左上角
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ Zone cell = new Zone(x0 + i * 2 * r2 + r2, y0 + j * 2 * r2 + r2, r2);
+ if (Env.foundAnyThing(f.x - n / 2 + i, f.y - n / 2 + j))
+ pic.fillZone(cell);
+ else
+ pic.drawZone(cell);
+ }
+ }
+ }
+
+ @Override
+ public Organ[] vary() {
+ if (RandomUtils.percent(50)) {
+ n = n + 1 - 2 * RandomUtils.nextInt(2);
+ if (n < 3)
+ n = 3;
+ if (n > 12)
+ n = 12;
+ }
+ return new Organ[] { this };
+ }
+
+ @Override
+ public void active(Frog f) {// 如果看到食物就激活对应脑区的所有输入触突
+ float r2 = r / n; // r2是每个感光细胞的半径
+ float x0 = x - r;
+ float y0 = y - r; // x0,y0是眼睛的左上角
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ if (Env.foundAnyThing(f.x - n / 2 + i, f.y - n / 2 + j)) {
+ Zone eyeCell = new Zone(x0 + i * 2 * r2 + r2, y0 + j * 2 * r2 + r2, r2);
+ for (Cell cell : f.cells)
+ for (Input input : cell.inputs)
+ if (input.nearby(eyeCell))
+ input.cell.energy += organOutputEnergy;
+ }
+ }
+ }
+ }
+
+}
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/Pain.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Pain.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/organ/Pain.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/brain/organ/Pain.java
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/egg/Egg.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
new file mode 100644
index 0000000..ac5128c
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
@@ -0,0 +1,101 @@
+/*
+ * 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.egg;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Organ;
+import com.github.drinkjava2.frog.brain.group.Group;
+import com.github.drinkjava2.frog.brain.organ.Active;
+import com.github.drinkjava2.frog.brain.organ.Chance;
+import com.github.drinkjava2.frog.brain.organ.Eat;
+import com.github.drinkjava2.frog.brain.organ.Eye;
+import com.github.drinkjava2.frog.brain.organ.Happy;
+import com.github.drinkjava2.frog.brain.organ.Hungry;
+import com.github.drinkjava2.frog.brain.organ.MoveDown;
+import com.github.drinkjava2.frog.brain.organ.MoveLeft;
+import com.github.drinkjava2.frog.brain.organ.MoveRight;
+import com.github.drinkjava2.frog.brain.organ.MoveUp;
+import com.github.drinkjava2.frog.brain.organ.NewEye;
+import com.github.drinkjava2.frog.brain.organ.Pain;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * Egg is the static structure description of frog, can save as text file, to
+ * build a frog, first need build a egg.
+ *
+ * 蛋存在的目的是为了以最小的字节数串行化存储Frog,它是Frog的生成算法描述,而不是Frog本身,这样一来Frog就不能"永生"了,因为每一个egg都不等同于
+ * 它的母体, 而且每一次测试,大部分条件反射的建立都必须从头开始训练,类似于人类,无论人类社会有多聪明, 婴儿始终是一张白纸,需要花大量的时间从头学习。
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Egg implements Serializable {
+ // 为了缩短时间,这个程序随机生成的联结将只落在固定的器官上而不是漫天撒网(见4.12提交),这是程序的优化,实现的逻辑和随机漫天撒网定是相同的。
+ // 但是这个优化带来的问题是这是一个硬编码逻辑,不利于器官的优胜劣汰, 而且下面这个 FIXED_ORGAN_QTY必须每次手工设定,以后需要重构这块的代码
+ public static int FIXED_ORGAN_QTY = 11;
+
+ private static final long serialVersionUID = 1L;
+
+ public List organs = new ArrayList<>();
+
+ public List groups = new ArrayList<>();
+
+ public Egg() {// 无中生有,创建一个蛋,先有蛋,后有蛙
+ organs.add(new Happy().setXYRN(600, 700, 60, "Happy")); // Happy必须第一个加入
+ organs.add(new Hungry().setXYRN(300, 100, 60, "Hungry"));
+ organs.add(new MoveUp().setXYRN(800, 100, 60, "Up"));
+ organs.add(new MoveDown().setXYRN(800, 400, 60, "Down"));
+ organs.add(new MoveLeft().setXYRN(700, 250, 60, "Left"));
+ organs.add(new MoveRight().setXYRN(900, 250, 60, "Right"));
+ organs.add(new Eye().setXYRN(100, 300, 100, "Eye"));
+ organs.add(new NewEye().setXYRN(200, 700, 200, "NewEye"));
+ organs.add(new Pain().setXYRN(800, 700, 60, "Pain")); // 痛苦在靠近边界时触发
+ organs.add(new Active().setXYRN(500, 100, 60, "Active")); // 永远激活
+ organs.add(new Chance().setXYRN(650, 100, 60, "Chance")); // 永远激活
+
+ // 以上为11个, 就是FIXED_ORGAN_QTY值
+
+ organs.add(new Eat().setXYRN(0, 0, 0, "Eat")); // EAT不是感觉或输出器官,没有位置和大小
+
+ }
+
+ /** Create egg from frog */
+ public Egg(Frog frog) { // 青蛙下蛋,每个青蛙的器官会创建自已的副本或变异,可以是0或多个
+ for (Organ organ : frog.organs)
+ for (Organ newOrgan : organ.vary())
+ organs.add(newOrgan);
+ }
+
+ /**
+ * Create a egg by join 2 eggs, x+y=zygote 模拟X、Y 染色体合并,两个蛋生成一个新的蛋, X从Y里借一个器官,
+ * 不用担心器官会越来越多,因为通过用进废退原则来筛选,没用到的器官会在几代之后被自然淘汰掉
+ * 器官不是越多越好,因为器官需要消耗能量,器官数量多了,在生存竞争中也是劣势
+ *
+ */
+ public Egg(Egg x, Egg y) {
+ // x里原来的organ
+ for (Organ organ : x.organs)
+ organs.add(organ);
+
+ // 从y里借一个organ
+ int yOrganSize = y.organs.size();
+ if (yOrganSize > 0) {
+ Organ o = y.organs.get(RandomUtils.nextInt(yOrganSize));
+ if (o.allowBorrow())
+ organs.add(o);
+ }
+ }
+
+}
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
new file mode 100644
index 0000000..4e36670
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
@@ -0,0 +1,110 @@
+/*
+ * 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.egg;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+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.Chance;
+import com.github.drinkjava2.frog.brain.organ.Eye;
+import com.github.drinkjava2.frog.util.FrogFileUtils;
+
+/**
+ * EggTool save eggs to disk
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class EggTool {
+
+ /**
+ * Frogs which have higher energy lay eggs
+ *
+ * 利用Java串行机制存盘。 能量多(也就是吃的更多)的Frog下蛋并存盘, 以进行下一轮测试,能量少的Frog被淘汰,没有下蛋的资格。
+ * 用能量的多少来简化生存竟争模拟,每次下蛋数量固定为EGG_QTY个
+ */
+ public static void layEggs() {
+ sortFrogsOrderByEnergyDesc();
+
+ 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++)
+ Env.eggs.add(new Egg(Env.frogs.get(i)));
+ FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs.ser");
+ ObjectOutputStream so = new ObjectOutputStream(fo);
+ so.writeObject(Env.eggs);
+ so.close();
+ System.out.print("\r1st frog has " + first.organs.size() + " organs, energy=" + first.energy + ", seeDist="
+ + ((Eye) first.organs.get(6)).seeDistance + ", chance=" + ((Chance) first.organs.get(10)).percent);
+ System.out.println(", Last frog has " + last.organs.size() + " organs, energy=" + last.energy);
+ System.out.println("Saved "+Env.eggs.size() +" eggs to file '" + Application.CLASSPATH + "eggs.ser'");
+ } catch (IOException e) {
+ System.out.println(e);
+ }
+ }
+
+ private static void sortFrogsOrderByEnergyDesc() {// 按能量多少给青蛙排序
+ Collections.sort(Env.frogs, new Comparator() {
+ public int compare(Frog a, Frog b) {
+ if (a.energy > b.energy)
+ return -1;
+ else if (a.energy == b.energy)
+ return 0;
+ else
+ return 1;
+ }
+ });
+ }
+
+ public static void deleteEggs() {
+ System.out.println("Delete exist egg file: '" + Application.CLASSPATH + "eggs.ser'");
+ FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs.ser");
+ }
+
+ /**
+ * 从磁盘读入一批Egg
+ */
+ @SuppressWarnings("unchecked")
+ public static void loadEggs() {
+ boolean errorfound = false;
+ 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" + "'.\n");
+ eggsInputStream.close();
+ } catch (Exception e) {
+ errorfound = true;
+ }
+ if (errorfound) {
+ Env.eggs.clear();
+ for (int j = 0; j < Env.EGG_QTY; j++)
+ Env.eggs.add(new Egg());
+ System.out.println("Fail to load egg file at path '" + Application.CLASSPATH + "', created "
+ + Env.eggs.size() + " eggs to do test.\n");
+ }
+
+ }
+
+}
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/Food.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/Food.java
new file mode 100644
index 0000000..ea03051
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/Food.java
@@ -0,0 +1,48 @@
+/* Copyright 2018-2020 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.objects;
+
+import static com.github.drinkjava2.frog.Env.ENV_HEIGHT;
+import static com.github.drinkjava2.frog.Env.ENV_WIDTH;
+import static com.github.drinkjava2.frog.Env.FOOD_QTY;
+import static com.github.drinkjava2.frog.Env.bricks;
+
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * Food randomly scatter on Env
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Food implements Object {
+
+ @Override
+ public void build() {
+ for (int i = 0; i < FOOD_QTY; i++) // 生成食物
+ bricks[RandomUtils.nextInt(ENV_WIDTH)][RandomUtils.nextInt(ENV_HEIGHT)] = Material.FOOD;
+ }
+
+ @Override
+ public void destory() {
+ for (int i = 0; i < ENV_WIDTH; i++) {// 清除食物
+ for (int j = 0; j < ENV_HEIGHT; j++)
+ if (bricks[i][j] == Material.FOOD)
+ bricks[i][j] = 0;
+ }
+ }
+
+ @Override
+ public void active(int screen) {
+ // Food do not have any active
+ }
+
+}
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/Material.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/Material.java
new file mode 100644
index 0000000..ca66cc7
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/Material.java
@@ -0,0 +1,40 @@
+/* Copyright 2018-2020 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.objects;
+
+import java.awt.Color;
+
+/**
+ * Object means some thing in Env
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Material {
+ public static final byte VISIBLE = 10; // if>=10 will visible to frog
+ public static final byte KILLFROG = 20; // if>=20 will kill frog
+
+ public static final byte NO = 0;
+ public static final byte SEESAW_BASE = 1; // 1~9 is invisible to frog
+
+ public static final byte FOOD = VISIBLE + 1;
+ public static final byte SEESAW = VISIBLE + 2; // if <0 will not cause frog die
+
+ public static final byte BRICK = KILLFROG + 1;
+ public static final byte TRAP = KILLFROG + 2;
+
+ public static Color color(byte material) {
+ if (material == TRAP)
+ return Color.LIGHT_GRAY;
+ else
+ return Color.BLACK;
+ }
+}
diff --git a/core/src/main/java/com/github/drinkjava2/frog/objects/Object.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/Object.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/objects/Object.java
rename to history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/Object.java
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java
new file mode 100644
index 0000000..5f220ae
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java
@@ -0,0 +1,93 @@
+/* Copyright 2018-2020 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.objects;
+
+import static com.github.drinkjava2.frog.Env.ENV_HEIGHT;
+import static com.github.drinkjava2.frog.Env.ENV_WIDTH;
+import static com.github.drinkjava2.frog.Env.bricks;
+
+import com.github.drinkjava2.frog.Env;
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * This is a seesaw to train frog's balance
+ *
+ * @author Yong Zhu
+ * @since 2.0.1
+ */
+public class SeeSaw implements Object {
+ private static final int LEGNTH = 300;
+ private static final int CENTER_X = Env.ENV_WIDTH / 2;
+ private static final int CENTER_Y = Env.ENV_HEIGHT / 2;
+
+ private double angle = 0;// -PI/4 to PI/4
+ private double leftWeight = 0;
+ private double rightWeight = 0;
+
+ @Override
+ public void build() {
+ angle = 0;
+ }
+
+ @Override
+ public void destory() {
+
+ }
+
+ @Override
+ public void active(int screen) {
+ for (int i = 0; i < ENV_WIDTH; i++) {// 清除食物
+ for (int j = 0; j < ENV_HEIGHT; j++)
+ if (bricks[i][j] == Material.SEESAW)
+ bricks[i][j] = 0;
+ }
+
+ if (RandomUtils.percent(2))
+ leftWeight = RandomUtils.nextFloat() * 3;
+ if (RandomUtils.percent(2))
+ rightWeight = RandomUtils.nextFloat() * 3;
+ Frog f = Env.frogs.get(screen);
+
+ if (f.x < (CENTER_X - LEGNTH / 2) || f.x > (CENTER_X + LEGNTH / 2))
+ f.energy -= 100000; // 如果走出跷跷板外则扣分,出局
+ double left = leftWeight - (f.x - CENTER_X);
+ double right = rightWeight + (f.x - CENTER_X);
+ // right - left need in -100 to +100
+ angle = angle + (right - left) * Math.PI * .000001;
+ if (angle > Math.PI / 6) {
+ angle = Math.PI / 6;
+ f.energy -= 200;
+ }
+ if (angle < -Math.PI / 6) {
+ angle = -Math.PI / 6;
+ f.energy -= 200;
+ }
+ f.y = CENTER_Y + (int) Math.round((f.x - CENTER_X) * Math.tan(angle));
+ f.energy -= Math.abs(angle) * 180; // 角度越大,扣分越多
+ int x;
+ int y;
+ for (int l = -LEGNTH / 2; l <= LEGNTH / 2; l++) {
+ x = (int) Math.round(l * Math.cos(angle));
+ y = (int) Math.round(l * Math.sin(angle));
+ Env.bricks[CENTER_X + x][CENTER_Y + y] = Material.SEESAW;
+ }
+
+ // 画底座
+ for (int i = 1; i < 10; i++) {
+ Env.bricks[CENTER_X - i][CENTER_Y + i] = Material.SEESAW_BASE;
+ Env.bricks[CENTER_X + i][CENTER_Y + i] = Material.SEESAW_BASE;
+ }
+ for (int i = -10; i < 10; i++)
+ Env.bricks[CENTER_X + i][CENTER_Y + 10] = Material.SEESAW_BASE;
+
+ }
+}
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/Trap.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/Trap.java
new file mode 100644
index 0000000..0b7fc68
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/objects/Trap.java
@@ -0,0 +1,56 @@
+/* Copyright 2018-2020 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.objects;
+
+import static com.github.drinkjava2.frog.Env.ENV_HEIGHT;
+import static com.github.drinkjava2.frog.Env.ENV_WIDTH;
+import static com.github.drinkjava2.frog.Env.bricks;
+
+import com.github.drinkjava2.frog.Frog;
+
+/**
+ * Trap will kill all frogs inside of it, if frog's position has material and
+ * it's not food, frog will die
+ *
+ * @author Yong Zhu
+ * @since 2019-08-05
+ */
+@SuppressWarnings("all")
+public class Trap implements Object {
+ private static final int X1 = ENV_WIDTH / 2 - 350 / 2; // 陷阱左上角
+ private static final int Y1 = ENV_HEIGHT / 2 - 20 / 2; // 陷阱左上角
+ private static final int X2 = ENV_WIDTH / 2 + 350 / 2; // 陷阱右下角
+ private static final int Y2 = ENV_HEIGHT / 2 + 20 / 2; // 陷阱右下角
+
+ @Override
+ public void build() {
+ for (int x = X1; x <= X2; x++)
+ for (int y = Y1; y <= Y2; y++)
+ bricks[x][y] = Material.TRAP;
+ }
+
+ @Override
+ public void destory() {
+ for (int x = X1; x <= X2; x++)
+ for (int y = Y1; y <= Y2; y++)
+ bricks[x][y] = 0;
+ }
+
+ @Override
+ public void active(int screen) {
+
+ }
+
+ public static boolean inTrap(Frog f) {
+ return f.x >= X1 && f.x <= X2 && f.y >= Y1 && f.y <= Y2;
+ }
+
+}
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java
new file mode 100644
index 0000000..16f1999
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java
@@ -0,0 +1,141 @@
+/* Copyright 2018-2020 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.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * File Utilities used in this project
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class FrogFileUtils {
+
+ private FrogFileUtils() {
+ // default constructor
+ }
+
+ public static boolean deleteFile(String fileFullPath) {
+ File file = new File(fileFullPath);
+ return file.delete(); // NOSONAR
+ }
+
+ public static void writeFile(String fileFullPath, byte[] byteArry) {
+ File file = new File(fileFullPath);
+ if (!file.getParentFile().exists())
+ file.getParentFile().mkdirs();
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ fos.write(byteArry);
+ fos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static void writeFile(String fileFullPath, String text, String encoding) {
+ File file = new File(fileFullPath);
+ if (!file.getParentFile().exists())
+ file.getParentFile().mkdirs();
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ byte[] bytes;
+ bytes = text.getBytes(encoding);
+ fos.write(bytes);
+ fos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static String readFile(String fileFullPath, String encoding) {
+ InputStream inputStream;
+ try {
+ inputStream = new FileInputStream(new File(fileFullPath));
+ } catch (FileNotFoundException e1) {
+ return null;
+ }
+ try {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = inputStream.read(buffer)) != -1)
+ result.write(buffer, 0, length);
+ String string = result.toString(encoding);
+ return string;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ } finally {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ public static void appendFile(String fileName, String content) {
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(fileName, true);
+ fos.write(content.getBytes());
+ fos.write("\r\n".getBytes());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+}
diff --git a/history/003_trap/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java b/history/003_trap/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java
new file mode 100644
index 0000000..6c85556
--- /dev/null
+++ b/history/003_trap/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java
@@ -0,0 +1,62 @@
+/* Copyright 2018-2020 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.util;
+
+import java.util.Random;
+
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Zone;
+import com.github.drinkjava2.frog.egg.Egg;
+
+/**
+ * Random Utilities used in this project
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class RandomUtils {
+ private static final Random rand = new Random();
+
+ public static int nextInt(int i) {
+ return rand.nextInt(i);
+ }
+
+ public static float nextFloat() {
+ return rand.nextFloat();
+ }
+
+ /** Return a random zone inside of a zone */
+ public static Zone randomZoneInZone(Zone z) { // 在一个区内随机取一个小小区
+ return new Zone(z.x - z.r + z.r * 2 * rand.nextFloat(), z.y - z.r + z.r * 2 * rand.nextFloat(),
+ z.r * rand.nextFloat() * .04f);
+ }
+
+ /** Return a random zone inside of frog's random organ */
+ public static Zone randomPosInAnyFrogOrgan(Frog f) {
+ if (f.organs == null || f.organs.size() == 0)
+ throw new IllegalArgumentException("Can not call randomPosInRandomOrgan method when frog has no organ");
+ return randomZoneInZone(f.organs.get(RandomUtils.nextInt(Egg.FIXED_ORGAN_QTY)));
+ }
+
+ /** Return a random zone inside of frog's random organ */
+ public static Zone randomPosMostInNewEye(Frog f) {
+ if (f.organs == null || f.organs.size() == 0)
+ throw new IllegalArgumentException("Can not call randomPosInRandomOrgan method when frog has no organ");
+ if (RandomUtils.percent(95))
+ return randomZoneInZone(f.organs.get(7));// 这是一个硬编码,大部分新联接建立在newEye中
+ return randomZoneInZone(f.organs.get(RandomUtils.nextInt(Egg.FIXED_ORGAN_QTY)));
+ }
+
+ public static boolean percent(float percent) {
+ return rand.nextFloat() * 100 < percent;
+ }
+
+}
diff --git a/history/004_seasaw/LICENSE b/history/004_seasaw/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/history/004_seasaw/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ 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.
diff --git a/history/004_seasaw/maven_clean.bat b/history/004_seasaw/maven_clean.bat
new file mode 100644
index 0000000..2f3d3e5
--- /dev/null
+++ b/history/004_seasaw/maven_clean.bat
@@ -0,0 +1 @@
+mvn clean
\ No newline at end of file
diff --git a/history/004_seasaw/maven_eclipse_clean.bat b/history/004_seasaw/maven_eclipse_clean.bat
new file mode 100644
index 0000000..a427bd7
--- /dev/null
+++ b/history/004_seasaw/maven_eclipse_clean.bat
@@ -0,0 +1 @@
+mvn eclipse:clean
\ No newline at end of file
diff --git a/history/004_seasaw/maven_eclipse_eclipse.bat b/history/004_seasaw/maven_eclipse_eclipse.bat
new file mode 100644
index 0000000..99fa0b2
--- /dev/null
+++ b/history/004_seasaw/maven_eclipse_eclipse.bat
@@ -0,0 +1,2 @@
+call mvn eclipse:eclipse
+call pause
\ No newline at end of file
diff --git a/history/004_seasaw/pom.xml b/history/004_seasaw/pom.xml
new file mode 100644
index 0000000..f53c7ae
--- /dev/null
+++ b/history/004_seasaw/pom.xml
@@ -0,0 +1,102 @@
+
+ 4.0.0
+ com.gitee.drinkjava2
+ frog004
+ jar
+ 2.0.1
+
+ frog
+ An artificial life test project
+ https://gitee.com/drinkjava2/jsqlbox/frog
+
+
+ gitee Issue
+ https://gitee.com/drinkjava2/jsqlbox/frog/issues
+
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+
+ Yong Zhu
+ yong9981@gmail.com
+ https://gitee.com/drinkjava2/
+
+
+
+
+ scm:git@gitee.com:drinkjava2/frog.git
+ scm:git@gitee.com:drinkjava2/frog.git
+ git@gitee.com:drinkjava2/frog.git
+
+
+
+ UTF-8
+ UTF-8
+ UTF-8
+
+ 1.8
+ 6
+ 3.3
+ 2.6
+ 3.0.0
+ 2.7
+ 2.19
+ 2.6
+ 2.4
+ 2.10.3
+ 1.6
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${version.compiler-plugin}
+
+ ${version.java}
+ ${version.java}
+ UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.2
+
+
+
+ true
+ false
+ lib/
+ com.github.drinkjava2.frog.Application
+
+
+
+
+
+
+
+
+
+
+
diff --git a/run3d.bat b/history/004_seasaw/run.bat
similarity index 86%
rename from run3d.bat
rename to history/004_seasaw/run.bat
index d6ffcc5..ab1bab3 100644
--- a/run3d.bat
+++ b/history/004_seasaw/run.bat
@@ -1,4 +1,3 @@
-cd core3d
call mvn clean compile
cd target\classes
java -classpath ".;*" com.github.drinkjava2.frog.Application
diff --git a/history/004_seasaw/run.sh b/history/004_seasaw/run.sh
new file mode 100644
index 0000000..836c941
--- /dev/null
+++ b/history/004_seasaw/run.sh
@@ -0,0 +1,2 @@
+mvn clean package
+java -jar target/frog-*.jar
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/Application.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/Application.java
new file mode 100644
index 0000000..97afaea
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/Application.java
@@ -0,0 +1,88 @@
+package com.github.drinkjava2.frog;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+
+import com.github.drinkjava2.frog.brain.BrainPicture;
+
+/**
+ * Application's main method start the program
+ *
+ * @author Yong Zhu
+ * @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 {
+ String classpath = new File("").getAbsolutePath();
+ int core = classpath.indexOf("\\frog\\");
+ if (core > 0)
+ CLASSPATH = classpath.substring(0, core) + "\\frog\\";
+ else
+ CLASSPATH = classpath.substring(0, core) + "/frog/"; // UNIX
+ }
+ public static JFrame mainFrame = new JFrame();
+ public static Env env = new Env();
+ public static BrainPicture brainPic = new BrainPicture(Env.ENV_WIDTH + 5, 0, Env.FROG_BRAIN_WIDTH,
+ Env.FROG_BRAIN_DISP_WIDTH);
+
+ public static void main(String[] args) throws InterruptedException {
+ mainFrame.setLayout(null);
+ mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 100); // 窗口大小
+ mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭时退出程序
+ mainFrame.add(env);
+
+ mainFrame.add(brainPic);
+
+ JButton button = new JButton("Show first frog's brain");
+ int buttonWidth = 180;
+ 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 first frog's 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 first frog's brain");
+ mainFrame.setSize(Env.ENV_WIDTH + 20, Env.ENV_HEIGHT + 100);
+ }
+ }
+ };
+ button.addActionListener(al);
+ mainFrame.add(button);
+
+ JButton stopButton = new JButton("Pause");
+ stopButton.setBounds(buttonXpos, Env.ENV_HEIGHT + 35, buttonWidth, buttonHeight);
+ 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/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/Env.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/Env.java
new file mode 100644
index 0000000..d3ecd3a
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/Env.java
@@ -0,0 +1,250 @@
+package com.github.drinkjava2.frog;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JPanel;
+
+import com.github.drinkjava2.frog.brain.group.RandomConnectGroup;
+import com.github.drinkjava2.frog.egg.Egg;
+import com.github.drinkjava2.frog.egg.EggTool;
+import com.github.drinkjava2.frog.objects.Food;
+import com.github.drinkjava2.frog.objects.Material;
+import com.github.drinkjava2.frog.objects.Object;
+import com.github.drinkjava2.frog.objects.SeeSaw;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * Env is the living space of frog. draw it on JPanel
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+@SuppressWarnings("all")
+public class Env extends JPanel {
+ /** Speed of test */
+ public static final int SHOW_SPEED = 500; // 测试速度,-1000~1000,可调, 数值越小,速度越慢
+
+ /** Delete eggs at beginning of each run */
+ public static final boolean DELETE_EGGS = true;// 每次运行是否先删除保存的蛋
+
+ public static final int EGG_QTY = 25; // 每轮下n个蛋,可调,只有最优秀的前n个青蛙们才允许下蛋
+
+ public static final int FROG_PER_EGG = 4; // 每个蛋可以孵出几个青蛙
+
+ public static final int SCREEN = 100; // 分几屏测完
+
+ public static final int FROG_PER_SCREEN = EGG_QTY * FROG_PER_EGG / SCREEN; // 每屏上显示几个青蛙,这个数值由上面三个参数计算得来
+
+ /** Draw first frog's brain after some steps */
+ public static int DRAW_BRAIN_AFTER_STEPS = 50; // 以此值为间隔动态画出脑图,设为0则关闭这个动态脑图功能,只显示一个静态、不闪烁的脑图
+
+ /** Environment x width, unit: pixels */
+ public static final int ENV_WIDTH = 400; // 虚拟环境的宽度, 可调
+
+ /** Environment y height, unit: pixels */
+ 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的脑图在屏幕上的显示大小,可调
+
+ /** Steps of one test round */
+ public static final int STEPS_PER_ROUND = 2000;// 每轮测试步数,可调
+
+ /** Frog's brain width, fixed to 1000 unit */
+ public static final float FROG_BRAIN_WIDTH = 1000; // frog的脑宽度固定为1000,不要随便调整,因为器官的相对位置和大小是按脑大小设定的
+
+ public static final int FOOD_QTY = 1500; // 食物数量, 可调
+
+ public static boolean pause = false; // 暂停按钮按下将暂停测试
+
+ public static byte[][] bricks = new byte[ENV_WIDTH][ENV_HEIGHT];// 组成环境的材料,0=无, 1=食, 其它=其它...
+
+ public static List frogs = new ArrayList<>(); // 这里存放所有待测的青蛙,可能分几次测完,由FROG_PER_SCREEN大小来决定
+
+ public static List eggs = new ArrayList<>(); // 这里存放从磁盘载入或上轮下的蛋,每个蛋可能生成1~n个青蛙,
+
+ public static Object[] things = new Object[] { new SeeSaw() };
+
+ static {
+ System.out.println("唵缚悉波罗摩尼莎诃!"); // 杀生前先打印往生咒,见码云issue#IW4H8
+ if (DELETE_EGGS)
+ EggTool.deleteEggs();
+ }
+
+ public Env() {
+ super();
+ this.setLayout(null);// 空布局
+ this.setBounds(1, 1, ENV_WIDTH, ENV_HEIGHT);
+ }
+
+ public static boolean insideEnv(int x, int y) {// 如果指定点在边界内
+ return !(x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT);
+ }
+
+ public static boolean outsideEnv(int x, int y) {// 如果指定点超出边界
+ return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT;
+ }
+
+ public static boolean closeToEdge(Frog f) {// 青蛙靠近边界? 离死不远了
+ return f.x < 20 || f.y < 20 || f.x > (Env.ENV_WIDTH - 20) || f.y > (Env.ENV_HEIGHT - 20);
+ }
+
+ public static boolean foundAnyThing(int x, int y) {// 如果指定点看到任意东西或超出边界
+ return x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT || Env.bricks[x][y] >= Material.VISIBLE;
+ }
+
+ public static boolean foundAndAteFood(int x, int y) {// 如果x,y有食物,将其清0,返回true
+ if (insideEnv(x, y) && Env.bricks[x][y] == Material.FOOD) {
+ bricks[x][y] = 0;
+ return true;
+ }
+ return false;
+ }
+
+ private void rebuildFrogs() {
+ frogs.clear();
+ for (int i = 0; i < eggs.size(); i++) {// 创建青蛙,每个蛋生成n个蛙,并随机取一个别的蛋作为精子
+ int loop = FROG_PER_EGG;
+ if (eggs.size() > 20) { // 如果数量多,进行一些优化,让排名靠前的Egg多孵出青蛙
+ if (i < FROG_PER_EGG)// 0,1,2,3
+ loop = FROG_PER_EGG + 1;
+ if (i >= (eggs.size() - FROG_PER_EGG))
+ loop = FROG_PER_EGG - 1;
+ }
+ for (int j = 0; j < loop; j++) {
+ Egg zygote = new Egg(eggs.get(i), eggs.get(RandomUtils.nextInt(eggs.size())));
+ frogs.add(new Frog(RandomUtils.nextInt(ENV_WIDTH), RandomUtils.nextInt(ENV_HEIGHT), zygote));
+ }
+ }
+ }
+
+ private void drawWorld(Graphics g) {
+ byte brick;
+ for (int x = 0; x < ENV_WIDTH; x++)
+ for (int y = 0; y < ENV_HEIGHT; y++) {
+ brick = bricks[x][y];
+ if (brick != 0) {
+ g.setColor(Material.color(brick));
+ if (brick == Material.FOOD)
+ g.fillRoundRect(x, y, 4, 4, 2, 2); // show food bigger
+ else
+ g.drawLine(x, y, x, y); // only 1 point
+ }
+ }
+ g.setColor(Color.BLACK);
+ }
+
+ static final NumberFormat format100 = NumberFormat.getPercentInstance();
+ static {
+ format100.setMaximumFractionDigits(2);
+ }
+
+ private static int foodFoundAmount() {// 统计找食数等
+ int leftfood = 0;
+ for (int x = 0; x < ENV_WIDTH; x++)
+ for (int y = 0; y < ENV_HEIGHT; y++)
+ if (bricks[x][y] == 1)
+ leftfood++;
+ return FOOD_QTY - leftfood;
+ }
+
+ private String foodFoundCountText() {// 统计找食数等
+ int foodFound = foodFoundAmount();
+ int maxFound = 0;
+ for (Frog f : frogs)
+ if (f.ateFood > maxFound)
+ maxFound = f.ateFood;
+ return new StringBuilder("找食率:").append(format100.format(foodFound * 1.00 / FOOD_QTY)).append(", 平均: ")
+ .append(foodFound * 1.0f / FROG_PER_SCREEN).append(",最多:").append(maxFound).toString();
+ }
+
+ private static void sleep(long millis) {
+ try {
+ Thread.sleep(millis);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+ EggTool.loadEggs(); // 从磁盘加载egg,或新建一批egg
+ Image buffImg = createImage(this.getWidth(), this.getHeight());
+ Graphics g = buffImg.getGraphics();
+ long time0;// 计时用
+ int round = 1;
+ do {
+ rebuildFrogs();
+ for (int screen = 0; screen < SCREEN; screen++) {// 分屏测试,每屏FROG_PER_SCREEN个蛙
+ time0 = System.currentTimeMillis();
+ if (pause)
+ do {
+ sleep(300);
+ } while (pause);
+ for (Object thing : things) // 创建食物、陷阱等物体
+ thing.build();
+ boolean allDead = false;
+ Frog firstFrog = frogs.get(screen * FROG_PER_SCREEN);
+ for (int i = 0; i < STEPS_PER_ROUND; i++) {
+ for (Object thing : things)// 调用食物、陷阱等物体的动作
+ thing.active(screen);
+ if (allDead)
+ break; // 青蛙全死光了就直接跳到下一轮,以节省时间
+ allDead = true;
+ for (int j = 0; j < FROG_PER_SCREEN; j++) {
+ Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
+ if (f.active(this))
+ allDead = false;
+ if (f.alive && RandomUtils.percent(0.5f)) {// 有很小的机率在青蛙活着时就创建新的器官
+ RandomConnectGroup newConGrp = new RandomConnectGroup();
+ newConGrp.initFrog(f);
+ f.organs.add(newConGrp);
+ }
+ }
+
+ if (SHOW_SPEED > 0 && i % SHOW_SPEED != 0) // 用画青蛙的方式来拖慢速度
+ continue;
+
+ if (SHOW_SPEED < 0) // 如果speed小于0,人为加入延迟
+ sleep(-SHOW_SPEED);
+
+ // 开始画青蛙
+ g.setColor(Color.white);
+ g.fillRect(0, 0, this.getWidth(), this.getHeight());
+ g.setColor(Color.BLACK);
+ drawWorld(g);
+ for (int j = 0; j < FROG_PER_SCREEN; j++) {
+ Frog f = frogs.get(screen * FROG_PER_SCREEN + j);
+ f.show(g);
+ }
+
+ if (firstFrog.alive) { // 开始显示第一个Frog的动态脑图
+ if (Application.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)
+ Application.brainPic.drawBrainPicture(firstFrog);
+ }
+ Graphics g2 = this.getGraphics();
+ g2.drawImage(buffImg, 0, 0, this);
+ }
+ 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").append(", energy:")
+ .append(firstFrog.energy).toString());
+ for (Object thing : things)// 去除食物、陷阱等物体
+ thing.destory();
+ }
+ round++;
+ EggTool.layEggs();
+ } while (true);
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/Frog.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/Frog.java
new file mode 100644
index 0000000..5f1af0c
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/Frog.java
@@ -0,0 +1,86 @@
+/*
+ * 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;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+
+import com.github.drinkjava2.frog.brain.Cell;
+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
+ *
+ * 青蛙由器官组成,器官中的Group类会生成各种脑细胞
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Frog {
+
+ /** brain cells */
+ public List cells = new ArrayList<>();
+
+ /** organs */
+ public List organs = new ArrayList<>();
+
+ public int x; // frog在Env中的x坐标
+ public int y; // frog在Env中的y坐标
+ public long energy = 100000; // 青蛙的能量为0则死掉
+ public boolean alive = true; // 设为false表示青蛙死掉了,将不参与计算和显示,以节省时间
+ public int ateFood = 0;
+
+ static Image frogImg;
+ static {
+ try {
+ frogImg = ImageIO.read(new FileInputStream(Application.CLASSPATH + "frog.png"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public Frog(int x, int y, Egg egg) {
+ this.x = x;
+ this.y = y;
+ for (Organ org : egg.organs) {
+ organs.add(org);
+ org.initFrog(this);// 每个新器官初始化,如果是Group类,它们会生成许多脑细胞
+ }
+ }
+
+ public boolean active(Env v) {
+ // 如果能量小于0则死、出界、与非食物的点重合则判死
+ if (!alive || energy < 0 || Env.outsideEnv(x, y) || Env.bricks[x][y] >= Material.KILLFROG) {
+ energy -= 100; // 死掉的青蛙也要消耗能量,确保淘汰出局
+ alive = false;
+ return false;
+ }
+ energy -= 20;
+ for (Organ o : organs) {
+ o.active(this);
+ }
+ return alive;
+ }
+
+ public void show(Graphics g) {// 显示青蛙的图象
+ if (!alive)
+ return;
+ g.drawImage(frogImg, x - 8, y - 8, 16, 16, null);
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java
new file mode 100644
index 0000000..44de23f
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java
@@ -0,0 +1,128 @@
+package com.github.drinkjava2.frog.brain;
+
+import static java.awt.Color.BLUE;
+import static java.awt.Color.CYAN;
+import static java.awt.Color.GREEN;
+import static java.awt.Color.MAGENTA;
+import static java.awt.Color.ORANGE;
+import static java.awt.Color.RED;
+import static java.awt.Color.YELLOW;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import javax.swing.JPanel;
+
+import com.github.drinkjava2.frog.Application;
+import com.github.drinkjava2.frog.Frog;
+
+/**
+ * BrainPicture show first frog's brain structure, for debug purpose only
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+@SuppressWarnings("serial")
+public class BrainPicture extends JPanel {
+ private float brainWidth; // real brain width
+ private int brainDispWidth; // screen display width
+ private Color color = Color.BLACK;
+
+ public void setColor(Color c) {
+ color = c;
+ }
+
+ public BrainPicture(int x, int y, float brainWidth, int brainDispWidth) {
+ super();
+ this.setLayout(null);// 空布局
+ this.brainDispWidth = brainDispWidth;
+ this.brainWidth = brainWidth;
+ this.setBounds(x, y, brainDispWidth + 1, brainDispWidth + 1);
+ }
+
+ public void drawZone( Zone z) {Graphics g = this.getGraphics();
+ g.setColor(color);
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ int radius = Math.round(z.r * rate);
+ g.drawRect(x - radius, y - radius, radius * 2, radius * 2);
+ }
+
+ public void drawCircle( Zone z) {Graphics g = this.getGraphics();
+ g.setColor(color);
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ g.drawArc(x - 5, y - 5, 10, 10, 0, 360);
+ }
+
+ public void fillZone( Zone z) {Graphics g = this.getGraphics();
+ g.setColor(color);
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ int radius = Math.round(z.r * rate);
+ g.fillRect(x - radius, y - radius, radius * 2, radius * 2);
+ }
+
+ public void drawLine(Zone z1, Zone z2) {
+ Graphics g = this.getGraphics();
+ g.setColor(color);
+ float rate = brainDispWidth / brainWidth;
+ int x1 = Math.round(z1.x * rate);
+ int y1 = Math.round(z1.y * rate);
+ int x2 = Math.round(z2.x * rate);
+ int y2 = Math.round(z2.y * rate);
+ g.drawLine(x1, y1, x2, y2);
+ }
+
+ public void drawText( Zone z, String text) {Graphics g = this.getGraphics();
+ g.setColor(color);
+ float rate = brainDispWidth / brainWidth;
+ int x = Math.round(z.x * rate);
+ int y = Math.round(z.y * rate);
+ g.drawString(text, x - text.length() * 3 - 2, y);
+ }
+
+ private static final Color[] rainbow = new Color[] { RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA };
+ private static int nextColor = 0;
+
+ public static Color nextRainbowColor() {
+ if (nextColor == rainbow.length)
+ nextColor = 0;
+ return rainbow[nextColor++];
+ }
+
+ public static Color color(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)
+ return;
+ Graphics g = this.getGraphics();// border
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, brainDispWidth, brainDispWidth);
+ g.setColor(Color.black);
+ g.drawRect(0, 0, brainDispWidth, brainDispWidth);
+
+ for (Organ organ : frog.organs)
+ organ.drawOnBrainPicture(frog, this); // each organ draw itself
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Cell.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
new file mode 100644
index 0000000..fdae751
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * Cell is the basic unit of frog's brain
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Cell {
+ public static final float MAX_ENERGY_LIMIT = 100.0f;
+
+ // this cell belong to frog's which organ
+ public Organ organ;
+
+ // inputs of cell
+ public Input[] inputs; // 每个细胞有一组输入触突
+
+ // outputs of cell
+ public Output[] outputs; // 每个细胞有一组输出触突
+
+ // energy of cell, energy got from food
+ public float energy; // 每个细胞当前的能量值
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Input.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Input.java
new file mode 100644
index 0000000..78f16b4
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Input.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+/**
+ * Input is the sensor of nerve cell
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+@SuppressWarnings("serial")
+public class Input extends Zone {
+ public Cell cell; // 这个输入触突属于哪个脑细胞
+
+ public Input(Zone z) {
+ super(z);
+ }
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Organ.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
new file mode 100644
index 0000000..c26da8f
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
@@ -0,0 +1,94 @@
+/*
+ * 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;
+
+import java.awt.Color;
+
+import com.github.drinkjava2.frog.Application;
+import com.github.drinkjava2.frog.Frog;
+
+/**
+ * Organ is a part of frog, organ can be saved in egg
+ *
+ * 器官是脑的一部分,多个器官在脑内可以允许重叠出现在同一位置。
+ *
+ * @author Yong Zhu
+ * @since 1.0.4
+ */
+public class Organ extends Zone {
+ private static final long serialVersionUID = 1L;
+ public String name; // 显示在脑图上的器官名称,可选
+ public long fat = 0; // 如果活跃多,fat值高,则保留(及变异)的可能性大,反之则很可能丢弃掉
+ // public float organWasteEnergy = 0.05f; //
+ // 器官在每个测试循环中需要消耗青蛙多少能量,可以通过调节这个参数抑制器官数量无限增长
+ public float organActiveEnergy = 1; // 输出器官激活需要消耗每个脑细胞多少能量
+ public float organOutputEnergy = 2; // 感觉器官激活会给每个脑细胞增加多少能量
+ public boolean initilized; // 通过这个标记判断是否需要手工给定它的参数初值
+
+ public boolean allowBorrow() { // 是否允许在精子中将这个器官借出
+ return false;
+ }
+
+ /** Each loop step call active method, Child class can override this method */
+ public void active(Frog f) { // 每一步都会调用器官的active方法 ,缺省啥也不干
+ }
+
+ /** If active in this organ's zone? */
+ public boolean outputActive(Frog f) { // 如果一个细胞能量>10,且它的输出触突位于这个器官内,则器官被激活
+ for (Cell cell : f.cells) {
+ if (cell.energy > organActiveEnergy)
+ for (Output output : cell.outputs) { //
+ if (this.nearby(output)) {
+ cell.organ.fat++;
+ cell.energy -= 30;//
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /** Set X, Y, Radius, name of current Organ */
+ public Organ setXYRN(float x, float y, float r, String name) {
+ this.setXYR(x, y, r);
+ this.name = name;
+ return this;
+ }
+
+ /** Child class can override this method to drawing picture */
+ public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来,子类可以重写这个方法
+ if (!Application.SHOW_FIRST_FROG_BRAIN)
+ return;
+ pic.setColor(Color.BLACK); // 缺省是黑色
+ pic.drawZone(this);
+ if (this.name != null)
+ pic.drawText(this, String.valueOf(this.name));
+ }
+
+ /** Only call once when frog created , Child class can override this method */
+ public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次,缺省啥也不干,通常用于Group子类的初始化
+ }
+
+ /** Only call once after organ be created by new() method */
+ public Organ[] vary() { // 在下蛋时每个器官会调用这个方法,缺省返回一个类似自已的副本,子类通常要覆盖这个方法
+ Organ newOrgan = null;
+ try {
+ newOrgan = this.getClass().newInstance();
+ } catch (Exception e) {
+ throw new UnknownError("Can not make new Organ copy for " + this);
+ }
+ copyXYR(this, newOrgan);
+ newOrgan.name = this.name;
+ newOrgan.fat = this.fat;
+ return new Organ[] { newOrgan };
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Output.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Output.java
new file mode 100644
index 0000000..b794b93
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Output.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+/**
+ * Output can active other nerve cell's input
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+@SuppressWarnings("serial")
+public class Output extends Zone {
+ public Cell cell; // 这个输出触突属于哪个脑细胞
+
+ public Output(Zone z) {
+ super(z);
+ }
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Zone.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Zone.java
new file mode 100644
index 0000000..d8ae70e
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/Zone.java
@@ -0,0 +1,84 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+
+import com.github.drinkjava2.frog.Env;
+
+/**
+ * Zone represents a rectangle zone in brain
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Zone implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ public float x;
+ public float y;
+ public float r;// r为这个矩形区边长的一半
+
+ public Zone() {
+ // 空构造器不能省
+ }
+
+ public Zone(float x, float y, float r) {// 用x,y,r来构造
+ this.x = x;
+ this.y = y;
+ this.r = r;
+ if (this.x < 0)
+ this.x = 0;
+ if (this.y < 0)
+ this.y = 0;
+ if (this.x > Env.FROG_BRAIN_WIDTH)
+ this.x = Env.FROG_BRAIN_WIDTH;
+ if (this.y > Env.FROG_BRAIN_WIDTH)
+ this.y = Env.FROG_BRAIN_WIDTH;
+ }
+
+ public Zone(Zone z) {// 用另一个Zone来构造
+ this.x = z.x;
+ this.y = z.y;
+ this.r = z.r;
+ }
+
+ public boolean nearby(Zone z) {
+ float dist = r + z.r;
+ return (Math.abs(x - z.x) < dist && Math.abs(y - z.y) < dist);
+ }
+
+ 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;
+ }
+
+ public static void copyXYR(Zone from, Zone to) {
+ to.x = from.x;
+ to.y = from.y;
+ to.r = from.r;
+ }
+
+ public void setXYR(float x, float y, float r) {
+ this.x = x;
+ this.y = y;
+ this.r = r;
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/group/Group.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/group/Group.java
new file mode 100644
index 0000000..a26f7ec
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/group/Group.java
@@ -0,0 +1,34 @@
+/*
+ * 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.group;
+
+import com.github.drinkjava2.frog.brain.Organ;
+
+/**
+ * Group presents a rectangle organ zone, Group only arranges a group of cells
+ *
+ * 在2.0之前,CellGroup是线型,不具备可进化性。在2.0之后引入Group概念,Group是矩形,大小可以覆盖整个大脑,也可以小到单个细胞。可以进行位置、大小变动、复制、分裂等多种形式的变异
+ *
+ * 为了与旧版CellGroup区分,新版的这个类命名为Group,它代表了一组分布于一个正方形内的细胞群,细胞数量、每个细胞的触突连接方式等参数由当前Group决定,
+ * 可以说每一种Group代表了一种神经网络算法, 通过无数个Group随机的分布、进化、变异,达到最终脑结构适应环境的变化
+ * Group会参与遗传和进化,但是它生成的细胞不会参与遗传。 各个Group生成的细胞相加总和就是脑细胞总数。
+ *
+ * Group在脑活动中不起作用,可以把Group比作播种机,把种子排列好后,就撒手不管了,在遗传过程中有一个fat参数,如果细胞活跃多,则Group保留及变异的可能性大,反之则舍弃掉。
+ * Group是器官的一种,所以蛋里存放着所有Group的位置、大小、内部参数等信息,但是蛋里面不保存具体的细胞。这样通过控制有多少个"播种机",就可以控制大脑的结构了,这样可以缩小蛋的尺寸。
+ * 原则上Group遗传的一下代与父代是同一个播种(算法)类型,但不排除也有可能突变成另一个类型的Group。
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public abstract class Group extends Organ {
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/group/RandomConnectGroup.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/group/RandomConnectGroup.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/group/RandomConnectGroup.java
rename to history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/group/RandomConnectGroup.java
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java
new file mode 100644
index 0000000..6724647
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Active.java
@@ -0,0 +1,47 @@
+/*
+ * 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 com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Cell;
+import com.github.drinkjava2.frog.brain.Input;
+import com.github.drinkjava2.frog.brain.Organ;
+
+/**
+ * Active always keep active
+ *
+ * 这个器官永远激活
+ */
+public class Active extends Organ {//以前的实验发现添加一个始终激活的区比用Hungry来驱动更能提高找食效率
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void initFrog(Frog f) {
+ if (!initilized) {
+ initilized = true;
+ organOutputEnergy = 2;
+ }
+ }
+
+ @Override
+ public void active(Frog f) {
+ for (Cell cell : f.cells) {
+ if (cell.energy > 0)
+ cell.energy--;
+ if (cell.energy < Cell.MAX_ENERGY_LIMIT)
+ for (Input input : cell.inputs)
+ if (input.nearby(this)) // if input zone near by happy zone
+ cell.energy += organOutputEnergy;
+ }
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Chance.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Chance.java
new file mode 100644
index 0000000..8527363
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Chance.java
@@ -0,0 +1,62 @@
+/*
+ * 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 com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Cell;
+import com.github.drinkjava2.frog.brain.Input;
+import com.github.drinkjava2.frog.brain.Organ;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * Chance is a random number generator
+ *
+ * 这个器官是一个随机数发生器,用来打乱青蛙的思维,防止它围着一个食物打转出不来
+ */
+public class Chance extends Organ { // 至于这个器官能不能被选中,是另外一回事,听天由命了
+ private static final long serialVersionUID = 1L;
+ public int percent; // 初始化的机率为5%
+
+ @Override
+ public void initFrog(Frog f) {
+ if (!initilized) {
+ initilized = true;
+ percent = 5;
+ }
+ }
+
+ @Override
+ public Organ[] vary() {
+ if (RandomUtils.percent(5)) {
+ percent = percent + 1 - 2 * RandomUtils.nextInt(2);
+ if (percent < 1)
+ percent = 1;
+ if (percent > 98)
+ percent = 98;
+ }
+ return new Organ[] { this };
+ }
+
+ @Override
+ public void active(Frog f) {
+ if (RandomUtils.percent(percent)) {// 如果靠近边界,痛苦信号生成
+ for (Cell cell : f.cells) {
+ if (cell.energy > 0)
+ cell.energy--;
+ if (cell.energy < Cell.MAX_ENERGY_LIMIT)
+ for (Input input : cell.inputs)
+ if (input.nearby(this)) // if input zone nearby this zone
+ cell.energy += 30;
+ }
+ }
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java
new file mode 100644
index 0000000..3b097d8
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Eat.java
@@ -0,0 +1,37 @@
+/*
+ * 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 com.github.drinkjava2.frog.Env;
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Organ;
+
+/**
+ * Eat food at current x, y position
+ */
+public class Eat extends Organ {// Eat这个类将食物转化为能量,能量小于0,则青蛙死掉
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void active(Frog f) {
+ if (Env.foundAndAteFood(f.x, f.y)) {
+ f.ateFood++;
+ // 所有的硬编码都是bug,包括这个1000
+ f.energy += 1000;// 如果青蛙的坐标与食物重合,吃掉food,能量境加
+
+ // 能量境加青蛙感觉不到,但是Happy区激活青蛙能感觉到,因为Happy区是一个脑器官
+
+ Organ o = f.organs.get(0);
+ ((Happy) o).happy += 2; // 找到食物有奖!
+ }
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
new file mode 100644
index 0000000..29d9686
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
@@ -0,0 +1,138 @@
+/*
+ * 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 com.github.drinkjava2.frog.Application;
+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.Input;
+import com.github.drinkjava2.frog.brain.Organ;
+import com.github.drinkjava2.frog.brain.Zone;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * Eye can only see 4 direction
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Eye extends Organ {// 这个Eye是老版的眼睛,只能看到四个方向,但它的调节距离会自动随机调整到一个最佳值,这就是随机试错算法的一个应用
+ private static final long serialVersionUID = 1L;
+ public int seeDistance; // 眼睛能看到的距离
+
+ @Override
+ public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次
+ if (!initilized) {
+ initilized = true;
+ organOutputEnergy = 30;
+ seeDistance = 8;
+ }
+ }
+
+ @Override
+ public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
+ if (!Application.SHOW_FIRST_FROG_BRAIN)
+ return;
+ super.drawOnBrainPicture(f, pic);
+ float qRadius = r / 4;
+ float q3Radius = (float) (r * .75);
+ Zone seeUp = new Zone(x, y + q3Radius, qRadius);
+ Zone seeDown = new Zone(x, y - q3Radius, qRadius);
+ Zone seeLeft = new Zone(x - q3Radius, y, qRadius);
+ Zone seeRight = new Zone(x + q3Radius, y, qRadius);
+ pic.drawZone(seeUp);
+ pic.drawZone(seeDown);
+ pic.drawZone(seeLeft);
+ pic.drawZone(seeRight);
+ }
+
+ @Override
+ public Organ[] vary() {
+ if (RandomUtils.percent(5)) { // 可视距离有5%的机率变异
+ seeDistance = seeDistance + 1 - 2 * RandomUtils.nextInt(2);
+ if (seeDistance < 1)
+ seeDistance = 1;
+ if (seeDistance > 50)
+ seeDistance = 50;
+ }
+ return new Organ[] { this };
+ }
+
+ @Override
+ public void active(Frog f) {
+ // 第一个眼睛只能观察上、下、左、右四个方向有没有食物
+ float qRadius = r / 4;
+ float q3Radius = (float) (r * .75);
+ Zone seeUp = new Zone(x, y + q3Radius, qRadius);
+ Zone seeDown = new Zone(x, y - q3Radius, qRadius);
+ Zone seeLeft = new Zone(x - q3Radius, y, qRadius);
+ Zone seeRight = new Zone(x + q3Radius, y, qRadius);
+
+ boolean seeSomething = false;
+ boolean atUp = false;
+ boolean atDown = false;
+ boolean atLeft = false;
+ boolean atRight = false;
+
+ for (int i = 1; i < seeDistance; i++)
+ if (Env.foundAnyThing(f.x, f.y + i)) {
+ seeSomething = true;
+ atUp = true;
+ break;
+ }
+
+ for (int i = 1; i < seeDistance; i++)
+ if (Env.foundAnyThing(f.x, f.y - i)) {
+ seeSomething = true;
+ atDown = true;
+ break;
+ }
+
+ for (int i = 1; i < seeDistance; i++)
+ if (Env.foundAnyThing(f.x - i, f.y)) {
+ seeSomething = true;
+ atLeft = true;
+ break;
+ }
+
+ for (int i = 1; i < seeDistance; i++)
+ if (Env.foundAnyThing(f.x + i, f.y)) {
+ seeSomething = true;
+ atRight = true;
+ break;
+ }
+
+ if (seeSomething)
+ for (Cell cell : f.cells) {
+ if (cell.energy < 100)
+ for (Input input : cell.inputs) {
+ if (input.nearby(this)) {
+ if (atUp && input.nearby(seeUp)) {
+ input.cell.energy += organOutputEnergy;
+ }
+ if (atDown && input.nearby(seeDown)) {
+ input.cell.energy += organOutputEnergy;
+ }
+ if (atLeft && input.nearby(seeLeft)) {
+ input.cell.energy += organOutputEnergy;
+ }
+ if (atRight && input.nearby(seeRight)) {
+ input.cell.energy += organOutputEnergy;
+ }
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Happy.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Happy.java
new file mode 100644
index 0000000..ad52bae
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Happy.java
@@ -0,0 +1,61 @@
+/*
+ * 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.Application;
+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.Input;
+import com.github.drinkjava2.frog.brain.Organ;
+
+/**
+ * Happy zone active after ate food
+ */
+public class Happy extends Organ { // Happy器官是进食后的产生的快感,痛苦和快感是条件反射形成的前题
+ private static final long serialVersionUID = 1L;
+ public float happy = 0; // happy初始值为0, 进食后将由eat器官增加happy值
+
+ @Override
+ public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
+ if (!Application.SHOW_FIRST_FROG_BRAIN)
+ return;
+ if (happy > 0) {
+ pic.setColor(Color.red);
+ pic.fillZone(this);
+ } else {
+ pic.setColor(Color.white);
+ pic.fillZone(this);
+ pic.setColor(Color.BLACK);
+ pic.drawZone(this);
+ }
+ if (this.name != null)
+ pic.drawText(this, String.valueOf(this.name));
+ }
+
+ @Override
+ public void active(Frog f) {
+ if (happy > 0) {
+ happy--;
+ for (Cell cell : f.cells) {
+ if (cell.energy > 0)
+ cell.energy--;
+ if (cell.energy < Cell.MAX_ENERGY_LIMIT)
+ for (Input input : cell.inputs)
+ if (input.nearby(this)) // if input zone near by happy zone
+ cell.energy += happy / 10; // 所有的硬编码都是bug,包括这个2和10
+ }
+ }
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Hungry.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Hungry.java
new file mode 100644
index 0000000..ee51b61
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Hungry.java
@@ -0,0 +1,73 @@
+/*
+ * 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.Application;
+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.Input;
+import com.github.drinkjava2.frog.brain.Organ;
+
+/**
+ * Hungry will active cell's inputs, if frog's energy not enough
+ */
+public class Hungry extends Organ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void initFrog(Frog f) { // 仅在Frog生成时这个方法会调用一次,缺省啥也不干,通常用于Organ类的初始化
+ if (!initilized) {
+ initilized = true;
+ // organWasteEnergy = 20f;
+ organOutputEnergy = 2;
+ }
+ }
+
+ @Override
+ public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
+ if (!Application.SHOW_FIRST_FROG_BRAIN)
+ return;
+ if (f.energy < 10000) {
+ pic.fillZone(this);
+ } else {
+ pic.setColor(Color.white);
+ pic.fillZone(this);
+ pic.setColor(Color.BLACK);
+ pic.drawZone(this);
+ }
+ if (this.name != null)
+ pic.drawText(this, String.valueOf(this.name));
+ }
+
+ @Override
+ public Organ[] vary() {
+ // if (RandomUtils.percent(20)) // 有20机率权重变化
+ // organOutputEnergy = RandomUtils.vary(organOutputEnergy);
+ return new Organ[] { this };
+ }
+
+ @Override
+ public void active(Frog f) {
+ if (f.energy < 10000)// 所有的硬编码都是bug
+ for (Cell cell : f.cells) {
+ if (cell.energy > 0)
+ cell.energy--;
+ if (cell.energy < Cell.MAX_ENERGY_LIMIT)
+ for (Input input : cell.inputs)
+ if (input.nearby(this)) // input zone near by hungry zone
+ cell.energy += 2;
+ }
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveDown.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveDown.java
new file mode 100644
index 0000000..62381d9
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveDown.java
@@ -0,0 +1,28 @@
+/*
+ * 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 com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Organ;
+
+/**
+ * Move down frog 1 unit if outputs of nerve cells active in this zone
+ */
+public class MoveDown extends Organ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void active(Frog f) {
+ if (outputActive(f))
+ f.y++;
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveLeft.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveLeft.java
new file mode 100644
index 0000000..04e5f2e
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveLeft.java
@@ -0,0 +1,27 @@
+/*
+ * 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 com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Organ;
+
+/**
+ * Move left frog 1 unit if outputs of nerve cells active in this zone
+ */
+public class MoveLeft extends Organ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void active(Frog f) {
+ if (outputActive(f))
+ f.x--;
+ }
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveRight.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveRight.java
new file mode 100644
index 0000000..21c50c8
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveRight.java
@@ -0,0 +1,29 @@
+/*
+ * 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 com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Organ;
+
+/**
+ * Move right frog 1 unit if outputs of nerve cells active in this zone
+ */
+public class MoveRight extends Organ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void active(Frog f) {
+ if (outputActive(f))
+ f.x++;
+ }
+
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveUp.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveUp.java
new file mode 100644
index 0000000..d02cd91
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveUp.java
@@ -0,0 +1,28 @@
+/*
+ * 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 com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Organ;
+
+/**
+ * Move up frog 1 unit if outputs of nerve cells active in this zone
+ */
+public class MoveUp extends Organ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void active(Frog f) {
+ if (outputActive(f))
+ f.y--;
+ }
+
+}
diff --git a/core/src/main/java/com/github/drinkjava2/frog/brain/organ/NewEye.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/NewEye.java
similarity index 100%
rename from core/src/main/java/com/github/drinkjava2/frog/brain/organ/NewEye.java
rename to history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/NewEye.java
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Pain.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Pain.java
new file mode 100644
index 0000000..bac4b18
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/brain/organ/Pain.java
@@ -0,0 +1,70 @@
+/*
+ * 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.Application;
+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.Input;
+import com.github.drinkjava2.frog.brain.Organ;
+
+/**
+ * Pain zone active after some bad thing happen like close to edge, hurt...
+ *
+ * 痛是一种惩罚,表示青蛙做错了什么,但是又不至严重到判其死亡的地步
+ */
+public class Pain extends Organ { // Pain器官目前激活的条件是离边境20个单元之类,痛苦和快感是条件反射形成的前题
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void initFrog(Frog f) {
+ if (!initilized) {
+ initilized = true;
+ organOutputEnergy = 5;
+ }
+ }
+
+ @Override
+ public void drawOnBrainPicture(Frog f, BrainPicture pic) {// 把自已这个器官在脑图上显示出来
+ if (!Application.SHOW_FIRST_FROG_BRAIN)
+ return;
+ if (Env.closeToEdge(f)) {
+ pic.fillZone(this);
+ } else {
+ pic.setColor(Color.white);
+ pic.fillZone(this);
+ pic.setColor(Color.BLACK);
+ pic.drawZone(this);
+ }
+ if (this.name != null)
+ pic.drawText(this, String.valueOf(this.name));
+ }
+
+ @Override
+ public void active(Frog f) {
+ if (Env.closeToEdge(f)) {// 如果靠近边界,痛苦信号生成
+ for (Cell cell : f.cells) {
+ if (cell.energy > 0)
+ cell.energy--;
+ if (cell.energy < Cell.MAX_ENERGY_LIMIT)
+ for (Input input : cell.inputs)
+ if (input.nearby(this)) // if input zone nearby this zone
+ cell.energy += organOutputEnergy;
+ }
+ }
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/egg/Egg.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
new file mode 100644
index 0000000..ac5128c
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
@@ -0,0 +1,101 @@
+/*
+ * 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.egg;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Organ;
+import com.github.drinkjava2.frog.brain.group.Group;
+import com.github.drinkjava2.frog.brain.organ.Active;
+import com.github.drinkjava2.frog.brain.organ.Chance;
+import com.github.drinkjava2.frog.brain.organ.Eat;
+import com.github.drinkjava2.frog.brain.organ.Eye;
+import com.github.drinkjava2.frog.brain.organ.Happy;
+import com.github.drinkjava2.frog.brain.organ.Hungry;
+import com.github.drinkjava2.frog.brain.organ.MoveDown;
+import com.github.drinkjava2.frog.brain.organ.MoveLeft;
+import com.github.drinkjava2.frog.brain.organ.MoveRight;
+import com.github.drinkjava2.frog.brain.organ.MoveUp;
+import com.github.drinkjava2.frog.brain.organ.NewEye;
+import com.github.drinkjava2.frog.brain.organ.Pain;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * Egg is the static structure description of frog, can save as text file, to
+ * build a frog, first need build a egg.
+ *
+ * 蛋存在的目的是为了以最小的字节数串行化存储Frog,它是Frog的生成算法描述,而不是Frog本身,这样一来Frog就不能"永生"了,因为每一个egg都不等同于
+ * 它的母体, 而且每一次测试,大部分条件反射的建立都必须从头开始训练,类似于人类,无论人类社会有多聪明, 婴儿始终是一张白纸,需要花大量的时间从头学习。
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Egg implements Serializable {
+ // 为了缩短时间,这个程序随机生成的联结将只落在固定的器官上而不是漫天撒网(见4.12提交),这是程序的优化,实现的逻辑和随机漫天撒网定是相同的。
+ // 但是这个优化带来的问题是这是一个硬编码逻辑,不利于器官的优胜劣汰, 而且下面这个 FIXED_ORGAN_QTY必须每次手工设定,以后需要重构这块的代码
+ public static int FIXED_ORGAN_QTY = 11;
+
+ private static final long serialVersionUID = 1L;
+
+ public List organs = new ArrayList<>();
+
+ public List groups = new ArrayList<>();
+
+ public Egg() {// 无中生有,创建一个蛋,先有蛋,后有蛙
+ organs.add(new Happy().setXYRN(600, 700, 60, "Happy")); // Happy必须第一个加入
+ organs.add(new Hungry().setXYRN(300, 100, 60, "Hungry"));
+ organs.add(new MoveUp().setXYRN(800, 100, 60, "Up"));
+ organs.add(new MoveDown().setXYRN(800, 400, 60, "Down"));
+ organs.add(new MoveLeft().setXYRN(700, 250, 60, "Left"));
+ organs.add(new MoveRight().setXYRN(900, 250, 60, "Right"));
+ organs.add(new Eye().setXYRN(100, 300, 100, "Eye"));
+ organs.add(new NewEye().setXYRN(200, 700, 200, "NewEye"));
+ organs.add(new Pain().setXYRN(800, 700, 60, "Pain")); // 痛苦在靠近边界时触发
+ organs.add(new Active().setXYRN(500, 100, 60, "Active")); // 永远激活
+ organs.add(new Chance().setXYRN(650, 100, 60, "Chance")); // 永远激活
+
+ // 以上为11个, 就是FIXED_ORGAN_QTY值
+
+ organs.add(new Eat().setXYRN(0, 0, 0, "Eat")); // EAT不是感觉或输出器官,没有位置和大小
+
+ }
+
+ /** Create egg from frog */
+ public Egg(Frog frog) { // 青蛙下蛋,每个青蛙的器官会创建自已的副本或变异,可以是0或多个
+ for (Organ organ : frog.organs)
+ for (Organ newOrgan : organ.vary())
+ organs.add(newOrgan);
+ }
+
+ /**
+ * Create a egg by join 2 eggs, x+y=zygote 模拟X、Y 染色体合并,两个蛋生成一个新的蛋, X从Y里借一个器官,
+ * 不用担心器官会越来越多,因为通过用进废退原则来筛选,没用到的器官会在几代之后被自然淘汰掉
+ * 器官不是越多越好,因为器官需要消耗能量,器官数量多了,在生存竞争中也是劣势
+ *
+ */
+ public Egg(Egg x, Egg y) {
+ // x里原来的organ
+ for (Organ organ : x.organs)
+ organs.add(organ);
+
+ // 从y里借一个organ
+ int yOrganSize = y.organs.size();
+ if (yOrganSize > 0) {
+ Organ o = y.organs.get(RandomUtils.nextInt(yOrganSize));
+ if (o.allowBorrow())
+ organs.add(o);
+ }
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
new file mode 100644
index 0000000..4e36670
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
@@ -0,0 +1,110 @@
+/*
+ * 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.egg;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+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.Chance;
+import com.github.drinkjava2.frog.brain.organ.Eye;
+import com.github.drinkjava2.frog.util.FrogFileUtils;
+
+/**
+ * EggTool save eggs to disk
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class EggTool {
+
+ /**
+ * Frogs which have higher energy lay eggs
+ *
+ * 利用Java串行机制存盘。 能量多(也就是吃的更多)的Frog下蛋并存盘, 以进行下一轮测试,能量少的Frog被淘汰,没有下蛋的资格。
+ * 用能量的多少来简化生存竟争模拟,每次下蛋数量固定为EGG_QTY个
+ */
+ public static void layEggs() {
+ sortFrogsOrderByEnergyDesc();
+
+ 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++)
+ Env.eggs.add(new Egg(Env.frogs.get(i)));
+ FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs.ser");
+ ObjectOutputStream so = new ObjectOutputStream(fo);
+ so.writeObject(Env.eggs);
+ so.close();
+ System.out.print("\r1st frog has " + first.organs.size() + " organs, energy=" + first.energy + ", seeDist="
+ + ((Eye) first.organs.get(6)).seeDistance + ", chance=" + ((Chance) first.organs.get(10)).percent);
+ System.out.println(", Last frog has " + last.organs.size() + " organs, energy=" + last.energy);
+ System.out.println("Saved "+Env.eggs.size() +" eggs to file '" + Application.CLASSPATH + "eggs.ser'");
+ } catch (IOException e) {
+ System.out.println(e);
+ }
+ }
+
+ private static void sortFrogsOrderByEnergyDesc() {// 按能量多少给青蛙排序
+ Collections.sort(Env.frogs, new Comparator() {
+ public int compare(Frog a, Frog b) {
+ if (a.energy > b.energy)
+ return -1;
+ else if (a.energy == b.energy)
+ return 0;
+ else
+ return 1;
+ }
+ });
+ }
+
+ public static void deleteEggs() {
+ System.out.println("Delete exist egg file: '" + Application.CLASSPATH + "eggs.ser'");
+ FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs.ser");
+ }
+
+ /**
+ * 从磁盘读入一批Egg
+ */
+ @SuppressWarnings("unchecked")
+ public static void loadEggs() {
+ boolean errorfound = false;
+ 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" + "'.\n");
+ eggsInputStream.close();
+ } catch (Exception e) {
+ errorfound = true;
+ }
+ if (errorfound) {
+ Env.eggs.clear();
+ for (int j = 0; j < Env.EGG_QTY; j++)
+ Env.eggs.add(new Egg());
+ System.out.println("Fail to load egg file at path '" + Application.CLASSPATH + "', created "
+ + Env.eggs.size() + " eggs to do test.\n");
+ }
+
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Food.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Food.java
new file mode 100644
index 0000000..ea03051
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Food.java
@@ -0,0 +1,48 @@
+/* Copyright 2018-2020 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.objects;
+
+import static com.github.drinkjava2.frog.Env.ENV_HEIGHT;
+import static com.github.drinkjava2.frog.Env.ENV_WIDTH;
+import static com.github.drinkjava2.frog.Env.FOOD_QTY;
+import static com.github.drinkjava2.frog.Env.bricks;
+
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * Food randomly scatter on Env
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Food implements Object {
+
+ @Override
+ public void build() {
+ for (int i = 0; i < FOOD_QTY; i++) // 生成食物
+ bricks[RandomUtils.nextInt(ENV_WIDTH)][RandomUtils.nextInt(ENV_HEIGHT)] = Material.FOOD;
+ }
+
+ @Override
+ public void destory() {
+ for (int i = 0; i < ENV_WIDTH; i++) {// 清除食物
+ for (int j = 0; j < ENV_HEIGHT; j++)
+ if (bricks[i][j] == Material.FOOD)
+ bricks[i][j] = 0;
+ }
+ }
+
+ @Override
+ public void active(int screen) {
+ // Food do not have any active
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Material.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Material.java
new file mode 100644
index 0000000..ca66cc7
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Material.java
@@ -0,0 +1,40 @@
+/* Copyright 2018-2020 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.objects;
+
+import java.awt.Color;
+
+/**
+ * Object means some thing in Env
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class Material {
+ public static final byte VISIBLE = 10; // if>=10 will visible to frog
+ public static final byte KILLFROG = 20; // if>=20 will kill frog
+
+ public static final byte NO = 0;
+ public static final byte SEESAW_BASE = 1; // 1~9 is invisible to frog
+
+ public static final byte FOOD = VISIBLE + 1;
+ public static final byte SEESAW = VISIBLE + 2; // if <0 will not cause frog die
+
+ public static final byte BRICK = KILLFROG + 1;
+ public static final byte TRAP = KILLFROG + 2;
+
+ public static Color color(byte material) {
+ if (material == TRAP)
+ return Color.LIGHT_GRAY;
+ else
+ return Color.BLACK;
+ }
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Object.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Object.java
new file mode 100644
index 0000000..daa3160
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Object.java
@@ -0,0 +1,26 @@
+/* Copyright 2018-2020 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.objects;
+
+/**
+ * Object means some thing in Env
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public interface Object {
+
+ public void build();
+
+ public void destory();
+
+ public void active(int screen);
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java
new file mode 100644
index 0000000..5f220ae
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java
@@ -0,0 +1,93 @@
+/* Copyright 2018-2020 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.objects;
+
+import static com.github.drinkjava2.frog.Env.ENV_HEIGHT;
+import static com.github.drinkjava2.frog.Env.ENV_WIDTH;
+import static com.github.drinkjava2.frog.Env.bricks;
+
+import com.github.drinkjava2.frog.Env;
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * This is a seesaw to train frog's balance
+ *
+ * @author Yong Zhu
+ * @since 2.0.1
+ */
+public class SeeSaw implements Object {
+ private static final int LEGNTH = 300;
+ private static final int CENTER_X = Env.ENV_WIDTH / 2;
+ private static final int CENTER_Y = Env.ENV_HEIGHT / 2;
+
+ private double angle = 0;// -PI/4 to PI/4
+ private double leftWeight = 0;
+ private double rightWeight = 0;
+
+ @Override
+ public void build() {
+ angle = 0;
+ }
+
+ @Override
+ public void destory() {
+
+ }
+
+ @Override
+ public void active(int screen) {
+ for (int i = 0; i < ENV_WIDTH; i++) {// 清除食物
+ for (int j = 0; j < ENV_HEIGHT; j++)
+ if (bricks[i][j] == Material.SEESAW)
+ bricks[i][j] = 0;
+ }
+
+ if (RandomUtils.percent(2))
+ leftWeight = RandomUtils.nextFloat() * 3;
+ if (RandomUtils.percent(2))
+ rightWeight = RandomUtils.nextFloat() * 3;
+ Frog f = Env.frogs.get(screen);
+
+ if (f.x < (CENTER_X - LEGNTH / 2) || f.x > (CENTER_X + LEGNTH / 2))
+ f.energy -= 100000; // 如果走出跷跷板外则扣分,出局
+ double left = leftWeight - (f.x - CENTER_X);
+ double right = rightWeight + (f.x - CENTER_X);
+ // right - left need in -100 to +100
+ angle = angle + (right - left) * Math.PI * .000001;
+ if (angle > Math.PI / 6) {
+ angle = Math.PI / 6;
+ f.energy -= 200;
+ }
+ if (angle < -Math.PI / 6) {
+ angle = -Math.PI / 6;
+ f.energy -= 200;
+ }
+ f.y = CENTER_Y + (int) Math.round((f.x - CENTER_X) * Math.tan(angle));
+ f.energy -= Math.abs(angle) * 180; // 角度越大,扣分越多
+ int x;
+ int y;
+ for (int l = -LEGNTH / 2; l <= LEGNTH / 2; l++) {
+ x = (int) Math.round(l * Math.cos(angle));
+ y = (int) Math.round(l * Math.sin(angle));
+ Env.bricks[CENTER_X + x][CENTER_Y + y] = Material.SEESAW;
+ }
+
+ // 画底座
+ for (int i = 1; i < 10; i++) {
+ Env.bricks[CENTER_X - i][CENTER_Y + i] = Material.SEESAW_BASE;
+ Env.bricks[CENTER_X + i][CENTER_Y + i] = Material.SEESAW_BASE;
+ }
+ for (int i = -10; i < 10; i++)
+ Env.bricks[CENTER_X + i][CENTER_Y + 10] = Material.SEESAW_BASE;
+
+ }
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Trap.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Trap.java
new file mode 100644
index 0000000..0b7fc68
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/objects/Trap.java
@@ -0,0 +1,56 @@
+/* Copyright 2018-2020 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.objects;
+
+import static com.github.drinkjava2.frog.Env.ENV_HEIGHT;
+import static com.github.drinkjava2.frog.Env.ENV_WIDTH;
+import static com.github.drinkjava2.frog.Env.bricks;
+
+import com.github.drinkjava2.frog.Frog;
+
+/**
+ * Trap will kill all frogs inside of it, if frog's position has material and
+ * it's not food, frog will die
+ *
+ * @author Yong Zhu
+ * @since 2019-08-05
+ */
+@SuppressWarnings("all")
+public class Trap implements Object {
+ private static final int X1 = ENV_WIDTH / 2 - 350 / 2; // 陷阱左上角
+ private static final int Y1 = ENV_HEIGHT / 2 - 20 / 2; // 陷阱左上角
+ private static final int X2 = ENV_WIDTH / 2 + 350 / 2; // 陷阱右下角
+ private static final int Y2 = ENV_HEIGHT / 2 + 20 / 2; // 陷阱右下角
+
+ @Override
+ public void build() {
+ for (int x = X1; x <= X2; x++)
+ for (int y = Y1; y <= Y2; y++)
+ bricks[x][y] = Material.TRAP;
+ }
+
+ @Override
+ public void destory() {
+ for (int x = X1; x <= X2; x++)
+ for (int y = Y1; y <= Y2; y++)
+ bricks[x][y] = 0;
+ }
+
+ @Override
+ public void active(int screen) {
+
+ }
+
+ public static boolean inTrap(Frog f) {
+ return f.x >= X1 && f.x <= X2 && f.y >= Y1 && f.y <= Y2;
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java
new file mode 100644
index 0000000..16f1999
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java
@@ -0,0 +1,141 @@
+/* Copyright 2018-2020 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.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * File Utilities used in this project
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class FrogFileUtils {
+
+ private FrogFileUtils() {
+ // default constructor
+ }
+
+ public static boolean deleteFile(String fileFullPath) {
+ File file = new File(fileFullPath);
+ return file.delete(); // NOSONAR
+ }
+
+ public static void writeFile(String fileFullPath, byte[] byteArry) {
+ File file = new File(fileFullPath);
+ if (!file.getParentFile().exists())
+ file.getParentFile().mkdirs();
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ fos.write(byteArry);
+ fos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static void writeFile(String fileFullPath, String text, String encoding) {
+ File file = new File(fileFullPath);
+ if (!file.getParentFile().exists())
+ file.getParentFile().mkdirs();
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ byte[] bytes;
+ bytes = text.getBytes(encoding);
+ fos.write(bytes);
+ fos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static String readFile(String fileFullPath, String encoding) {
+ InputStream inputStream;
+ try {
+ inputStream = new FileInputStream(new File(fileFullPath));
+ } catch (FileNotFoundException e1) {
+ return null;
+ }
+ try {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = inputStream.read(buffer)) != -1)
+ result.write(buffer, 0, length);
+ String string = result.toString(encoding);
+ return string;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ } finally {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ public static void appendFile(String fileName, String content) {
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(fileName, true);
+ fos.write(content.getBytes());
+ fos.write("\r\n".getBytes());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+}
diff --git a/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java
new file mode 100644
index 0000000..b7827bc
--- /dev/null
+++ b/history/004_seasaw/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java
@@ -0,0 +1,115 @@
+/* Copyright 2018-2020 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.util;
+
+import java.util.Random;
+
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.brain.Zone;
+import com.github.drinkjava2.frog.egg.Egg;
+
+/**
+ * Random Utilities used in this project
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class RandomUtils {
+ private static final Random rand = new Random();
+
+ public static int nextInt(int i) {
+ return rand.nextInt(i);
+ }
+
+ public static float nextFloat() {
+ return rand.nextFloat();
+ }
+
+ /** Return a random zone inside of a zone */
+ public static Zone randomZoneInZone(Zone z) { // 在一个区内随机取一个小小区
+ return new Zone(z.x - z.r + z.r * 2 * rand.nextFloat(), z.y - z.r + z.r * 2 * rand.nextFloat(),
+ z.r * rand.nextFloat() * .04f);
+ }
+
+ /** Return a random zone inside of frog's random organ */
+ public static Zone randomPosInAnyFrogOrgan(Frog f) {
+ if (f.organs == null || f.organs.size() == 0)
+ throw new IllegalArgumentException("Can not call randomPosInRandomOrgan method when frog has no organ");
+ return randomZoneInZone(f.organs.get(RandomUtils.nextInt(Egg.FIXED_ORGAN_QTY)));
+ }
+
+ /** Return a random zone inside of frog's random organ */
+ public static Zone randomPosMostInNewEye(Frog f) {
+ if (f.organs == null || f.organs.size() == 0)
+ throw new IllegalArgumentException("Can not call randomPosInRandomOrgan method when frog has no organ");
+ if (RandomUtils.percent(95))
+ return randomZoneInZone(f.organs.get(7));// 这是一个硬编码,大部分新联接建立在newEye中
+ return randomZoneInZone(f.organs.get(RandomUtils.nextInt(Egg.FIXED_ORGAN_QTY)));
+ }
+
+ public static boolean percent(float percent) {
+ return rand.nextFloat() * 100 < percent;
+ }
+
+ // /** vary a zone position, size a little bit */
+ // public static void varyZone(Zone z) {
+ // int i = rand.nextInt(100);
+ // if (i < 95) // 有95的机率不变异
+ // return;
+ // z.x = varyByRate(z.x, 0.01f);
+ // z.y = varyByRate(z.y, 0.01f);
+ // z.r = varyByRate(z.r, 0.03f);
+ // }
+
+ // public static float varyByRate(float f, float rate) { // 用指定的机率变异
+ // boolean bigger = rand.nextInt(2) > 0;
+ // if (bigger)
+ // f = f + f * rate * rand.nextFloat() + .001f;
+ // else
+ // f = f - f * rate * rand.nextFloat() - .001f;
+ // if (Float.isNaN(f))
+ // f = 0f;
+ // if (f > 1000000f)
+ // f = 1000000f;
+ // else if (f < -1000000f)
+ // f = -1000000f;
+ // return f;
+ // }
+
+ // public static float vary(float f) { // 大部分时候不变,有极小机会变异,有极极小机会大变异,有极极极小机会大大大变异
+ // int i = rand.nextInt(100);
+ // if (i < 50) // 有50的机率不变异
+ // return f;
+ // float rate = 0.2f; // 50%机率在0.2倍范围变异
+ // if (i > 80)
+ // rate = 1f; // 有20%的机率在1倍的范围变异
+ // if (i > 90)
+ // rate = 10f; // 有10%的机率在10倍的范围变异
+ // if (i > 95)
+ // rate = 100f; // 有5%的机率在100倍的范围变异
+ // if (i > 98)
+ // rate = 1000f; // 有1%的机率在1000倍的范围变异
+ //
+ // boolean bigger = rand.nextInt(2) > 0;
+ // if (bigger)
+ // f = f + f * rate * rand.nextFloat() + .001f;
+ // else
+ // f = f - f * rate * rand.nextFloat() - .001f;
+ // if (Float.isNaN(f))
+ // f = 0f;
+ // if (f > 1000000f)
+ // f = 1000000f;
+ // else if (f < -1000000f)
+ // f = -1000000f;
+ // return f;
+ // }
+
+}
diff --git a/history/005_letter_test/LICENSE b/history/005_letter_test/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/history/005_letter_test/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ 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.
diff --git a/history/005_letter_test/maven_clean.bat b/history/005_letter_test/maven_clean.bat
new file mode 100644
index 0000000..2f3d3e5
--- /dev/null
+++ b/history/005_letter_test/maven_clean.bat
@@ -0,0 +1 @@
+mvn clean
\ No newline at end of file
diff --git a/history/005_letter_test/maven_eclipse_clean.bat b/history/005_letter_test/maven_eclipse_clean.bat
new file mode 100644
index 0000000..a427bd7
--- /dev/null
+++ b/history/005_letter_test/maven_eclipse_clean.bat
@@ -0,0 +1 @@
+mvn eclipse:clean
\ No newline at end of file
diff --git a/history/005_letter_test/maven_eclipse_eclipse.bat b/history/005_letter_test/maven_eclipse_eclipse.bat
new file mode 100644
index 0000000..99fa0b2
--- /dev/null
+++ b/history/005_letter_test/maven_eclipse_eclipse.bat
@@ -0,0 +1,2 @@
+call mvn eclipse:eclipse
+call pause
\ No newline at end of file
diff --git a/history/005_letter_test/pom.xml b/history/005_letter_test/pom.xml
new file mode 100644
index 0000000..5851f54
--- /dev/null
+++ b/history/005_letter_test/pom.xml
@@ -0,0 +1,102 @@
+
+ 4.0.0
+ com.gitee.drinkjava2
+ frog005
+ jar
+ 1.0
+
+ frog
+ An artificial life test project
+ https://gitee.com/drinkjava2/jsqlbox/frog
+
+
+ gitee Issue
+ https://gitee.com/drinkjava2/jsqlbox/frog/issues
+
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+
+ Yong Zhu
+ yong9981@gmail.com
+ https://gitee.com/drinkjava2/
+
+
+
+
+ scm:git@gitee.com:drinkjava2/frog.git
+ scm:git@gitee.com:drinkjava2/frog.git
+ git@gitee.com:drinkjava2/frog.git
+
+
+
+ UTF-8
+ UTF-8
+ UTF-8
+
+ 1.8
+ 6
+ 3.3
+ 2.6
+ 3.0.0
+ 2.7
+ 2.19
+ 2.6
+ 2.4
+ 2.10.3
+ 1.6
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${version.compiler-plugin}
+
+ ${version.java}
+ ${version.java}
+ UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.2
+
+
+
+ true
+ false
+ lib/
+ com.github.drinkjava2.frog.Application
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/history/005_letter_test/run.bat b/history/005_letter_test/run.bat
new file mode 100644
index 0000000..ab1bab3
--- /dev/null
+++ b/history/005_letter_test/run.bat
@@ -0,0 +1,4 @@
+call mvn clean compile
+cd target\classes
+java -classpath ".;*" com.github.drinkjava2.frog.Application
+@pause
\ No newline at end of file
diff --git a/history/005_letter_test/run.sh b/history/005_letter_test/run.sh
new file mode 100644
index 0000000..836c941
--- /dev/null
+++ b/history/005_letter_test/run.sh
@@ -0,0 +1,2 @@
+mvn clean package
+java -jar target/frog-*.jar
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/Application.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/Application.java
similarity index 93%
rename from core3d/src/main/java/com/github/drinkjava2/frog/Application.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/Application.java
index e035d51..8d96ff0 100644
--- a/core3d/src/main/java/com/github/drinkjava2/frog/Application.java
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/Application.java
@@ -21,8 +21,11 @@ public class Application {
static {
String classpath = new File("").getAbsolutePath();
- int core = classpath.indexOf("core");
- CLASSPATH = classpath.substring(0, core);
+ int core = classpath.indexOf("\\frog\\");
+ if (core > 0)
+ CLASSPATH = classpath.substring(0, core) + "\\frog\\";
+ else
+ CLASSPATH = classpath.substring(0, core) + "/frog/"; // UNIX
}
public static JFrame mainFrame = new JFrame();
public static Env env = new Env();
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/Env.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/Env.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/Env.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/Env.java
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/Frog.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/Frog.java
similarity index 90%
rename from core3d/src/main/java/com/github/drinkjava2/frog/Frog.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/Frog.java
index f49cf3b..c2efea6 100644
--- a/core3d/src/main/java/com/github/drinkjava2/frog/Frog.java
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/Frog.java
@@ -28,18 +28,19 @@ import com.github.drinkjava2.frog.egg.Egg;
import com.github.drinkjava2.frog.objects.Material;
/**
- * Frog = organs + cells
- * cells = brain cells + photons
- * organs = cell parameters + cell actions
+ * Frog = cells
+ * cells = actions + photons
*
- * 青蛙脑由器官播种出的细胞组成,器官Organ会播种出各种脑细胞填充在一个cells三维数组代表的空间中,每个cell里可以存在多个脑细胞和光子,光子是信息的载体,永远不停留。
+ * Frog's name is Sam.
+ *
+ * 青蛙脑由一个cells三维数组组成,每个cell里可以存在多个行为,行为是由器官决定,同一个细胞可以存在多种行为。光子是信息的载体,永远不停留。
*
* @author Yong Zhu
* @since 1.0
*/
-public class Frog {
+public class Frog {// 这个程序大量用到public变量而不是getter/setter,主要是为了编程方便和简洁,但缺点是编程者需要小心维护各个变量
/** brain cells */
- public Cell[][][] cells;// 一开始不要初始化,只在调用getCell方法时才初始化相关维以节约内存
+ public Cell[][][] cells;// 一开始不要初始化,只在调用getOrCreateCell方法时才初始化相关维以节约内存
/** organs */
public List organs = new ArrayList<>();
@@ -59,8 +60,8 @@ public class Frog {
}
}
- public Frog(int x, int y, Egg egg) {
- this.x = x; // x, y 是虑拟环境的坐标
+ public Frog(int x, int y, Egg egg) {// x, y 是虑拟环境的坐标
+ this.x = x;
this.y = y;
for (Organ org : egg.organs)
organs.add(org);
@@ -197,7 +198,8 @@ public class Frog {
}
}
- public void prepareNewTraining() {// for test purpose, reset some values for prepare next training.
+ // for test purpose, reset some values for prepare next training.
+ public void prepareNewTraining() {
for (int i = 0; i < Env.FROG_BRAIN_XSIZE; i++) {
if (cells[i] != null)
for (int j = 0; j < Env.FROG_BRAIN_YSIZE; j++)
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/BrainPicture.java
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Cell.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
similarity index 86%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
index c5a89e5..7dcb8ba 100644
--- a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Cell.java
@@ -96,27 +96,31 @@ public class Cell {
return;
}
- if(RandomUtils.percent(2))
- for (int i = 0; i < holes.length; i++) { // 这部分很关键,光子如果与坑同向或角度相近,会在与坑绑定的坑上撞出新的光子反向飞回,注意只针对绑定的坑
- Hole h = holes[i];
- if (h != null ) {
- float r = h.angleCompare(p);
- if(r<0.01) {
- if(RandomUtils.percent(100-r*100))
- createBackPhoton(h);
+ if (RandomUtils.percent(10)) // 这个机率纯粹是为了减少光子数,增加运行速度
+ for (int i = 0; i < holes.length; i++) { // 这部分很关键,光子如果与坑同向或角度相近,会在与坑绑定的坑上撞出新的光子反向飞回,注意只针对绑定的坑
+ Hole h = holes[i];
+ if (h != null) {
+ float r = h.angleCompare(p);
+ if (r < 0.05) {
+ if (RandomUtils.percent(h.size))
+ createBackPhoton(h); // 产生光子的机率与洞的大小有关
+ } else if (r > 0.1 && r < 0.5) { // 这个叫侧抑制,角度不等但相近的光子射过来会使洞变小
+ h.size -= 10;
+ if (h.size < 10)
+ h.size = 10;
+ }
}
}
- }
Hole found = null;
for (int i = 0; i < holes.length; i++) { // 先看看已存在的洞是不是与光子同向,是的话就把洞挖大一点
Hole h = holes[i];
- if (h != null && h.ifSameWay(p)) { // 找到了与入射光子同向的洞,实际上就是同一个波源发来的
+ if (h != null && h.ifSimilarWay(p)) { // 找到了与入射光子同向的洞,实际上就是同一个波源发来的
found = h;
- h.size *= 1.2f;
- if (h.size > 10000)
- h.size = 10000;
- h.age = 0;
+ h.size += 10;
+ h.age = 0; // 为0表示这个洞被重新激活,可以参与绑定
+ if (h.size > 100)
+ h.size = 100;
break;
}
}
@@ -145,7 +149,7 @@ public class Cell {
else if (h.equals(r.h2))
f = r.h1; // h1与h是一对绑定的
if (f != null) {
- Photon back = new Photon(-1, ColorUtils.RED, f.x, f.y, f.z, -f.mx, -f.my, -f.mz, 90);// 生成反向的光子
+ Photon back = new Photon(-1, ColorUtils.RED, f.x, f.y, f.z, -f.mx, -f.my, -f.mz);// 生成反向的光子
addPhoton(back);
// energy -= 90;
}
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/CellActions.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/CellActions.java
new file mode 100644
index 0000000..9251262
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/CellActions.java
@@ -0,0 +1,117 @@
+/*
+ * 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;
+
+import com.github.drinkjava2.frog.Env;
+import com.github.drinkjava2.frog.Frog;
+import com.github.drinkjava2.frog.util.RandomUtils;
+
+/**
+ * CellActions have many cell action stored
+ *
+ * CellActions写死了许多硬编码的脑细胞活动,用act方法来调用这些活动,type参数来区分调用哪个单例的方法
+ *
+ * @author Yong Zhu
+ * @since 2.0.2
+ */
+public class CellActions {
+
+ /*-
+ * Each cell's act method will be called once at each loop step
+ *
+ * 在每个测试步长中act方法都会被调用一次,这个方法针对不同的细胞类型有不同的行为逻辑,这是硬
+ * 编码,所以要准备多套不同的行为(可以参考动物脑细胞的活动逻辑),然后抛给电脑去随机筛选,不怕多。
+ * 同一个细胞可能有多个action,由organs数组中登记的器官号决定,调用顺序也是按器官号顺序
+ *
+ *
+ * 举例来说,以下是一些假想中的脑细胞行为:
+ * 一对一,穿透,光子会穿过细胞,细胞起到中继站的作用,如果没有细胞中继,光子在真空中不能传播
+ * 一对一,转向,光子传播角度被改变成另一个绝对角度发出
+ * 一对一,转向,光子传播角度被改变成与器官有关的角度发出,可以模拟光线的发散(如视网膜细胞)和聚焦(如脑内成像,即沿光线发散的逆路径)
+ * 一对多,拆分,入射光子被拆分成多个光子,以一定的发散角发出,通常发散光子的总能量小于入射+细胞输出能量之和
+ * 一对多,拆分,入射光子被拆分成多个光子,发散角与器官相关
+ * 多对一,聚合,入射光子被细胞捕获
+ */
+ public static void act(Frog frog, int activeNo, Cell c) {
+ if (c.holes != null)
+ for (Hole h : c.holes) {// 洞的年龄增加,目的是让年龄越接近的洞之间,绑定的概率和强度越大
+ h.age++;
+ }
+ if (c.organs != null)
+ for (int orgNo : c.organs) {
+ Organ o = frog.organs.get(orgNo);
+ switch (o.type) { // 添加细胞的行为,这是硬编码
+ case Organ.MOVE: // 如果是MOVE细胞,它的行为是让每个光子穿过这个细胞走到下一格,保持光子沿直线运动
+ if (c.x == 0 || c.z == Env.FROG_BRAIN_ZSIZE - 1) {// 但是对于输入区,将删除光子,并合计一共收到多少
+ if (c.photonQty > 0) {
+ c.photonSum += c.photonQty;
+ c.photons = null;
+ }
+ break;
+ }
+ if (c.photons != null) {
+ for (int ii = 0; ii < c.photons.length; ii++) {
+ Photon p = c.photons[ii];
+ if (p == null || p.activeNo == activeNo)// 同一轮新产生的光子或处理过的光子不再走了
+ continue;
+ p.activeNo = activeNo;
+ c.removePhoton(ii);
+ frog.addAndWalk(p); // 让光子自已往下走,走到哪就停到哪个细胞里
+ }
+ }
+ break;
+ case Organ.MOVE_JELLY: // 如果是MOVE_JELLY细胞,它让每个光子穿过这个细胞走到下一格,并在下一个细胞上打出洞来
+ if (c.x == 0 || c.z == Env.FROG_BRAIN_ZSIZE - 1) {// 但是对于输入区,将删除光子,并合计一共收到多少
+ if (c.photonQty > 0) {
+ c.photonSum += c.photonQty;
+ c.photons = null;
+ }
+ break;
+ }
+ if (c.photons != null) {
+ for (int ii = 0; ii < c.photons.length; ii++) {
+ Photon p = c.photons[ii];
+ if (p == null || p.activeNo == activeNo)// 同一轮新产生的光子或处理过的光子不再走了
+ continue;
+ p.activeNo = activeNo;
+ c.removePhoton(ii);
+ frog.addAndWalkAndDig(p); // 让光子自已往下走,走到哪就停到哪个细胞里,并且还在细胞上挖洞
+ }
+ }
+ break;
+ case Organ.EYE: // 如果是视网膜细胞,它的行为是只要Cell有输入信号,就产生向右的多个光子发散出去,模拟波源
+ if (c.hasInput && RandomUtils.percent(40)) {// 随机数的作用是减少光子数,加快速度
+ for (float yy = -0.1f; yy <= 0.1f; yy += 0.03) {// 形成一个扇面向右发送
+ for (float zz = -0.1f; zz <= 0.1f; zz += 0.03) {
+ Photon p = new Photon(orgNo, o.color, c.x, c.y, c.z, 1.0f, yy, zz);
+ p.activeNo = activeNo; // 用这个activeNo防止一直被赶着走
+ frog.addAndWalk(p);// 光子不是直接添加,而是走一格后添加在相邻的细胞上
+ }
+ }
+ }
+ break;
+ case Organ.EAR: // 如果是听力细胞,它的行为是将只要Cell有输入信号,就产生向下的多个光子发散出去,模拟波源
+ if (c.hasInput && RandomUtils.percent(40)) {// 随机数的作用是减少光子数,加快速度
+ for (float xx = -0.3f; xx <= 0.3f; xx += 0.15) {// 形成一个扇面向下发送
+ for (float yy = -1f; yy <= 1f; yy += 0.06) {
+ Photon p = new Photon(o.organNo, o.color, c.x, c.y, c.z, xx, yy, -1);
+ p.activeNo = activeNo;
+ frog.addAndWalk(p);// 光子不是直接添加,而是走一格后添加在相邻的细胞上
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Cone.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Cone.java
new file mode 100644
index 0000000..ce94e8e
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Cone.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+import com.github.drinkjava2.frog.Frog;
+
+/**
+ * Cone represents a cone 3d zone in brain
+ *
+ * Cone是一个锥形体(圆锥或棱锥),通常用来表示脑内器官的形状。另一个常用形状是Cuboid长方体.
+ *
+ * @author Yong Zhu
+ * @since 2.0.2
+ */
+@SuppressWarnings("all")
+public class Cone implements Shape {
+ private static final long serialVersionUID = 1L;
+
+ public int x1; // 这6个变量定义了Cone的中心线起点和终点,器官不能拐弯,但拐弯可以用一个锥体分成两个首尾相接的锥体再进一步变异演化出来
+ public int y1;
+ public int z1;
+ public int x2;
+ public int y2;
+ public int z2;
+
+ public int r1 = 8; // 起点的半径,为了简化编程,通常是是指起点矩形边长的一半,因为圆形计算麻烦
+ public int r2 = 8; // 终点的半径
+
+ public Cone() {
+ // 空构造器不能省
+ }
+
+ public Cone(int x1, int y1, int z1, int x2, int y2, int z2, int r1, int r2) {// 用x,y,z,r来构造
+ this.x1 = x1;
+ this.y1 = y1;
+ this.z1 = z1;
+ this.x2 = x2;
+ this.y2 = y2;
+ this.z2 = z2;
+ this.r1 = r1;
+ this.r2 = r2;
+ }
+
+ @Override
+ public void drawOnBrainPicture(BrainPicture pic) {
+ pic.drawCone(this);
+ }
+
+ @Override
+ public void createCellsRegOrgan(Frog f, int o) {
+ // TODO 待添加Cone形器官播种脑细胞的代码
+ }
+
+}
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Cuboid.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Cuboid.java
new file mode 100644
index 0000000..4635267
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Cuboid.java
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+import com.github.drinkjava2.frog.Frog;
+
+/**
+ * Cuboid represents a rectangular prism 3d zone in brain
+ *
+ * Cuboid是一个长方体,通常用来表示脑内器官的形状。另一个功能类似的形装是Cone锥形体。
+ *
+ * @author Yong Zhu
+ * @since 2.0.2
+ */
+@SuppressWarnings("all")
+public class Cuboid implements Shape {
+ private static final long serialVersionUID = 1L;
+
+ public int x;// x,y,z是长方体的左下角坐标
+ public int y;
+ public int z;
+ public int xe;// xe,ye,ze分别是长方体三边长
+ public int ye;
+ public int ze;
+
+ public Cuboid() {
+ // 空构造器不能省
+ }
+
+ public Cuboid(int x, int y, int z, int xe, int ye, int ze) {// 用x,y,z,r来构造
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.xe = xe;
+ this.ye = ye;
+ this.ze = ze;
+ }
+
+ public Cuboid(Cuboid c) {// 用另一个Cuboid来构造
+ this.x = c.x;
+ this.y = c.y;
+ this.z = c.z;
+ this.xe = c.xe;
+ this.ye = c.ye;
+ this.ze = c.ze;
+ }
+
+ @Override
+ public void drawOnBrainPicture(BrainPicture pic) {
+ pic.drawCuboid(this);
+ }
+
+ @Override
+ public void createCellsRegOrgan(Frog f, int orgNo) {// 创建Cell并登记Organ, 先忽略密度分布等参数
+ for (int i = x; i < x + xe; i++)
+ for (int j = y; j < y + ye; j++)
+ for (int k = z; k < z + ze; k++) {
+ Cell cell = f.getOrCreateCell(i, j, k);
+ if (cell != null)
+ cell.regOrgan(orgNo);
+ }
+ }
+
+ public void createCells(Frog f) {// 创建Cell, 先忽略密度分布等参数
+ for (int i = x; i < x + xe; i++)
+ for (int j = y; j < y + ye; j++)
+ for (int k = z; k < z + ze; k++)
+ f.getOrCreateCell(i, j, k);
+ }
+}
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Hole.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Hole.java
new file mode 100644
index 0000000..c4d53a5
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Hole.java
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+/**
+ * Hole is a hole on jelly cell, it works like synapse on nerve cell
+ *
+ * 以前叫突触,现在改名叫洞,更形象一点,每个光子传来就好象在果冻上砸出个洞。管它符不符合生物脑突触这个形象,张牙舞爪的神经元变成了千创百孔的果冻,先乱试一通再说。
+ *
+ * @author Yong Zhu
+ * @since 2.0.2
+ */
+public class Hole {
+ public float x;// x,y,z 是 洞的中心坐标点,这个是脑内的绝对坐标
+ public float y;
+ public float z;
+ public float mx; // mx,my,mz分别是光子砸出这个洞时的光子每单元移动方向在三个轴上的投影
+ public float my;
+ public float mz;
+ public int size = 50;// 洞的大小1~100,这个size会按记忆曲线慢慢回复到0,接近0后这个洞就被删除回收内存,
+ public int age;// 洞的年龄,一直在增长,但一个洞有完全同向的光子再次砸进来,洞的年龄就归0
+ public int organNo;// 这里记录第一个撞出来这个洞的产子是由哪个器官产生出来的
+
+ public Hole(Photon p) {
+ this.x = p.x;
+ this.y = p.y;
+ this.z = p.z;
+ this.mx = p.mx;
+ this.my = p.my;
+ this.mz = p.mz;
+ this.organNo = p.organNo;
+ }
+
+ public float angleCompare(Hole p) {// 比较洞与光子之间的角度差值
+ return Math.abs(p.mx - mx) + Math.abs(p.my - my) + Math.abs(p.mz - mz);
+ }
+
+ public float angleCompare(Photon p) {// 比较洞与光子之间的角度差值
+ return Math.abs(p.mx - mx) + Math.abs(p.my - my) + Math.abs(p.mz - mz);
+ }
+
+ public boolean ifSameWay(Photon p) {// 如果光子运动方向与洞完全同向,实际上也就是说从同一个波源发出来的
+ return Math.abs(p.mx - mx) < 0.0001 && Math.abs(p.my - my) < 0.0001 && Math.abs(p.mz - mz) < 0.0001;
+ }
+
+ public boolean ifSimilarWay(Photon p) {// 如果光子运动方向与洞近似相同
+ return Math.abs(p.mx - mx) < 0.05 && Math.abs(p.my - my) < 0.05 && Math.abs(p.mz - mz) < 0.05;
+ }
+
+}
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/MouseAction.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/MouseAction.java
new file mode 100644
index 0000000..de5b59f
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/MouseAction.java
@@ -0,0 +1,106 @@
+package com.github.drinkjava2.frog.brain;
+
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+
+/**
+ * MouseAction
+ *
+ * 这个类用来处理脑图BrainPicture上的鼠标动作,有平移、旋转、缩放三种
+ *
+ * @author Yong Zhu
+ * @since 2.0.2
+ */
+public class MouseAction implements MouseListener, MouseWheelListener, MouseMotionListener {
+ private BrainPicture brainPic;
+ private int buttonPressed = 0;
+ private int x;
+ private int y;
+
+ public MouseAction(BrainPicture brainPic) {
+ this.brainPic = brainPic;
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {// 记录当前鼠标点
+ if (e.getButton() == 1)// 旋转
+ buttonPressed = 1;
+ else if (e.getButton() == 2)// 缩放
+ buttonPressed = 2;
+ else
+ buttonPressed = 0;
+ x = e.getPoint().x;
+ y = e.getPoint().y;
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ buttonPressed = 0;
+ }
+
+ @Override
+ public void mouseWheelMoved(MouseWheelEvent e) {// 缩放
+ if (e.getWheelRotation() < 0) {
+ brainPic.scale *= 1.1;
+ brainPic.xOffset *= 1.1;
+ brainPic.yOffset *= 1.1;
+ } else {
+ brainPic.scale /= 1.1;
+ brainPic.xOffset /= 1.1;
+ brainPic.yOffset /= 1.1;
+ }
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {// 旋转
+ if (buttonPressed == 1) {
+ if (e.getX() > x && e.getY() > y)
+ brainPic.zAngle -= .00f;
+ else if (e.getX() < x && e.getY() < y)
+ brainPic.zAngle += .00f;
+ else {
+ if (e.getX() > x)
+ brainPic.yAngle += .02f;
+ if (e.getX() < x)
+ brainPic.yAngle -= .02f;
+ if (e.getY() > y)
+ brainPic.xAngle -= .02f;
+ if (e.getY() < y)
+ brainPic.xAngle += .02f;
+ }
+ x = e.getX();
+ y = e.getY();
+ }
+ if (buttonPressed == 2) {// 平移
+ if (e.getX() > x)
+ brainPic.xOffset += 6;
+ if (e.getX() < x)
+ brainPic.xOffset -= 6;
+ if (e.getY() > y)
+ brainPic.yOffset += 6;
+ if (e.getY() < y)
+ brainPic.yOffset -= 6;
+ x = e.getX();
+ y = e.getY();
+ }
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {// do nothing
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e) {// do nothing
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {// do nothing
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) { // do nothing
+ }
+}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Organ.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
similarity index 89%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
index f9e6099..d2ce3ff 100644
--- a/core3d/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Organ.java
@@ -22,20 +22,19 @@ import com.github.drinkjava2.frog.util.RandomUtils;
* egg, organ will create cells in brain. Most organ's size, angle, location and
* cell parameters are randomly created
*
- * 器官是脑的一部分,多个器官在脑内可以允许部分或完全重叠出现在同一脑内位置,器官都是可以变异的, 器官负责在青蛙脑生成时播种脑细胞
- * 器官是可串行化的,所有器官都会保存在蛋里面
+ * 器官是脑的一部分,多个器官在脑内可以允许部分或完全重叠出现在同一脑内位置,器官都是可以变异的,所有器官都会保存在蛋里面。
*
- * 器官是一种外形为锥圆柱体或长方体的脑内区,它的作用是在它的形状范围内播种脑细胞,
- * 它的数量、形状、大小、角度、位置、神经元分布方式,以及神经元的内部参数可以随机生成和变异, 并由生存竟争来淘汰筛选。
+ * 器官是一种外形为锥圆柱体或长方体的脑内区,它的作用是在它的形状范围内在脑细胞内登记行为,当然如果脑细胞不存在它首先会新建一个脑细胞。
+ * 器官的数量、形状、大小、角度、位置、神经元分布方式,以及神经元的内部参数可以随机生成和变异, 并由生存竟争来淘汰筛选。
*
* 器官可以组合成复杂的网络结构或曲折的信号传导路径,例如一个圆柱形神经传导器官,可以变异为由两个圆柱状传导器官首尾相接,然后这两个器官各
* 自变异,就有可能形成弯的传导路径或更复杂的网络结构。看起来复杂,但大自然可以做到比这更复杂的进化逻辑,先假设大自然是万能的,只要是有用的
* 变异逻辑,就有可能出现。
*
- * 器官描述细胞的形状和行为,其中洞数量和参数是有可能随机变异的。行为则是硬编码不可以变异,模拟单个神经元的逻辑,不同的细胞有不同的
- * 行为,通过type来区分,虽然行为不可以变异,但是可以写出尽可能多种不同的行为(貌似神经元的活动也只有有限的几种),由生存竟争来筛选。
+ * 器官描述细胞的行为,其中洞数量和参数是有可能随机变异的。行为则是硬编码不可以变异,模拟单个神经元的逻辑,不同的细胞可以登记属于多个不同的
+ * 器官,虽然器官行为不可以变异,但是可以写出尽可能多种不同的行为(貌似神经元的活动也只有有限的几种),由生存竟争来筛选。
*
- * 器官通常是单例,每个脑细胞都指向某个器官单例,器官这个单例参与神经活动时是无状态的,有状态的神经元的参数是保存在Cell中而不是器官中,这种设计是为了减少
+ * 器官通常是单例,每个脑细胞都指向一些器官单例,器官这个单例参与神经活动时是无状态的,有状态的神经元的参数是保存在Cell中而不是器官中,这种设计是为了减少
* Cell的内存占用
*
* 信息(光子)的逻辑:
@@ -44,8 +43,8 @@ import com.github.drinkjava2.frog.util.RandomUtils;
* 能量,光子总是直线传播,不在合适交点(波的驻点)位置的细胞吸收不到能量。
*
* 光子自带传播方向,并在每个测试步长中自动走一格,为什么还需要脑细胞的静态洞和动态洞?
- * 因为光子只能直线传播,而洞具有分发、收集、改变光子方向等作用,能增加脑的复杂,在器官中的洞是无状态的,只能进行简单的信号传导、发
- * 散、会聚等处理,而cell中根据光子的方向动态生成的洞是智能的基石,它能将有关联关系的 重复光子信号从海量的自然界噪声信号中抽取出来产生关联。
+ * 因为光子只能直线传播,而洞具有分发、收集、改变光子方向等作用,能增加脑的复杂,cell中根据光子的方向动态生成的洞是智能的基石,它能将有关联关系的
+ * 重复光子信号从海量的自然界噪声信号中抽取出来产生关联。
*
* @author Yong Zhu
* @since 1.0.4
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Photon.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Photon.java
new file mode 100644
index 0000000..b8e9db6
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Photon.java
@@ -0,0 +1,60 @@
+/*
+ * 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;
+
+import com.github.drinkjava2.frog.Env;
+
+/**
+ * Photon has direction and strength
+ *
+ * 用光子来代表信息传递的载体,这是一个矢量,具有方向和能量,能量可以为负值,x,y,z值表示它的脑空间的坐标值,mx,my,mz表示每次移动多少
+ * 光子永远在移动,直到被吸收转化为Cell的能量贮存或出界
+ *
+ * @author Yong Zhu
+ * @since 2.0.2
+ */
+public class Photon {
+ public float x;
+ public float y;
+ public float z;
+ public float mx;
+ public float my;
+ public float mz;
+ public int organNo;// 每个光子是由哪个器官产生的,为-1表示它不是器官产生而是由细胞动态生成的反向光子信号
+ public int color;// 每个光子都有自已的颜色,由产生光子的器官的颜色来决定,颜色不重要,但能方便观察
+ public int activeNo;// 每一轮循环都有一个编号,光子走一格后就加上这个编号,同一个循环如果遇到相同编号的光子就跳过,防止光子被一直赶着走
+ public int energy;
+
+ public Photon() { // 缺省构造器
+ }
+
+ public Photon(int organNo, int color, float x, float y, float z, float mx, float my, float mz) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.mx = mx;
+ this.my = my;
+ this.mz = mz;
+ this.organNo = organNo;
+ this.color = color;
+ }
+
+ public boolean isBackway() {// 是反向光子? 通常反向传播的光子不再参与在果冻细胞上挖洞
+ return organNo < 0;
+ }
+
+ /** Check if x,y,z out of frog's brain bound */
+ public boolean outBrainBound() {// 检查指定坐标是否超出frog脑空间界限
+ return x < 0 || x >= Env.FROG_BRAIN_XSIZE || y < 0 || y >= Env.FROG_BRAIN_YSIZE || z < 0
+ || z >= Env.FROG_BRAIN_ZSIZE;
+ }
+
+}
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Relation.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Relation.java
new file mode 100644
index 0000000..c6a7d2f
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Relation.java
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+/**
+ * Relation is the relationship betweeen 2 holes
+ *
+ * Relation 表示细胞上的两个洞之间存在关联关系,多对多关系用很多个一对一关系来表达
+ *
+ * @author Yong Zhu
+ * @since 2.0.2
+ */
+public class Relation {
+ public Hole h1;
+ public Hole h2;
+ public int strength = 1;
+
+ public Relation(Hole h1, Hole h2) {
+ this.h1 = h1;
+ this.h2 = h2;
+ }
+
+}
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Shape.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Shape.java
new file mode 100644
index 0000000..6e179e6
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/Shape.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+
+import com.github.drinkjava2.frog.Frog;
+
+/**
+ * Shape represents a 3d zone in brain
+ *
+ * Shape用来表示脑内器官的形状,一个器官只能有一个shape
+ *
+ * @author Yong Zhu
+ * @since 2.0.2
+ */
+public interface Shape extends Serializable {
+ /* Draw self on brain picture */
+ public void drawOnBrainPicture(BrainPicture pic); // 把自己在脑图上画出来
+
+ public void createCellsRegOrgan(Frog f, int orgNo); // 在Shape所代表的脑区内找到或创建Cell对象,并将器官号orgNo登记在cell里
+}
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/organ/Ear.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/organ/Ear.java
new file mode 100644
index 0000000..cbb7b59
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/organ/Ear.java
@@ -0,0 +1,67 @@
+/*
+ * 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 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.ColorUtils;
+
+/**
+ * Ear can accept sound input
+ *
+ * 耳朵的信号输入区能输入多少个信号取决于它的长度,它的每个输入点都与视觉视号正交
+ *
+ * @author Yong Zhu
+ * @since 2.0.2
+ */
+@SuppressWarnings("all")
+public class Ear extends Organ {// 耳朵位于脑的顶上,也是长方体
+ private static final long serialVersionUID = 1L;
+
+ public Ear() {
+ this.shape = new Cuboid(15, 5, Env.FROG_BRAIN_ZSIZE - 1, 1, 10, 1);// 手工固定耳区的大小
+ this.type = Organ.EAR;
+ this.organName = "Ear";
+ this.allowVary = false;// 不允许变异
+ this.allowBorrow = false;// 不允许借出
+ this.color = ColorUtils.BLUE;
+ }
+
+ public void hearSound(Frog f, int code) {
+ Cuboid c = (Cuboid) this.shape;
+ f.getOrCreateCell(c.x, c.y + code, c.z).hasInput = true;
+ }
+
+ public int readcode(Frog f) {//找出收取光子数最多的点
+ int temp = -10000;
+ int yPos = -1;
+ Cuboid c = (Cuboid) this.shape;
+ System.out.print("Ear received photons qty: ");
+ for (int y = 0; y < 10; y++) {
+ int sum = f.getOrCreateCell(c.x, c.y + y, c.z).photonSum;
+ System.out.print(sum + ",");
+ if (sum > temp) {
+ yPos = y;
+ temp = sum;
+ }
+ }
+ System.out.println();
+ return yPos;
+ }
+
+ /** 给这个耳朵听到一个字母,激活它的听觉输入区, 注意听觉输入区并不等于听觉成像区 */
+ public void hearNothing(Frog f) {
+ f.setCuboidVales((Cuboid) shape, false);
+ }
+
+}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/organ/Eye.java
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveJelly.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveJelly.java
new file mode 100644
index 0000000..89795d0
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/brain/organ/MoveJelly.java
@@ -0,0 +1,36 @@
+/*
+ * 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 com.github.drinkjava2.frog.Env;
+import com.github.drinkjava2.frog.brain.Cuboid;
+import com.github.drinkjava2.frog.brain.Organ;
+
+/**
+ * Move is a special organ the action move photon go to next cell
+ *
+ * Move这个器官会让Cell中的光子沿着它的运动方向走到下一格
+ *
+ * @author Yong Zhu
+ */
+public class MoveJelly extends Organ {
+ private static final long serialVersionUID = 1L;
+
+ public MoveJelly() {
+ super();
+ this.shape = new Cuboid(0, 0, 0, Env.FROG_BRAIN_XSIZE - 5, Env.FROG_BRAIN_YSIZE, Env.FROG_BRAIN_ZSIZE);
+ this.organName = "MoveJelly";
+ this.type = Organ.MOVE_JELLY; // Empty这个器官并不播种cell,它存在的唯一目的只是充当光子媒介,否则光子会一直走下去消失
+ this.allowVary = false;// 不允许变异
+ this.allowBorrow = false;// 不允许借出
+ }
+
+}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/egg/Egg.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
similarity index 93%
rename from core3d/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
index 58681ee..54de0a4 100644
--- a/core3d/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/egg/EggTool.java
@@ -48,13 +48,13 @@ public class EggTool {
Env.eggs.clear();
for (int i = 0; i < Env.EGG_QTY; i++)
Env.eggs.add(new Egg(Env.frogs.get(i)));
- FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs3d.ser");
+ FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs.ser");
ObjectOutputStream so = new ObjectOutputStream(fo);
so.writeObject(Env.eggs);
so.close();
System.out.print("Fist frog has " + first.organs.size() + " organs, energy=" + first.energy);
System.out.println(", Last frog has " + last.organs.size() + " organs, energy=" + last.energy);
- System.out.println("Saved " + Env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs3d.ser'");
+ System.out.println("Saved " + Env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs.ser'");
} catch (IOException e) {
System.out.println(e);
}
@@ -74,8 +74,8 @@ public class EggTool {
}
public static void deleteEggs() {
- System.out.println("Delete exist egg file: '" + Application.CLASSPATH + "eggs3d.ser'");
- FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs3d.ser");
+ System.out.println("Delete exist egg file: '" + Application.CLASSPATH + "eggs.ser'");
+ FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs.ser");
}
/**
@@ -85,11 +85,11 @@ public class EggTool {
public static void loadEggs() {
boolean errorfound = false;
try {
- FileInputStream eggsFile = new FileInputStream(Application.CLASSPATH + "eggs3d.ser");
+ 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 + "eggs3d.ser" + "'.\n");
+ "Loaded " + Env.eggs.size() + " eggs from file '" + Application.CLASSPATH + "eggs.ser" + "'.\n");
eggsInputStream.close();
} catch (Exception e) {
errorfound = true;
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/EnvObject.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/EnvObject.java
new file mode 100644
index 0000000..85eda65
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/EnvObject.java
@@ -0,0 +1,26 @@
+/* Copyright 2018-2020 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.objects;
+
+/**
+ * EnvObject means some virtual object in Env
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public interface EnvObject {
+
+ public void build(); // 在Env中创建本身物体,指改变Env.bricks数组元素为本身物体的组成材料。只在每屏测试前调用一次
+
+ public void destory();// 从Env中清除本身物体,只在每屏测试完成后调用一次
+
+ public void active(int screen); // 每个步长都会调用一次这个方法
+}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/objects/Food.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/Food.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/objects/Food.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/Food.java
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java
new file mode 100644
index 0000000..dd0531c
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/LetterTester.java
@@ -0,0 +1,66 @@
+/* Copyright 2018-2020 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.objects;
+
+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.organ.Ear;
+import com.github.drinkjava2.frog.brain.organ.Eye;
+import com.github.drinkjava2.frog.util.StringPixelUtils;
+
+/**
+ * ChineseTester used to test test recognition
+ *
+ * 这是一个临时类,用来测试耳朵对汉字的模式识别及汉字的逆向成像
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class LetterTester implements EnvObject {
+ public static final String STR = "一二三";
+ public static final int TIME = 120;
+
+ @Override
+ public void build() { // do nothing
+ }
+
+ @Override
+ public void destory() {// do nothing
+ }
+
+ @Override
+ public void active(int screen) {
+ Frog frog = Env.frogs.get(screen * Env.FROG_PER_SCREEN); // 这个测试只针对每屏的第一只青蛙,因为脑图固定只显示第一只青蛙
+ Eye eye = frog.findOrganByName("Eye");
+ Ear ear = frog.findOrganByName("Ear");
+
+ int index = Env.step / TIME;
+ if (Env.step % TIME == 0)
+ frog.prepareNewTraining();
+
+ if (index < STR.length()) {
+ BrainPicture.setNote("第" + (index + 1) + "个字训练");
+ ear.hearSound(frog, index);
+ eye.seeImageWithOffset(frog, StringPixelUtils.getSanserif12Pixels(STR.substring(index, index + 1)),0,0);
+ } else {
+ int index2 = index % STR.length();
+ BrainPicture.setNote("第" + (index2 + 1) + "个字识别");
+ eye.seeImageWithOffset(frog, StringPixelUtils.getSanserif12Pixels(STR.substring(index2, index2 + 1)),1,1);
+ if (Env.step % TIME > (TIME - 2)) {
+ int result = ear.readcode(frog);
+ System.out.println("Max=" + result+", 即 '"+STR.substring(result, result+1)+"'");
+ frog.prepareNewTraining();
+ }
+ }
+ }
+
+}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/objects/Material.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/Material.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/objects/Material.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/Material.java
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/SeeSaw.java
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/objects/Trap.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/Trap.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/objects/Trap.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/objects/Trap.java
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/ColorUtils.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/ColorUtils.java
new file mode 100644
index 0000000..46e30db
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/ColorUtils.java
@@ -0,0 +1,70 @@
+/* Copyright 2018-2020 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.util;
+
+import java.awt.Color;
+
+/**
+ * Color Utilities used in this project
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class ColorUtils {
+ public static final int RED = 0;
+ public static final int ORANGE = 1;
+ public static final int YELLOW = 2;
+ public static final int GREEN = 3;
+ public static final int CYAN = 4;
+ public static final int BLUE = 5;
+ public static final int MAGENTA = 6;
+ public static final int GRAY = 7;
+
+ private static final Color[] rainbow = new Color[] { Color.RED, Color.ORANGE, Color.YELLOW, Color.GREEN, Color.CYAN,
+ Color.BLUE, Color.MAGENTA,Color.GRAY };
+
+ private static int nextColor = 0;
+
+ private ColorUtils() {// default private constr
+ }
+
+ public static int nextColorCode() {
+ return nextColor++;
+ }
+
+ public static Color nextRainbowColor() {// 返回下一个彩虹色
+ if (nextColor == rainbow.length)
+ nextColor = 0;
+ return rainbow[nextColor++];
+ }
+
+ public static Color colorByCode(int i) {// 数值取模后返回一个固定彩虹色
+ return rainbow[i % rainbow.length];
+ }
+
+ public static Color rainbowColor(float i) { // 根据数值大小范围,在8种彩虹色中取值
+ 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;
+ }
+}
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java
new file mode 100644
index 0000000..16f1999
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/FrogFileUtils.java
@@ -0,0 +1,141 @@
+/* Copyright 2018-2020 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.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * File Utilities used in this project
+ *
+ * @author Yong Zhu
+ * @since 1.0
+ */
+public class FrogFileUtils {
+
+ private FrogFileUtils() {
+ // default constructor
+ }
+
+ public static boolean deleteFile(String fileFullPath) {
+ File file = new File(fileFullPath);
+ return file.delete(); // NOSONAR
+ }
+
+ public static void writeFile(String fileFullPath, byte[] byteArry) {
+ File file = new File(fileFullPath);
+ if (!file.getParentFile().exists())
+ file.getParentFile().mkdirs();
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ fos.write(byteArry);
+ fos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static void writeFile(String fileFullPath, String text, String encoding) {
+ File file = new File(fileFullPath);
+ if (!file.getParentFile().exists())
+ file.getParentFile().mkdirs();
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ byte[] bytes;
+ bytes = text.getBytes(encoding);
+ fos.write(bytes);
+ fos.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static String readFile(String fileFullPath, String encoding) {
+ InputStream inputStream;
+ try {
+ inputStream = new FileInputStream(new File(fileFullPath));
+ } catch (FileNotFoundException e1) {
+ return null;
+ }
+ try {
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = inputStream.read(buffer)) != -1)
+ result.write(buffer, 0, length);
+ String string = result.toString(encoding);
+ return string;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ } finally {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ public static void appendFile(String fileName, String content) {
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(fileName, true);
+ fos.write(content.getBytes());
+ fos.write("\r\n".getBytes());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (fos != null) {
+ try {
+ try {
+ fos.flush();
+ } catch (Exception e) {
+ }
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+}
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/PixelsUtils.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/PixelsUtils.java
new file mode 100644
index 0000000..920d568
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/PixelsUtils.java
@@ -0,0 +1,39 @@
+/* Copyright 2018-2020 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.util;
+
+/**
+ * PixelUtils used to do some transform of pixel picture
+ *
+ * 针对给定的二维图像,进行一些变换, [0][0]是图像左下角素
+ *
+ * @author Yong Zhu
+ * @since 2.0.2
+ */
+public class PixelsUtils {
+
+ public static byte[][] offset(byte[][] pixels, int xOff, int yOff) {// 对图像进行xOff和yOff偏移变换
+ int w = pixels.length;
+ int h = pixels[0].length;
+ byte[][] result = new byte[w + Math.abs(xOff)][h + Math.abs(yOff)];
+ for (int y = 0; y < h + Math.abs(yOff); y++) {
+ for (int x = 0; x < w + Math.abs(xOff); x++) {
+ int newX = x - xOff;
+ int newY = y - yOff;
+ if (newX >= 0 && newX < w && newY >= 0 && newY < h && pixels[newX][newY] != 0)
+ result[x][y] = 1;
+ else
+ result[x][y] = 0;
+ }
+ }
+ return result;
+ }
+}
diff --git a/core3d/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java
similarity index 100%
rename from core3d/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java
rename to history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/RandomUtils.java
diff --git a/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/StringPixelUtils.java b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/StringPixelUtils.java
new file mode 100644
index 0000000..fda6766
--- /dev/null
+++ b/history/005_letter_test/src/main/java/com/github/drinkjava2/frog/util/StringPixelUtils.java
@@ -0,0 +1,88 @@
+/* Copyright 2018-2020 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.util;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * StringPixelUtils used to get pixel array from a given string
+ *
+ * 根据给定的字体和字符串,返回它的像素点阵,lettersMap[0][0]是左下角素
+ *
+ * @author Yong Zhu
+ * @since 2.0.2
+ */
+public class StringPixelUtils {
+ private static final Map lettersMap = new HashMap<>();
+
+ public static byte[][] getSanserif10Pixels(String s) {
+ return getStringPixels(Font.SANS_SERIF, Font.PLAIN, 10, s);
+ }
+
+ public static byte[][] getSanserif12Pixels(String s) {
+ return getStringPixels(Font.SANS_SERIF, Font.PLAIN, 12, s);
+ }
+
+ public static byte[][] getSanserifItalic10Pixels(String s) {
+ return getStringPixels(Font.SANS_SERIF, Font.ITALIC, 10, s);
+ }
+
+ /* 在内存 BufferedImage里输出文本并获取它的像素点 */
+ public static byte[][] getStringPixels(String fontName, int fontStyle, int fontSize, String s) {
+ String key = new StringBuilder(fontName).append("_").append(fontStyle).append("_").append(fontSize).append("_")
+ .append(s).toString();
+ if (lettersMap.containsKey(key))
+ return lettersMap.get(key);
+ Font font = new Font(fontName, fontStyle, fontSize);
+
+ BufferedImage bi = new BufferedImage(fontSize * 10, fontSize * 50, BufferedImage.TYPE_INT_RGB);
+ Graphics g = bi.getGraphics();
+ Graphics2D g2d = (Graphics2D) g;
+ 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);
+ byte[][] b = new byte[strWidth][strHeight];
+ for (int y = 0; y < strHeight; y++)
+ for (int x = 0; x < strWidth; x++)
+ if (bi.getRGB(x, y) == -1)
+ b[x][strHeight - y - 1] = 1;
+ else
+ b[x][strHeight - y - 1] = 0;
+ lettersMap.put(key, b);
+ return b;
+ }
+
+ /*- 这个是测试输出,平时不需要用
+ public static void main(String[] args) {
+ byte[][] 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] > 0)
+ System.out.print("*");
+ else
+ System.out.print(" ");
+ }
+ System.out.println();
+ }
+ }
+ */
+}
diff --git a/版本提交记录.md b/版本提交记录.md
index dd077a4..8028df7 100644
--- a/版本提交记录.md
+++ b/版本提交记录.md
@@ -1,8 +1,9 @@
-## 版本提交记录(只记录重要更新)
+## 版本提交记录(只记录重要更新)
-如果想要运行Frog项目的以前版本,可以结合gitk命令和参考本提交记录对每个更新的简介,用git reset命令回复到以前任一个版本,例如用:
-git reset --hard ae34b07e 可以转回到2019-08-04提交的分组测试的找食版本。
+在history目录里存放着比较重大的历史版本,可以直接运行这些子目录里的run.bat进行演示。
+如果想要回到Frog项目的以前任一个提交,可以结合gitk命令和参考本提交记录对每个更新的简介,用git reset命令回复到以前任一个提交版本,例如用:
+git reset --hard ae34b07e 可以转回到2019-08-04提交的分组测试的找食版本。
### 2018-1-3
@@ -186,3 +187,6 @@ T:顶视 F:前视 L:左视 R:右视 X:斜视 方向键:剖视 空格:
### 2019-11-26 commit: Chinese test
这次更新用汉字"对酒当歌人生几何"来测试模式识别,优化了一下程序,目前这个图像识别基本没有容错性,图像像素多的会干拢像素少的文字的识别。下面考虑拉大听力信号间隔,以及引入侧抑制等机制(如果一个洞中砸进了光子,但是却和这个洞不同向,有可能产生负值的反向光子,这个负值与角度差有关),这和算法上的侧抑制很象,世界上的道理都是相通的。以后算法上的卷积、深度学习等现成的成果,也可以考虑融入进来,用图形化表示。反过来说,目前以算法进行的神经网络研究,如果借签这个项目的基本思路,把输入输出器官和适应环境进化做为重点,采用遗传淘汰的方式调整算法架构本身,尽量减少人为的设计,最后达到的行为表现可能和这个人工生命项目是一致的。我走图形化是没办法,因为基础差,但是精通算法的人如果明白我的意思,也可能很快做出表现比较复杂的人工生命来,毕竟算法研究已经到了很高的水平了,是现成的。
+
+### 2019-12-05 commit: add history folder
+重整理了一下目录,将当前工作版本放在core目录下, 比较重大的历史版本放在history目录下,以方便初学者直接运行各个历史版本,而不需要使用git reset命令去手工回到以前的历史版本。同时,如果有未完成的子功能研究(如模式识别,见005_letter_test目录),也可以开一个子目录在history里,以后有时间再去慢慢研究这个子功能。