Now, I haven't really done any research on this and I'm probably over-simplifying a very complicated thing, but I have been thinking about this in the back of my mind for a bit and finally put something down in the form of code. This is very basic and rudamentary, but I would like an opinion on it:
package ai;
/**
* @author Matthew D. Hicks
*/
public interface Thinker {
public Decision[] getDecisions();
public void decisionMade(Decision decision);
}
package ai;
/**
* @author Matthew D. Hicks
*/
public class Decision {
private int id;
private int probability;
private Object object;
public Decision(int id, int probability, Object object) {
this.id = id;
this.probability = probability;
this.object = object;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public int getProbability() {
return probability;
}
public void setProbability(int probability) {
this.probability = probability;
}
}
package ai;
import java.util.*;
/**
* @author Matthew D. Hicks
*/
public class DecisionMaker extends Thread {
private ArrayList<Thinker> thinkers;
private long delay;
private long recycle;
private boolean keepAlive;
public DecisionMaker(long delay, long recycle) {
thinkers = new ArrayList<Thinker>();
this.delay = delay;
this.recycle = recycle;
keepAlive = true;
}
public void addThinker(Thinker thinker) {
thinkers.add(thinker);
}
public void run() {
Decision decision;
while (keepAlive) {
for (int i = 0; i < thinkers.size(); i++) {
decision = makeDecision(thinkers.get(i).getDecisions());
thinkers.get(i).decisionMade(decision);
try {
Thread.sleep(delay);
} catch(InterruptedException exc) {
}
}
try {
Thread.sleep(recycle);
} catch(InterruptedException exc) {
}
}
}
public void shutdown() {
keepAlive = false;
}
public static final Decision makeDecision(Decision[] decisions) {
int potentialsTotal = 0;
for (int i = 0; i < decisions.length; i++) {
potentialsTotal += decisions[i].getProbability();
}
long decision = Math.round(Math.random() * potentialsTotal);
potentialsTotal = 0;
for (int i = 0; i < decisions.length; i++) {
potentialsTotal += decisions[i].getProbability();
if (potentialsTotal >= decision) {
return decisions[i];
}
}
return decisions[decisions.length - 1];
}
}
and finally, here is a simple test use of it that is really pretty useless as it would normally need specific external insight into the world around it to do anything useful:
package test;
import ai.*;
/**
* @author Matthew D. Hicks
*/
public class TestThinker implements Thinker {
private Decision[] decisions;
public TestThinker() {
decisions = new Decision[3];
decisions[0] = new Decision(0, 1, "Apple");
decisions[1] = new Decision(1, 1, "Orange");
decisions[2] = new Decision(2, 1, "Bannana");
}
public Decision[] getDecisions() {
return decisions;
}
public void decisionMade(Decision decision) {
System.out.println("Decision was made: " + decision.getId() + ", " + decision.getProbability() + ", " + decision.getObject());
// Increase probability that another decision will be made next time
if (decision.getProbability() == 1) {
for (int i = 0; i < decisions.length; i++) {
if (decision != decisions[i]) {
decisions[i].setProbability(decisions[i].getProbability() + 1);
}
}
} else {
decision.setProbability(1);
}
}
public static void main(String[] args) throws Exception {
DecisionMaker dm = new DecisionMaker(100, 2000);
dm.addThinker(new TestThinker());
dm.start();
}
}