mirror of
https://github.com/brmlab/brmlife.git
synced 2025-08-02 18:03:37 +02:00
Introduce pheromones
This commit is contained in:
parent
61cc3ef015
commit
a821e72661
9 changed files with 133 additions and 1 deletions
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
CFLAGS=-Wall -g -pthread
|
CFLAGS=-Wall -g -pthread
|
||||||
LDFLAGS=-pthread
|
LDFLAGS=-pthread
|
||||||
|
|
||||||
OBJS=main.o map.o agent.o connection.o
|
OBJS=main.o map.o agent.o connection.o pheromone.o
|
||||||
|
|
||||||
brmlife: $(OBJS)
|
brmlife: $(OBJS)
|
||||||
$(CXX) $(LDFLAGS) -o $@ $^
|
$(CXX) $(LDFLAGS) -o $@ $^
|
||||||
|
|
13
agent.cc
13
agent.cc
|
@ -91,6 +91,15 @@ agent::attack_dir(int dir_x, int dir_y)
|
||||||
return attack_roll >= defense_roll;
|
return attack_roll >= defense_roll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
agent::secrete(int id, double intensity)
|
||||||
|
{
|
||||||
|
pheromone p(id, intensity);
|
||||||
|
pheromones.secrete(p);
|
||||||
|
chenergy(intensity * world::pheromone_cost);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
agent::chenergy(int delta)
|
agent::chenergy(int delta)
|
||||||
{
|
{
|
||||||
|
@ -129,9 +138,13 @@ agent::on_action_takes(void)
|
||||||
void
|
void
|
||||||
agent::on_tick(void)
|
agent::on_tick(void)
|
||||||
{
|
{
|
||||||
|
pheromones.decay(world::phdecay_gamma, world::phdecay_delta);
|
||||||
|
|
||||||
if (!tile)
|
if (!tile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
pheromones.seep(tile->pheromones, world::phseep_alpha, world::phseep_beta);
|
||||||
|
|
||||||
if (!dead) {
|
if (!dead) {
|
||||||
chenergy(world::sun_energy);
|
chenergy(world::sun_energy);
|
||||||
chenergy(attr.move * world::move_idle_cost);
|
chenergy(attr.move * world::move_idle_cost);
|
||||||
|
|
4
agent.h
4
agent.h
|
@ -2,6 +2,7 @@
|
||||||
#define BRMLIFE__AGENT_H
|
#define BRMLIFE__AGENT_H
|
||||||
|
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
#include "pheromone.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
|
|
||||||
class connection;
|
class connection;
|
||||||
|
@ -23,6 +24,8 @@ public:
|
||||||
int energy;
|
int energy;
|
||||||
bool dead;
|
bool dead;
|
||||||
|
|
||||||
|
class pheromones pheromones;
|
||||||
|
|
||||||
agent(int id_, class connection *conn_, class map &map_)
|
agent(int id_, class connection *conn_, class map &map_)
|
||||||
: id (id_), conn (conn_), map (map_), tile (NULL)
|
: id (id_), conn (conn_), map (map_), tile (NULL)
|
||||||
{
|
{
|
||||||
|
@ -37,6 +40,7 @@ public:
|
||||||
|
|
||||||
bool move_dir(int dir_x, int dir_y);
|
bool move_dir(int dir_x, int dir_y);
|
||||||
bool attack_dir(int dir_x, int dir_y);
|
bool attack_dir(int dir_x, int dir_y);
|
||||||
|
bool secrete(int id, double intensity);
|
||||||
|
|
||||||
void chenergy(int delta);
|
void chenergy(int delta);
|
||||||
void die(void);
|
void die(void);
|
||||||
|
|
|
@ -37,6 +37,19 @@ connection::senses(int tick_id, class agent &a)
|
||||||
}
|
}
|
||||||
bufp += snprintf(bufp, sizeof(buf) - (bufp - buf), "\r\n");
|
bufp += snprintf(bufp, sizeof(buf) - (bufp - buf), "\r\n");
|
||||||
|
|
||||||
|
bufp += snprintf(bufp, sizeof(buf) - (bufp - buf), "pheromones");
|
||||||
|
for (int i = 0; i < dir_n; i++) {
|
||||||
|
bufp += snprintf(bufp, sizeof(buf) - (bufp - buf), " (");
|
||||||
|
class pheromones &ps = a.tile->tile_in_dir(dirs[i][0], dirs[i][1]).pheromones;
|
||||||
|
for (std::list<class pheromone>::iterator pi = ps.spectrum.begin(); pi != ps.spectrum.end(); pi++) {
|
||||||
|
if (pi != ps.spectrum.begin())
|
||||||
|
bufp += snprintf(bufp, sizeof(buf) - (bufp - buf), ",");
|
||||||
|
bufp += snprintf(bufp, sizeof(buf) - (bufp - buf), "%d:%f", pi->id, pi->val);
|
||||||
|
}
|
||||||
|
bufp += snprintf(bufp, sizeof(buf) - (bufp - buf), ")");
|
||||||
|
}
|
||||||
|
bufp += snprintf(bufp, sizeof(buf) - (bufp - buf), "\r\n");
|
||||||
|
|
||||||
bufp += snprintf(bufp, sizeof(buf) - (bufp - buf), "\r\n");
|
bufp += snprintf(bufp, sizeof(buf) - (bufp - buf), "\r\n");
|
||||||
pthread_mutex_lock(&buf_lock);
|
pthread_mutex_lock(&buf_lock);
|
||||||
out_buf.append(buf);
|
out_buf.append(buf);
|
||||||
|
@ -102,6 +115,14 @@ connection::actions(class agent &agent)
|
||||||
if (!agent.attack_dir(x, y))
|
if (!agent.attack_dir(x, y))
|
||||||
bump();
|
bump();
|
||||||
mask |= 2;
|
mask |= 2;
|
||||||
|
} else if (!negotiation && !cmd.compare("secrete")) {
|
||||||
|
int id = 0; double v = 0;
|
||||||
|
sscanf(line.c_str(), "%d %lf", &id, &v);
|
||||||
|
if (id < 0) id = 0; if (id >= PH_COUNT) id = PH_COUNT - 1;
|
||||||
|
if (v < 0) v = 0;
|
||||||
|
if (!agent.secrete(id, v))
|
||||||
|
bump();
|
||||||
|
/* We deliberately allow multiple secrete commands. */
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
std::cout << "unknown line " << cmd << " " << line << " ...\n";
|
std::cout << "unknown line " << cmd << " " << line << " ...\n";
|
||||||
|
|
2
map.cc
2
map.cc
|
@ -39,6 +39,8 @@ tile::on_tick(void)
|
||||||
if (tile_in_dir(-1, 0).herb_here()) { tile_in_dir(-1, 0).agent->chenergy(world::soil_energy / herbs); }
|
if (tile_in_dir(-1, 0).herb_here()) { tile_in_dir(-1, 0).agent->chenergy(world::soil_energy / herbs); }
|
||||||
if (tile_in_dir(0, -1).herb_here()) { tile_in_dir(0, -1).agent->chenergy(world::soil_energy / herbs); }
|
if (tile_in_dir(0, -1).herb_here()) { tile_in_dir(0, -1).agent->chenergy(world::soil_energy / herbs); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pheromones.decay(world::phdecay_gamma, world::phdecay_delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
3
map.h
3
map.h
|
@ -1,6 +1,8 @@
|
||||||
#ifndef BRMLIFE__MAP_H
|
#ifndef BRMLIFE__MAP_H
|
||||||
#define BRMLIFE__MAP_H
|
#define BRMLIFE__MAP_H
|
||||||
|
|
||||||
|
#include "pheromone.h"
|
||||||
|
|
||||||
class agent;
|
class agent;
|
||||||
class map;
|
class map;
|
||||||
|
|
||||||
|
@ -10,6 +12,7 @@ public:
|
||||||
class map ↦
|
class map ↦
|
||||||
|
|
||||||
class agent *agent;
|
class agent *agent;
|
||||||
|
class pheromones pheromones;
|
||||||
|
|
||||||
tile(int x_, int y_, class map &map_)
|
tile(int x_, int y_, class map &map_)
|
||||||
: x(x_), y(y_), map(map_), agent(NULL) {};
|
: x(x_), y(y_), map(map_), agent(NULL) {};
|
||||||
|
|
48
pheromone.cc
Normal file
48
pheromone.cc
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "pheromone.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
pheromones::secrete(class pheromone &p)
|
||||||
|
{
|
||||||
|
for (std::list<class pheromone>::iterator pi = spectrum.begin(); pi != spectrum.end(); pi++) {
|
||||||
|
if (pi->id < p.id)
|
||||||
|
continue;
|
||||||
|
if (pi->id == p.id) {
|
||||||
|
pi->val += p.val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spectrum.insert(pi, p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spectrum.push_back(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pheromones::seep(class pheromones &to, double alpha, double beta)
|
||||||
|
{
|
||||||
|
for (std::list<class pheromone>::iterator pi = spectrum.begin(); pi != spectrum.end(); pi++) {
|
||||||
|
class pheromone p(pi->id, pi->val * (alpha * PH_COUNT / pi->id + beta));
|
||||||
|
to.secrete(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pheromones::decay(double gamma, double delta)
|
||||||
|
{
|
||||||
|
for (std::list<class pheromone>::iterator pi = spectrum.begin(); pi != spectrum.end(); pi++) {
|
||||||
|
next_p:
|
||||||
|
pi->val *= gamma;
|
||||||
|
pi->val -= delta;
|
||||||
|
if (pi->val < 0.001) {
|
||||||
|
pi = spectrum.erase(pi);
|
||||||
|
if (pi != spectrum.end())
|
||||||
|
goto next_p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
pheromone.h
Normal file
35
pheromone.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef BRMLIFE__PHEROMONE_H
|
||||||
|
#define BRMLIFE__PHEROMONE_H
|
||||||
|
|
||||||
|
/* Pheromone spectrum in a particular state. */
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#define PH_COUNT 65536
|
||||||
|
|
||||||
|
class pheromone {
|
||||||
|
public:
|
||||||
|
int id;
|
||||||
|
double val;
|
||||||
|
|
||||||
|
pheromone(int id_ = 0, double val_ = 0)
|
||||||
|
: id (id_), val (val_) {};
|
||||||
|
};
|
||||||
|
|
||||||
|
class pheromones {
|
||||||
|
public:
|
||||||
|
std::list<class pheromone> spectrum;
|
||||||
|
|
||||||
|
/* Add a pheromone to the spectrum. */
|
||||||
|
void secrete(class pheromone &p);
|
||||||
|
/* Merge slight trail of spectrum to another spectrum (transfer
|
||||||
|
* by touching). Pheromones with lower index are transmitted
|
||||||
|
* better than those with higher index:
|
||||||
|
* v' = v * (alpha / i + beta) */
|
||||||
|
void seep(class pheromones &to, double alpha, double beta);
|
||||||
|
/* Decay the spectrum, multiplying each value by gamma and
|
||||||
|
* then reducing it by delta. */
|
||||||
|
void decay(double gamma, double delta);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
6
world.h
6
world.h
|
@ -9,6 +9,7 @@ struct world {
|
||||||
const static int move_cost = -50;
|
const static int move_cost = -50;
|
||||||
const static int attack_cost = -400;
|
const static int attack_cost = -400;
|
||||||
const static int defense_cost = -200;
|
const static int defense_cost = -200;
|
||||||
|
const static int pheromone_cost = -10;
|
||||||
|
|
||||||
const static int move_idle_cost = -15; /* ... * attr.move */
|
const static int move_idle_cost = -15; /* ... * attr.move */
|
||||||
const static int attack_idle_cost = -15; /* ... * attr.attack */
|
const static int attack_idle_cost = -15; /* ... * attr.attack */
|
||||||
|
@ -21,6 +22,11 @@ struct world {
|
||||||
const static int dead_decay = -50;
|
const static int dead_decay = -50;
|
||||||
|
|
||||||
const static int herb_rate = 15; /* initially, one herb per herb_rate tiles */
|
const static int herb_rate = 15; /* initially, one herb per herb_rate tiles */
|
||||||
|
|
||||||
|
const static double phseep_alpha = 0.1;
|
||||||
|
const static double phseep_beta = 0.05;
|
||||||
|
const static double phdecay_gamma = 0.95;
|
||||||
|
const static double phdecay_delta = 0.01;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue