Reorganized, no weight

pull/1/head
Yong Zhu 6 years ago
parent 0bc599c46d
commit d47385fd16

@ -21,7 +21,7 @@ import com.github.drinkjava2.frog.egg.EggTool;
@SuppressWarnings("serial")
public class Env extends JPanel {
/** Speed of test */
public static final int SHOW_SPEED = 80; // 测试速度1~1000,可调, 数值越小,速度越慢
public static final int SHOW_SPEED = 1; // 测试速度1~1000,可调, 数值越小,速度越慢
public static final int ENV_WIDTH = 400; // 虚拟环境的宽度, 可调
@ -40,6 +40,8 @@ public class Env extends JPanel {
/** Delete eggs at beginning of each run */
public static final boolean DELETE_EGGS = false;// 每次运行是否先删除保存的蛋
public static final boolean DEBUG_MODE = false; // Debug 模式下会打印出更多的调试信息
static {
if (DELETE_EGGS)
EggTool.deleteEggs();
@ -53,7 +55,7 @@ public class Env extends JPanel {
public static boolean pause = false; // 暂停按钮按下将暂停测试
public static final boolean[][] foods = new boolean[ENV_WIDTH][ENV_HEIGHT];// 食物数组定义
private static final boolean[][] foods = new boolean[ENV_WIDTH][ENV_HEIGHT];// 食物数组定义
public List<Frog> frogs = new ArrayList<>();
@ -65,6 +67,26 @@ public class Env extends JPanel {
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 foundFood(int x, int y) {
return !(x < 0 || y < 0 || x >= ENV_WIDTH || y >= ENV_HEIGHT) && Env.foods[x][y];
}
public static boolean foundAndDeleteFood(int x, int y) {// 如果x,y有食物将其清0返回true
if (foundFood(x, y)) {
foods[x][y] = false;
return true;
}
return false;
}
private void rebuildFrogAndFood() {
frogs.clear();
for (int i = 0; i < ENV_WIDTH; i++) {// 清除食物
@ -124,7 +146,7 @@ public class Env extends JPanel {
for (int i = 0; i < STEPS_PER_ROUND; i++) {
if (allDead) {
System.out.println("All dead at round:" + i);
break; // 全死光了就直接跳到下一轮,以节省时间
break; // 青蛙全死光了就直接跳到下一轮,以节省时间
}
allDead = true;
for (Frog frog : frogs)

@ -15,43 +15,35 @@ 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.brain.Zone;
import com.github.drinkjava2.frog.brain.group.RandomConnectGroup;
import com.github.drinkjava2.frog.egg.Egg;
/**
* Frog = brain + organ, but now let's only focus on brain, organs are hard
* coded in egg
* Frog = organs + brain cells
*
*
* Group
*
* @author Yong Zhu
* @since 1.0
*/
public class Frog {
public RandomConnectGroup[] cellGroups;
/** brain cells */
public List<Cell> cells = new ArrayList<>();
/** organs */
public List<Organ> 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表示青蛙死掉了将不参与任何计算和显示,以节省时间
public int x; // frog在Env中的x坐标
public int y; // frog在Env中的y坐标
public long frogEngery = 100000; // 能量为0则死掉
public boolean alive = true; // 设为false表示青蛙死掉了将不参与计算和显示,以节省时间
static final Random r = new Random();
static Image frogImg;
static {
try {
@ -64,62 +56,36 @@ public class Frog {
public Frog(int x, int y, Egg egg) {
this.x = x;
this.y = y;
// Brain cells
if (egg.cellGroups != null) {
cellGroups = new RandomConnectGroup[egg.cellGroups.length];
for (int k = 0; k < egg.cellGroups.length; k++) {
RandomConnectGroup g = egg.cellGroups[k];
cellGroups[k] = new RandomConnectGroup(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);
}
}
for (Organ org : egg.organs) {
organs.add(org);
org.init(this);// 每个新器官初始化如果是Group类它们会生成许多脑细胞
}
for (Organ org : egg.organs)
organs.add(org.newCopy());
}
public boolean active(Env v) {
energy -= 20;
if (!alive)
frogEngery -= 1;
if (!alive) {
frogEngery -= 50;// 死了需要消耗更多的能量,退出生存竞争
return false;
if (energy < 0) {
}
if (frogEngery < 0) { // 如果能量小于0则死
alive = false;
return false;
}
for (Organ o : organs)
// for (Cell cell1 : cells) {// 大脑主循环
// if (cell1.energy > 0)
// cell1.energy--;
// for (Input input : cell1.inputs) {
// // TODO
// }
// }
for (Organ o : organs) { // 调用每个Organ的active方法
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) {
public void show(Graphics g) {// 显示青蛙的图象
if (!alive)
return;
g.drawImage(frogImg, x - 8, y - 8, 16, 16, null);

@ -15,7 +15,6 @@ import javax.swing.JPanel;
import com.github.drinkjava2.frog.Application;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.group.RandomConnectGroup;
/**
* BrainPicture show first frog's brain structure, for debug purpose only
@ -36,30 +35,30 @@ public class BrainPicture extends JPanel {
this.setBounds(x, y, brainDispWidth + 1, brainDispWidth + 1);
}
void drawZone(Graphics g, Zone z) {
public 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);
int radius = Math.round(z.r * rate);
g.drawRect(x - radius, y - radius, radius * 2, radius * 2);
}
void drawCircle(Graphics g, Zone z) {
public 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) {
public 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);
int radius = Math.round(z.r * rate);
g.fillRect(x - radius, y - radius, radius * 2, radius * 2);
}
void drawLine(Graphics g, Zone z1, Zone z2) {
public 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);
@ -68,11 +67,11 @@ public class BrainPicture extends JPanel {
g.drawLine(x1, y1, x2, y2);
}
void drawText(Graphics g, Zone z, String text) {
public 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 - text.length() * 3, y);
g.drawString(text, x - text.length() * 3 - 2, y);
}
private static final Color[] rainbow = new Color[] { RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA };
@ -84,8 +83,10 @@ public class BrainPicture extends JPanel {
return rainbow[nextColor++];
}
private static Color color(float i) {
if (i <= 1)
public static Color color(float i) {
if (i == 0)
return Color.black;
if (i == 1)
return Color.RED;
if (i <= 3)
return Color.ORANGE;
@ -109,26 +110,7 @@ public class BrainPicture extends JPanel {
g.setColor(Color.black);
g.drawRect(0, 0, brainDispWidth, brainDispWidth);
for (Organ organ : frog.organs) {
g.setColor(Color.BLACK);
drawZone(g, organ);
if (organ.name != null)
drawText(g, organ, String.valueOf(organ.name));
}
for (RandomConnectGroup 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); // 如果胖了,表示激活过了,下次下蛋少不了这一组
}
}
for (Organ organ : frog.organs)
organ.drawOnBrainPicture(this); // each organ draw itself
}
}

@ -10,16 +10,25 @@
*/
package com.github.drinkjava2.frog.brain;
import com.github.drinkjava2.frog.brain.group.Group;
/**
* Cell is a brain nerve cell, this is the basic unit of frog's brain
* Cell 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;
// this cell belong to frog's which organ
public Group group;
// inputs of cell
public Input[] inputs; // 每个细胞有一组输入触突
// outputs of cell
public Output[] outputs; // 每个细胞有一组输出触突
// energy of cell, energy got from food
public long energy; // 每个细胞当前的能量值
}

@ -18,5 +18,9 @@ package com.github.drinkjava2.frog.brain;
*/
@SuppressWarnings("serial")
public class Input extends Zone {
public Cell cell;
public Cell cell; // 这个输入触突属于哪个脑细胞
public Input(Zone z) {
super(z);
}
}

@ -10,6 +10,9 @@
*/
package com.github.drinkjava2.frog.brain;
import java.awt.Color;
import java.awt.Graphics;
import com.github.drinkjava2.frog.Frog;
/**
@ -20,20 +23,23 @@ import com.github.drinkjava2.frog.Frog;
* @author Yong Zhu
* @since 1.0.4
*/
public class Organ extends Zone {
public abstract class Organ extends Zone {
private static final long serialVersionUID = 1L;
public String name; // 显示在脑图上的器官名称
public long fat = 0; // 如果细胞活跃多fat值高则保留以及变异的可能性大反之则舍弃掉
public int qtyLimit = 5; // 最多允许数量
public boolean inherit = false; // 器官是继承来的,还是变异来的,后者淘汰率会高
public String name; // 显示在脑图上的器官名称,可选
public long fat = 0; // 如果活跃多fat值高则保留及变异的可能性大反之则很可能丢弃掉
public boolean allowBorrow() { // 是否允许在精子中将这个器官借出
return false;
}
/** If active in this organ's zone? */
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;
cell.group.fat++;
cell.energy -= 1;
return true;
}
}
@ -41,8 +47,26 @@ public class Organ extends Zone {
return false;
}
/** Set X, Y, Radius, name of current Organ */
public Organ setXYRN(float x, float y, float r, String name) {
this.x = x;
this.y = y;
this.r = r;
this.name = name;
return this;
}
/** Child class can override this method to drawing picture */
public void drawOnBrainPicture(BrainPicture pic) {// 把自已这个器官在脑图上显示出来,子类可以重写这个方法
Graphics g = pic.getGraphics();// border
g.setColor(Color.BLACK); // 缺省是黑色
pic.drawZone(g, this);
if (this.name != null)
pic.drawText(g, this, String.valueOf(this.name));
}
/** make a new copy of current organ */
public Organ newCopy() { // 新建一份用于从蛋复制到Frog
public Organ newCopy() { // 创建一个当前器官的副本
Organ newOrgan = null;
try {
newOrgan = this.getClass().newInstance();
@ -55,29 +79,17 @@ public class Organ extends Zone {
}
}
/** Set X, Y, Radius of current Organ */
public Organ setXYR(float x, float y, float radius) {
this.x = x;
this.y = y;
this.radius = radius;
return this;
}
/** Set X, Y, Radius, name of current Organ */
public Organ setXYRN(float x, float y, float radius, String name) {
this.x = x;
this.y = y;
this.radius = radius;
this.name = name;
return this;
/** Only call once when frog created , Child class can override this method */
public void init(Frog f) { // 仅在Frog生成时这个方法会调用一次缺省啥也不干通常用于Group子类的初始化
}
/** Only call once when frog created , Child class can override this method */
public void init(Frog f) {
public Organ[] vary() { // 在下蛋时每个器官会调用这个方法缺省返回自已的副本Group类通常要覆盖这个方法
return new Organ[] { newCopy() };
}
/** Each loop step call active method, Child class can override this method */
public void active(Frog f) {
public void active(Frog f) { // 每一步都会调用器官的active方法 ,缺省啥也不干
}
}

@ -18,5 +18,9 @@ package com.github.drinkjava2.frog.brain;
*/
@SuppressWarnings("serial")
public class Output extends Zone {
public Cell cell;
public Cell cell; // 这个输出触突属于哪个脑细胞
public Output(Zone z) {
super(z);
}
}

@ -22,18 +22,19 @@ import com.github.drinkjava2.frog.Env;
*/
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 float r;// r为这个矩形区边长的一半
public Zone() {
// 空构造器不能省FastJSON实例化时要用到
// 空构造器不能省
}
public Zone(float x, float y, float radius) {
public Zone(float x, float y, float r) {
this.x = x;
this.y = y;
this.radius = radius;
this.r = r;
if (this.x < 0)
this.x = 0;
if (this.y < 0)
@ -47,11 +48,11 @@ public class Zone implements Serializable {
public Zone(Zone z) {
this.x = z.x;
this.y = z.y;
this.radius = z.radius;
this.r = z.r;
}
public boolean nearby(Zone z) {
float dist = radius + z.radius;
float dist = r + z.r;
return (Math.abs(x - z.x) < dist && Math.abs(y - z.y) < dist);
}
@ -71,6 +72,13 @@ public class Zone implements Serializable {
public static void copyXYR(Zone from, Zone to) {
to.x = from.x;
to.y = from.y;
to.radius = from.radius;
to.r = from.r;
}
public void setXYR(float x, float y, float r) {
this.x = x;
this.y = y;
this.r = r;
}
}

@ -10,6 +10,7 @@
*/
package com.github.drinkjava2.frog.brain.group;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Organ;
/**
@ -19,15 +20,32 @@ import com.github.drinkjava2.frog.brain.Organ;
*
* CellGroupGroupGroup,
* Group Group
* CellGroup Group
* Group Group
*
* GroupGroup,fat
* GroupGroup"播种机"
* Group,GroupGroup
* GroupGroup,fatGroup
* GroupGroup"播种机"
* Group()Group
*
* @author Yong Zhu
* @since 1.0
*/
public class Group extends Organ {
public abstract class Group extends Organ {
private static final long serialVersionUID = 1L;
@Override
public boolean allowBorrow() { // 是否允许在精子中将这个器官借出
return true;
}
/** Each loop step call active method, Child class can override this method */
@Override
public void active(Frog f) { // 每一步都会调用器官的active方法
f.frogEngery -= 3; // 每个器官运动都要消耗能量, 死了也要消耗能量
if (!f.alive)
return;
if (f.frogEngery < 0) { // 如果能量小于0则死
f.alive = false;
return;
}
}
}

@ -10,17 +10,25 @@
*/
package com.github.drinkjava2.frog.brain.group;
import java.util.Random;
import java.awt.Color;
import java.awt.Graphics;
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
*
* GroupCellGroup
* ZonefrogRandomConnectGroup
* GroupCellGroupZone
* frogRandomConnectGroup
*
* (Group )
* (Group )
*
* @author Yong Zhu
* @since 1.0
@ -28,50 +36,58 @@ import com.github.drinkjava2.frog.brain.Zone;
public class RandomConnectGroup extends Group {
private static final long serialVersionUID = 1L;
// TODO need delete below fields, use grid replace
public Zone groupInputZone; // input distribute zone
public Zone inputZone; // 输入触突区
public Zone outputZone; // 输出触突区
public Zone groupOutputZone; // output distribute zone
@Override
public void init(Frog f) {
if (inputZone == null)
inputZone = RandomUtils.randomPosInZone(this);
if (outputZone == null)
outputZone = RandomUtils.randomPosInZone(this);
public float cellInputRadius; // input radius of each cell
public float cellOutputRadius; // output radius of each cell
Cell c = new Cell();
Input in = new Input(inputZone);
in.cell = c;
c.inputs = new Input[] { in };
public float inputQtyPerCell; // input qty per cell
public float outputQtyPerCell; // output qty per cell
// TODO need delete above fields
Output out = new Output(outputZone);
out.cell = c;
c.outputs = new Output[] { out };
public float cellQty; // how many nerve cells in this CellGroup
private static final Random r = new Random();
public RandomConnectGroup() {
c.group = this;
f.cells.add(c);
}
@Override
public Organ[] vary() {
if (fat <= 0)
if (RandomUtils.percent(30))
return new Organ[] {};
if (RandomUtils.percent(80))
return new Organ[] { this };
return new Organ[] { this, newRandomConnGroup(this) };
}
public RandomConnectGroup(RandomConnectGroup 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 static RandomConnectGroup newRandomConnGroup(Zone z) {
RandomConnectGroup newOne = new RandomConnectGroup();
newOne.inputZone = RandomUtils.randomPosInZone(z);
newOne.outputZone = RandomUtils.randomPosInZone(z);
return newOne;
}
public RandomConnectGroup(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);
/** Child class can override this method to drawing picture */
public void drawOnBrainPicture(BrainPicture pic) {// 把自已这个器官在脑图上显示出来,子类可以重写这个方法
Graphics g = pic.getGraphics();// border
g.setColor(Color.gray); // 缺省是灰色
pic.drawZone(g, this);
pic.drawLine(g, inputZone, outputZone);
pic.drawZone(g, inputZone);
pic.fillZone(g, outputZone);
if (fat > 0) {
g.setColor(Color.red);
pic.drawCircle(g, outputZone); // 如果胖了,表示激活过了,下次下蛋少不了这一组
}
}
}

@ -15,24 +15,15 @@ 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
* Eat food at current x, y position
*/
public class Eat extends Organ {
public class Eat extends Organ {// Eat这个类将食物转化为能量能量小于0则青蛙死掉
private static final long serialVersionUID = 1L;
@Override
public void active(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能量境加
}
if (Env.foundAndDeleteFood(f.x, f.y))
f.frogEngery = f.frogEngery + 1000;// 如果青蛙的坐标与食物重合吃掉food能量境加
}
}

@ -27,15 +27,11 @@ import com.github.drinkjava2.frog.brain.Zone;
public class Eye extends Organ {
private static final long serialVersionUID = 1L;
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];
}
@Override
public void active(Frog f) {
// 第一个眼睛只能观察上、下、左、右四个方向有没有食物
float qRadius = radius / 4;
float q3Radius = (float) (radius * .75);
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);
@ -49,28 +45,28 @@ public class Eye extends Organ {
int seeDist = 10;
for (int i = 1; i < seeDist; i++)
if (hasFood(f.x, f.y + i)) {
if (Env.foundFood(f.x, f.y + i)) {
seeFood = true;
foodAtUp = true;
break;
}
for (int i = 1; i < seeDist; i++)
if (hasFood(f.x, f.y - i)) {
if (Env.foundFood(f.x, f.y - i)) {
seeFood = true;
foodAtDown = true;
break;
}
for (int i = 1; i < seeDist; i++)
if (hasFood(f.x - i, f.y)) {
if (Env.foundFood(f.x - i, f.y)) {
seeFood = true;
foodAtLeft = true;
break;
}
for (int i = 1; i < seeDist; i++)
if (hasFood(f.x + i, f.y)) {
if (Env.foundFood(f.x + i, f.y)) {
seeFood = true;
foodAtRight = true;
break;

@ -24,10 +24,7 @@ public class Hungry extends Organ {
@Override
public void active(Frog f) {
for (Cell cell : f.cells) {
if (cell.energy > 0)
cell.energy--;
if (f.energy < 10000 && cell.energy < 100)
if (f.frogEngery < 10000 && cell.energy < 1000)
for (Input input : cell.inputs)
if (input.nearby(this)) // input zone near by hungry zone
cell.energy += 2;

@ -0,0 +1,14 @@
/*
* 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;
public class CellGroup {
}

@ -13,12 +13,10 @@ 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.Env;
import com.github.drinkjava2.frog.Frog;
import com.github.drinkjava2.frog.brain.Organ;
import com.github.drinkjava2.frog.brain.Zone;
import com.github.drinkjava2.frog.brain.group.Group;
import com.github.drinkjava2.frog.brain.group.RandomConnectGroup;
import com.github.drinkjava2.frog.brain.organ.Eat;
import com.github.drinkjava2.frog.brain.organ.Eye;
@ -27,6 +25,7 @@ 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.util.RandomUtils;
/**
* Egg is the static structure description of frog, can save as text file, to
@ -40,117 +39,57 @@ import com.github.drinkjava2.frog.brain.organ.MoveUp;
*/
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 RandomConnectGroup[] cellGroups;
public List<Organ> organs = new ArrayList<>();
public List<Organ> organs = new ArrayList<Organ>();
public List<Group> groups = new ArrayList<>();
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 RandomConnectGroup[x.cellGroups.length + 1 + randomCellGroupQty];
for (int i = 0; i < x.cellGroups.length; i++) {
RandomConnectGroup oldCellGroup = x.cellGroups[i];
RandomConnectGroup cellGroup = new RandomConnectGroup();
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;
public Egg() {// 无中生有,创建一个蛋,先有蛋,后有鸡
organs.add(new Hungry().setXYRN(300, 100, 100, "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 Eat().setXYRN(0, 0, 0, "Eat"));
organs.add(new Eye().setXYRN(100, 400, 100, "Eye"));
for (int i = 0; i <10; i++) {
organs.add( new RandomConnectGroup().setXYRN(500, 500, 500, null));
}
// 从y里借一个CellGroup
RandomConnectGroup randomY = y.cellGroups[r.nextInt(y.cellGroups.length)];
RandomConnectGroup cellGroup = new RandomConnectGroup(randomY);
cellGroups[x.cellGroups.length] = cellGroup;
// 随机生成一批CellGroup
for (int i = 0; i < randomCellGroupQty; i++)
cellGroups[i + x.cellGroups.length + 1] = new RandomConnectGroup(Env.FROG_BRAIN_WIDTH, x.randomCellQtyPerGroup,
x.randomInputQtyPerCell, x.randomOutQtyPerCell);
addInitialOrgans();
}
/** create a brand new Egg */
public static Egg createBrandNewEgg() { // 无中生有,创建一个蛋,先有蛋,后有鸡
Egg egg = new Egg();
egg.cellGroups = new RandomConnectGroup[egg.randomCellGroupQty];
for (int i = 0; i < egg.randomCellGroupQty; i++)
egg.cellGroups[i] = new RandomConnectGroup(Env.FROG_BRAIN_WIDTH, egg.randomCellQtyPerGroup,
egg.randomInputQtyPerCell, egg.randomOutQtyPerCell);
egg.addInitialOrgans();
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<RandomConnectGroup> 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;// 继承下来的神经元,但是本轮并没用到, 扔掉又可惜,可以小概率丢掉
}
RandomConnectGroup cellGroup = new RandomConnectGroup();
RandomConnectGroup 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);
public Egg(Frog frog) { // 青蛙下蛋每个青蛙的器官会创建自已的副本或变异可以是0或多个
for (Organ organ : frog.organs)
for (Organ newOrgan : organ.vary())
organs.add(newOrgan);
for (int i = 0; i <10; i++) {
organs.add( new RandomConnectGroup().setXYRN(500, 500, 500, null));
}
cellGroups = gpList.toArray(new RandomConnectGroup[gpList.size()]);
addInitialOrgans();
}
/** Hard code add initial organs */
public void addInitialOrgans() { // 这是硬编码添加初始器官, 器官的数量、位置、内部参数会参加遗传、变异
organs.add(new Hungry().setXYRN(300, 100, 100, "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 Eat().setXYRN(0, 0, 0, "Eat"));
organs.add(new Eye().setXYRN(100, 400, 100, "Eye"));
//organs.add(new Eye().setXYRN(100, 700, 100, "Eye"));
/**
* Create a egg by join 2 eggs, x+y=zygote XY XY,
* 退,
*
*
*/
public Egg(Egg x, Egg y) {
// x里原来的organ
for (Organ organ : x.organs)
for (Organ newOrgan : organ.vary())
organs.add(newOrgan);
// 从y里借一个organ
int yOrganSize = y.organs.size();
if (yOrganSize > 0) {
Organ o = y.organs.get(RandomUtils.nextInt(yOrganSize));
if (o.allowBorrow())
organs.add(o);
}
for (int i = 0; i <10; i++) {
organs.add( new RandomConnectGroup().setXYRN(500, 500, 500, null));
}
}
}

@ -23,10 +23,11 @@ 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;
import com.github.drinkjava2.frog.util.FrogFileUtils;
/**
* EggTool store public static methods of egg
* EggTool save eggs to disk
*
* @author Yong Zhu
* @since 1.0
@ -34,18 +35,30 @@ import com.github.drinkjava2.frog.util.FrogFileUtils;
public class EggTool {
/**
* Frogs which have higher energy lay eggs
*
* 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 + ", ");
Frog first = env.frogs.get(0);
Frog last = env.frogs.get(env.frogs.size() - 1);
System.out.print("First frog has " + first.organs.size() + " organs, energy=" + first.frogEngery);
System.out.print(", Last frog has " + last.organs.size() + " organs, energy=" + last.frogEngery);
if (Env.DEBUG_MODE)
for (int i = 0; i < first.organs.size(); i++) {
Organ org = first.organs.get(i);
System.out.println("Organ(" + i + ")=" + org + ", fat=" + org.fat);
}
try {
List<Egg> 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 + ", ");
System.out.print("organs =" + newEggs.get(0).organs.size() + ", ");
FileOutputStream fo = new FileOutputStream(Application.CLASSPATH + "eggs.ser");
ObjectOutputStream so = new ObjectOutputStream(fo);
@ -53,20 +66,19 @@ public class EggTool {
so.close();
env.eggs = newEggs;
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);
}
}
private static void sortFrogsOrderByEnergyDesc(Env env) {
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.frogEngery > b.frogEngery)
return -1;
else if (a.energy == b.energy)
else if (a.frogEngery == b.frogEngery)
return 0;
else
return 1;
@ -75,7 +87,6 @@ public class EggTool {
}
public static void deleteEggs() {
FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs.json");
FrogFileUtils.deleteFile(Application.CLASSPATH + "eggs.ser");
}
@ -100,7 +111,7 @@ public class EggTool {
+ " new eggs to do test.");
env.eggs = new ArrayList<Egg>();
for (int i = 0; i < Env.EGG_QTY; i++)
env.eggs.add(Egg.createBrandNewEgg());
env.eggs.add(new Egg());
}
}

@ -0,0 +1,53 @@
/* 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.brain.Zone;
/**
* 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();
}
public static Zone randomPosInZone(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() * .02f);
}
public static boolean percent(int percent) {
return rand.nextInt(100) < percent;
}
public static float vary(float f) { // 大部分时候不变,有极小机会变异,有极极小机会大变异,有极极极小机会大大大变异
int i = rand.nextInt(100);
if (i < 95)
return f;
float rate = .05f;
if (i > 97)
rate = .1f;
return (float) (f * ((1 - rate) + rand.nextFloat() * rate * 2));
}
}

Binary file not shown.
Loading…
Cancel
Save