package core;
import grafic.LiveObject;
import measurements.GeneratorFloat;
import measurements.HasNext;
import processing.core.PApplet;
import static core.AgentiEpistemici.*;
final class Agent {
protected Student students;
protected Teacher teachers;
protected int nStudents, nTeachers;
protected int age; // zile traite
protected int deathAge; // durata de viata (numarul de zile pana la moarte)
protected float belief; // increderea in ipoteza
protected float pragmatism; // pragmatism, coeficientul de invatare din experienta
protected float charisma;
protected float exaggerate;
protected int chats;
protected final static GeneratorFloat
success = LiveObject.readRegulator("Psuccess")
,experiment = LiveObject.readRegulator("Pexperiment")
,communication = LiveObject.readRegulator("Pcommunication")
//,speechSteps = LiveObject.readRegulator("speech steps")
,maturity = LiveObject.readRegulator("sexual maturity")
,randomDeath = LiveObject.readRegulator("death age")
,randomBelief = LiveObject.readRegulator("belief at birth")
,randomPragmatism = LiveObject.readRegulator("pragmatism at birth")
,randomTrust = LiveObject.readRegulator("trust at birth")
,randomCharisma = LiveObject.readRegulator("charisma at birth")
,randomIniT = LiveObject.readRegulator("trust in parent")
,randomD = LiveObject.readRegulator("trust diffusion")
,agreementInfluence = LiveObject.readRegulator("agreement influence on trust")
,trustDecay = LiveObject.readRegulator("trust decay")
,needForTeachers = LiveObject.readRegulator("need for teachers")
,pragmatismDecay = LiveObject.readRegulator("pragmatism decay")
,trustInfluence = LiveObject.readRegulator("trust influence on belief")
,trustDump = LiveObject.readRegulator("trust thresh. to dump teacher")
,tolerance = LiveObject.readRegulator("listen to untrusted")
,successFrequency = LiveObject.readRegulator("success frequency")
,beliefFrequency = LiveObject.readRegulator("belief frequency")
,exaggeration = LiveObject.readRegulator("exaggeration")
,globalExaggeration = LiveObject.readRegulator("global exaggeration")
;
Agent() {
init();
}
Agent(Agent parent) {
this();
linkFrom(parent, randomIniT.getValue());
getNewTeacher();
}
private void init() {
deathAge = PApplet.round(randomDeath.getValue());
belief = randomBelief.getValue();
pragmatism = randomPragmatism.getValue();
charisma = randomCharisma.getValue();
exaggerate = exaggeration.getValue();
}
public void socialize() {
for (int k=0; k<5; k++) {
Agent candidate;
do {candidate = mediu.randomAgentOtherThan(this);} while (candidate.isTeacherOf(this));
linkFrom(candidate, randomTrust.getValue());
}
}
public void live() {
chats = 0;
// experimentează
if (experiment.happens()) {
if (success.happens()) {
belief += pragmatism*(1.0f-belief);
}
else {
belief -= pragmatism*belief;
}
}
// parcurge lista de profi și învață de la ei
for (Teacher him=teachers; him!=null; him=him.next) {
him.trust -= trustDecay.getValue()*him.trust; // viteza de scădere a încrederii odată cu înaintarea în vârstă
if (communication.happens(map(him.trust, 0.0f, 1.0f, tolerance.getValue(), 1.0f))) {
chats++;
Agent teacher = him.theAgent();
if (him.lastSpeech>=0.0f && agreementInfluence.getValue()>0.001f)
him.trust += map(age, 0, 100, 0.001f, agreementInfluence.getValue()) * (agreeWith(him.lastSpeech) - him.trust);
him.lastSpeech = teacher.speak();
belief += teacher.charisma * him.trust * trustInfluence.getValue() * (him.lastSpeech - belief);
}
}
// dacă nu prea are încredere într-un profesor, îl abandonează
for (Teacher him=teachers; him!=null;) { // atenție că trecerea la next o fac manual în corpul ciclului !!!
Teacher nextTeacher = him.next;
if (trustDump.happens(him.trust)) {
him.student.detach();
him.detach();
}
him = nextTeacher;
}
// eventual își alege un profesor nou
if (needForTeachers.happens(1.0f/nTeachers)) {
getNewTeacher();
}
// îmbătrânește
age++;
pragmatism -= pragmatismDecay.getValue()*pragmatism;
}
boolean isTeacherOf(Agent other) {
if (students==null) return false;
for (Student him=students; him!=null; him=him.next) if (other==him.theAgent()) return true;
return false;
}
boolean isStudentOf(Agent other) {
if (teachers==null) return false;
for (Teacher him=teachers; him!=null; him=him.next) if (other==him.theAgent()) return true;
return false;
}
protected float agreeWith(float speech) { // în ce măsură speechul lui este apropiat de părerea mea
// apropiere mare: agree -> 100%; apropiere mică: agree -> 0%
return 1 - Math.abs(speech - belief);
}
void getNewTeacher() {
Answer answer;
Agent teacher;
do {
answer = askRandomFriend(this);
teacher = answer.agent;
} while(teacher==this
|| teacher.isTeacherOf(this)
|| teacher.isStudentOf(this));
linkFrom(answer.agent, answer.trust);
}
public Answer askRandomFriend(Agent whoAsks) {
float diffusion = randomD.getValue();
float nGenericStudents = (nStudents + 1)*diffusion;
float nFriends = nGenericStudents+nTeachers;
float n;
int nmax;
float trust;
Agent candidate;
do {
n = nFriends * random.nextFloat();
if (n<diffusion) { // omul de pe stradă
trust = 0.0f;
candidate = mediu.randomAgentOtherThan(this, whoAsks);
} else if (n<nGenericStudents) { // un student
n -= diffusion;
nmax = Math.min(nStudents, (int) Math.floor(n/diffusion));
assert nmax<=nStudents : "nStudents = "+nStudents+", n = "+nmax;
Student student = students;
for (int i=0; i<nmax; i++) student = student.next;
trust = 0.0f;
if (student==null) student = students;
assert student!=null : "Student is null! WHY THE FUCK??? nStudents = "+nStudents+", nmax = "+nmax;
candidate = student.theAgent();
} else { // un profesor
n -= nGenericStudents;
nmax = Math.min(nTeachers, (int) Math.floor(n));
assert nmax<=nTeachers : "nTeachers = "+nTeachers+", n = "+nmax;
Teacher teacher = teachers;
for (int i=0; i<nmax; i++) teacher = teacher.next;
if (teacher==null) teacher = teachers;
assert teacher!=null : "Teacher is null! WHY THE FUCK??? nTeachers = "+nTeachers+", nmax = "+nmax;
trust = teacher.trust;
candidate = teacher.theAgent();
}
} while (candidate==whoAsks);
if (trust==0.0f) return candidate.askRandomFriend(this).withNoTrust(); // recursie prin elev/omul de pe stradă
else if (happens(trust)) return new Answer(candidate, trust); // e profesor de încredere, îl întorc chiar pe el
else return candidate.askRandomFriend(this).with(trust); // recursie prin profesor de neîncredere
}
protected float speak() {
/*
if (speechSteps.getValue()==1) return belief;
else if (belief==1.0f) return 1.0f;
else return 1.0f/(speechSteps.getValue()-1) * PApplet.floor(speechSteps.getValue() * belief);
*/
float e = exaggerate * globalExaggeration.getValue();
e = (1+e)/(1-e);
if (e==0.0f) return belief;
else if (belief==0.5f) return 0.5f;
else if (belief<0.5f) return 0.5f*(float) Math.pow(2*belief,e);
else return 1-0.5f*(float) Math.pow(2*(1-belief),e);
}
public boolean isRipe() {
return age>=deathAge;
}
public void die() {
if (teachers !=null) {
teachers.die();
teachers = null; // doar pentru ușurarea de Garbage Collection
}
if (students !=null) {
students.die();
students = null; // doar pentru ușurarea de Garbage Collection
}
}
public void linkFrom(Agent teacherAgent, float trust) {
Teacher teacher = teacherAgent.new Teacher(trust);
Student student = new Student();
this.addTeacher(teacher);
teacherAgent.addStudent(student);
teacher.student = student;
student.teacher = teacher;
}
/*
public void linkTo(Agent studentAgent, float i, float p) {
Teacher teacher = new Teacher(i, p);
Student student = studentAgent.new Student();
studentAgent.addTeacher(teacher);
this.addStudent(student);
teacher.student = student;
student.teacher = teacher;
}
*/
private void addStudent(Student student) {
if (students !=null) students.prev = student;
student.next = students;
students = student;
nStudents++;
}
private void addTeacher(Teacher teacher) {
if (teachers !=null) teachers.prev = teacher;
teacher.next = teachers;
teachers = teacher;
nTeachers++;
}
protected final class Teacher extends HasNext<Teacher> { // vârf de săgeată
protected Teacher prev;
protected Student student; // celălalt capăt (fundul)
protected float trust;
protected float lastSpeech;
private Teacher(float trust) {
this.trust = trust;
lastSpeech = -1.0f;
}
private void detach() { // se auto-scoate din lista teachers a nodului-părinte
if (next!=null) next.prev = prev;
if (prev!=null) prev.next = next;
else student.theAgent().teachers = next;
student.theAgent().nTeachers--;
student = null; // doar pentru ușurarea de Garbage Collection
}
private void die() { // auto-distrugere recursivă a listei teachers
if (next!=null) next.die(); // recursie
student.detach();
this.detach(); // doar pentru ușurarea de Garbage Collection
}
public Agent theAgent() {
return Agent.this;
}
}
protected final class Student extends HasNext<Student> { // fund de săgeată
private Student prev;
private Teacher teacher; // celălalt capăt (vârful)
private void detach() { // se auto-scoate din lista students a nodului-părinte
if (next!=null) next.prev = prev;
if (prev!=null) prev.next = next;
else teacher.theAgent().students = next;
teacher.theAgent().nStudents--;
teacher = null; // doar pentru ușurarea de Garbage Collection
}
private void die() { // auto-distrugere recursivă a listei students
if (next!=null) next.die(); // recursie
teacher.detach();
this.detach(); // doar pentru ușurarea de Garbage Collection
}
public Agent theAgent() {
return Agent.this;
}
}
}
final class Answer {
Agent agent;
float trust;
Answer(Agent agent, float trust) {
this.agent = agent;
this.trust = trust;
}
Answer with(float trust) {
this.trust *= trust;
return this;
}
public Answer withNoTrust() {
this.trust = 0.0f;
return this;
}
}