diff --git a/config/defaultConfig.xml b/config/defaultConfig.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a46de59807704a59e53bd3a5b969fa1d434cdd46
--- /dev/null
+++ b/config/defaultConfig.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8" ?>
+
+<config>
+    <!-- NarParameters -->
+    <conf name="NOVELTY_HORIZON" value="100000"/>
+    <conf name="DECISION_THRESHOLD" value="0.51"/>
+    <conf name="CONCEPT_BAG_SIZE" value="10000"/>
+    <conf name="CONCEPT_BAG_LEVELS" value="1000"/>
+    
+    <conf name="DURATION" value="5"/>
+    <conf name="HORIZON" value="1"/>
+    
+    <conf name="TRUTH_EPSILON" value="0.01"/>
+    <conf name="BUDGET_EPSILON" value="0.0001"/>
+    <conf name="BUDGET_THRESHOLD" value="0.01"/>
+    
+    <conf name="DEFAULT_CONFIRMATION_EXPECTATION" value="0.6"/>
+    <conf name="DEFAULT_CREATION_EXPECTATION" value="0.66"/>
+    <conf name="DEFAULT_CREATION_EXPECTATION_GOAL" value="0.6"/>
+    
+    <conf name="DEFAULT_JUDGMENT_CONFIDENCE" value="0.9"/>
+    <conf name="DEFAULT_JUDGMENT_PRIORITY" value="0.8"/>
+    <conf name="DEFAULT_JUDGMENT_DURABILITY" value="0.5"/>
+    
+    <conf name="DEFAULT_QUESTION_PRIORITY" value="0.9"/>
+    <conf name="DEFAULT_QUESTION_DURABILITY" value="0.9"/>
+    
+    <conf name="DEFAULT_GOAL_CONFIDENCE" value="0.9"/>
+    <conf name="DEFAULT_GOAL_PRIORITY" value="0.9"/>
+    <conf name="DEFAULT_GOAL_DURABILITY" value="0.9"/>
+    <conf name="DEFAULT_QUEST_PRIORITY" value="0.9"/>
+    <conf name="DEFAULT_QUEST_DURABILITY" value="0.9"/>
+    
+    <conf name="BAG_THRESHOLD" value="1.0"/>
+    <conf name="FORGET_QUALITY_RELATIVE" value="0.1"/>
+    <conf name="REVISION_MAX_OCCURRENCE_DISTANCE" value="10"/>
+    
+    <conf name="TASK_LINK_BAG_SIZE" value="100"/>
+    <conf name="TASK_LINK_BAG_LEVELS" value="10"/>
+    
+    <conf name="TERM_LINK_BAG_SIZE" value="100"/>
+    <conf name="TERM_LINK_BAG_LEVELS" value="10"/>
+    <conf name="TERM_LINK_MAX_MATCHED" value="10"/>
+    
+    <conf name="NOVEL_TASK_BAG_SIZE" value="100"/>
+    <conf name="NOVEL_TASK_BAG_LEVELS" value="10"/>
+    
+    <conf name="SEQUENCE_BAG_SIZE" value="30"/>
+    <conf name="SEQUENCE_BAG_LEVELS" value="10"/>
+    
+    <conf name="OPERATION_BAG_SIZE" value="10"/>
+    <conf name="OPERATION_BAG_LEVELS" value="10"/>
+    <conf name="OPERATION_SAMPLES" value="6"/>
+    
+    <conf name="PROJECTION_DECAY" value="0.1"/>
+    
+    <conf name="MAXIMUM_EVIDENTAL_BASE_LENGTH" value="20000"/>
+    
+    <conf name="TERMLINK_MAX_REASONED" value="3"/>
+    <conf name="TERM_LINK_RECORD_LENGTH" value="10"/>
+    
+    <conf name="CONCEPT_BELIEFS_MAX" value="28"/>
+    <conf name="CONCEPT_QUESTIONS_MAX" value="5"/>
+    <conf name="CONCEPT_GOALS_MAX" value="7"/>
+    
+    <conf name="reliance" value="0.9"/>
+    <conf name="DISCOUNT_RATE" value="0.5"/>
+    
+    <conf name="IMMEDIATE_ETERNALIZATION" value="true"/>
+    <conf name="SEQUENCE_BAG_ATTEMPTS" value="10"/>
+    <conf name="CONDITION_BAG_ATTEMPTS" value="10"/>
+    
+    <conf name="DERIVATION_PRIORITY_LEAK" value="0.4"/>
+    <conf name="DERIVATION_DURABILITY_LEAK" value="0.4"/>
+    
+    <conf name="CURIOSITY_BUSINESS_THRESHOLD" value="0.18"/>
+    <conf name="CURIOSITY_PRIORITY_THRESHOLD" value="0.3"/>
+    <conf name="CURIOSITY_CONFIDENCE_THRESHOLD" value="0.8"/>
+    <conf name="CURIOSITY_DESIRE_CONFIDENCE_MUL" value="0.1"/>
+    <conf name="CURIOSITY_DESIRE_PRIORITY_MUL" value="0.1"/>
+    <conf name="CURIOSITY_DESIRE_DURABILITY_MUL" value="0.3"/>
+    <conf name="CURIOSITY_FOR_OPERATOR_ONLY" value="false"/>
+    <conf name="CURIOSITY_ALSO_ON_LOW_CONFIDENT_HIGH_PRIORITY_BELIEF" value="false"/>
+    
+    <conf name="HAPPY_EVENT_HIGHER_THRESHOLD" value="0.75"/>
+    <conf name="HAPPY_EVENT_LOWER_THRESHOLD" value="0.25"/>
+    
+    <conf name="BUSY_EVENT_HIGHER_THRESHOLD" value="0.9"/>
+    <conf name="BUSY_EVENT_LOWER_THRESHOLD" value="0.1"/>
+    
+    <conf name="CONSIDER_REMIND" value="false"/>
+    <conf name="BREAK_NAL_HOL_BOUNDARY" value="false"/>
+    
+    <conf name="QUESTION_GENERATION_ON_DECISION_MAKING" value="false"/>
+    <conf name="HOW_QUESTION_GENERATION_ON_DECISION_MAKING" value="false"/>
+    
+    <conf name="ANTICIPATION_CONFIDENCE" value="0.33"/>
+    <conf name="ANTICIPATION_TOLERANCE" value="50.0"/>
+    
+    <conf name="CONSIDER_NEW_OPERATION_BIAS" value="0.05"/>
+    <conf name="TEMPORAL_INDUCTION_PRIORITY_PENALTY" value="1.0"/>
+    <conf name="AUTOMATIC_DECISION_USUAL_DECISION_BLOCK_CYCLES" value="500"/>
+    <conf name="SATISFACTION_TRESHOLD" value="0.0"/>
+    <conf name="COMPLEXITY_UNIT" value="1.0"/>
+    
+    <conf name="INTERVAL_ADAPT_SPEED" value="4.0"/>
+    <conf name="TASKLINK_PER_CONTENT" value="4"/>
+    
+    <conf name="DEFAULT_FEEDBACK_PRIORITY" value="0.9"/>
+    <conf name="DEFAULT_FEEDBACK_DURABILITY" value="0.5"/>
+    
+    <conf name="CONCEPT_FORGET_DURATIONS" value="2.0"/>
+    <conf name="TERMLINK_FORGET_DURATIONS" value="10.0"/>
+    <conf name="TASKLINK_FORGET_DURATIONS" value="4.0"/>
+    <conf name="EVENT_FORGET_DURATIONS" value="4.0"/>
+    
+    <conf name="VARIABLE_INTRODUCTION_COMBINATIONS_MAX" value="8"/>
+    <conf name="ANTICIPATIONS_PER_CONCEPT_MAX" value="8"/>
+
+    <conf name="THREADS_AMOUNT" value="1"/>
+    <conf name="VOLUME" value="100"/>
+    <conf name="MILLISECONDS_PER_STEP" value="0"/>
+    <conf name="STEPS_CLOCK" value="true"/>
+
+    <!-- plugins -->
+    <plugins>
+    </plugins>
+</config>
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bb1ab9e085a79116b0053ed9c773497d45e10b84
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.opennars</groupId>
+    <artifactId>Applications</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.opennars</groupId>
+            <artifactId>opennars</artifactId>
+            <version>3.0.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.processing</groupId>
+            <artifactId>core</artifactId>
+            <version>2.2.1</version>
+        </dependency>
+    </dependencies>
+    <licenses>
+        <license>
+            <name>MIT</name>
+            <url>https://opensource.org/licenses/MIT</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+</project>
\ No newline at end of file
diff --git a/src/main/java/com/opennars/applications/crossing/Camera.java b/src/main/java/com/opennars/applications/crossing/Camera.java
new file mode 100644
index 0000000000000000000000000000000000000000..562c5a37a0144a8f05c6006eb274cfdde7bab19c
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/Camera.java
@@ -0,0 +1,50 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.opennars.applications.crossing;
+
+import java.util.List;
+import org.opennars.main.Nar;
+import processing.core.PApplet;
+
+/**
+ *
+ * @author patha
+ */
+public class Camera {
+    int posX;
+    int posY;
+    int radius=60;
+    int minX;
+    int minY;
+    public Camera(int posX, int posY) {
+        this.posX = posX;
+        this.posY = posY;
+        this.minX = posX-radius*2;
+        this.minY = posY-radius*2;
+    }
+    
+    InformNARS informer = new InformNARS();
+    boolean see(Nar nar, List<Entity> entities, List<TrafficLight> trafficLights) {
+        //InformNARS.informAboutEntity(nar, chosen);
+        for (Entity ent : entities) {
+            if (Util.distance(posX, posY, ent.posX, ent.posY) < radius) {
+                informer.informAboutEntity(nar, ent, minX, minY);
+            }
+        }
+        for (TrafficLight ent : trafficLights) {
+            if (Util.distance(posX, posY, ent.posX, ent.posY) < radius) {
+                informer.informAboutTrafficLight(nar, ent, minX, minY);
+                break;
+            }
+        }
+        return informer.Input(nar);
+    }
+    
+    public void draw(PApplet applet) {
+        applet.fill(0,0,255,20);
+        applet.ellipse(posX,posY,radius*2,radius*2);
+    }
+}
diff --git a/src/main/java/com/opennars/applications/crossing/Car.java b/src/main/java/com/opennars/applications/crossing/Car.java
new file mode 100644
index 0000000000000000000000000000000000000000..86aec689d115fd7a09dafc182b6b8b6422d7496d
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/Car.java
@@ -0,0 +1,42 @@
+/* 
+ * The MIT License
+ *
+ * Copyright 2018 The OpenNARS authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.opennars.applications.crossing;
+
+import java.util.List;
+import org.opennars.entity.TruthValue;
+import processing.core.PApplet;
+
+public class Car extends Entity {
+
+    public Car(int id, double posX, double posY, double velocity, double angle) {
+        super(id, posX, posY, velocity, angle);
+        maxSpeed = 2;
+    }
+
+    public void draw(PApplet applet, List<Street> streets, List<TrafficLight> trafficLights, List<Entity> entities, TruthValue truth, long time) {
+        float mul = Util.truthToValue(truth) * Util.timeToValue(time);
+        applet.fill(255, 0, 255, mul*255.0f);
+        super.draw(applet, streets, trafficLights, entities, truth, time);
+    }
+}
diff --git a/src/main/java/com/opennars/applications/crossing/Crossing.java b/src/main/java/com/opennars/applications/crossing/Crossing.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5d9a3c922d52d951c77e8c0085e54822c4e254e
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/Crossing.java
@@ -0,0 +1,206 @@
+/* 
+ * The MIT License
+ *
+ * Copyright 2018 The OpenNARS authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.opennars.applications.crossing;
+
+import com.opennars.applications.crossing.NarListener.Prediction;
+import com.opennars.sgui.NarSimpleGUI;
+import java.util.ArrayList;
+import java.util.List;
+import org.opennars.io.events.Events;
+import org.opennars.io.events.OutputHandler.DISAPPOINT;
+import org.opennars.main.Nar;
+import processing.core.PApplet;
+import processing.event.MouseEvent;
+
+public class Crossing extends PApplet {
+    Nar nar;
+    int entityID = 1;
+    
+    List<Prediction> predictions = new ArrayList<Prediction>();
+    List<Prediction> disappointments = new ArrayList<Prediction>();
+    final int streetWidth = 40;
+    final int fps = 50;
+    @Override
+    public void setup() {
+        cameras.add(new Camera(500+streetWidth/2, 500+streetWidth/2));
+        try {
+            nar = new Nar();
+            nar.narParameters.VOLUME = 0;
+            nar.narParameters.DURATION*=10;
+            NarListener listener = new NarListener(cameras.get(0), nar, predictions, disappointments);
+            nar.on(Events.TaskAdd.class, listener);
+            nar.on(DISAPPOINT.class, listener);
+        } catch (Exception ex) {
+            System.out.println(ex);
+            System.exit(1);
+        }
+        int trafficLightRadius = 25;
+        streets.add(new Street(false, 0, 500, 1000, 500 + streetWidth));
+        streets.add(new Street(true, 500, 0, 500 + streetWidth, 1000));
+        int trafficLightID = 1;
+        trafficLights.add(new TrafficLight(trafficLightID++, trafficLightRadius, 500 + streetWidth + trafficLightRadius, 500 + streetWidth/2, 0));
+        trafficLights.add(new TrafficLight(trafficLightID++, trafficLightRadius, 500 - trafficLightRadius, 500 + streetWidth/2, 0));
+        trafficLights.add(new TrafficLight(trafficLightID++, trafficLightRadius/2, 500 + streetWidth, 500 + streetWidth + trafficLightRadius, 1));
+        trafficLights.add(new TrafficLight(trafficLightID++, trafficLightRadius/2, 500, 500 - trafficLightRadius, 1));
+        int cars = 4; //cars and pedestrians
+        for (float i = 0; i < cars/2; i += 1.05) {
+            entities.add(new Car(entityID++, 500 + streetWidth - Util.discretization+1, 900 - i * 100, 0.3, -PI / 2));
+            entities.add(new Car(entityID++, 500 + Util.discretization, 900 - i * 100, 0.3, PI / 2));
+        }
+        int pedestrians = 4;//4;
+        for (float i = 0; i < pedestrians/2; i += 1.05) {
+            entities.add(new Pedestrian(entityID++, 900 - i * 100, 500 + streetWidth - Util.discretization, 0.3, 0));
+            entities.add(new Pedestrian(entityID++, 900 - i * 100, 500 + Util.discretization, 0.3, -PI));
+        }
+        /*for (TrafficLight l : trafficLights) { //it can't move anyway, so why would the coordinates matter to NARS?
+            String pos = Util.positionToTerm(l.posX, l.posY);
+            String narsese = "<(*,{" + l.id + "}," + pos + ") --> at>.";
+            nar.addInput(narsese);
+        }*/
+        
+        size(1000, 1000);
+        frameRate(fps);
+        new NarSimpleGUI(nar);
+    }
+
+    List<Street> streets = new ArrayList<Street>();
+    List<TrafficLight> trafficLights = new ArrayList<TrafficLight>();
+    List<Entity> entities = new ArrayList<Entity>();
+    List<Camera> cameras = new ArrayList<Camera>();
+    int t = 0;
+    public static boolean showAnomalies = false;
+
+    String questions = "<trafficLight --> [?whatColor]>? :|:";
+    int perception_update = 1;
+    @Override
+    public void draw() {
+        viewport.Transform();
+        background(64,128,64);
+        fill(0);
+        for (Street s : streets) {
+            s.draw(this);
+        }
+        if (t % perception_update == 0) {
+            boolean hadInput = false;
+            for(Camera c : cameras) {
+                hadInput = hadInput || c.see(nar, entities, trafficLights);
+            }
+            if(hadInput) {
+                nar.addInput(questions);
+            }
+        }
+        for (int i = 0; i < 1000; i += Util.discretization) {
+            stroke(128);
+            line(0, i, 1000, i);
+            line(i, 0, i, 1000);
+        }
+        for (Entity e : entities) {
+            e.draw(this, streets, trafficLights, entities, null, 0);
+        }
+        for (TrafficLight tl : trafficLights) {
+            tl.draw(this, t);
+        }
+        t++;
+        nar.cycles(10);
+        removeOutdatedPredictions(predictions);
+        removeOutdatedPredictions(disappointments);
+        for (Prediction pred : predictions) {
+            Entity e = pred.ent;
+            e.draw(this, streets, trafficLights, entities, pred.truth, pred.time - nar.time());
+        }
+        if(showAnomalies) {
+            for (Prediction pred : disappointments) {
+                Entity e = pred.ent;
+                if(e instanceof Car) {
+                    fill(255,0,0);
+                }
+                if(e instanceof Pedestrian) {
+                    fill(0,0,255);
+                }
+                this.text("ANOMALY", (float)e.posX, (float)e.posY);
+                e.draw(this, streets, trafficLights, entities, pred.truth, pred.time - nar.time());
+            }
+        }
+        for(Camera c : cameras) {
+            c.draw(this);
+        }
+    }
+
+    public void removeOutdatedPredictions(List<Prediction> predictions) {
+        List<Prediction> toDelete = new ArrayList<Prediction>();
+        for(Prediction pred : predictions) {
+            if(pred.time <= nar.time()) {
+                toDelete.add(pred);
+            }
+        }
+        predictions.removeAll(toDelete);
+    }
+    
+    float mouseScroll = 0;
+    Viewport viewport = new Viewport(this);
+    public void mouseWheel(MouseEvent event) {
+        mouseScroll = -event.getCount();
+        viewport.mouseScrolled(mouseScroll);
+    }
+    @Override
+    public void keyPressed() {
+        viewport.keyPressed();
+    }
+    @Override
+    public void mousePressed() {
+        viewport.mousePressed();
+    }
+    @Override
+    public void mouseReleased() {
+        viewport.mouseReleased();
+    }
+    @Override
+    public void mouseDragged() {
+        viewport.mouseDragged();
+    }
+
+    public static void main(String[] args) {
+        /* Set the Nimbus look and feel */
+        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
+        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
+         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
+         */
+        try {
+            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
+                if ("Nimbus".equals(info.getName())) {
+                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
+                    break;
+                }
+            }
+        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
+            java.util.logging.Logger.getLogger(NarSimpleGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+        }
+        //</editor-fold>
+        //</editor-fold>
+        String[] args2 = {"Crossing"};
+        Crossing mp = new Crossing();
+        new IncidentSimulator().show();
+        PApplet.runSketch(args2, mp);
+    }
+}
diff --git a/src/main/java/com/opennars/applications/crossing/Entity.java b/src/main/java/com/opennars/applications/crossing/Entity.java
new file mode 100644
index 0000000000000000000000000000000000000000..f44544355d275ce997da35cd01faf943b1375e1d
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/Entity.java
@@ -0,0 +1,123 @@
+/* 
+ * The MIT License
+ *
+ * Copyright 2018 The OpenNARS authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.opennars.applications.crossing;
+
+import java.util.List;
+import org.opennars.entity.TruthValue;
+import processing.core.PApplet;
+
+public class Entity {
+
+    public static int entityID = 0;
+    public double posX, posY;
+    public double velocity;
+    public double angle;
+    public int id;
+    public float scale = 1.0f;
+    public float maxSpeed = 2.0f;
+    public static boolean pedestrianIgnoreTrafficLight = false;
+    public static boolean carIgnoreTrafficLight = false;
+    
+    public Entity() {
+    }
+
+    public Entity(int id, double posX, double posY, double velocity, double angle) {
+        this.id = id;
+        this.posX = posX;
+        this.posY = posY;
+        this.velocity = velocity;
+        this.angle = angle;
+    }
+
+    public void draw(PApplet applet, List<Street> streets, List<TrafficLight> trafficLights, List<Entity> entities, TruthValue truth, long time) {
+        applet.pushMatrix();
+        //float posXDiscrete = (((int) this.posX)/Util.discretization * Util.discretization);
+        //float posYDiscrete = (((int) this.posY)/Util.discretization * Util.discretization);
+        applet.translate((float) posX, (float) posY);
+        applet.rotate((float) angle);
+        if(truth == null) {
+            applet.rect(0, 0, Util.discretization*scale, Util.discretization/2*scale);
+        }
+        applet.ellipse(2.5f, 2.5f, Util.discretization*scale, Util.discretization*scale);
+        applet.popMatrix();
+        applet.fill(0);
+        applet.text(String.valueOf(id), (float)posX, (float)posY);
+        if(truth != null) {
+            return;
+        }
+
+        boolean accelerate = true;
+        for (TrafficLight l : trafficLights) {
+            if (Util.distance(posX, posY, l.posX, l.posY) < l.radius) {
+                if (l.colour == l.RED) {
+                    if (Util.rnd.nextFloat() > 0.3 && ((this instanceof Car && !carIgnoreTrafficLight) || (this instanceof Pedestrian && !pedestrianIgnoreTrafficLight))) {
+                        velocity *= 0.5;
+                        accelerate = false;
+                    }
+                }
+            }
+        }
+        for (Entity e : entities) {
+            boolean collidable = !(this instanceof Pedestrian && e instanceof Pedestrian);
+            if (e != this && collidable) {
+                double nearEnough = 10;
+                for (double k = 0; k < nearEnough; k += 0.1) {
+                    double pXNew = posX + k * Math.cos(angle);
+                    double pYNew = posY + k * Math.sin(angle);
+                    if (Util.distance(pXNew, pYNew, e.posX, e.posY) < nearEnough) {
+                        velocity *= 0.8;
+                        accelerate = false;
+                    }
+                }
+            }
+        }
+
+        if (accelerate && velocity < maxSpeed) {
+            velocity += 0.02;
+        }
+
+        double aX = Math.cos(angle);
+        double aY = Math.sin(angle);
+        posX += aX * velocity;
+        posY += aY * velocity;
+
+        double epsilon = 1;
+        if (posY < 0) {
+            posY = 1000 - epsilon;
+            //this.id = entityID++;
+        }
+        if (posY > 1000) {
+            posY = epsilon;
+            //this.id = entityID++;
+        }
+        if (posX < 0) {
+            posX = 1000 - epsilon;
+            //this.id = entityID++;
+        }
+        if (posX > 1000) {
+            posX = epsilon;
+            //this.id = entityID++;
+        }
+    }
+}
diff --git a/src/main/java/com/opennars/applications/crossing/IncidentSimulator.form b/src/main/java/com/opennars/applications/crossing/IncidentSimulator.form
new file mode 100644
index 0000000000000000000000000000000000000000..677135ccdb33c11d2a2784e1d5b4d393c555b571
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/IncidentSimulator.form
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
+  <Properties>
+    <Property name="defaultCloseOperation" type="int" value="3"/>
+  </Properties>
+  <SyntheticProperties>
+    <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
+    <SyntheticProperty name="generateCenter" type="boolean" value="false"/>
+  </SyntheticProperties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="jCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="jCheckBox2" alignment="0" min="-2" max="-2" attributes="0"/>
+                  <Component id="jCheckBox3" alignment="0" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace pref="221" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace type="unrelated" max="-2" attributes="0"/>
+              <Component id="jCheckBox2" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jCheckBox3" min="-2" max="-2" attributes="0"/>
+              <EmptySpace pref="221" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JCheckBox" name="jCheckBox1">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="Car ignoring traffic light"/>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jCheckBox1ActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JCheckBox" name="jCheckBox2">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="Pedestrian ignoring traffic light"/>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jCheckBox2ActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JCheckBox" name="jCheckBox3">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="Show anomalies"/>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jCheckBox3ActionPerformed"/>
+      </Events>
+    </Component>
+  </SubComponents>
+</Form>
diff --git a/src/main/java/com/opennars/applications/crossing/IncidentSimulator.java b/src/main/java/com/opennars/applications/crossing/IncidentSimulator.java
new file mode 100644
index 0000000000000000000000000000000000000000..668c16d0878a7ca6bbc9e5046cc470185e10a8e5
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/IncidentSimulator.java
@@ -0,0 +1,101 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.opennars.applications.crossing;
+
+/**
+ *
+ * @author patha
+ */
+public class IncidentSimulator extends javax.swing.JFrame {
+
+    /**
+     * Creates new form IncidentSimulator
+     */
+    public IncidentSimulator() {
+        initComponents();
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jCheckBox1 = new javax.swing.JCheckBox();
+        jCheckBox2 = new javax.swing.JCheckBox();
+        jCheckBox3 = new javax.swing.JCheckBox();
+
+        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+
+        jCheckBox1.setText("Car ignoring traffic light");
+        jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jCheckBox1ActionPerformed(evt);
+            }
+        });
+
+        jCheckBox2.setText("Pedestrian ignoring traffic light");
+        jCheckBox2.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jCheckBox2ActionPerformed(evt);
+            }
+        });
+
+        jCheckBox3.setText("Show anomalies");
+        jCheckBox3.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jCheckBox3ActionPerformed(evt);
+            }
+        });
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+        getContentPane().setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addComponent(jCheckBox1)
+                    .addComponent(jCheckBox2)
+                    .addComponent(jCheckBox3))
+                .addContainerGap(221, Short.MAX_VALUE))
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addComponent(jCheckBox1)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                .addComponent(jCheckBox2)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jCheckBox3)
+                .addContainerGap(221, Short.MAX_VALUE))
+        );
+
+        pack();
+    }// </editor-fold>//GEN-END:initComponents
+
+    private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox1ActionPerformed
+        Entity.carIgnoreTrafficLight = jCheckBox1.isSelected();
+    }//GEN-LAST:event_jCheckBox1ActionPerformed
+
+    private void jCheckBox2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox2ActionPerformed
+        Entity.pedestrianIgnoreTrafficLight = jCheckBox2.isSelected();
+    }//GEN-LAST:event_jCheckBox2ActionPerformed
+
+    private void jCheckBox3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox3ActionPerformed
+        Crossing.showAnomalies = jCheckBox3.isSelected();
+    }//GEN-LAST:event_jCheckBox3ActionPerformed
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JCheckBox jCheckBox1;
+    private javax.swing.JCheckBox jCheckBox2;
+    private javax.swing.JCheckBox jCheckBox3;
+    // End of variables declaration//GEN-END:variables
+}
diff --git a/src/main/java/com/opennars/applications/crossing/InformNARS.java b/src/main/java/com/opennars/applications/crossing/InformNARS.java
new file mode 100644
index 0000000000000000000000000000000000000000..b962a8dd1a20df56e5aacbb2497ce123b4ea4d37
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/InformNARS.java
@@ -0,0 +1,79 @@
+/* 
+ * The MIT License
+ *
+ * Copyright 2018 The OpenNARS authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.opennars.applications.crossing;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opennars.main.Nar;
+
+public class InformNARS {
+    String lastInput = "";
+    String input = "";
+    List<String> inputs = new ArrayList<String>();
+    //minX and minY define the lower end of the relative coordinate system
+    public void informAboutEntity(Nar nar, Entity ent, int minX, int minY) {
+        String id = String.valueOf(ent.id);
+        boolean useMultipleIDs = true;
+        if(!useMultipleIDs) {
+            id = "0";
+        }
+        String pos = Util.positionToTerm((int) ent.posX-minX, (int) ent.posY-minY);
+        if (ent instanceof Car) {
+            inputs.add("<(*,car" + id + ","+ pos + ") --> at>. :|:");
+            input += inputs.get(inputs.size()-1);
+        }
+        if (ent instanceof Pedestrian) {
+            inputs.add("<(*,pedestrian" + id + "," + pos + ") --> at>. :|:");
+            input += inputs.get(inputs.size()-1);
+        }
+    }
+
+    String trafficLightInput = "";
+    String lastTrafficLightInput = "";
+    public void informAboutTrafficLight(Nar nar, TrafficLight light, int minX, int minY) {
+        //String id = String.valueOf(light.id);
+        String colour = light.colour == 0 ? "green" : "red";
+        String narsese = "<trafficLight --> ["+colour+"]>. :|:";
+        trafficLightInput = narsese;
+    }
+    
+    public boolean Input(Nar nar) {
+        boolean hadInput = false;
+        if(!input.equals(lastInput)) {
+            for(String inp : inputs) {
+                nar.addInput(inp);
+                hadInput = true;
+            }
+            lastInput = input;
+        }
+        if(!trafficLightInput.equals(lastTrafficLightInput)) {
+            nar.addInput(trafficLightInput);
+            hadInput = true;
+            lastTrafficLightInput = trafficLightInput;
+        }
+        input = "";
+        inputs.clear();
+        return hadInput;
+    }
+}
diff --git a/src/main/java/com/opennars/applications/crossing/NarListener.java b/src/main/java/com/opennars/applications/crossing/NarListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf33439df399cfc9ba307242f2638352d27f0639
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/NarListener.java
@@ -0,0 +1,127 @@
+/* 
+ * The MIT License
+ *
+ * Copyright 2018 The OpenNARS authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.opennars.applications.crossing;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opennars.entity.Sentence;
+import org.opennars.entity.Stamp;
+import org.opennars.entity.Task;
+import org.opennars.entity.TruthValue;
+import org.opennars.interfaces.Timable;
+import org.opennars.io.Symbols;
+import org.opennars.io.events.EventEmitter;
+import org.opennars.io.events.Events;
+import org.opennars.io.events.OutputHandler;
+import org.opennars.language.Inheritance;
+import org.opennars.language.Product;
+import org.opennars.language.Term;
+import org.opennars.main.Nar;
+import org.opennars.storage.Memory;
+
+public class NarListener implements EventEmitter.EventObserver {  
+    public class Prediction
+    {
+        public Entity ent;
+        public long time;
+        public TruthValue truth;
+        public Prediction(Entity ent, TruthValue truth, long time) {
+            this.ent = ent;
+            this.time = time;
+            this.truth = truth;
+        }
+    }
+    
+    List<NarListener.Prediction> predictions;
+    List<NarListener.Prediction> disappointments;
+    Nar nar;
+    Camera camera;
+    public NarListener(Camera camera, Nar nar, List<NarListener.Prediction> predictions, List<NarListener.Prediction> disappointments) {
+        this.predictions = predictions;
+        this.disappointments = disappointments;
+        this.nar = nar;
+        this.camera = camera;
+    }
+    Term pedestrian = Term.get("pedestrian");
+    Term car = Term.get("car");
+    Term at = Term.get("at");
+    @Override
+    public void event(Class event, Object[] args) {
+        if(event == OutputHandler.DISAPPOINT.class) {
+            Term term = (Term) args[0];
+            Sentence s = new Sentence(term, Symbols.JUDGMENT_MARK, new TruthValue(0.0f,0.9f, nar.narParameters), new Stamp(nar, nar.memory));
+            Task t = new Task(s, null, Task.EnumType.DERIVED);
+            Prediction result = predictionFromTask(t);
+            if(result != null) {
+                int showFor = 100; //how long the disappointment should be displayed in the GUI
+                result.time = nar.time() + showFor;
+                disappointments.add(result);
+            }
+        }
+        if (event == Events.TaskAdd.class) {
+            Task t = (Task) args[0];
+            if (/*t.sentence.getOccurenceTime() > nar.time() && */t.sentence.isJudgment() && t.sentence.getTruth().getExpectation() >= nar.narParameters.DEFAULT_CONFIRMATION_EXPECTATION) {
+                Prediction result = predictionFromTask(t);
+                if(result != null) {
+                    predictions.add(result);
+                }
+            }
+        }
+    }
+
+    public Prediction predictionFromTask(Task t) {
+        Prediction prediction = null;
+        //format: "<(*,car,50_82) --> at>. %0.45;0.26%";
+        if(t.sentence.term instanceof Inheritance) {
+            Inheritance positionInh = (Inheritance) t.sentence.term;
+            if(positionInh.getSubject() instanceof Product) {
+                Product prod = (Product) positionInh.getSubject();
+                if(prod.size() == 2) {
+                    Term type = prod.term[0];
+                    String position = prod.term[1].toString();
+                    if(position.contains("_")) {
+                        try {
+                            int posX = camera.minX + Util.discretization * Integer.valueOf(position.split("_")[0]);
+                            int posY = camera.minY + Util.discretization * Integer.valueOf(position.split("_")[1]);
+                            //int id = 0; //Integer.valueOf(idStr.toString()); often a dep var
+                            Entity pred;
+                            if(type.toString().startsWith(car.toString())) {
+                                String id = type.toString().substring(car.toString().length(), type.toString().length());
+                                pred = new Car(Integer.valueOf(id), posX, posY, 0, 0);
+                                prediction = new Prediction(pred, t.sentence.truth, t.sentence.getOccurenceTime());
+                            }
+                            else  
+                            if(type.toString().startsWith(pedestrian.toString())) {
+                                String id = type.toString().substring(pedestrian.toString().length(), type.toString().length());
+                                pred = new Pedestrian(Integer.valueOf(id), posX, posY, 0, 0);
+                                prediction = new Prediction(pred, t.sentence.truth, t.sentence.getOccurenceTime());
+                            }
+                        } catch(Exception ex) {} //wrong format, it's not such a type of prediction but something else
+                    }
+                }
+            }
+        }
+        return prediction;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/opennars/applications/crossing/Pedestrian.java b/src/main/java/com/opennars/applications/crossing/Pedestrian.java
new file mode 100644
index 0000000000000000000000000000000000000000..96c74db2238895e1650d4616b3b7fae515716c5e
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/Pedestrian.java
@@ -0,0 +1,64 @@
+/* 
+ * The MIT License
+ *
+ * Copyright 2018 The OpenNARS authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.opennars.applications.crossing;
+
+import java.util.List;
+import org.opennars.entity.TruthValue;
+import processing.core.PApplet;
+
+public class Pedestrian extends Entity {
+
+    double initialAngle;
+    double prevX = 0;
+    double prevY = 0;
+    public final static float pedestrianScale = 0.75f;
+    public Pedestrian(int id, double posX, double posY, double velocity, double angle) {
+        super(id, posX, posY, velocity, angle);
+        initialAngle = angle;
+        scale = pedestrianScale;
+        maxSpeed = 1;
+    }
+
+    public void draw(PApplet applet, List<Street> streets, List<TrafficLight> trafficLights, List<Entity> entities, TruthValue truth, long time) {
+        prevX = posX;
+        prevY = posY;
+        float mul = Util.truthToValue(truth) * Util.timeToValue(time);
+        applet.fill(0, 255, 255, mul*255.0f);
+        super.draw(applet, streets, trafficLights, entities, truth, time);
+        angle+=(Util.rnd.nextFloat()*0.1-0.05);
+        //ok pedestrian, don't go on grass
+        boolean forPedestrians = false;
+        for(Street street : streets) {
+            if(!street.forCarsOnly && this.posX > street.startX && this.posX < street.endX && this.posY > street.startY && this.posY < street.endY) {
+                forPedestrians = true;
+                break;
+            }
+        }
+        if(!forPedestrians) {
+            this.angle = this.initialAngle;
+            this.posX = prevX;
+            this.posY = prevY;
+        }
+    }
+}
diff --git a/src/main/java/com/opennars/applications/crossing/Street.java b/src/main/java/com/opennars/applications/crossing/Street.java
new file mode 100644
index 0000000000000000000000000000000000000000..4686eba161dd4642a62307d4c1c9d2ae8696ce8e
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/Street.java
@@ -0,0 +1,45 @@
+/* 
+ * The MIT License
+ *
+ * Copyright 2018 The OpenNARS authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.opennars.applications.crossing;
+
+import processing.core.PApplet;
+
+public class Street {
+
+    public int startX, startY, endX, endY;
+    public boolean forCarsOnly = false;
+
+    public Street(boolean forCarsOnly, int startX, int startY, int endX, int endY) {
+        this.startX = startX;
+        this.startY = startY;
+        this.endX = endX;
+        this.endY = endY;
+        this.forCarsOnly = forCarsOnly;
+    }
+
+    public void draw(PApplet applet) {
+        applet.fill(188);
+        applet.rect(startX, startY, endX - startX, endY - startY);
+    }
+}
diff --git a/src/main/java/com/opennars/applications/crossing/TrafficLight.java b/src/main/java/com/opennars/applications/crossing/TrafficLight.java
new file mode 100644
index 0000000000000000000000000000000000000000..27685ffffcd6f7e75b5e2f24a4add433c0a19f83
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/TrafficLight.java
@@ -0,0 +1,53 @@
+/* 
+ * The MIT License
+ *
+ * Copyright 2018 The OpenNARS authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.opennars.applications.crossing;
+
+import processing.core.PApplet;
+
+public class TrafficLight {
+
+    public int GREEN = 0, RED = 1;
+    public int posX, posY;
+    public int id;
+    public int colour = 0;
+    public int radius = 0;
+
+    public TrafficLight(int id, int radius, int positionX, int positionY, int colour) {
+        this.radius = radius;
+        this.id = id;
+        this.posX = positionX;
+        this.posY = positionY;
+        this.colour = colour;
+    }
+
+    public void draw(PApplet applet, int t) {
+        int g = colour == 0 ? 255 : 0;
+        int r = colour == 1 ? 255 : 0;
+        applet.fill(r, g, 0);
+        applet.ellipse(posX, posY, 10, 10);
+        if (t % 200 == 0) {
+            colour = (colour + 1) % 2;
+        }
+    }
+}
diff --git a/src/main/java/com/opennars/applications/crossing/Util.java b/src/main/java/com/opennars/applications/crossing/Util.java
new file mode 100644
index 0000000000000000000000000000000000000000..f1442d00270009e0002beec824c627ed8d7e4d35
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/Util.java
@@ -0,0 +1,60 @@
+/* 
+ * The MIT License
+ *
+ * Copyright 2018 The OpenNARS authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.opennars.applications.crossing;
+
+import java.util.Random;
+import org.opennars.entity.TruthValue;
+
+/**
+ *
+ * @author patha
+ */
+public class Util {
+
+    public static Random rnd = new Random();
+    public static final int discretization =10;
+    
+    public static double distance(double posX, double posY, double posX2, double posY2) {
+        double dx = posX - posX2;
+        double dy = posY - posY2;
+        return Math.sqrt(dx * dx + dy * dy);
+    }
+    
+    public static String positionToTerm(int X, int Y) {
+        int posX = X / discretization;
+        int posY = Y / discretization;
+        return posX + "_" + posY;
+    }
+    
+    public static float truthToValue(TruthValue truth) {
+        if(truth == null) {
+            return 1.0f;
+        }
+        return truth.getExpectation();
+    }
+    
+    public static float timeToValue(long time) {
+        return 10f/(1f+((float)time));
+    }
+}
diff --git a/src/main/java/com/opennars/applications/crossing/Viewport.java b/src/main/java/com/opennars/applications/crossing/Viewport.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ec4fc8584eceebc75fad50d142970a0836d284a
--- /dev/null
+++ b/src/main/java/com/opennars/applications/crossing/Viewport.java
@@ -0,0 +1,148 @@
+/* 
+ * The MIT License
+ *
+ * Copyright 2018 The OpenNARS authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.opennars.applications.crossing;
+
+import processing.core.PApplet;
+import static processing.core.PConstants.DOWN;
+import static processing.core.PConstants.LEFT;
+import static processing.core.PConstants.RIGHT;
+import static processing.core.PConstants.UP;
+
+class Viewport
+{
+    PApplet applet;
+    public Viewport(PApplet applet){ 
+        this.applet = applet;
+    }
+    float savepx=0;
+    float savepy=0;
+    int selID=0;
+    float zoom=1.0f;
+    float difx=0;
+    float dify=0;
+    int lastscr=0;
+    boolean EnableZooming=true;
+    float scrollcamspeed=1.1f;
+
+    float MouseToWorldCoordX(int x)
+    {
+        return 1/zoom*(x-difx-applet.width/2);
+    }
+    float MouseToWorldCoordY(int y)
+    {
+        return 1/zoom*(y-dify-applet.height/2);
+    }
+    boolean md=false;
+    void mousePressed()
+    {
+        md=true;
+        if(applet.mouseButton==RIGHT)
+        {
+            savepx=applet.mouseX;
+            savepy=applet.mouseY;
+        }
+    }
+    void mouseReleased()
+    {
+        md=false;
+    }
+    void mouseDragged()
+    {
+        if(applet.mouseButton==RIGHT)
+        {
+            difx+=(applet.mouseX-savepx);
+            dify+=(applet.mouseY-savepy);
+            savepx=applet.mouseX;
+            savepy=applet.mouseY;
+        }
+    }
+    float camspeed=20.0f;
+    float scrollcammult=0.92f;
+    boolean keyToo=true;
+    void keyPressed()
+    {
+        if((keyToo && applet.key=='w') || applet.keyCode==UP)
+        {
+            dify+=(camspeed);
+        }
+        if((keyToo && applet.key=='s') || applet.keyCode==DOWN)
+        {
+            dify+=(-camspeed);
+        }
+        if((keyToo && applet.key=='a') || applet.keyCode==LEFT)
+        {
+            difx+=(camspeed);
+        }
+        if((keyToo && applet.key=='d') || applet.keyCode==RIGHT)
+        {
+            difx+=(-camspeed);
+        }
+        if(!EnableZooming)
+        {
+            return;
+        }
+        if(applet.key=='-' || applet.key=='#')
+        {
+            float zoomBefore=zoom;
+            zoom*=scrollcammult;
+            difx=(difx)*(zoom/zoomBefore);
+            dify=(dify)*(zoom/zoomBefore);
+        }
+        if(applet.key=='+')
+        {
+            float zoomBefore=zoom;
+            zoom/=scrollcammult;
+            difx=(difx)*(zoom/zoomBefore);
+            dify=(dify)*(zoom/zoomBefore);
+        }
+    }
+    void Init()
+    {
+        difx=-applet.width/2;
+        dify=-applet.height/2;
+    }
+    void mouseScrolled(float mouseScroll)
+    {
+        if(!EnableZooming)
+        {
+            return;
+        }
+        float zoomBefore=zoom;
+        if(mouseScroll>0)
+        {
+            zoom*=scrollcamspeed;
+        }
+        else
+        {
+            zoom/=scrollcamspeed;
+        }
+        difx=(difx)*(zoom/zoomBefore);
+        dify=(dify)*(zoom/zoomBefore);
+    }
+    void Transform()
+    {
+        applet.translate(difx+0.5f*applet.width,dify+0.5f*applet.height);
+        applet.scale(zoom,zoom);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/opennars/sgui/NarSimpleGUI.form b/src/main/java/com/opennars/sgui/NarSimpleGUI.form
new file mode 100644
index 0000000000000000000000000000000000000000..7fe8d3b75e191ff01515c073e95e8ae76830eca5
--- /dev/null
+++ b/src/main/java/com/opennars/sgui/NarSimpleGUI.form
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
+  <Properties>
+    <Property name="defaultCloseOperation" type="int" value="3"/>
+  </Properties>
+  <SyntheticProperties>
+    <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
+    <SyntheticProperty name="generateCenter" type="boolean" value="false"/>
+  </SyntheticProperties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="1" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" attributes="0">
+                      <Component id="jButton1" min="-2" pref="68" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jButton2" min="-2" pref="68" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jButton4" min="-2" pref="68" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jButton3" min="-2" pref="68" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
+                      <Component id="jSlider1" min="-2" pref="173" max="-2" attributes="0"/>
+                      <EmptySpace type="unrelated" max="-2" attributes="0"/>
+                      <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jSlider2" min="-2" pref="173" max="-2" attributes="0"/>
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
+                      <EmptySpace min="0" pref="9" max="32767" attributes="0"/>
+                  </Group>
+                  <Group type="102" attributes="0">
+                      <Group type="103" groupAlignment="0" attributes="0">
+                          <Component id="jScrollPane1" max="32767" attributes="0"/>
+                          <Component id="jScrollPane2" max="32767" attributes="0"/>
+                      </Group>
+                      <EmptySpace max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="0" attributes="0">
+              <EmptySpace min="-2" pref="9" max="-2" attributes="0"/>
+              <Component id="jScrollPane1" min="-2" pref="95" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="1" attributes="0">
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="jButton1" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="jButton2" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="jButton3" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
+                      <Component id="jButton4" alignment="3" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <Component id="jSlider2" min="-2" max="-2" attributes="0"/>
+                  <Component id="jSlider1" min="-2" max="-2" attributes="0"/>
+                  <Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jScrollPane2" pref="313" max="32767" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JTextPane" name="jTextPane1">
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JButton" name="jButton1">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="Input"/>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
+      </Events>
+    </Component>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane2">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JTextPane" name="jTextPane2">
+          <Properties>
+            <Property name="editable" type="boolean" value="false"/>
+            <Property name="doubleBuffered" type="boolean" value="true"/>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Component class="javax.swing.JSlider" name="jSlider1">
+      <Events>
+        <EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="jSlider1StateChanged"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel1">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="Volume"/>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JButton" name="jButton2">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="Start"/>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton2ActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JButton" name="jButton3">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="Focus"/>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton3ActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JLabel" name="jLabel2">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="Speed"/>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JSlider" name="jSlider2">
+      <Events>
+        <EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="jSlider2StateChanged"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JButton" name="jButton4">
+      <Properties>
+        <Property name="text" type="java.lang.String" value="Stop"/>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton4ActionPerformed"/>
+      </Events>
+    </Component>
+    <Component class="javax.swing.JCheckBox" name="jCheckBox1">
+      <Properties>
+        <Property name="selected" type="boolean" value="true"/>
+        <Property name="text" type="java.lang.String" value="Show derivaitons"/>
+      </Properties>
+    </Component>
+  </SubComponents>
+</Form>
diff --git a/src/main/java/com/opennars/sgui/NarSimpleGUI.java b/src/main/java/com/opennars/sgui/NarSimpleGUI.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f5ee6ce24a48f91e53699f35025f931fc186c68
--- /dev/null
+++ b/src/main/java/com/opennars/sgui/NarSimpleGUI.java
@@ -0,0 +1,297 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.opennars.sgui;
+
+import javax.swing.text.DefaultCaret;
+import static javax.swing.text.DefaultCaret.ALWAYS_UPDATE;
+import org.opennars.entity.Task;
+import org.opennars.io.events.EventEmitter;
+import org.opennars.io.events.Events;
+import org.opennars.io.events.OutputHandler.EXE;
+import org.opennars.main.Nar;
+
+/**
+ *
+ * @author patha
+ */
+public class NarSimpleGUI extends javax.swing.JFrame {
+
+    String narText = "";
+    public class NarListener implements EventEmitter.EventObserver {  
+        @Override
+        public void event(Class event, Object[] args) {
+            synchronized(narText) {
+                boolean changed = false;
+                if (jCheckBox1.isSelected() && event == Events.TaskAdd.class) {
+                    Task t = (Task) args[0];
+                    if (t.isInput() || t.getPriority()*100.0f > 100.0f-nar.narParameters.VOLUME) {
+                        narText += t + "\n";;
+                        changed = true;
+                    }
+                }
+                if (event == Events.Answer.class) {
+                    Task t = (Task) args[0];
+                    if (t.isInput()) {
+                        narText += t + " solution: "+t.getBestSolution() + "\n";
+                        changed = true;
+                    }
+                }
+                if(event == EXE.class) {
+                    Task t = (Task) args[0];
+                    narText += "Executed: " + t + "\n";
+                    changed = true;
+                }
+                int maxChars = 2000;
+                if(changed) {
+                    if(narText.length() > maxChars) {
+                        narText = narText.substring(narText.length() / 2, narText.length());
+                    }
+                    jTextPane2.setText(narText);
+                }
+            }
+        }
+    }
+     
+    Nar nar = null;
+    /**
+     * Creates new form NARSimpleGUI
+     */
+    public NarSimpleGUI(Nar nar) {
+        this.nar = nar;
+        initComponents();
+        DefaultCaret caret = (DefaultCaret) jTextPane2.getCaret();
+        caret.setUpdatePolicy(ALWAYS_UPDATE);
+        jSlider1.setValue(nar.narParameters.VOLUME);
+        this.setTitle("OpenNARS v3.0.0 Simple GUI");
+        NarListener handler = new NarListener();
+        nar.on(Events.TaskAdd.class, handler);
+        nar.on(Events.Answer.class, handler);
+        nar.on(EXE.class, handler);
+        this.show();
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jScrollPane1 = new javax.swing.JScrollPane();
+        jTextPane1 = new javax.swing.JTextPane();
+        jButton1 = new javax.swing.JButton();
+        jScrollPane2 = new javax.swing.JScrollPane();
+        jTextPane2 = new javax.swing.JTextPane();
+        jSlider1 = new javax.swing.JSlider();
+        jLabel1 = new javax.swing.JLabel();
+        jButton2 = new javax.swing.JButton();
+        jButton3 = new javax.swing.JButton();
+        jLabel2 = new javax.swing.JLabel();
+        jSlider2 = new javax.swing.JSlider();
+        jButton4 = new javax.swing.JButton();
+        jCheckBox1 = new javax.swing.JCheckBox();
+
+        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+
+        jScrollPane1.setViewportView(jTextPane1);
+
+        jButton1.setText("Input");
+        jButton1.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jButton1ActionPerformed(evt);
+            }
+        });
+
+        jTextPane2.setEditable(false);
+        jTextPane2.setDoubleBuffered(true);
+        jScrollPane2.setViewportView(jTextPane2);
+
+        jSlider1.addChangeListener(new javax.swing.event.ChangeListener() {
+            public void stateChanged(javax.swing.event.ChangeEvent evt) {
+                jSlider1StateChanged(evt);
+            }
+        });
+
+        jLabel1.setText("Volume");
+
+        jButton2.setText("Start");
+        jButton2.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jButton2ActionPerformed(evt);
+            }
+        });
+
+        jButton3.setText("Focus");
+        jButton3.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jButton3ActionPerformed(evt);
+            }
+        });
+
+        jLabel2.setText("Speed");
+
+        jSlider2.addChangeListener(new javax.swing.event.ChangeListener() {
+            public void stateChanged(javax.swing.event.ChangeEvent evt) {
+                jSlider2StateChanged(evt);
+            }
+        });
+
+        jButton4.setText("Stop");
+        jButton4.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                jButton4ActionPerformed(evt);
+            }
+        });
+
+        jCheckBox1.setSelected(true);
+        jCheckBox1.setText("Show derivaitons");
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+        getContentPane().setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+                .addContainerGap()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(layout.createSequentialGroup()
+                        .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 68, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 68, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(jButton4, javax.swing.GroupLayout.PREFERRED_SIZE, 68, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 68, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(jLabel1)
+                        .addGap(2, 2, 2)
+                        .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, 173, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+                        .addComponent(jLabel2)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, 173, javax.swing.GroupLayout.PREFERRED_SIZE)
+                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                        .addComponent(jCheckBox1)
+                        .addGap(0, 9, Short.MAX_VALUE))
+                    .addGroup(layout.createSequentialGroup()
+                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                            .addComponent(jScrollPane1)
+                            .addComponent(jScrollPane2))
+                        .addContainerGap())))
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGap(9, 9, 9)
+                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+                        .addComponent(jButton1)
+                        .addComponent(jLabel1)
+                        .addComponent(jButton2)
+                        .addComponent(jButton3)
+                        .addComponent(jLabel2)
+                        .addComponent(jButton4))
+                    .addComponent(jSlider2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(jSlider1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                    .addComponent(jCheckBox1))
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 313, Short.MAX_VALUE)
+                .addContainerGap())
+        );
+
+        pack();
+    }// </editor-fold>//GEN-END:initComponents
+
+    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
+        nar.addInput(jTextPane1.getText());
+        jTextPane1.setText("");
+    }//GEN-LAST:event_jButton1ActionPerformed
+
+    private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSlider1StateChanged
+        nar.narParameters.VOLUME = jSlider1.getValue();
+    }//GEN-LAST:event_jSlider1StateChanged
+
+    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
+        nar.start();
+    }//GEN-LAST:event_jButton2ActionPerformed
+
+    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
+        jSlider1.setValue(0);
+        jSlider2.setValue(jSlider2.getMaximum());
+    }//GEN-LAST:event_jButton3ActionPerformed
+
+    private void jSlider2StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSlider2StateChanged
+        nar.narParameters.MILLISECONDS_PER_STEP = jSlider2.getMaximum() - jSlider2.getValue();
+        nar.stop();
+        nar.start();
+    }//GEN-LAST:event_jSlider2StateChanged
+
+    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed
+        nar.stop();
+    }//GEN-LAST:event_jButton4ActionPerformed
+
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String args[]) {
+        /* Set the Nimbus look and feel */
+        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
+        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
+         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
+         */
+        try {
+            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
+                if ("Nimbus".equals(info.getName())) {
+                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
+                    break;
+                }
+            }
+        } catch (ClassNotFoundException ex) {
+            java.util.logging.Logger.getLogger(NarSimpleGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+        } catch (InstantiationException ex) {
+            java.util.logging.Logger.getLogger(NarSimpleGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+        } catch (IllegalAccessException ex) {
+            java.util.logging.Logger.getLogger(NarSimpleGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
+            java.util.logging.Logger.getLogger(NarSimpleGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+        }
+        //</editor-fold>
+        //</editor-fold>
+        Nar nar = null;
+        try {
+            nar = new Nar();
+        } catch (Exception ex) {
+            System.out.println("Failed to init Nar: "+ex.toString());
+            System.exit(1);
+        }
+        final Nar narForGui = nar;
+        /* Create and display the form */
+        java.awt.EventQueue.invokeLater(new Runnable() {
+            public void run() {
+                new NarSimpleGUI(narForGui).setVisible(true);
+            }
+        });
+    }
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JButton jButton1;
+    private javax.swing.JButton jButton2;
+    private javax.swing.JButton jButton3;
+    private javax.swing.JButton jButton4;
+    private javax.swing.JCheckBox jCheckBox1;
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JLabel jLabel2;
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JScrollPane jScrollPane2;
+    private javax.swing.JSlider jSlider1;
+    private javax.swing.JSlider jSlider2;
+    private javax.swing.JTextPane jTextPane1;
+    private javax.swing.JTextPane jTextPane2;
+    // End of variables declaration//GEN-END:variables
+}