오늘은 새로운 도전을 하는 날입니다~^^*
간단하지만 새로운 도전이 될 것 같아요~~^^* YEAH~^^*
크리스마스 후 1일이니까요~^^* 새로운 한 해의 시작 느낌이기도 하니까요~^^*
일요일 같은 수요일이었고 월요일 같은 목요일이예요~~^^*
새해 새 주를 시작하는 마음으로~^^* 마법의 양탄자를 타고 새로운 세계로 출발~^^*
네~^^*
오늘의 새로운 도전은요~^^* 좀더 자연스러운 진화에 관한 프로그램이예요~^^*
이전까지의 프로그램은, 현재 세대 군집에서 다음 세대 군집으로 세대교체가 전면적으로 수행되었는데요~^^*
사실 그렇게 이루어 지는 세대교체는 잘 없을 것 같아요~^^*
개체별로 따로따로 부모세대가 자녀세대로 세대교체를 수행하게 될 것 같네요~^^*
그래서요~~^^*
개체별로 따로 움직이고 따로 먹이를 구하고 따로 기대수명이 조절되고 따로 재생산을 하는 프로그램을 살펴볼까 해요~^^*
있잖아요~~^^* 어떤 재미있는 생명체가 있는데요~~^^*
크기가 작으면 빨리 움직이고~^^*
크기가 크면 근처에 있는 먹이를 쉽게 섭취하고~^^*
시간이 흐르면서 기대수명은 꾸준히 줄어들지만~^^*
잘 먹으면 기대수명이 늘어나고~^^*
재생산확률 기반 무작위로 자녀를 생산하고~^^*
그러면서 살짝 돌연변이도 시켜주고~^^*
그런데~^^*
좀 색다른 점은요~^^*
짝짓기 없이, 자신의 유전자를 그대로 복사하여 자녀를 생산하고 거기에 살짝쿵 돌연변이를 가미한다는 점이예요~^^*
네~^^*
자녀생산 과정이 매우 간단할 것 같네요~^^*
그럼 우리 핵심 코드를 함께 살펴 볼까요~~^^* YEAH~~^^*
class Bloop {
constructor(position, dna) {
this.position = position; // 위치
this.health = 200; // 기대수명
this.xoff = random(1000); // 페를린 노이즈 관련 변수
this.yoff = random(1000); // Perlin Noise 방식으로 운동한다고 합니다~
this.dna = dna; // DNA
// DNA의 genes[0]이 Bloop의 속력과 크기를 결정한다고 해요~
this.maxspeed = map(this.dna.genes[0], 0, 1, 15, 0);
// genes[0]이 작으면 빨리 움직여요.
this.r = map(this.dna.genes[0], 0, 1, 0, 25);
// genes[0]이 크면 크기가 커요.
}
run() {
this.update();
this.borders();
this.show();
}
eat(food) {
let positions = food.foodPositions; //먹이 위치
for (let i = positions.length - 1; i >= 0; i--) {
let distance = p5.Vector.dist(this.position, positions[i]);
//먹이와 자신 Bloop과의 거리를 계산해요.
if (distance < this.r * 2) {
//먹이가 자신 Bloop 근처에 있으면
this.health += 100;
//기대수명 100 증가해요.
positions.splice(i, 1); //먹이 위치 데이터 배열에서 삭제해요.먹이가 사라져요. Bloop이 맛있게 먹었거든요^^*
}
}
}
//먹이의 위치를 파악하고, 자신의 근처에 있으면 먹어요. 그래서 기대수명이 늘어나요. 그리고 그 먹이는 사라져요.
reproduce() {
if (random(1) < 0.0005) {
//재생산 확률은 매우 작지만, 일단 그 확률 범위에 들어오면~
let childDNA = this.dna.copy();
//자신과 똑! 같은 자녀를 생산해요.
childDNA.mutate(0.01);
//살짝쿵 돌연변이시켜요.
return new Bloop(this.position.copy(), childDNA);
} else {
return null;
}
}
update() {
let vx = map(noise(this.xoff), 0, 1, -this.maxspeed, this.maxspeed);
let vy = map(noise(this.yoff), 0, 1, -this.maxspeed, this.maxspeed);
//Perlin Noise 기반 변화량으로 움직여요.
let velocity = createVector(vx, vy);
this.xoff += 0.01;
this.yoff += 0.01;
this.position.add(velocity);
this.health -= 0.2;
//기대수명 조금씩 줄어들어요
}
borders() {
if (this.position.x < -this.r) this.position.x = width + this.r;
if (this.position.y < this.r) this.position.y = height + this.r;
if (this.position.x > width + this.r) this.position.x = -this.r;
if (this.position.y > height + this.r) this.position.y = -this.r;
}
//화면 경계선 잇기 //화면 밖으로 나가면 반대방향에서 다시 들어와요.
show() {
stroke(0, this.health);
fill(0, this.health);
circle(this.position.x, this.position.y, this.r * 2);
}
//기대 수명이 진하기 정도로 표현되어요
dead() {
return this.health < 0.0;
}
//기대수명이 0보다 작으면 무지개다리를 건넙니다.
}
class DNA {
constructor() {
this.genes = [];
for (let i = 0; i < 1; i++) {
this.genes[i] = random(0, 1);
}
//0과 1 사이 무작위 실수가 유전자 데이터를 이룹니다.
}
copy() {
let newDNA = new DNA();
//일단 무작위 DNA로 newDNA를 만듭니다.
newDNA.genes = this.genes.slice();
//자신의 DNA 정보를 newDNA에 덮어씁니다.
return newDNA;
//결국 자신의 DNA를 그대로 복사한 newDNA를 반환하는 결과입니다.
}
mutate(mutationRate) {
for (let i = 0; i < this.genes.length; i++) {
if (random(1) < mutationRate) {
this.genes[i] = random(1);
}
}
}
//genes 배열의 모든 구성원 각각 this.genes[i]에 대해
//0에서 1 사이의 무작위 수가 돌연변이 확률보다 작을 경우 돌연변이시킵니다.
}
그럼 우리 이제 이 신기한 생명체 Bloop들을 만나러 함께 가볼까요~~^^*
뭔가…자신 내부에서 어떤 혁신을 일으켜서 새로운 삶을 또 시작하는 우리들의 모습 같기도 한데요~^^* 어제와 다른 오늘의 자신??? ^^*
크리스마스를 보내며 더욱 새로워진 오늘의 우리???~~^^*
크리스마스 트리에 소원 카드를 써서 걸어두는 진지하고 순수한 이 마음을 한 해 동안 간직하며 자신이 소망하는 새로운 모습을 이루어 가는 멋진 한 해가 되면 좋겠어요~~^^*
오늘 저와 함께 새로운 도전 해내어 주셔서 감사합니다~^^*
내일 우리 또 만나서 새로운 도전을 또 시작해 볼까요~^^*
이제는 우리 손으로 직접 Genetic Algorithm 기반 프로그램 코드를 만들어 보는 것은 어떨까요~~^^*
Genetic Algorithm 코드분석을 꾸준히 성실하게 해왔기 때문에 가능할 것 같아요~~^^* YEAH~~^^*
우리 손으로 코드 만들기! 다시 시작~~^^* 더욱 단단해진 우리 실력이 느껴져 깜짝 놀라며 서로 감사해 할 것 같아요~~^^* 함께 공부해 주셔서 정말 감사합니다~~^^*
오늘도 맛있는 음식 많이 드시고요~~^^*
설렘과 보람과 감사가 충만한 하루 보내시기 바래요~^^*
네~^^* 꿈은 이루어 집니다~^^*
댓글 남기기