mirror of
https://gitee.com/drinkjava2/frog.git
synced 2024-11-25 16:04:06 +08:00
Go one way
This commit is contained in:
parent
0d112e2256
commit
1d9dd6ebd9
@ -27,12 +27,10 @@ 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;
|
||||
import com.github.drinkjava2.frog.env.Food;
|
||||
|
||||
/**
|
||||
* Frog = brain + body(mouth, eye, leg), but now let's focus on brain, ignore
|
||||
* body
|
||||
*
|
||||
* 为了简化模型,这个类里出现多个固定数值的编码,以后要改进成可以可以放在蛋里遗传进化的动态数值,先让生命延生是第一步,优化是以后的事
|
||||
* Frog = brain + body(mouth, eye, leg)
|
||||
*
|
||||
* @author Yong Zhu
|
||||
* @since 1.0.0
|
||||
@ -45,8 +43,8 @@ public class Frog {
|
||||
/** brain cells */
|
||||
List<Cell> cells = new ArrayList<Cell>();
|
||||
|
||||
/** 视觉细胞的输入区在脑中的坐标,先随便取 在原点附件就可以了,分瓣率为60x60, 以后再考虑放到蛋里去进化 */
|
||||
public static int eyeRadius = Math.round(30);
|
||||
/** 视觉细胞的输入区在脑中的坐标,先随便取 在原点附件就可以了,以后再考虑放到蛋里去进化 */
|
||||
public static Zone eye = new Zone(0, 0, 300);
|
||||
|
||||
/** 运动细胞的输入区在脑中的坐标,先随便取就可以了,以后再考虑放到蛋里去进化 */
|
||||
public static Zone moveUp = new Zone(500, 100, 10);
|
||||
@ -56,7 +54,7 @@ public class Frog {
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
public long energy = Env.STEPS_PER_ROUND;
|
||||
public long energy = 10000;
|
||||
public Egg egg;
|
||||
|
||||
static final Random r = new Random();
|
||||
@ -82,14 +80,12 @@ public class Frog {
|
||||
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;
|
||||
}
|
||||
@ -100,64 +96,43 @@ public class Frog {
|
||||
}
|
||||
|
||||
public void active(Env env) {
|
||||
// 每个step即使啥都不干,也要消耗能量
|
||||
energy--;
|
||||
|
||||
// 如果青蛙位置与food重合,吃掉它
|
||||
// this.x = this.x - 1 + r.nextInt(3);
|
||||
// this.y = this.y - 1 + r.nextInt(3);
|
||||
// eat 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,能量境加
|
||||
int j = env.foods.size() - 1;
|
||||
for (int i = j; i >= 0; i--) {
|
||||
Food food = env.foods.get(i);
|
||||
if (x == food.x && y == food.y) {
|
||||
energy = energy + food.energy;
|
||||
env.foods.remove(i);
|
||||
eatedFood = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 吃掉food有奖励
|
||||
// 奖励
|
||||
if (eatedFood) {
|
||||
|
||||
}
|
||||
|
||||
// move
|
||||
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)) {
|
||||
if (Zone.nearby(moveUp, output)) {
|
||||
y += 1;
|
||||
}
|
||||
if (moveDown.nearby(output)) {
|
||||
break;
|
||||
} else if (Zone.nearby(moveDown, output)) {
|
||||
y -= 1;
|
||||
|
||||
}
|
||||
if (moveLeft.nearby(output)) {
|
||||
break;
|
||||
} else if (Zone.nearby(moveLeft, output)) {
|
||||
x -= 1;
|
||||
}
|
||||
if (moveRight.nearby(output)) {
|
||||
break;
|
||||
} else if (Zone.nearby(moveRight, output)) {
|
||||
x += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// 即使什么也不干,output的能量总在以95%的速度下降
|
||||
output.energy *= 0.95;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,7 +156,7 @@ public class Frog {
|
||||
}
|
||||
|
||||
public Egg layEgg() {
|
||||
if (r.nextInt(100) > 75) // 变异率先固定在75%
|
||||
if (r.nextInt(100) > 25) // 变异率先固定在25%
|
||||
allowVariation = false;// 如果不允许变异,下的蛋就相当于克隆原来的蛋
|
||||
else
|
||||
allowVariation = true;
|
||||
|
@ -18,13 +18,17 @@ package com.github.drinkjava2.frog.brain;
|
||||
*/
|
||||
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 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 boolean used = false;
|
||||
|
||||
public void activateOutputs() {
|
||||
for (Output output : outputs)
|
||||
output.energy += 55;
|
||||
}
|
||||
public void activate() {
|
||||
used = true;
|
||||
for (Input xy : inputs) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -20,5 +20,4 @@ import com.github.drinkjava2.frog.egg.Zone;
|
||||
*/
|
||||
public class Input extends Zone{
|
||||
public float energy;
|
||||
public Cell cell;
|
||||
}
|
||||
|
@ -20,5 +20,4 @@ import com.github.drinkjava2.frog.egg.Zone;
|
||||
*/
|
||||
public class Output extends Zone {
|
||||
public float energy;
|
||||
public Cell cell;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import java.util.Random;
|
||||
public class Egg implements Serializable {
|
||||
private static final long serialVersionUID = 2L;
|
||||
public static final int CELL_GROUP_QTY = 30;
|
||||
public float brainRadius = 100;
|
||||
public float brainRadius = 1000;
|
||||
public CellGroup[] cellgroups;
|
||||
|
||||
public static Egg createBrandNewEgg() {
|
||||
@ -38,9 +38,9 @@ public class Egg implements Serializable {
|
||||
(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.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);
|
||||
}
|
||||
|
@ -34,21 +34,13 @@ public class Zone implements Serializable {
|
||||
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)
|
||||
public static boolean nearby(Zone z1, Zone z2) {
|
||||
float dist = z1.radius + z2.radius;
|
||||
if (Math.abs(z1.x - z2.x) < dist && Math.abs(z1.y - z2.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;
|
||||
|
@ -18,7 +18,7 @@ import com.github.drinkjava2.frog.util.EggTool;
|
||||
@SuppressWarnings("serial")
|
||||
public class Env extends JPanel {
|
||||
/** Speed of test */
|
||||
public static int SHOW_SPEED = 100;
|
||||
public static int SHOW_SPEED = 10;
|
||||
|
||||
/** Steps of one test round */
|
||||
public static int STEPS_PER_ROUND = 1000;
|
||||
@ -29,13 +29,12 @@ public class Env extends JPanel {
|
||||
/** 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 = 2500; // as name
|
||||
|
||||
public int FOOD_QTY =6000; // as name
|
||||
|
||||
public int EGG_QTY = 2; // as name
|
||||
public int EGG_QTY = 10; // as name
|
||||
|
||||
public List<Frog> frogs = new ArrayList<Frog>();
|
||||
public List<Food> foods = new ArrayList<Food>();
|
||||
public List<Egg> eggs;
|
||||
|
||||
public Env() {
|
||||
@ -46,27 +45,16 @@ public class Env extends JPanel {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
foods.clear();
|
||||
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 < eggs.size(); i++) { // 1个Egg生出4个Frog
|
||||
frogs.add(new Frog(rand.nextInt(ENV_XSIZE - 3), rand.nextInt(ENV_YSIZE - 3), eggs.get(i)));
|
||||
frogs.add(new Frog(rand.nextInt(ENV_XSIZE - 3), rand.nextInt(ENV_YSIZE - 3), eggs.get(i)));
|
||||
frogs.add(new Frog(rand.nextInt(ENV_XSIZE - 3), rand.nextInt(ENV_YSIZE - 3), eggs.get(i)));
|
||||
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);
|
||||
}
|
||||
foods.add(new Food(rand.nextInt(ENV_XSIZE - 3), rand.nextInt(ENV_YSIZE - 3)));
|
||||
}
|
||||
|
||||
public void run() throws InterruptedException {
|
||||
@ -84,8 +72,8 @@ public class Env extends JPanel {
|
||||
Graphics g = buffImg.getGraphics();
|
||||
for (Frog frog : frogs)
|
||||
frog.show(g);
|
||||
|
||||
drawFood(g);
|
||||
for (Food food : foods)
|
||||
food.show(g);
|
||||
Graphics g2 = this.getGraphics();
|
||||
g2.drawImage(buffImg, 0, 0, this);
|
||||
Thread.sleep(10);
|
||||
|
23
core/src/main/java/com/github/drinkjava2/frog/env/Food.java
vendored
Normal file
23
core/src/main/java/com/github/drinkjava2/frog/env/Food.java
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
package com.github.drinkjava2.frog.env;
|
||||
|
||||
import java.awt.Graphics;
|
||||
|
||||
/**
|
||||
* Food is food for frogs, one food = 500 unit energy
|
||||
*/
|
||||
public class Food {
|
||||
public int energy = 500;
|
||||
|
||||
public int x;
|
||||
|
||||
public 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);
|
||||
}
|
||||
}
|
@ -35,31 +35,35 @@ public class EggTool {
|
||||
|
||||
public static final boolean JSON_FILE_FORMAT = false; // JSON is slow but easier to debug
|
||||
|
||||
public static void layEggs(Env env) {
|
||||
if (JSON_FILE_FORMAT)
|
||||
layJsonEggs(env);
|
||||
else
|
||||
laySerializedEggs(env);
|
||||
}
|
||||
|
||||
public static void loadEggs(Env env) {
|
||||
if (JSON_FILE_FORMAT)
|
||||
loadJsonEggs(env);
|
||||
else
|
||||
loadSerializedEggs(env);
|
||||
}
|
||||
|
||||
/**
|
||||
* 利用Java串行机制存盘。 能量多(也就是吃的更多,更fat)的Frog下蛋并存盘, 以进行下一伦测试,能量少的Frog被淘汰,没有下蛋的资格。
|
||||
*/
|
||||
public static void layEggs(Env env) {
|
||||
public static void laySerializedEggs(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++)
|
||||
for (int i = 0; i < env.frogs.size() / 4; 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();
|
||||
}
|
||||
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" + "'");
|
||||
@ -68,11 +72,27 @@ public class EggTool {
|
||||
}
|
||||
}
|
||||
|
||||
/** 类似laySerializedEggs方法,但是存为JSON格式 ,以方便调试 */
|
||||
public static void layJsonEggs(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 + ", ");
|
||||
List<Egg> newEggs = new ArrayList<Egg>();
|
||||
for (int i = 0; i < env.frogs.size() / 4; i++)
|
||||
newEggs.add(env.frogs.get(i).layEgg());
|
||||
String newEggsString = JSON.toJSONString(newEggs);
|
||||
FrogFileUtils.writeFile(Application.CLASSPATH + "eggs.json", newEggsString, "utf-8");
|
||||
env.eggs = newEggs;
|
||||
System.out.println("Saved " + env.eggs.size() + " eggs to file '" + Application.CLASSPATH + "eggs.json" + "'");
|
||||
}
|
||||
|
||||
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)
|
||||
if (a.energy > b.energy)
|
||||
return -1;
|
||||
else if (a.energy == b.energy)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
@ -83,41 +103,44 @@ public class EggTool {
|
||||
* 从磁盘读入一批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.");
|
||||
public static void loadSerializedEggs(Env env) {
|
||||
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) {
|
||||
System.out.println("No eggs files ' " + Application.CLASSPATH + "eggs.ser" + "' 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());
|
||||
}
|
||||
}
|
||||
|
||||
/** 类似loadSerializedEggs方法,但是读取的是JSON格式,以方便调试 */
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void loadJsonEggs(Env env) {
|
||||
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 {
|
||||
System.out.println("No eggs files ' " + Application.CLASSPATH + "eggs.json" + "' 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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user