mirror of
https://gitee.com/drinkjava2/frog.git
synced 2024-11-25 16:04:06 +08:00
stuck, need improve speed
This commit is contained in:
parent
4a1c0fd630
commit
0efc6b9021
29
.gitignore
vendored
29
.gitignore
vendored
@ -1,19 +1,20 @@
|
||||
# Bat files
|
||||
*.bat
|
||||
/build/
|
||||
target/
|
||||
bin/
|
||||
.project
|
||||
.classpath
|
||||
.settings/
|
||||
*~
|
||||
*.orig
|
||||
*.new
|
||||
.idea/
|
||||
*.iml
|
||||
*.ipr
|
||||
test/**/build/
|
||||
examples/**/build/
|
||||
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
@ -21,5 +22,5 @@
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
# virtual machine crash logs
|
||||
hs_err_pid*
|
||||
|
1
command.bat
Normal file
1
command.bat
Normal file
@ -0,0 +1 @@
|
||||
cmd
|
BIN
core/frog.png
BIN
core/frog.png
Binary file not shown.
Before Width: | Height: | Size: 930 B |
@ -57,6 +57,14 @@
|
||||
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- For JSON translate -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.54</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
3
core/run.bat
Normal file
3
core/run.bat
Normal file
@ -0,0 +1,3 @@
|
||||
cd target\classes
|
||||
java -classpath ".;*" com.github.drinkjava2.frog.env.Application
|
||||
@pause
|
@ -1,23 +0,0 @@
|
||||
package com.github.drinkjava2.env;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
/**
|
||||
* Application will build env, frogs and let them run
|
||||
*/
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
JFrame frame = new JFrame();
|
||||
frame.setLayout(null);
|
||||
frame.setSize(Env.XSIZE + 220, Env.YSIZE + 250); // 窗口大小
|
||||
frame.setTitle("Stage#1: First Artifical Life"); // 标题
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭时退出程序
|
||||
|
||||
Env env = new Env();
|
||||
frame.add(env);
|
||||
frame.setVisible(true);
|
||||
env.run();
|
||||
}
|
||||
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
package com.github.drinkjava2.env;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.swing.JButton;
|
||||
|
||||
import com.github.drinkjava2.frog.Frog;
|
||||
|
||||
/**
|
||||
* Env is the living space of frog. Use Java Swing to drawing the environment.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class Env extends JButton {
|
||||
/** Metric width is 500 pixels */
|
||||
public static final int XSIZE = 300;
|
||||
|
||||
/** Metric height is 500 pixels */
|
||||
public static final int YSIZE = 300;
|
||||
|
||||
public int frogAmount = 10;
|
||||
public int foodAmount = 500;
|
||||
|
||||
public List<Frog> frogs = new ArrayList<Frog>();
|
||||
public List<Food> foods = new ArrayList<Food>();
|
||||
|
||||
public Env() {
|
||||
super();
|
||||
this.setLayout(null);// 空布局
|
||||
this.setBounds(100, 100, XSIZE, YSIZE);
|
||||
Random rand = new Random();
|
||||
for (int i = 0; i < frogAmount; i++)
|
||||
frogs.add(new Frog(rand.nextInt(Env.XSIZE - 3), rand.nextInt(Env.YSIZE - 3)));
|
||||
for (int i = 0; i < foodAmount; i++)
|
||||
foods.add(new Food(rand.nextInt(Env.XSIZE - 3), rand.nextInt(Env.YSIZE - 3)));
|
||||
}
|
||||
|
||||
public void eatFoods() {
|
||||
eating = true;
|
||||
for (Frog frog : frogs) {
|
||||
int j = foods.size() - 1;
|
||||
for (int i = j; i >= 0; i--) {
|
||||
Food food = foods.get(i);
|
||||
if (frog.x == food.x && frog.y == food.y)
|
||||
foods.remove(i);
|
||||
}
|
||||
}
|
||||
eating = false;
|
||||
}
|
||||
|
||||
static boolean eating = true;
|
||||
|
||||
public void run() throws InterruptedException {
|
||||
Random r = new Random();
|
||||
int count = 0;
|
||||
do {
|
||||
count++;
|
||||
for (Frog frog : frogs) {
|
||||
frog.x += r.nextInt(3) - 1;
|
||||
frog.y += r.nextInt(3) - 1;
|
||||
}
|
||||
eatFoods();
|
||||
if (count % 50 != 0)
|
||||
continue;
|
||||
Image buffImg = createImage(this.getWidth(), this.getHeight());
|
||||
Graphics g = buffImg.getGraphics();
|
||||
for (Frog frog : frogs)
|
||||
frog.show(g);
|
||||
for (Food food : foods)
|
||||
food.show(g);
|
||||
Graphics g2 = this.getGraphics();
|
||||
g2.drawImage(buffImg, 0, 0, this);
|
||||
Thread.sleep(10);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package com.github.drinkjava2.env;
|
||||
|
||||
import java.awt.Graphics;
|
||||
|
||||
/**
|
||||
* Food is food for frogs, one food = 100 unit energy
|
||||
*/
|
||||
public class Food {
|
||||
int x;
|
||||
|
||||
int y;
|
||||
|
||||
public Food(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public void show(Graphics g) {
|
||||
g.fillOval(x, y, 4, 4);
|
||||
}
|
||||
}
|
@ -12,46 +12,202 @@ package com.github.drinkjava2.frog;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.io.File;
|
||||
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.Brain;
|
||||
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)
|
||||
* 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<Cell> cells = new ArrayList<Cell>();
|
||||
|
||||
/** 视觉细胞的输入区在脑中的坐标,先随便取 在原点附件就可以了,分瓣率为60x60, 以后再考虑放到蛋里去进化 */
|
||||
public static int eyeRadius = Math.round(30);
|
||||
|
||||
/** 运动细胞的输入区在脑中的坐标,先随便取就可以了,以后再考虑放到蛋里去进化 */
|
||||
public static Zone moveUp = new Zone(500, 100, 10);
|
||||
public static Zone moveDown = new Zone(500, 200, 10);
|
||||
public static Zone moveLeft = new Zone(500, 300, 10);
|
||||
public static Zone moveRight = new Zone(500, 400, 10);
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
public int face = 1 + new Random().nextInt(4); // 0:sleep 1:up 2:right 3:down 4:left 5:right
|
||||
public int move = 0; // 0: stop 1:up 2:right 3:down 4:left 5:right turn 6 left turn
|
||||
public long energy = 10000;
|
||||
public long energy = Env.STEPS_PER_ROUND;
|
||||
public Egg egg;
|
||||
|
||||
static final Random r = new Random();
|
||||
static Image frogImg;
|
||||
static {
|
||||
try {
|
||||
frogImg = ImageIO.read(new FileInputStream(new File("").getAbsolutePath() + "/frog.png"));
|
||||
frogImg = ImageIO.read(new FileInputStream(Application.CLASSPATH + "frog.png"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Brain brain;
|
||||
|
||||
public Frog(int x, int y) {
|
||||
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;// 保留一份蛋,如果没被淘汰掉,将来下蛋时要用这个蛋来下新蛋
|
||||
}
|
||||
|
||||
public void show(Graphics g) {
|
||||
g.drawLine(x, y-2, x, y+2);
|
||||
g.drawImage(frogImg, x - 16, y - 16, 32, 32, null);
|
||||
public void active(Env env) {
|
||||
// 每个step即使啥都不干,也要消耗能量
|
||||
energy--;
|
||||
|
||||
// 如果青蛙位置与food重合,吃掉它
|
||||
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;
|
||||
}
|
||||
|
||||
// 吃掉food有奖励
|
||||
if (eatedFood) {
|
||||
|
||||
}
|
||||
|
||||
for (Cell cell : cells) {
|
||||
// 输入部分
|
||||
for (Input input : cell.inputs) {
|
||||
// 如果食物出现在视觉区,激活对应frog视觉区的输入触突
|
||||
if (input.x > (-eyeRadius) && input.y > (-eyeRadius) && input.x < eyeRadius && input.y < eyeRadius) {
|
||||
int xx = x + input.roundX();
|
||||
int yy = y + input.roundY();
|
||||
if (xx > 0 && xx < env.ENV_XSIZE && yy > 0 && yy < env.ENV_YSIZE && env.foods[xx][yy] > 0)
|
||||
input.energy += 500;
|
||||
}
|
||||
|
||||
// 如果任意输入触突激活,增加对应细胞的输出区激活
|
||||
if (input.energy > 50)
|
||||
cell.activateOutputs();
|
||||
|
||||
// 即使什么也不干,input的能量总在以95%的速度下降
|
||||
input.energy *= .95;
|
||||
}
|
||||
|
||||
// 如果输出触突位于运动区且兴奋,则frog移动一个单位
|
||||
for (Output output : cell.outputs) {
|
||||
// if (output.energy < 30)
|
||||
// continue;
|
||||
if (moveUp.nearby(output)) {
|
||||
y += 1;
|
||||
}
|
||||
if (moveDown.nearby(output)) {
|
||||
y -= 1;
|
||||
|
||||
}
|
||||
if (moveLeft.nearby(output)) {
|
||||
x -= 1;
|
||||
}
|
||||
if (moveRight.nearby(output)) {
|
||||
x += 1;
|
||||
}
|
||||
|
||||
// 即使什么也不干,output的能量总在以95%的速度下降
|
||||
output.energy *= 0.95;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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) > 75) // 变异率先固定在75%
|
||||
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) {
|
||||
g.drawImage(frogImg, x - 8, y - 8, 16, 16, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,21 +11,20 @@
|
||||
package com.github.drinkjava2.frog.brain;
|
||||
|
||||
/**
|
||||
* Cell represents a brain nerve cell, this is the basic unit of 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 x;
|
||||
public int y;
|
||||
public int active;
|
||||
public int drop;
|
||||
public int inX;
|
||||
public int inY;
|
||||
public int inSize;
|
||||
public int outX;
|
||||
public int outY;
|
||||
public int outSize;
|
||||
public int fat;
|
||||
public int group; // this cell belong to which group?
|
||||
public Input[] inputs; // inputs of cell
|
||||
public Output[] outputs; // outputs of cell
|
||||
public boolean used = false;
|
||||
|
||||
public void activateOutputs() {
|
||||
for (Output output : outputs)
|
||||
output.energy += 55;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,11 +8,17 @@
|
||||
* 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;
|
||||
package com.github.drinkjava2.frog.brain;
|
||||
|
||||
import com.github.drinkjava2.frog.egg.Zone;
|
||||
|
||||
/**
|
||||
* Egg is the static description of frog, can save as text file
|
||||
* Input is the sensor of nerve cell
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class Egg {
|
||||
|
||||
public class Input extends Zone{
|
||||
public float energy;
|
||||
public Cell cell;
|
||||
}
|
@ -10,33 +10,15 @@
|
||||
*/
|
||||
package com.github.drinkjava2.frog.brain;
|
||||
|
||||
import com.github.drinkjava2.frog.egg.Zone;
|
||||
|
||||
/**
|
||||
* Brain is consisted by lots of cells
|
||||
* Output can active other nerve cell's input
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class Brain {
|
||||
/** Brain dimension X is 10000 cells */
|
||||
private int xSize = 10000;
|
||||
|
||||
/** Brain dimension Y is 100 cells */
|
||||
private int ySize = 1000;
|
||||
|
||||
/** Brain dimension Z is 10 cells */
|
||||
private int zSize = 10;
|
||||
|
||||
/** cells in brain */
|
||||
public Cell[][][] cells;
|
||||
|
||||
public Brain() {
|
||||
cells = new Cell[xSize][ySize][zSize];
|
||||
}
|
||||
|
||||
public Brain(int xSize, int ySize, int zSize) {
|
||||
this.xSize = xSize;
|
||||
this.ySize = ySize;
|
||||
this.zSize = zSize;
|
||||
cells = new Cell[xSize][ySize][zSize];
|
||||
}
|
||||
public class Output extends Zone {
|
||||
public float energy;
|
||||
public Cell cell;
|
||||
}
|
@ -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 <br/>
|
||||
*
|
||||
* 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
|
||||
}
|
50
core/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
Normal file
50
core/src/main/java/com/github/drinkjava2/frog/egg/Egg.java
Normal file
@ -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.<br/>
|
||||
*
|
||||
* 蛋存在的目的是为了以最小的字节数串行化存储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 = 100;
|
||||
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(30);
|
||||
cellGroup.cellInputRadius = (float) (r.nextFloat());
|
||||
cellGroup.cellOutputRadius = (float) (r.nextFloat() );
|
||||
cellGroup.inputQtyPerCell = r.nextInt(10);
|
||||
cellGroup.outputQtyPerCell = r.nextInt(5);
|
||||
}
|
||||
return egg;
|
||||
}
|
||||
|
||||
}
|
56
core/src/main/java/com/github/drinkjava2/frog/egg/Zone.java
Normal file
56
core/src/main/java/com/github/drinkjava2/frog/egg/Zone.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
30
core/src/main/java/com/github/drinkjava2/frog/env/Application.java
vendored
Normal file
30
core/src/main/java/com/github/drinkjava2/frog/env/Application.java
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
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("core");
|
||||
CLASSPATH = classpath.substring(0, core);
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
96
core/src/main/java/com/github/drinkjava2/frog/env/Env.java
vendored
Normal file
96
core/src/main/java/com/github/drinkjava2/frog/env/Env.java
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
package com.github.drinkjava2.frog.env;
|
||||
|
||||
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 = 100;
|
||||
|
||||
/** Steps of one test round */
|
||||
public static int STEPS_PER_ROUND = 1000;
|
||||
|
||||
/** 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 =6000; // as name
|
||||
|
||||
public int EGG_QTY = 2; // as name
|
||||
|
||||
public List<Frog> frogs = new ArrayList<Frog>();
|
||||
public List<Egg> eggs;
|
||||
|
||||
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++) {
|
||||
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生出10个Frog
|
||||
for (int j = 0; j < 10; j++) {
|
||||
frogs.add(new Frog(rand.nextInt(ENV_XSIZE - 3), rand.nextInt(ENV_YSIZE - 3), eggs.get(i)));
|
||||
}
|
||||
}
|
||||
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;
|
||||
do {
|
||||
Application.mainFrame.setTitle("Frog test round: " + round++);
|
||||
rebuildFrogAndFood();
|
||||
for (int i = 0; i < STEPS_PER_ROUND; i++) {
|
||||
for (Frog frog : frogs)
|
||||
frog.active(this);
|
||||
if (i % SHOW_SPEED != 0) // 显示会拖慢速度
|
||||
continue;
|
||||
Image buffImg = createImage(this.getWidth(), this.getHeight());
|
||||
Graphics g = buffImg.getGraphics();
|
||||
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);
|
||||
} while (true);
|
||||
}
|
||||
}
|
123
core/src/main/java/com/github/drinkjava2/frog/util/EggTool.java
Normal file
123
core/src/main/java/com/github/drinkjava2/frog/util/EggTool.java
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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<Egg> newEggs = new ArrayList<Egg>();
|
||||
for (int i = 0; i < env.frogs.size() / 10; 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<Frog>() {
|
||||
public int compare(Frog a, Frog b) {
|
||||
if (a.energy >= b.energy)
|
||||
return -1;
|
||||
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<JSONObject> jsonEggs = (List<JSONObject>) JSON.parse(eggsString);
|
||||
env.eggs = new ArrayList<Egg>();
|
||||
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<Egg>) eggsInputStream.readObject();
|
||||
System.out.println(
|
||||
"Loaded " + env.eggs.size() + " eggs from file '" + Application.CLASSPATH + "eggs.ser" + "'.");
|
||||
eggsInputStream.close();
|
||||
} catch (Exception e) {
|
||||
errorfound = true;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (errorfound) {
|
||||
System.out.println("No eggs files ' " + Application.CLASSPATH + " found, created " + env.EGG_QTY
|
||||
+ " new eggs to do test.");
|
||||
env.eggs = new ArrayList<Egg>();
|
||||
for (int i = 0; i < env.EGG_QTY; i++)
|
||||
env.eggs.add(Egg.createBrandNewEgg());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
/* 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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user