package nars.lab.grid2d.main;
import nars.storage.Memory;
import nars.NAR;
import nars.lab.grid2d.main.Cell.Logic;
import static nars.lab.grid2d.main.Cell.Logic.AND;
import static nars.lab.grid2d.main.Cell.Logic.BRIDGE;
import static nars.lab.grid2d.main.Cell.Logic.NOT;
import static nars.lab.grid2d.main.Cell.Logic.OFFSWITCH;
import static nars.lab.grid2d.main.Cell.Logic.OR;
import static nars.lab.grid2d.main.Cell.Logic.SWITCH;
import static nars.lab.grid2d.main.Cell.Logic.UNCERTAINBRIDGE;
import static nars.lab.grid2d.main.Cell.Logic.WIRE;
import static nars.lab.grid2d.main.Cell.Logic.XOR;
import nars.lab.grid2d.main.Cell.Machine;
import nars.lab.grid2d.main.Cell.Material;
import nars.lab.grid2d.object.Key;
import nars.lab.grid2d.object.Pizza;
public class Hauto {
private final NAR nar;
boolean is_logic(Cell c){
return (c.logic==OR || c.logic==XOR || c.logic==AND || c.logic==NOT);
}
public static int doornumber(Cell c) {
if(c.material!=Material.Door) {
return -2;
}
return Integer.parseInt(c.name.replaceAll("door", "").replaceAll("\\}", "").replaceAll("\\{", ""));
}
public boolean bridge(Logic c) {
if(c==Logic.UNCERTAINBRIDGE || c==Logic.BRIDGE) {
return true;
}
return false;
}
//put to beginning because we will need this one most often
public void ExecutionFunction(int t,int i,int j,Cell w,Cell r,Cell left,Cell right,Cell up,
Cell down,Cell left_up,Cell left_down,Cell right_up,Cell right_down,Cell[][] readcells)
{
w.charge=r.charge;
w.value=r.value;
w.value2=r.value2;
w.is_solid=r.is_solid;
w.chargeFront=false;
//
if((r.machine==Machine.Light || r.machine==Machine.Turret) && r.charge==1)
{
if(r.light!=1.0f) {
boolean nope=false;
if(r.machine==Machine.Turret) {
for(GridObject gr : TestChamber.space.objects) {
if(gr instanceof LocalGridObject) {
LocalGridObject o=(LocalGridObject) gr;
if(o.x==i && o.y==j) {
nope=true;
}
}
}
if(!nope) {
TestChamber.space.add(new Pizza((int)i, (int)j, ""));
if(TestChamber.staticInformation)
//nar.addInput("<{pizza"+entityID.toString()+"} --> pizza>.");
entityID++;
}
}
nar.addInput("<"+r.name+" --> [on]>. :|:");
}
w.light=1.0f;
}
else
{
w.light=NeighborsValue2("op_max", i, j, readcells, "get_light", (r.is_solid || r.material==Material.StoneWall) ? 1 : 0)/1.1f; //1.1
}
///door
if(r.material==Material.Door) {
if(NeighborsValue2("op_or", i, j, readcells, "having_charge", 1.0f) != 0) {
w.is_solid=false;
if(r.is_solid) {
nar.addInput("<"+r.name+" --> [opened]>. :|:");
}
}
else {
if(!r.is_solid && TestChamber.keyn!=doornumber(r)) {
w.is_solid=true;
nar.addInput("(--,<"+r.name+" --> [opened]>). :|: %1.00;0.90%");
}
}
}
//////// WIRE / CURRENT PULSE FLOW /////////////////////////////////////////////////////////////
if(r.logic==WIRE)
{
if(!r.chargeFront && r.charge==0.0 && NeighborsValue2("op_or", i, j, readcells, "having_charge", 1.0f) != 0) {
w.charge = 1.0f;
w.chargeFront=true; //it's on the front of the wave of change
}
if(!r.chargeFront && r.charge==1.0 && NeighborsValue2("op_or", i, j, readcells, "having_charge", 0.0f) != 0)
{
w.charge=0.0f;
w.chargeFront=true; //it's on the front of the wave of change
}
if(r.chargeFront==false && r.charge==0 && (up.logic==SWITCH || down.logic==SWITCH || (left.logic==SWITCH || (is_logic(left) && left.value==1)) || (right.logic==SWITCH || (is_logic(right) && right.value==1))))
{
w.charge=1.0f;
w.chargeFront=true; //it's on the front of the wave of change
}
if(r.chargeFront==false && r.charge==1 && (up.logic==OFFSWITCH || down.logic==OFFSWITCH || (left.logic==OFFSWITCH || (is_logic(left) && left.value==0)) || (right.logic==OFFSWITCH || (is_logic(right) && right.value==0))))
{
w.charge=0.0f;
w.chargeFront=true; //it's on the front of the wave of change
}
}
//////////// LOGIC ELEMENTS ////////////////////////////////////////////////////////////////////
if(r.logic==Cell.Logic.NOT && (up.charge==0 || up.charge==1))
w.value=(up.charge==0 ? 1 : 0); //eval state from input connection
if(r.logic==Cell.Logic.NOT && (down.charge==0 || down.charge==1))
w.value=(down.charge==0 ? 1 : 0); //eval state from input connection
if(r.logic==Cell.Logic.AND)
w.value=(up.charge==1 && down.charge==1) ? 1.0f : 0.0f; //eval state from input connections
if(r.logic==Cell.Logic.OR)
w.value=(up.charge==1 || down.charge==1) ? 1.0f : 0.0f; //eval state from input connections
if(r.logic==Cell.Logic.XOR)
w.value=(up.charge==1 ^ down.charge==1) ? 1.0f : 0.0f; //eval state from input connections
//ADD BIDIRECTIONAL LOGIC BRIDGE TO OVERCOME 2D TOPOLOGY
if(r.logic==BRIDGE || (r.logic==UNCERTAINBRIDGE && Memory.randomNumber.nextDouble()>0.5))
{
if(left.chargeFront && left.logic==WIRE)
w.value=left.charge;
else
if(right.chargeFront && right.logic==WIRE)
w.value=right.charge;
if(up.chargeFront && up.logic==WIRE)
w.value2=up.charge;
else
if(down.chargeFront && down.logic==WIRE)
w.value2=down.charge;
}
if(!r.chargeFront && r.charge==0 && (((bridge(right.logic) && right.value==1) || (bridge(left.logic) && left.value==1)) || ((bridge(down.logic) && down.value2==1))))
{
w.charge=1;
w.chargeFront=true;
}
if(!r.chargeFront && r.charge==1 && (((bridge(right.logic) && right.value==0) || (bridge(left.logic) && left.value==0)) || ((bridge(down.logic) && down.value2==0))))
{
w.charge=0;
w.chargeFront=true;
}
if (r.logic == Cell.Logic.Load) {
w.charge = Math.max(up.charge, Math.max(down.charge, Math.max(left.charge, right.charge)));
w.chargeFront = false;
}
if(r.machine==Machine.Light || r.machine==Machine.Turret) {
if(r.light==1.0f && w.light!=1.0f) { //changed
nar.addInput("(--,<"+r.name+" --> [on]>). :|: %1.00;0.90%");
}
}
//w.charge *= w.conductivity;
}
String doorname="";
public static Integer entityID=0;
public static boolean allow_imitating=false;
public static String lastWish = "";
public static boolean goalInputPeriodic = false;
public void clicked(int x,int y, Grid2DSpace space)
{
if((int)x == 0 || (int) y==0 || (int)x == w-1 || (int) y==h-1)
return;
if(!doorname.equals("") && !doorname.contains("{")) {
doorname="{"+doorname+"}";
}
if(oper.equals("perceive")) {
readCells[(int) x][(int) y].name = "{place"+entityID.toString()+"}";
writeCells[(int) x][(int) y].name = "{place"+entityID.toString()+"}";
if(TestChamber.staticInformation)
nar.addInput("<"+"{place"+entityID.toString()+"} --> place>.");
if(TestChamber.curiousity) {
space.nar.addInput("<(^go-to," + "{place"+entityID.toString() + "}) =/> <Self --> [curious]>>.");
}
entityID++;
return;
}
if(!"".equals(oper)) {
if(!"".equals(readCells[x][y].name) && !"pick".equals(oper)) {
if(allow_imitating) {
nar.addInput("(^" + oper + ","+readCells[x][y].name+")! :|:"); //we will force the action
}
else {
nar.addInput("(^" + oper + ","+readCells[x][y].name+"). :|:");
TestChamber.operateObj(readCells[x][y].name, oper);
}
//nar.addInput("(^" + oper + ","+readCells[x][y].name+"). :|:"); //in order to make NARS an observer
//--nar.step(1);
//.operateObj(readCells[x][y].name, oper);
}
String s=TestChamber.getobj(x, y);
if(!s.equals("")) {
if(allow_imitating) {
nar.addInput("(^" + oper + ","+s+")! :|:");
}
else {
nar.addInput("(^" + oper + ","+s+"). :|:");
TestChamber.operateObj(s, oper);
}
//nar.executeDummyDecision("(^" + oper + ","+s+")");
//--nar.step(1);
// TestChamber.operateObj(s, oper);
}
return;
}
if(!"".equals(wish)) {
boolean inverse=false;
if(wish.equals("closed") || wish.equals("off")) {
inverse=true;
}
String wishreal=wish.replace("closed", "opened").replace("off", "on");
if(!"".equals(readCells[x][y].name)) {
//nar.addInput("(^" + oper + ","+readCells[x][y].name+")!"); //we will force the action
if(!inverse) {
String inp = "<" + readCells[x][y].name+" --> ["+wishreal+"]>! :|:";
nar.addInput(inp); //in order to make NARS an observer
lastWish = inp;
} else {
String inp = "(--,<" + readCells[x][y].name+" --> ["+wishreal+"]>)! :|: %1.00;0.90%";
nar.addInput(inp);
lastWish = inp;
}
//--nar.step(1);
}
String s=TestChamber.getobj(x, y);
if(!s.equals("")) {
//nar.addInput("(^" + oper + ","+s+")!");
if(!inverse) {
String inp = "<" + s +" --> ["+wishreal+"]>! :|:";
nar.addInput(inp); //in order to make NARS an observer
lastWish = inp;
} else {
String inp = "(--,<" + s +" --> ["+wishreal+"]>)! :|: %1.00;0.90%";
nar.addInput(inp);
lastWish = inp;
}
//--nar.step(1);
}
return;
}
if(!"".equals(doorname) && selected.material==Material.Door) {
space.add(new Key((int)x, (int)y, doorname.replace("door", "key")));
if(TestChamber.staticInformation)
nar.addInput("<"+doorname.replace("door", "key")+" --> key>.");
if(TestChamber.curiousity) {
space.nar.addInput("<(^go-to," +doorname.replace("door", "key") + ") =/> <Self --> [curious]>>.");
space.nar.addInput("<(^pick," + doorname.replace("door", "key") + ") =/> <Self --> [curious]>>.");
}
doorname="";
return;
}
if(selected.material==Material.Pizza) {
doorname="{pizza"+entityID.toString()+"}";
}
if(!"".equals(doorname) && selected.material==Material.Pizza) {
space.add(new Pizza((int)x, (int)y, doorname));
if(TestChamber.staticInformation)
nar.addInput("<"+doorname+" --> pizza>.");
if(TestChamber.curiousity) {
space.nar.addInput("<(^go-to," + doorname + ") =/> <Self --> [curious]>>.");
}
entityID++;
doorname="";
return;
}
if(!(selected.material==Material.Door) && !(selected.material==Material.Pizza))
doorname="";
readCells[(int) x][(int) y].charge = selected.charge;
writeCells[(int) x][(int) y].charge = selected.charge;
readCells[(int) x][(int) y].logic = selected.logic;
writeCells[(int) x][(int) y].logic = selected.logic;
readCells[(int) x][(int) y].material = selected.material;
writeCells[(int) x][(int) y].material = selected.material;
readCells[(int) x][(int) y].machine = selected.machine;
writeCells[(int) x][(int) y].machine = selected.machine;
if(selected.material==Material.Pizza || selected.material==Material.Door || selected.logic==Logic.OFFSWITCH || selected.logic==Logic.SWITCH || selected.machine==Machine.Light || selected.machine==Machine.Turret) //or other entity...
{
String name="";
if(selected.material==Material.Door) {
name="door";
}
if(selected.logic==Logic.SWITCH || selected.logic==Logic.OFFSWITCH)
name="switch";
if(selected.machine==Machine.Light)
name="light";
if(selected.machine==Machine.Turret)
name="oven";
String Klass=name;
name += (entityID.toString());
if(selected.material==Material.Door) {
doorname=name;
}
name="{"+name+"}";
//if it has name already, dont allow overwrite
if(readCells[(int) x][(int) y].name.equals("")) {
if(TestChamber.staticInformation)
nar.addInput("<"+name+" --> "+Klass+">.");
readCells[(int) x][(int) y].name = name;
writeCells[(int) x][(int) y].name = name;
if(selected.logic==Logic.OFFSWITCH) {
nar.addInput("(--,<"+name+" --> "+"[on]>). :|: %1.00;0.90%");
if(TestChamber.curiousity) {
space.nar.addInput("<(^go-to," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
space.nar.addInput("<(^activate," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
space.nar.addInput("<(^deactivate," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
}
}
if(selected.logic==Logic.SWITCH) {
nar.addInput("<"+name+" --> "+"[on]>. :|:");
if(TestChamber.curiousity) {
space.nar.addInput("<(^go-to," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
space.nar.addInput("<(^activate," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
space.nar.addInput("<(^deactivate," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
}
}
}
else
{
if(selected.logic==Logic.OFFSWITCH) { //already has a name so use this one
nar.addInput("<"+readCells[(int) x][(int) y].name+" --> "+"[off]>. :|:");
if(TestChamber.curiousity) {
space.nar.addInput("<(^go-to," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
space.nar.addInput("<(^activate," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
space.nar.addInput("<(^deactivate," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
}
}
if(selected.logic==Logic.SWITCH) {
nar.addInput("<"+readCells[(int) x][(int) y].name+" --> "+"[on]>. :|:");
if(TestChamber.curiousity) {
space.nar.addInput("<(^go-to," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
space.nar.addInput("<(^activate," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
space.nar.addInput("<(^deactivate," + readCells[(int) x][(int) y].name + ") =/> <Self --> [curious]>>.");
}
}
}
entityID++;
}
}
Cell selected=new Cell();
String oper="";
String label="";
String wish="";
public void click(String label, String oper, String wish) {
this.label=label;
this.oper=oper;
this.wish=wish;
if("".equals(label)) {
return;
}
selected.is_solid=false;
if("StoneWall".equals(label)) {
selected.material = Material.StoneWall;
selected.is_solid=true;
selected.logic=Logic.NotALogicBlock;
selected.charge=0;
}
if("Water".equals(label)) {
selected.material = Material.Water;
selected.is_solid=false;
selected.logic=Logic.NotALogicBlock;
selected.charge=0;
}
if("DirtFloor".equals(label)) {
selected.material = Material.DirtFloor;
selected.is_solid=false;
selected.logic=Logic.NotALogicBlock;
selected.charge=0;
}
if("GrassFloor".equals(label)) {
selected.material = Material.GrassFloor;
selected.is_solid=false;
selected.logic=Logic.NotALogicBlock;
selected.charge=0;
}
selected.machine = null;
if("NOT".equals(label)) {
selected.setLogic(Cell.Logic.NOT, 0);
}
if("AND".equals(label))
{
selected.setLogic(Cell.Logic.AND, 0);
}
if("OR".equals(label))
{
selected.setLogic(Cell.Logic.OR, 0);
}
if("XOR".equals(label))
{
selected.setLogic(Cell.Logic.XOR, 0);
}
if("bridge".equals(label))
{
selected.setLogic(Cell.Logic.BRIDGE, 0);
}
if("uncertainbridge".equals(label))
{
selected.setLogic(Cell.Logic.UNCERTAINBRIDGE, 0);
}
if("OnWire".equals(label))
{
selected.setLogic(Cell.Logic.WIRE, 1.0f);
selected.chargeFront = true;
}
if("OffWire".equals(label))
{
selected.setLogic(Cell.Logic.WIRE, 0);
selected.chargeFront = true;
}
if("onswitch".equals(label))
{
selected.setLogic(Cell.Logic.SWITCH, 1.0f);
}
if("offswitch".equals(label))
{
selected.setLogic(Cell.Logic.OFFSWITCH, 0);
}
if("Pizza".equals(label)) {
selected.logic = Logic.NotALogicBlock;
selected.material = Material.Pizza;
selected.is_solid=false;
}
if("Door".equals(label)) {
selected.logic = Logic.NotALogicBlock;
selected.charge=0;
selected.material = Material.Door;
selected.is_solid=true;
}
if("Light".equals(label)) {
selected.logic = Logic.Load;
selected.material = Material.Machine;
selected.machine = Machine.Light;
selected.is_solid=true;
}
if("Turret".equals(label)) {
selected.logic = Logic.Load;
selected.material = Material.Machine;
selected.machine = Machine.Turret;
selected.is_solid=true;
}
}
public float Neighbor_Value(Cell c,String mode,float data)
{
if("having_charge".equals(mode)) {
if(c.logic!=Cell.Logic.WIRE)
return -1.0f; //not a charge
return c.charge==data ? 1.0f : 0.0f;
}
if("just_getcharge".equals(mode)) {
return c.charge;
}
if("get_light".equals(mode) && (data==1 || !c.is_solid && !(c.material==Material.StoneWall))) {
return Math.max(c.charge*0.2f, c.light);
}
return 0.0f;
}
final public static int RIGHT = -90;
final public static int DOWN = 180;
final public static int LEFT = 90;
final public static int UP = 0;
final public static int UPLEFT = (UP+LEFT)/2;
final public static int UPRIGHT = (UP+RIGHT)/2;
final public static int DOWNLEFT = (DOWN+LEFT)/2;
final public static int DOWNRIGHT = (DOWN+RIGHT)/2;
public int t = 0;
public Cell[][] readCells; //2D-array(**) of Cell objects(*)
public Cell[][] writeCells; //2D-array(**) of Cell objects(*)
public final int w;
public final int h;
public static int irand(int max) {
return (int)(Math.random()*max);
}
public Hauto(int w, int h, NAR nar) {
this.nar=nar;
this.w = w;
this.h = h;
readCells = new Cell[w][];
writeCells = new Cell[w][];
for (int i = 0; i < w; i++) {
readCells[i] = new Cell[h];
writeCells[i] = new Cell[h];
for (int j = 0; j < h; j++) {
CellState s = new CellState(i, j);
readCells[i][j] = new Cell(s);
writeCells[i][j] = new Cell(s);
if ((i == 0) || (i == w-1))
readCells[i][j].setBoundary();
else if ((j == 0) || (j == h-1))
readCells[i][j].setBoundary();
}
}
copyReadToWrite();
click("StoneWall","","");
}
public void copyReadToWrite() {
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
writeCells[i][j].copyFrom(readCells[i][j]);
}
}
}
public void Exec() {
this.t++;
for (int i = 1; i < this.w - 1; i++) {
for (int j = 1; j < this.h - 1; j++) {
ExecutionFunction(this.t, i, j, this.writeCells[i][j], this.readCells[i][j], this.readCells[i - 1][j], this.readCells[i + 1][j], this.readCells[i][j + 1], this.readCells[i][j - 1], this.readCells[i - 1][j + 1], this.readCells[i - 1][j - 1], this.readCells[i + 1][j + 1], this.readCells[i + 1][j - 1], this.readCells);
}
}
//change write to read and read to write
Cell[][] temp2 = this.readCells;
this.readCells = this.writeCells;
this.writeCells = temp2;
}
public Cell FirstNeighbor(int i, int j, Cell[][] readCells, String Condition, float data) {
int k;
int l;
for (k = i - 1; k <= i + 1; k++) {
for (l = j - 1; l <= j + 1; l++) {
if (!(k == i && j == l)) {
if (Neighbor_Value(readCells[k][l], Condition, data) != 0) {
return readCells[k][l];
}
}
}
}
return null;
}
public float NeighborsValue(String op, int i, int j, Cell[][] readCells, String Condition, float data) {
return Op(op, Op(op, Op(op, Op(op, Op(op, Op(op, Op(op, Neighbor_Value(readCells[i + 1][j], Condition, data), Neighbor_Value(readCells[i - 1][j], Condition, data)), Neighbor_Value(readCells[i + 1][j + 1], Condition, data)), Neighbor_Value(readCells[i - 1][j - 1], Condition, data)), Neighbor_Value(readCells[i][j + 1], Condition, data)), Neighbor_Value(readCells[i][j - 1], Condition, data)), Neighbor_Value(readCells[i - 1][j + 1], Condition, data)), Neighbor_Value(readCells[i + 1][j - 1], Condition, data));
}
public float NeighborsValue2(String op, int i, int j, Cell[][] readCells, String Condition, float data) {
return Op(op, Op(op, Op(op, Neighbor_Value(readCells[i + 1][j], Condition, data), Neighbor_Value(readCells[i - 1][j], Condition, data)), Neighbor_Value(readCells[i][j + 1], Condition, data)), Neighbor_Value(readCells[i][j - 1], Condition, data));
}
public float Op(String op,float a,float b)
{
if("op_or".equals(op)) {
return (a==1.0f || b==1.0f) ? 1.0f : 0.0f;
}
if("op_and".equals(op)) {
return (a==1.0f && b==1.0f) ? 1.0f : 0.0f;
}
if("op_max".equals(op)) {
return Math.max(a, b);
}
if("op_min".equals(op)) {
return Math.min(a, b);
}
if("op_plus".equals(op)) {
return a+b;
}
if("op_mul".equals(op)) {
return a*b;
}
return 0.0f;
}
public void forEach(int x1, int y1, int x2, int y2, CellFunction c) {
x1 = Math.max(1, x1);
x2 = Math.min(w-1, x2);
x2 = Math.max(x1, x2);
y1 = Math.max(1, y1);
y2 = Math.min(h-1, y2);
y2 = Math.max(y1, y2);
for (int tx = x1; tx < x2; tx++)
for (int ty = y1; ty < y2; ty++) {
c.update(readCells[tx][ty]);
}
copyReadToWrite();
}
public void at(int x, int y, CellFunction c) {
c.update(readCells[x][y]);
copyReadToWrite();
}
public Cell at(int x, int y) {
return readCells[x][y];
}
public static class SetMaterial implements CellFunction {
private final Cell.Material material;
public SetMaterial(Cell.Material m) {
this.material = m;
}
@Override
public void update(Cell cell) {
cell.material = material;
cell.height = (material == Cell.Material.StoneWall) ? 64 : 1;
}
}
}