import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.math.*;
//mainClassName SmartyMain
import javax.swing.filechooser.*;
import javax.swing.border.TitledBorder;
import javax.swing.border.*;
import java.text.*;
import javax.swing.undo.UndoManager;
import java.nio.charset.Charset;
import java.text.NumberFormat;
import java.awt.datatransfer.StringSelection;
import javax.imageio.metadata.*;
import javax.imageio.stream.*;
import java.text.SimpleDateFormat;
import javax.swing.event.AncestorListener;
import javax.swing.event.AncestorEvent;
import javax.swing.Timer;
import java.util.TimeZone;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.geom.Rectangle2D;
import java.nio.file.Path;
class main {
//set flag Reparse.
// AI begins here
static String substring(String s, int x) {
return substring(s, x, strL(s));
}
static String substring(String s, int x, int y) {
if (s == null) return null;
if (x < 0) x = 0;
int n = s.length();
if (y < x) y = x;
if (y > n) y = n;
if (x >= y) return "";
return s.substring(x, y);
}
// convenience method for quickly dropping a prefix
static String substring(String s, CharSequence l) {
return substring(s, lCharSequence(l));
}
public static String join(String glue, Iterable strings) {
if (strings == null) return "";
if (strings instanceof Collection) {
if (((Collection) strings).size() == 1) return str(first(((Collection) strings)));
}
StringBuilder buf = new StringBuilder();
Iterator i = strings.iterator();
if (i.hasNext()) {
buf.append(i.next());
while (i.hasNext())
buf.append(glue).append(i.next());
}
return buf.toString();
}
public static String join(String glue, String... strings) {
return join(glue, Arrays.asList(strings));
}
static String join(Iterable strings) {
return join("", strings);
}
static String join(Iterable strings, String glue) {
return join(glue, strings);
}
public static String join(String[] strings) {
return join("", strings);
}
static String join(String glue, Pair p) {
return p == null ? "" : str(p.a) + glue + str(p.b);
}
static int lastIndexOf(String a, String b) {
return a == null || b == null ? -1 : a.lastIndexOf(b);
}
static int lastIndexOf(String a, char b) {
return a == null ? -1 : a.lastIndexOf(b);
}
// starts searching from i-1
static int lastIndexOf(List l, int i, A a) {
if (l == null) return -1;
for (i = min(l(l), i)-1; i >= 0; i--)
if (eq(l.get(i), a))
return i;
return -1;
}
static int lastIndexOf(List l, A a) {
if (l == null) return -1;
for (int i = l(l)-1; i >= 0; i--)
if (eq(l.get(i), a))
return i;
return -1;
}
static String padLeft(String s, char c, int n) {
return rep(c, n-l(s)) + s;
}
// default to space
static String padLeft(String s, int n) {
return padLeft(s, ' ', n);
}
static String trim(String s) { return s == null ? null : s.trim(); }
static String trim(StringBuilder buf) { return buf.toString().trim(); }
static String trim(StringBuffer buf) { return buf.toString().trim(); }
static class Smarty extends Concept {
static final String _fieldOrder = "IntensityRange Sense Processing50 MaxBodies World bodies VB_Name JND Smarty LeftArrow RightArrow UpArrow DownArrow FourWay Smarty0 BodySetting BodyConfig BodyValue BodyPointing North East South West NumSenses MaxSenses IsSense Senses SensorStimuli PropertyBinonType SymbolicOrMagnitude LowerRangeLimit UpperRangeLimit LinearOrCircular IntegersOrLogs NumberOfSensors SensorsDependentOrIndependent Symbolic Magnitude Linear Circular IntegerValues LogValues Dependent Independent SensorValues Valu XQCnt NoName Motion NoMove WheelMovement ABlock Wall EmptySquare Fired Current NumDevices MaxDevices Device IsDevice Devices DeviceResponses DeviceValues NoResp WheelsTurn MoveForward MoveToLeft MoveToRight MoveBackward TurnRght TurnLft TurnArnd NoMoveOrTurn NumActs RotateActs NumBinons MaxBinons OverLimit Binons BType O1 TQ O2 GQ IDL IntVl OLv SP TriggerList TriggerCount GoalList GoalCount AE NullObject NOVEL INTERESTING FAMILIAR NoInterest InterestLevels Sequential Parallel Action Attention MaxBinonTypes NumBinonTypes BinonTypeName BinName BinAbbreviation BinonTypes ActBin NumProperties NullType SensOrDevNum SensedBinons NumPercepts MaxPercepts Percepts BinId PerceptSources FirstSource SecondSource PerceptLevel NumTargets MaxTargets Targets NLnk TargetBinon NullTarget NumDHabits TopLevel HighestPerceptLvl MaxLevels STM TQCnt MoveAmount PerceivedBinon LTMEMORY LtmPerceptTyp LtmPerceptBin LtmESType LtmESActBin LtmARType LtmARActBin LtmActionTyp LtmActionBin StoreAt MaxMemory INPUTS OUTPUTS SizeBase IntensityBase ASpace SequentialSign ParallelSign CreateAll Normal Happy Unhappy PartMatch DoingReaction DoingRepeat LastAct LIN COUNTIN RecentWorld RecentBody OperatingMode Running Started vbDblQuote Black White LightBlue DarkBlue";
int IntensityRange;
String[] Sense = new String[10+1];
boolean Processing50 = false;
int MaxBodies;
transient TheWorld World;
Bodies bodies = new Bodies();
static class TheWorld {
public String LookUnder() {
return "";
}
public void MoveWest() {
}
public void MoveSouth() {
}
public void MoveEast() {
}
public void MoveNorth() {
}
public void PointUnder() {
}
public void PointNorth() {
}
public void PointSouth() {
}
public void PointWest() {
}
public void PointEast() {
}
public void DisplayStimuliAndResponse(int[][][] sensorValues, char resp) {
}
public int RangeSouth() {
return 0;
}
public int RangeNorth() {
return 0;
}
public int RangeEast() {
return 0;
}
public int RangeWest() {
return 0;
}
public String LookSouth() {
return "";
}
public String LookNorth() {
return "";
}
public String LookEast() {
return "";
}
public String LookWest() {
return "";
}
public void Update_View() {}
public void setBinonDisplayObjList(String text) {}
public void setBinonDisplayChngResults(String text) {}
public void appendBinonDisplayChngResults(String text) {}
public void showSensorValues(String text) {}
public void showDeviceValues(String text) {}
} // end of TheWorld
String VB_Name = "Adaptron";
// Originally was a TEST VERSION WHICH PRODUCES RANDOM INPUT AND
//CHECKS MEMORY TO SEE IF IT CONTAINS THE SAME STUFF
//Obviously must have spun it off of Think 5
// Adaptron/Cognitron Algorithm - Program - Feb. 2003 test
// (C) Copyright 2007, Adaptron Inc.
//
//THINK3 IS NOT HANDLING CONSCIOUS HABITS PROPERLY
//THINK4 IS EXPERIMENT IN EXPECTATIONS BEING SAVED
//THINK5 DOES A PROPER JOB OF HANDLING R-HABITS
//11 July 2002 - attempting to get the 2 bugs out of pattern matching
//13th July 2002 - put back the stimulus matching mem location use for
// habit continuation checking in the right order - resulting stimulus
// first then is it an expected trigger.
//pattern4 - July 28, format display better
//pattern5 - July 29 week - trace display improvements -got out bug in
// habit collapsing
//pattern6 - Aug 3 - test some more
//pattern7 - Aug 9 - more tests with manual input, THEN AUTOMATED AGAIN
//pattern8 - Aug 13 - I did top and bottom expected stimuli in habit in
// previous version - now I need to introduce expected stimuli
// in the habit stack fixed up Context saving too - but I think
// some context could be put in LTM for pattern matching on
// context so it doesn't get too long or do pattern matching on
// context while in STM.
//Pattern9 - incorporate thinking changes from Think8 and turn on responses
//Went back to the THINK versions and incorporated results from Pattern9
//THINK7 DOES A PROPER JOB OF HANDLING R-HABITS
//THINK8 Well documented version
// Fixed up some stuff and comments and made it into ACTIONS8.BAS Aug 16th 2002
//ACTIONS8 - Work on comments and then responses -Then went back to Pattern
//versions and worked on Pattern0 -Active Habits that fail attract attention
//and then incorporated these results into Actions8.
//Actions9 - Started to investigate response habits - fixed up
// NOADDSHABITS and removed NOADDHABITS.
//ACTION10 - Make no distinction between doing nothing and doing something
// until the last minute when go to do it.
// - Refine priority of what attracts attention especially for
// familiar input.
//EXPLORE1 - Test it out
//EXPLORE2 - Improve context saving. Use 16 bit memory locations.
// - HAVING PROBLEM WITH HABIT MATCHING - CREATE NEW VERSION
//EXPLORE3 - Change habit stack so current one is on top and any ADDSHABITS
// are below it. Stopped it using context in habits being done.
//EXPLORE4 - Removed code for context saving.
//Explore5 - Visual Basic 6 Version with different windows for LTM, STM etc.
// Boredom turned on for current stimulus and result
// habitualized and this habit has a familiar or novel result
// based on InterestLevel. Old Boredom code commented out.
//Explore6 13th July 2003 Try to make feelings of novel, familiar etc.
// into a new stimulus type which result in information about
// success or failure.
// 12th Aug 2003 Decided not to do this. Instead am
// going to add R-Habits. Decided R-Habits already taken care
// of. Added continuous stimuli from both senses. Investigate
// looping behaviour and subconscious habit execution. Haven't
// done looping but it seems pretty stable.
//Explore7 11th Sept 2003 Now work on subconscious habit execution.
// Add loop execution in subconscious habits
// 24th Sept Allow multiple stimuli on S-List - 1 external &
// 1 internal stimulus. Then fix bugs / features
//Explore8 1st Oct 2003 Now work on R-habits and their execution.
//Explore9 6th Nov 2003 Major change required in how memory stored and
// used - less emphasis on efficiency and episodic accuracy.
// Added multiple S-habit recognition and context of S-habit
// Added conscious looping of permanent S-habits
//Happy1 25th Nov 2003 Add in pain and pleasure. 11th Dec Added
// expectation of Novel as Interesting - exploration is better.
//Happy2 17th Dec 2003 First attempt at adding thinking
// 7th Jan 2004 small changes
//Happy3 10th Jan 2004 turn off separate Trigger and Result stimuli,
// add control flags for it and DoingReflex.
//Happy4 13th Jan,Seperate permanence property from feeling for stimuli
// Add Response Habits containing Response-Stimulus-Response
// Get looping (repeating same stimulus) working properly
//Happy5 20th Jan, getting permanent working, remove stimulus roles
//Happy6 21st Jan, handle dynamic environments
//Happy7 23rd Jan, Try handling S-Habits as R-Habits-no go.
//Happy8 27th Jan, Try to get R-habits as R-S-R working. Feb 12th. Add
// subconscious processes.
//Happy9 23rd Feb, Novel stimulus becomes interesting, then familiar
// Enhance thinking, strategies for handling Interesting
//Works1 6th Mar, 2004, Attend to stimuli
//Works2 30th March, Expectation processing
//Works3 31st March, Stimulus context in LTM for S-Habits too.
//Works4 8th Apr, Recognize loops in R-Habits, Good/Bad testing
//Works5 15th Apr, turn on Kinesthetics, do subconscious habits
//Works6 work on repetition / loops
//Works7 18th July 2004, new learning strategy, Test Cases
//Works8 29th July, Good and Bad processing
//Works9 7th Sept, Generalization & Discrimination - 2 or more senses
// and subconscious habit processing
//Learn1 18th Sept, Conscious versus subconscious behaviour, added
// levels and context at end of LTM
//Learn2 3rd Nov, Kinesthetic stimuli, loops, action habits
//Learn3 23rd Nov, Rename things, subconscious A-Habits, A-sequences
//Learn4 6th Dec, Chained A-Habits, Concentration, A-Sequences
//Learn5 6th Jan, 2005, A&B sequence, thinking refined, kinesthtics,
// order of For's, Separate world
//Learn6 World front-end, ABC repeating pattern & permanent S-Habits
//Learn7 Body info, still working on S-Habits, R-Habits, separate body
//Learn8 11 May 05, separate body & Test Cases, R-Habits, P-Stimuli,
// Difference in R-Habits
//Learn9 21 June 05, 31st Dec 05, removed linked habits, novelty/familarity
// stored as feeling, work on 2nd sense and R-Habits
//Habit1 3rd March 06, New attention algorithm, only collapse permanent
// triggers of S-Habits, practice non-permanent S-Habits
//Habit2 March - Interestlevel based on A & S-Habit feelings
//Habit3 March - Good & Bad, Reward & Punishment, Feelings
//Habit4 Jan 2007 reworking interest levels
//Habit5 29th Jan 07, S-habits collapse when both stimuli are permanent
// A-habits interest propagate back to trigger, S-Habits interest
// propagates up the heirarchy.
//Habit6 16th Feb 07, Rearrange attention algorithm
//Habit7 14th March 07, Add graduated stimuli
//Habit8 25th March 07, New attention algorithm
//Habit9 3rd April 07, Sort out permanent stimuli, attention algorithm
//Cogni1 18th April 07, Work on thinking part, replace feature with sensor
// Recog1, Recog2 Recognition of objects from graduated senses.
// Add discrete Sensor Array, discrete and graduated sensors
//Cogni2 New interest derivation for experiences, new expected interest
//Cogni3 27th July 07, Each Habit has its own expected interest
//In here I worked on lines
//Cogni5 Sept 07, Reworking multiple sensors with graduated values
//Cogni6 Oct 12, 07, New S-Habit matching and find difference, multi-sensors
//Cogni7 Oct 28, 07, Multi-sensors
//Cogni8 Nov 16, 07, Use recency to solve which S-Habit to attend to. Change
// action selection strategy, use FindInstead, not FindDifference
//Cogni9 Nov 25, 07, Bucket stimuli readings, Change as a stimulus
//Grad1 Dec 14, 07, Graduated sensors, S-Habits use LTM pointers
//Grad2 Feb 4, 2008, sequences of graduated stimuli - C-Habits, generalization
//Grad3 Feb 14, 2008, Change as stimulus, new S-Habit structure
//Grad4 Feb 26, 2008, new S-Habit structure
//Grad5 Mar 9, 2008, new S-Habit structure
//Grad6 April 2008, Remove Change as a stimulus - objects represent the changes experienced
//In here I worked on lines and developed course 447
//Grad7 Jan 2009, Subconscious action habits, Interest levels
//Grad8 Feb 2009, new S-Habit structure changes
//Grad9 Mar 20, 2009, Overlapping parts of S-habits, add line recognition from Sense1
//Ideas1 April 18, 2009, Add change objects, get thinking working and upto testcase #25
//Ideas2 May 19, 2009, Use tree of sense stimuli and P-habits - not on S-List
//Ideas3 June 17, 2009, Finish conversion of S-List, Conscious Habit rework, attention alg.
//Ideas4 July 8, P-Habits
//Ideas5 July 10, Remove context processing, ignore repeating S-Habits,
//Ideas6 Aug 2, Incorporate new line recognition, Where and Order processing
//Ideas7 Sept 1st, Partial trigger matching - generalization
//Ideas8 Sept 15th, Graduated readings, 8th Dec new recognition routines, Change Reading Object
//Ideas9 Dec 15th, Separation object
//Change1 Dec 31st, Save Change objects in LTM, Add STM for sequences
//Change2 Jan 10th, 2010 create SepRdgObj, remove LTM Separs(), move STM process
//Change3 Feb 2nd, STM processing, new line recognition, sequence recognition
//Change4 May 2nd, New LTM episodic memory representation, new STM
//Change5 May 26th, Sequence and Action LTM separated
//Change6 Jun 13th, new Where obj, STM per Sense & Sensor if independent
//Change7 Jun 23rd, Interest on sequences in STM, T-List
//Change8 Jul 4th, P-Habits in STM, Body and World changes
//Change9 Jul 20th, A_Sequences implemented, Fix STM S-habit recognition / distraction
//Active1 Jul 31st, Boredom and sub-conscious A-Habits
//Active2 Aug 12th, Conscious STM and/or A-Habits
//Active3 Sept 21st, New Sequence recognition, Conscious STM
//Active4 Oct 7th, Action Habits(practicing & doing), remove partial sequential match,
// Convert interest into a property of all binons
//Active5 Nov 4th, New binon structure, thinking
//Active6 Dec 7th, Another new binon structure, fix partial match, remove reset interest
//Active7 Dec 17th, Separate Change and Interest, reduce interest upon repetition, no concentration
//Active8 Jan 22nd, 2011 remove permanent, remove current habit, separate S-habit and A-Habits
//Active9 Feb 12th, New binon structure, P-habits before Sequences, better attention
//Expect1 Mar 6th, Expect Interesting, new A-Habit structure, remove dependence concept
//Expect2 Mar 23rd, Changed DoIt structure, Experiences in STM, Conscious Seq's in STM
//Expect3 Apr 9th, New Acton structure, sequential trigger and goal recognition, removed
// Novel and Fresh concepts
//Expect4 May 3rd, Add device stimuli, Unexpected, New Acton structure
//Expect5 Aug 2nd, Action habits, STM changes
//Expect6 Sept 4th, STM just recognizes (no expectations), remove orient actons, directed
// attention on expected goal
//Expect7 Sept 20th,Added UnInteresting
//Expect8 Oct 4th, New acton structure
//Expect9 Oct 16th, P-Habits, kinesthetic sense fixed, formation of combo by A-Habit?
//Practic1 Nov 7th, Sequences and Action Habits
//Practic2 Nov 15th, STM processing and Permanent
//Practic3 Dec 12th, Before and after conscious STMs, S-Level 1 stimuli familiar
//Practic4 Jan 10th, STMs do not create A-Habits, Practice mode - redo-interest
//Practic5 Jan 31st, Practice and Goal Actons, STM processing conscious sequences
//Practic6 Feb 15th, P-Habit processing, Directed Attention, sequences of permanent stimuli
//Practic7 Mar 14th, brought in new pattern recognition
//Practic8 Apr 7th, new novel/familiar combinations and STM processing, P-Habits working
//Practic9 Apr 24th, generalization for 2 senses
//General1 May 23rd, Incorporate new Object Recognition (twice)
//General2 July 1st, Practice and Thinking, Redo versus goal interest, Random next responses
//General3 July 11th, A-habits at lowest level first, Unexpected sequential interest
//General4 July 23rd, Expectation inhibits familiar from attention, should binons come with
// habituation of a repeat sequence built in?
//General5 12th Jan 2017 - started to document it - going to insert PerceptionAction from Act2
//15th Jan 2017 'Inserted PerceptionAction() and got Inpu_KeyPress(0 and TestCases working with no babbling output.
//22nd Jan 'adding motor babbling when known action habits are familiar
//23rd Jan 'thinking and bodies starting to work
//24th Jan 'adding body #6 with two senses - vision and motion
//28th Jan 'Got Thinking Approach #1 working
//29th Jan 'Make Binon type one of the Binon properties
//30th Jan 'Create P-Habit combinations for any number of senses = properties
//2018 Aug 29th 'Clean up code before sending to Jianyong
//31st Aug 'Renamed it Smarty. Continue to clean up the code
//25th August 2019
// 'renaming percpts, actions etc. to conform with the perception-action hierarchy paper
//DefInt A - Z; //16 bits / 2 bytes
int JND; //set to 20%
final static String Smarty = "J"; // J = wingdings happy face
final static String LeftArrow = chr(239); // "<"
final static String RightArrow = chr(240); // ">"
final static String UpArrow = chr(241); // "^"
final static String DownArrow = chr(242); // "v"
String FourWay; // "+" - unused
String Smarty0; // "Smarty0" The initial / default Body name
String[] BodySetting = new String[22]; //Contains the current body being used
//Bodysetting$(0) contains the number of settings in use
String BodyConfig; //The values in the configure forms when go to Design or Select
//For determining if a change has been made.
String[] BodyValue; //Contain the values read and written to the .BDY file
//The values on the body configuration forms
int BodyPointing; //direction body is pointing, 0=East, 1=South, 2=West, 3=North
//direction body is pointing, 0=East, 1=South, 2=West, 3=North
transient final int North = 3;
transient final int East = 0;
transient final int South = 1;
transient final int West = 2; //direction body is pointing, 0=East, 1=South, 2=West, 3=North
// -------------------------- Senses and Sensors --------------------------
int NumSenses; //The number of physical senses, Max of 10, dynamically set in SetUpSense()
//Currently equals the NumProperties since each sense currently = 1 property type
int MaxSenses; //Maximum number of senses = max 10 physical senses
int IsSense; //1, Flag for Senses versus Devices
//unused String StringSense; //Names of senses, up to 10 physical senses - assigned in SetupSense()
int[][] Senses = new int[10 + 1][8 + 1]; //Properties of the different senses
//1st index = Sense number
//2nd index = Sense property
String[] SensorStimuli = new String[10 + 1]; //A string of the possible symbolic stimuli for the sensor
//---- Senses() - 2nd index values - Sense Properties - same used for Devices below
int PropertyBinonType; //1, Stimulus property binon type e.g. 1 = TextBin or 2 = ContBin
int SymbolicOrMagnitude; //2, Symbolic or Magnitude indicator
int LowerRangeLimit; //3, Lower limit of range of values, zero is minimum (65 = "A")
int UpperRangeLimit; //4, Upper limit of range of values, 255 is maximum (90 ="Z")
int LinearOrCircular; //5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Compass degrees are Circular (0 to 360)
int IntegersOrLogs; //6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs
int NumberOfSensors; //7 Number of sensors in sensor array
int SensorsDependentOrIndependent; //8 are sensors adjacent (dependent) or independent
int Symbolic; //1, Indicates that the values from this sense are symbolic, range A -> Z
int Magnitude; //2, Indicates that the values from this sense are numeric, integers, range 0 -> Limit
int Linear; //1, Indicates that the values go from the lower limit to upper limit
int Circular; //2, Indicates that the values rap around from the upper limit to 0
int IntegerValues; //1, Indicates that the values are integer readings
int LogValues; //2, Indicates that the values are already logs - orders of magnitude
int Dependent; //1, Sensors in array are beside each other (adjacent)
int Independent; //2, Sensors are not associated with each other
//-------------------- Values of stimuli from senses / sensors ------------------------------
int[][][] SensorValues = new int[10 + 1][2 + 1][1+1]; //Stimulus values from senses/sensors
//1st index is sense number, currently = property /sense binon type
//2nd index is what type of information is in the SensorValues(), XQCnt or Valu
//3rd index is Fired for the most recent stimulus value and Current for the previous
//---- SensorValues 2nd index values - type of information in SensorValues()
int Valu; //=1, the value for the stimulus, if symbolic then value = Asc(Symbol$)
int XQCnt; //=2, the count of times the value has repeated, also used below
String NoName; //"_", The character used when no letter provided for the IDL value of a TextBin binon
String Motion; //World.MoveDown() etc set this to indicate the direction the robot moved
String NoMove; //"-" to indicate there was no motion in the Motion$ stimulus value
String WheelMovement; //"-flrb..." 'will contains the possible wheel motions
//WheelMovement$ = "-flrb" & TurnRght$ & TurnLft$ & TurnArnd$ ' rotate right, left and around 180 degrees
String ABlock;
static final String Wall = chr(219); //a block, Chr$(219) is a black square in Terminal font
static final String EmptySquare = chr(177); //Chr$(177) is a fuzzy square in Terminal font
//---- SensorValues 3rd index values - which past stimulus it is - also used below
int Fired; //=0 'stimulus put in this level upon firing before being processed
int Current; //=1 'The Fired one becomes the Current one after processing
//-------------------- Devices ------------------------------------------------
int NumDevices; //Number of output devices - max 4 - dynamically set in SetupDevice()
int MaxDevices; //Maximum number of devices = max 4 devices
String[] Device = new String[4 + 1]; //Names of device, up to 4 devices - assigned in SetupDevice()
int IsDevice; //2, Flag for Devices versus Senses
int[][] Devices = new int[4 + 1][6 + 1]; //Properties of the output / response devices
//1st index = Device number
//2nd index = Device property
String[] DeviceResponses = new String[4 + 1]; //A string of the possible symbolic responses for the device
//---- Devices() - 2nd index values - Device Properties - DEFINED ABOVE
// Public PropertyBinonType '1, Response property binon type e.g. 1 = LetrBin
// Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator
// Public LowerRangeLimit '3, Lower limit of range of response values, zero is minimum (97 = "a")
// Public UpperRangeLimit '4, Upper limit of range of response values, 255 is maximum (122 = "z")
// Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Motor rotations are Circular (0 to 360)
// Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs
// Public Symbolic '1, Indicates that the values for this device are symbolic, Range a -> z
// Public Magnitude '2, Indicates that the values for this device are numeric, integers, range 0 -> limit
// Public Linear '1, Indicates that the values go from the lower limit to upper limit
// Public Circular '2, Indicates that the values rap around from the upper limit to 0
// Public IntegerValues '1, Indicates that the values are integer readings
// Public LogValues '2, Indicates that the values are already logs - orders of magnitude
//-------------------- Values of responses to devices ------------------------------
int[][] DeviceValues = new int[4 + 1][2 + 1]; //Response values for devices
//1st index is device number, currently = response property binon type
//2nd index is what type of information is in the DeviceValues(), XQCnt or Valu
//---- DeviceValues 2nd index values - type of information in DeviceValues() - DEFINED ABOVE
// Public Valu '=1, the value for the response, if symbolic then Symbol$ = Chr$(value)
// Public XQCnt '=2, the count of times the value needs repeating, also used below
transient final char NoResp = '-'; //"-", The character representing no response for a LetrBin binon
//c Public Relax$ '"-", used for a Relaxing response - currently the same as NoResp$
//and it is used as the stimulus input of the Motion sense
boolean WheelsTurn = false; //If it is false then Smarty displays as an O else it displays as ^>1 means it has more than one goal
// Used for prediction reliability, may be set >1 if needs to be combined with previous
int GoalList; //12, points to the linked list of target binons [Targets()]
// for which this binon is the right source binon (not the left source binon)
int GoalCount; //13, Count of its sequential left targets, >1 means can not predict its trigger
// Used for reliability of determining the cause, may be set >1 if needs to be combined with next
int AE; //14, Action (Percept - Act) or Attention (Act - Percept) level 1 Sequential binon
int NullObject; //-1, Indicates the O1 or O2 pointer is not pointing to another binon
//---- Interest values for Binons(x, IntVl) - must be numeric for comparison purposes
// New - 1st time experienced - attention paid to it
//---- Interest values for Binons(x, IntVl) - must be numeric for comparison purposes
final int NOVEL = 3; //3 New - 1st time experienced - attention paid to it
// To indicate it has been experienced for the second time
final int INTERESTING = 2; //2 To indicate it has been experienced for the second time
// Neutral, experienced 2 or 3 or more times
final int FAMILIAR = 1; //1 Neutral, experienced 2 or 3 or more times
int NoInterest; //-1 Interest not known yet
int InterestLevels; //2 or 3 - number of interest levels, 2= Novel and Familiar, 3= Novel, Interesting, and Familiar
//---- Sequential or Parallel property values for Binons(x, SP)
int Sequential; //-1
int Parallel; //+1
//---- Action or Attention property values for Binons(x, AE) - value = 0 for Parallel Percepts
int Action; //1
int Attention; //2
//---- BinonType property values for Binons(x, BType)
int MaxBinonTypes; //with 2 senses and 1 device this is =6, 4 senses & 4 devices = 33
int NumBinonTypes; //= 2^N+1, number of property binons, Percept combination binon types, Action type and
//the D-Habit response types - set dynamically based on SetupSense() and SetupDevice()
String[][] BinonTypeName = new String[68 + 1][2 + 1]; //The names and abbreviations for the various binon types
//---- BinonTypeName$() 2nd index values
int BinName; //1
int BinAbbreviation; //2
//The source types of property binons are 1=TextBin, 2=ContBin. There are N of these
//and all other Percept combinations such as Name&Cont.
//There are 2^N-1 Property plus Percept types
//There is just the one Action type - a sequential combination of the
//Property binons, Percept binons, response D-Habit binons and/or Action binons.
int[][] BinonTypes = new int[68 + 1][1 + 2]; //The binon types for stimuli (Percepts 15), ActBin (1) and responses (D-Habits 15)
//1st index = the type of binon (dimension = NumBinonTypes)
//2nd index = binon type property
//---- BinonTypes() - 1st Index values - stimulus and response binon types
int ActBin; //Binon type for Actions, Expectations, percepts, and action binons = NumPercepts + 1. Dynamically set
int NumProperties; //N=4, The number of stimulus property binon types - currently one property per sense
final int NullType = 0; //0, Indicates the type not set, binon will be NullObject
//---- BinonTypes() 2nd index values
int SensOrDevNum; //1, Pointer points back to sense or device
// Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator - defined above
//-------------------- Percept Stimuli Perceived ---------------------------------------
int[] SensedBinons = new int[1 + 10]; //the source binons for the Percepts() tree (only uses = Numsenses=NumProperties)
int NumPercepts; //N=63, The number of property binons and Percept combinations of them 2^NumProperties-1
int MaxPercepts; //=63 currently = (2^6)-1 would need to be (2^10) if 10 sensors
int[][][] Percepts = new int[1 + 63][1 + 2][2]; //Current and Fired Property binon and Percept IDs and XQ count
//1st index is the property / Percept binon type (dimension = NumPercepts)
//2nd index is what type of information is in the Percepts()
//3rd index is Fired=0 or Current=1
//---- Percepts 2nd index values - type of information in Percepts()
int BinId; //=1, the 2nd index value for the binon ID - defined / used below
//Public XQCnt '=2, the count of times the fired binon has been recognized / fired - DEFINED ABOVE
int[][] PerceptSources = new int[1 + 63][1 + 3]; //pointers to the lower level Percepts that are used in forming this Percept
//---- PerceptSources() 2nd index values
int FirstSource; //=1, the first / left source Percept binon
int SecondSource; //=2, the second / right source Percept binon
int PerceptLevel; //=3, The level in the Percept tree
//-------------------- Left and Right Targets ---------------------------------------
//--- Linked List of Target Binons - for all binons -------------
int NumTargets; //The number of Target binon entries created so far
int MaxTargets; //10000 = the max number of Target binon entries possible
int[][] Targets = new int[1 + 10000][1 + 2]; //pointed to by Binons(ID, TriggerList) or by Binons(ID, GoalList)
//---- Targets' 2nd index property values
int NLnk; //1 = The pointer to the next Targets() entry in this linked list,
// may be a NullTarget at end of linked list
int TargetBinon; //2 = a left or right Target binon
int NullTarget; //=0, an NLnk pointer at end of linked list
//-------------------- D-Habit Response Produced ---------------------------------------
//unused int[] RespondedBinons = new int[1 + 2]; //the response binons for the DHabits() tree (only uses = NumDevices=NumResponses)
int NumDHabits; //N=15, The number of response binons and D-Habit combinations of them 2^NumDevices-1
//unused int MaxDHabits; //=15 currently = (2^4)-1
//unused int[][][] DHabits = new int[1 + 15][1 + 2][1 + 1]; //Current and Fired Property binon and Percept IDs and XQ count
//1st index is the property / Percept binon type (dimension = NumPercepts)
//2nd index is what type of information is in the Percepts()
//3rd index is Fired=0 or Current=1
//---- Percepts 2nd index values - type of information in Percepts()
//Public BinId '=1, the 2nd index value for the binon ID - defined above
//Public XQCnt '=2, the count of times the fired binon has been recognized / fired - DEFINED ABOVE
//-------------------- Action Stimuli Perceived ---------------------------------------
int TopLevel; //The highest level with any binons in it in STM
int HighestPerceptLvl; //The highest STM() entry produced / fired per cycle
int MaxLevels; //=25, The highest level of complexity to which the tree can grow
int[][][] STM = new int[25+1][3+1][25+1]; //STM current history of Patterns - a tree with parts at level 1
//1st index is the stimulus object level
//2nd index =1 for binon type, =2 for binon ID, =3 for XQCnt, =4 for TQCnt
//3rd index = Fired = 0 for the just fired stimulus
// = Current = 1 for the Current perceived stimuli
//They can all be expecting a repeat or a changed / different value
// = Last one whose position is the last STM entry that has something in it
//---- STM 2nd index values - type of information in STM()
//Public BinId '=1, the binon ID - DEFINED ABOVE
//Public XQCnt '=2, the count of times the fired binon has been recognized / fired / repeated - Defined above
int TQCnt; //=3, the count of times its trigger fired for repeat size comparison
//---- STM 3rd index values - which past stimulus is it - DEFINED ABOVE
// Public Fired '=0 'stimulus put in this level upon firing before being processed
// Public Current '=1 'The fired one becomes the current one after processing
int MoveAmount; //Move right amount to eliminate previous pattern - set in ProcessSTMLevel()
//--------------------- Conscious Binons -----------------------------------------
int PerceivedBinon; //predicting/expecting the next binon as the goal. May have 0, 1 or more associating binons.
//-------------------- Long Term Memory (LTM) - Monitoring Info. -------------------------
//For Display purposes only by Adapt.DUMPLTM in Adapt.LTMem
//Long term memory contains a list of the stimuli that have been paid attention to.
//It stores Perceptual sequences as a pair of sequential memory locations.
int[][] LTMEMORY = new int[2000+1][8+1];
//1st index is StoreAt cycle number
//2nd index is what type of information is in the LTM
//---- LTMEMORY() 2nd index values - type of information in LTMEMORY()
int LtmPerceptTyp; //1 Percept binon type
int LtmPerceptBin; //2 Percept binon
int LtmESType; //3 Type of ES Binon - may be an S
int LtmESActBin; //4 ES Actbin
int LtmARType; //5 Type of AR Binon - may be an R
int LtmARActBin; //6 AR ActBin
int LtmActionTyp; //7 Action binon type
int LtmActionBin; //8 Action binon
int StoreAt; //LTM POSITION OF LAST STIMULUS - location in LTMEMORY() - incremented by PerceptionAction()
int MaxMemory; //2000
//----------------------Input/Output History ----------------------------------------
//For display by Adapt.HISTORYDISPLAY in Adapt.IO
String[][] INPUTS = new String[2000][10+1]; //INPUT history - List of sense stimuli for each sense (1 to 10)
String[][] OUTPUTS = new String[2000][4+1]; //OUTPUT history - List of Responses for each device (1 to 4)
//-------------------- Other Variables ------------------------------------------
double SizeBase; //1.2 for a 20% just noticeable difference
double IntensityBase; //If it is 2.0 then that is a 100% just noticeable difference
//-------------------- Operational Values - Adaptron --------------------
String ASpace;
//char SequentialSign = first(unicode_rightPointingTriangle()); //Chr$(16) ">"
transient char SequentialSign = '>';
String ParallelSign; // "+" was Chr$(186) two vertical lines was "/"
boolean CreateAll = false; //True if create all combinations
//False if use only familiar parts
// ********* Counters, Temporary values, Flags and Pointers ******
//---------------------- Operational Values -------------------------------
int Normal;
int Happy;
int Unhappy;
int PartMatch; //Used as ActTypes for body display
//unused boolean PracticeMode; //Practicing the PracticeActon. Still performing it.
//When finished in PracticeMode then we switch to GoalMode.
//unused Public PracticeActon; //The acton that is being practiced
//static Public ActiveActon; //The highest level active acton being done subconsciously
//If set then this is being done subconsciously (not being practiced)
//static Public DoingAct1; //The Act is being done even though it is not being practiced
//This does not include the do Relax act
//unused Public GoalExpected; //Goal expected by Action started - to measure success or failure
//= 0 if no expectation because doing reflexive response
//unused Public GoalSoFar; //Keeps track of the part of the expected goal obtained so far
//unused boolean GoalMode; //Concentrating on the goal of the action being practiced.
//We have finished the acton execution.
//If set it will cause directed attention to the GoalExpected
//unused Public ExpectedGoal; //Goal expected for thinking about
//unused Public TraceGoal; //Used for Trace - The goal we are either trying to achieve or avoid
//unused Public MATCHUSE; //Trigger match Action in Actons() that is interesting to do
//unused Public ActionDesire; //Interest in the MATCHUSE entry for AttendTo
//unused Public PartialMATCHUSE; //same as MATCHUSE but for partial matches
//unused Public PartialActionDesire;
//unused Public PartialTrigger; //set to the partial trigger object if partial trigger true
//unused boolean ThoughtUsed;
boolean DoingReaction = false; //set true if last response was reactive / reflex
boolean DoingRepeat = false; //set true if repeating a known response as a reflexive reaction
int LastAct; //Last reflexive response used from Acts list
//unused Public NextAct; //The next output act for reflexive response from Acts()
//unused Public ResponseOutput; //The one output in this cycle for storing in LTM trace
//unused Public Recency;
//unused boolean PracticeIt; //Global because used in Trace()
//unused boolean DoIt; //Global because used in Trace()
//unused boolean React; //Global because used in Trace()
int LIN; //Count of how many stimuli have been input/output in INPUTS$() and OUTPUTS$()
//unused boolean FreezeSList; //When true don't do the DUMPSTIMS any more
int COUNTIN; //Count of inputs for display of history
String[] RecentWorld = new String[4]; //The list of recent .WLD files created - kept in RecentWldList.TXT
String[] RecentBody = new String[4]; //The list of recent .BDY files created - kept in RecentBdyList.TXT
int OperatingMode; //Either, Running World or just Started
int Running;
int Started;
// ********* Counters, Temporary values, Flags and Pointers ******
//unused Public I, J, T, M, H, N, K, P, F, S, Hab;
//unused Public ThoughtDesire;
char vbDblQuote;
// --------------- Colours --------------
int Black;
int White;
int LightBlue;
int DarkBlue;
// End of (Declarations)
public void Initialize_Adaptron() {
//Called only once from World form when it loads, World.Form_Load()
//Initialize all values that don't change
FourWay = chr(170);
Smarty0 = "Smarty0"; //The initial / default Body name
InitBodySettingsToSmarty0(); //sets the inital values in BodySetting$()
// -------------------------- Senses and Sensors --------------------------
MaxSenses = 10; //max no. of physical senses possible in Values$ arrays
IsSense = 1; // Flag for Senses versus Devices
//---- Senses() and Devices() - 2nd index values - Sense and device Properties
PropertyBinonType = 1; // Stimulus property binon type e.g. 1 = TextBin or 2 = ContBin
SymbolicOrMagnitude = 2; // Symbolic or Magnitude indicator
LowerRangeLimit = 3; // Lower limit of range of values, zero is minimum (65 = "A")
UpperRangeLimit = 4; // Upper limit of range of values, 255 is maximum (90 ="Z")
LinearOrCircular = 5; // Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Compass degrees are Circular (0 to 360)
IntegersOrLogs = 6; // Integer Values or Log Values, Temperatures are Integers while Decibels are Logs
NumberOfSensors = 7; // Number of sensors in sensor array
SensorsDependentOrIndependent = 8; // Are sensors adjacent (dependent) or independent
Symbolic = 1; // Indicates that the values from this sense are symbolic, range A -> Z
Magnitude = 2; // Indicates that the values from this sense are numeric, integers, range 0 -> Limit
Linear = 1; // Indicates that the values go from the lower limit to upper limit
Circular = 2; // Indicates that the values rap around from the upper limit to 0
IntegerValues = 1; // Indicates that the values are integer readings
LogValues = 2; // Indicates that the values are already logs - orders of magnitude
Dependent = 1; // Sensors in array are beside each other (adjacent)
Independent = 2; // Sensors are not associated with each other
//-------------------- Values of stimuli from senses / sensors ------------------------------
//---- SensorValues 2nd index values - type of information in SensorValues()
Valu = 1; // the value for the stimulus, if symbolic then value = Asc(Symbol$)
XQCnt = 2; // the count of times the value has repeated, also used below
NoName = "_"; // The character used when no letter provided for the IDL value of a TextBin binon
ABlock = "#"; //a # for internal use to indicate a block at the location
//---- SensorValues 3rd index values - which past stimulus it is - also used below
Fired = 0; //stimulus put in this level upon firing before being processed
Current = 1; //The Fired one becomes the Current one after processing
//-------------------- Devices ------------------------------------------------
MaxDevices = 4; //Maximum number of devices = max 4 devices
IsDevice = 2; // Flag for Devices versus Senses
NoMoveOrTurn = "z"; //"z" indicates Smarty does not have this move ability
WheelMovement = "-flrb" + TurnRght + TurnLft + TurnArnd; // rotate right, left and around 180 degrees
NoMove = WheelMovement.substring(0, 1); //"-" to indicate there was no motion in the Motion$ stimulus value
//-------------------- The Stimulus Objects (Binons) -------------------------
MaxBinons = 5000; // Max number of binons per type
MaxBinonTypes = 68; //with 2 senses and 1 device this is =5
//---- BinonTypeName$() 2nd index values
BinName = 1;
BinAbbreviation = 2;
//---- BinonTypes() 2nd index values
SensOrDevNum = 1; // Pointer points back to sense or device
// SymbolicOrMagnitude = 2 ' Symbolic or Magnitude indicator - initialized above
//-------------------- Percept Stimuli Perceived ---------------------------------------
MaxPercepts = 63; // currently based on maxsenses=5 senses=number of property types
//---- Percepts() 2nd index values - type of information in Percepts()
BinId = 1; // the 2nd index value for the binon ID - defined / used below
//XQCnt = 2 ' the count of times the fired binon has been recognized / fired - DEFINED ABOVE
//---- PerceptSources() 2nd index values
FirstSource = 1; // the first / left source Percept binon
SecondSource = 2; // the second / right source Percept binon
PerceptLevel = 3; // The level in the Percept tree
//---- Binons() Properties - 2nd index values
BType = 1; // The type of binon
O1 = 2; // Left source binon pointer
TQ = 3; // the count of times the trigger has fired
O2 = 4; // Right source binon pointer
GQ = 5; // the number of times the goal has fired
IDL = 6; // The ratio value of the binon
IntVl = 7; // Interest Value (NOVEL, INTERESTING, or Familiar)
OLv = 8; // Level of object = number of lowest level parts involved
SP = 9; // Sequential or Parallel property
TriggerList = 10; // points to the linked list of right target binons [Targets()]
TriggerCount = 11; // Count of its sequential right targets, >1 means it has more than one goal
GoalList = 12; // points to the linked list of left target binons [Targets()]
GoalCount = 13; // Count of its sequential left targets, >1 means can not predict its trigger
AE = 14; // Action (Stimulus - Response) or Attention (Response - Stimulus) level 1 Sequential binon
NullObject = -1; // Indicates the O1 or O2 pointer is not pointing to another binon
NoInterest = -1; // Interest not known yet
InterestLevels = 2; //2 or 3 - number of interest levels, 2= Novel and Familiar, 3= Novel, Interesting, and Familiar
//---- Sequential or Parallel property values for Binons(x, SP)
Sequential = -1;
Parallel = 1;
//---- Action or Attention property values for Binons(x, AE)
Action = 1;
Attention = 2;
//--- Linked List of Target Binons - for Percepts and Actions -------------
MaxTargets = 10000; // = the max number of Target binon entries possible
//---- Targets' 2nd index property values
NLnk = 1; // = The pointer to the next Targets() entry in this linked list,
TargetBinon = 2; // = a left or right Target binon
NullTarget = 0; // an NLnk pointer at end of linked list
//-------------------- Stimuli Perceived STM() ---------------------------------------
MaxLevels = 25; // The highest level of complexity to which the tree can grow
//---- STM 2nd index values - type of information in STM()
//BinId = 1 ' the binon ID - initialized above
//XQCnt = 2 ' the count of times the fired binon has been recognized / fired / repeated - initialized above
TQCnt = 3; // the count of times its trigger fired for repeat size comparison
//-------------------- Long Term Memory (LTM) - Monitoring Info. -------------------------
LtmPerceptTyp = 1;
LtmPerceptBin = 2;
LtmESType = 3;
LtmESActBin = 4;
LtmARType = 5;
LtmARActBin = 6;
LtmActionTyp = 7;
LtmActionBin = 8;
MaxMemory = 2000;
//---------------------- Operational Values -------------------------------
ASpace = " ";
ParallelSign = "+"; //Was Chr$(186), 'was "/"
Normal = 0; //Used as ActTypes for body display
Happy = 1;
PartMatch = 2;
Unhappy = 3;
vbDblQuote = (char) 34; // = "
Running = 2;
Started = 1;
OperatingMode = Started; //Just started so WorldHelp is displayed
Black = 0x0;
White = 0xFFFFFF;
LightBlue = 0xFF8080;
DarkBlue = 0xC00000;
change(); // persist changes
}
private static String chr(int c) {
return String.valueOf((char) c);
}
public final void GetTypeInfo(int BinTyp, ISetter BinonTyp, ISetter Rdgs) {
//Returns the names of the BinonTyp$ and Rdg$ for the given BinTyp
// Public BinonTypeName$(1 To 5, 1 To 2) 'The names and abbreviations for the various binon types
// '---- BinonTypeName$() 2nd index values
// Public BinName '1
// Public BinAbbreviation '2
Rdgs.set("");
BinonTyp.set("");
if (BinTyp == NullType) {
BinonTyp.set("Null");
Rdgs.set("~ = ");
} else {
BinonTyp.set(BinonTypeName[BinTyp][BinName]);
Rdgs.set(BinonTypeName[BinTyp][BinAbbreviation] + "= ");
}
} //End of GetTypeInfo()
public final int BinonTypeOf(int TheBinon) {
int tempBinonTypeOf;
if (TheBinon == NullObject) {
tempBinonTypeOf = NullType;
} else {
tempBinonTypeOf = Binons[TheBinon][BType];
}
return tempBinonTypeOf;
} //End of BinonTypeOf()
public final void GetValue(int OOO, Var v) {
//Returns the value for the object based on its Type
int Readng;
int TheBinon;
int LeftBinon;
//Recursive routine to add values to V$ for any binon/object
if (OOO == NullObject) {
return;
}
//VB TO JAVA CONVERTER NOTE: The following VB 'Select Case' included either a non-ordinal switch expression or non-ordinal, range-type, or non-constant 'Case' expressions and was converted to Java 'if-else' logic:
// Select Case BinonTypeOf(OOO)
var tempVar = BinonTypeOf(OOO);
//ORIGINAL LINE: Case ActBin //Public ActBin = sequential - action = NumPercepts+1
if (tempVar == ActBin) //Public ActBin = sequential - action = NumPercepts+1
{
TheBinon = OOO;
while (BinonTypeOf(TheBinon) == ActBin) //While we have an Action
{ ping();
LeftBinon = TheBinon;
//Go down the left side to the bottom Property or Percept binon
while (BinonTypeOf(LeftBinon) == ActBin) //While we have an Action
{ ping();
LeftBinon = Binons[LeftBinon][O1]; //Get the left source part
}
GetValue(LeftBinon, v); //get the property and/or Percept binon
v.set(v.get() + SequentialSign);
//Go to the right side and repeat going down its left side
TheBinon = Binons[TheBinon][O2];
}
GetValue(TheBinon, v); //get the last Property or Percept binon on the right side
}
//ORIGINAL LINE: Case 1 To NumProperties //Senses / property binon
else if (tempVar >= 1 && tempVar <= NumProperties) //Senses / property binon
{
Readng = Binons[OOO][IDL]; //The binons value
if (BinonTypes[BinonTypeOf(OOO)][SymbolicOrMagnitude] == Symbolic) {
if (Readng < 32) {
v.set(v.get() + "~");
} else {
v.set(v.get() + chr(Readng)); //text
}
} else //Else the property is Magnitude
{
v.set(v.get() + vbToStr(Readng)); //a number
}
}
//ORIGINAL LINE: Case NumProperties + 1 To NumPercepts //Percept binons
else if (tempVar >= NumProperties + 1 && tempVar <= NumPercepts) //Percept binons
{
TheBinon = OOO;
while (BinonTypeOf(TheBinon) > NumProperties) //While we have a Percept
{ ping();
LeftBinon = TheBinon;
//Go down the left side to the bottom property binon
while (BinonTypeOf(LeftBinon) > NumProperties) //While we have a Percept
{ ping();
LeftBinon = Binons[LeftBinon][O1]; //Get the left source part
}
GetValue(LeftBinon, v); //get the property binon
v.set(v.get() + ParallelSign);
//Go to the right side and repeat going down its left side
TheBinon = Binons[TheBinon][O2];
}
GetValue(TheBinon, v); //get the last Property binon on the right side
}
//ORIGINAL LINE: Case ActBin + 1 To NumBinonTypes //A response / device binon
else if (tempVar >= ActBin + 1 && tempVar <= NumBinonTypes) //A response / device binon
{
Readng = Binons[OOO][IDL];
if (Readng < 32) {
v.set(v.get() + "~");
} else {
v.set(v.get() + chr(Readng)); //symbolic
}
}
} //End of GetValue()
public final void RememberResponse(int RespBin, int StoreAtPlace) {
//Save the last response for LTM display
// Public LTMEMORY&(1 To 2000, 1 To 6) -- comment stefan: not really - it's going to 8
// '1st index is StoreAt cycle number
// '2nd index is what type of information is in the LTM
//
// '---- LTMEMORY() 2nd index values - type of information in LTMEMORY()
// Public LtmPerceptTyp '1 Percept binon type
// Public LtmPerceptBin '2 Percept binon
// Public LtmESType '3 Type of ES Binon - may be an S
// Public LtmESActBin '4 ES Actbin
// Public LtmARType '5 Type of AR Binon - may be an R
// Public LtmARActBin '6 AR ActBin
// Public LtmActionTyp '7 Action binon type
// Public LtmActionBin '8 Action binon
LTMEMORY[StoreAtPlace][LtmActionTyp] = BinonTypeOf(RespBin);
LTMEMORY[StoreAtPlace][LtmActionBin] = RespBin;
} //End of RememberResponse()
public final void RememberStimulus(int TrigObj, int StoreAtPlace) {
//Save the given relationship / association in LTM for display
// Public LTMEMORY&(1 To 2000, 1 To 6)
// '1st index is StoreAt cycle number
// '2nd index is what type of information is in the LTM
//
// '---- LTMEMORY() 2nd index values - type of information in LTMEMORY()
// Public LtmPerceptTyp '1 Percept binon type
// Public LtmPerceptBin '2 Percept binon
// Public LtmESType '3 Type of ES Binon - may be an S
// Public LtmESActBin '4 ES Actbin
// Public LtmARType '5 Type of AR Binon - may be an R
// Public LtmARActBin '6 AR ActBin
// Public LtmActionTyp '7 Action binon type
// Public LtmActionBin '8 Action binon
LTMEMORY[StoreAtPlace][LtmPerceptTyp] = BinonTypeOf(TrigObj);
LTMEMORY[StoreAtPlace][LtmPerceptBin] = TrigObj;
} //End of RememberStimulus()
public final void SetupSense(int SenseNum, String Sense_Name, String BinonName, String BinonAbbrev, int MagnOrSymb, int LowerLimit, int UpperLimit, String Stimuli, int LinOrCirc, int IntOrLog, int NumSensrs, int SensorDependency) {
printVars_str("SetupSense","SenseNum", SenseNum, "Sense_Name", Sense_Name, "NumSensrs", NumSensrs);
//If the SenseNum passed in is zero this routine returns the Sense number (SenseNum)
//for the given Sense, else it modifies the given SenseNum
//The range or number of sensors is NumSensrs - max 256
//IntensityRange: is the range or number of intensity values for the sensors
//Stimuli$: is a string of possible stimuli for this sensor - saved in SensorStimuli$()
//Sense_Name$: is the name of the sense
//MagnOrSymb: = Magnitude if each sensor measures a Magnitude range of intensity
// = Symbolic if each sensor provides readings that are symbolic.
//LinOrCirc: = Linear
// = Circular
//unused String Ssr = null;
int UseSense;
//unused String SG = null;
int Sns;
var BinTypNum = new Var<>(0);
String DisplayStimuli;
// Public NumSenses 'The number of physical senses, Max of 8
// 'Currently equals the NumProperties since each sense currently = 1 property type
// Public MaxSenses 'Maximum number of senses = max 8 physical senses
// Public Sense$(1 To 8) 'Names of senses, up to 8 physical senses
//
// Public Senses[1 To 8][1 To 6] 'Properties of the different senses
// '1st index = Sense number
// '2nd index = Sense property
// Public SensorStimuli$(1 To 10) 'A string of the possible symbolic stimuli for the sensor
//
// '---- Senses() - 2nd index values - Sense Properties
// Public PropertyBinonType '1, Stimulus property binon type e.g. 1 = TextBin or 2 = ContBin
// Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator
// Public LowerRangeLimit '3, Lower limit of range of values, zero is minimum (65 = "A")
// Public UpperRangeLimit '4, Upper limit of range of values, 255 is maximum (90 ="Z")
// Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Compass degrees are Circular (0 to 360)
// Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs
// Public NumberOfSensors '7 Number of sensors in sensor array
// Public SensorsDependentOrIndependent '8 are sensors adjacent (dependent) or independent
//
// Public Symbolic '1, Indicates that the values from this sense are symbolic, range A -> Z
// Public Magnitude '2, Indicates that the values from this sense are numeric, integers, range 0 -> Limit
//
// Public Linear '1, Indicates that the values go from the lower limit to upper limit
// Public Circular '2, Indicates that the values rap around from the upper limit to 0
//
// Public IntegerValues '1, Indicates that the values are integer readings
// Public LogValues '2, Indicates that the values are already logs - orders of magnitude
//
if (NumSenses == MaxSenses) //Can't assign another new sense number
{
Stop();
}
//There are only so many senses in SensorValues array
//currently set to 8 in Adaptron.Initialize_Adaptron()
if (SenseNum == 0) //don't have a sense number yet so assign and return it
{
NumSenses = NumSenses + 1; //The new sense number for this sense
SenseNum = NumSenses; //The returned sense number
} else if (SenseNum > MaxSenses) //else it is more than allowed
{
Stop();
} else if (SenseNum > NumSenses + 1) //else is it higher than the next one available
{
Stop();
} else if (SenseNum <= NumSenses) //else use the one passed in - overriding an existing sense
{
} else if (SenseNum == NumSenses + 1) //else is it equal to the next one available
{
NumSenses = SenseNum; //which equals NumSenses + 1
}
UseSense = SenseNum;
if (NumSensrs > 8) //only 8 sensors allowed per sense for now - maybe only
{
Stop();
}
//need this limit if independent sensors
if (IntensityRange > 256) //only 256 values allowed for intensity
{
Stop();
}
Sense[UseSense] = Sense_Name;
Senses[UseSense][SymbolicOrMagnitude] = MagnOrSymb;
Senses[UseSense][LowerRangeLimit] = LowerLimit;
Senses[UseSense][UpperRangeLimit] = UpperLimit;
SensorStimuli[UseSense] = Stimuli; //If not "" these take preference over the upper and lower limit
if (Senses[UseSense][SymbolicOrMagnitude] == Magnitude) //Magnitude READINGS
{
Senses[UseSense][LinearOrCircular] = LinOrCirc; //can be circular or linear
SensorStimuli[UseSense] = ""; //can not have symbolic list
} else //Symbolic readings can not be circular
{
Senses[UseSense][LinearOrCircular] = Linear; //non circular
}
Senses[UseSense][IntegersOrLogs] = IntOrLog;
Senses[UseSense][NumberOfSensors] = NumSensrs;
Senses[UseSense][SensorsDependentOrIndependent] = SensorDependency;
//SetupBinonTypes(SenseOrDeviceNum, BinNam$, BinAbb$, IsASense, BinonTypReturned)
SetupBinonTypes(UseSense, BinonName, BinonAbbrev, IsSense, BinTypNum);
Senses[UseSense][PropertyBinonType] = BinTypNum.get(); //Currently BinonType = Sense = property binon
//and fill in sense info on world page
StringBuilder sensorInfo = new StringBuilder();
for (Sns = 1; Sns <= NumSenses; Sns++) { ping();
if (Senses[Sns][SymbolicOrMagnitude] == Magnitude) {
DisplayStimuli = StringHelper.trim(String.valueOf(Senses[Sns][LowerRangeLimit]), ' ') + " to" + Senses[Sns][UpperRangeLimit];
} else //symbolic values
{
if (SensorStimuli[Sns].equals("")) //If no symbolic list then use upper and lower limit
{
DisplayStimuli = chr(Senses[Sns][LowerRangeLimit]) + " to " + chr(Senses[Sns][UpperRangeLimit]);
} else {
DisplayStimuli = SensorStimuli[Sns];
DisplayStimuli = replace(DisplayStimuli, NoMoveOrTurn, ASpace);
}
}
sensorInfo.append(takeFirst(8, Sense[Sns] + ": ")
+ " " + DisplayStimuli + " " + SymbOrMagn(IsSense, Sns) + "\r\n");
}
World.showSensorValues(str(sensorInfo));
} //End of SetupSense()
private static void Stop() { Stop("STOP"); }
private static void Stop(String msg) {
throw new RuntimeException(msg);
}
public final void SetupVision() //Called from DesignBody.UseThisBody_Click()
{
int VisionSense;
int MS = 0;
int ll = 0; // renamed because of clash with JavaX's LL
int UL = 0;
// BodySetting$(7) = VisionConfig.VisionDown
// BodySetting$(8) = VisionConfig.VisionLeft
// BodySetting$(9) = VisionConfig.VisionRight
// BodySetting$(10) = VisionConfig.VisionInFront
// BodySetting$(11) = VisionConfig.VisionBehind
// BodySetting$(12) = VisionConfig.VisionSymbolicOrMagnitude(0)
// BodySetting$(13) = VisionConfig.VisionSymbolicOrMagnitude(1)
// BodySetting$(21) = VisionConfig.VisionSymbolicOrMagnitude(2)
VisionSense = 0; //so a new sense number assigned automatically by SetupSense()
// Body 1 'Sense #1 looks down at square, Device #1 moves Left, Right, Up, Down
// 'set up Sense #1, 1 sensor
// 'SetupSense(SenseNum, Sense_Name$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _
// LinOrCirc, IntOrLog, NumSensrs, SensorDependency)
// Call SetupSense(InputSense, "Input", "Text", "Tx", Symbolic, 65, 122, Linear, IntegerValues, 1, Independent)
//
// 'SetupDevice(DeviceNum, DName$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _
// Responses$, LinOrCirc, IntOrLog)
// Call SetupDevice(DevNum, "Output", "Letter", "Lt", Symbolic, 97, 100, "", Linear, IntegerValues)
//
// Body 2 'Looks forward at next cell, Turns left, right & moves forward
// 'set up Sense #1, 1 Sensor
// Call SetupSense(InputSense, "Input", "Text", "Tx", Symbolic, 65, 113, Linear, IntegerValues, 1, Independent)
// Call SetupDevice(DevNum, "Output", "Letter", "Lt", Symbolic, 97, 99, "", Linear, IntegerValues)
if (isTrue(BodySetting[12])) //radio button VisionSymbolicOrMagnitude(0) selected
{
MS = Symbolic;
ll = 65; //"A" 1st cell location
UL = 122; //"z" last possible cell location - actually if 8 x 8 then it is Chr$(129)
}
if (isTrue(BodySetting[13])) //radio button VisionSymbolicOrMagnitude(1) selected
{
MS = Magnitude;
ll = 1;
UL = 8; //max 8 cells in any direction
}
if (isTrue(BodySetting[21])) //radio button VisionSymbolicOrMagnitude(2) selected
{
MS = Symbolic;
ll = asc(Wall); //Wall$ = Chr$(20) Terminal font
UL = asc(EmptySquare); //empty square beside it
}
if (eq(BodySetting[7], "1")) //Looking down box is checked
{
//SetupSense(SenseNum, Sense_Name$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _
//Stimuli, LinOrCirc, IntOrLog, NumSensrs, SensorDependency);
SetupSense(VisionSense, "VisionD", "VisionD", "VD", MS, ll, UL, "", Linear, IntegerValues, 1, Independent);
}
VisionSense = 0;
if (eq(BodySetting[8], "1")) //Looking left box is checked
{
SetupSense(VisionSense, "VisionL", "VisionL", "Vl", MS, ll, UL, "", Linear, IntegerValues, 1, Independent);
}
VisionSense = 0;
if (eq(BodySetting[9], "1")) //Looking right box is checked
{
SetupSense(VisionSense, "VisionR", "VisionR", "Vr", MS, ll, UL, "", Linear, IntegerValues, 1, Independent);
}
VisionSense = 0;
if (eq(BodySetting[10], "1")) //Looking InFront box is checked
{
SetupSense(VisionSense, "VisionF", "VisionF", "Vf", MS, ll, UL, "", Linear, IntegerValues, 1, Independent);
}
VisionSense = 0;
if (eq(BodySetting[11], "1")) //Looking Behind box is checked
{
SetupSense(VisionSense, "VisionB", "VisionB", "Vb", MS, ll, UL, "", Linear, IntegerValues, 1, Independent);
}
} //End of SetupVision()
private int asc(String s) {
return empty(s) ? 0 : s.charAt(0);
}
private boolean isTrue(String s) {
return "True".equals(s);
}
public final void SetupTouch() {
} //End of SetupTouch()
public final void SetupWheels() {
int WheelsDevice;
int MS;
//unused String LL = null;
//unused String UL = null;
StringBuilder WheelResponses;
int MotionSense;
// BodySetting$(14) = WheelsConfig.MoveForward
// BodySetting$(15) = WheelsConfig.MoveLeft
// BodySetting$(16) = WheelsConfig.MoveRight
// BodySetting$(17) = WheelsConfig.MoveBackward
// BodySetting$(18) = WheelsConfig.TurnRight
// BodySetting$(19) = WheelsConfig.TurnLeft
// BodySetting$(20) = WheelsConfig.TurnAround
// BodySetting$(4) = WheelsConfig.AddAWheelSensor
// Body 1 'Sense #1 looks down at square, Device #1 moves Left, Right, Up, Down
// 'set up Sense #1, 1 sensor
// 'SetupSense(SenseNum, Sense_Name$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _
// LinOrCirc, IntOrLog, NumSensrs, SensorDependency)
// Call SetupSense(InputSense, "Input", "Text", "Tx", Symbolic, 65, 113, Linear, IntegerValues, 1, Independent)
//
// Call SetupDevice(DevNum, "Output", "Letter", "Lt", Symbolic, 97, 100, "", Linear, IntegerValues)
//
// Body 2 'Looks forward at next cell, Turns left, right & moves forward
// 'set up Sense #1, 1 Sensor
// Call SetupSense(InputSense, "Input", "Text", "Tx", Symbolic, 65, 113, Linear, IntegerValues, 1, Independent)
// Call SetupDevice(DevNum, "Output", "Letter", "Lt", Symbolic, 97, 99, "", Linear, IntegerValues)
WheelsDevice = 0; //The device number assigned to the device by SetupDevice()
MS = Symbolic;
WheelResponses = new StringBuilder("-"); //will be filled in with move symbols "-flrb" and turn symbols,
//a "z" for an invalid movement, the "-" for do nothing
WheelsTurn = false; //Assume no turning capability, display Smarty as Happy face
if (MS == Symbolic) {
for (var I = 14; I <= 20; I++) { ping();
if (eq(BodySetting[I], "1")) //if it is checked then
{
switch (I) {
case 14: //Forward
WheelResponses.append(MoveForward);
break;
case 15: //Left
WheelResponses.append(MoveToLeft);
break;
case 16: //Right
WheelResponses.append(MoveToRight);
break;
case 17: //Backward
WheelResponses.append(MoveBackward);
break;
case 18: //Turn right 90 degrees
WheelResponses.append(TurnRght); //right angle symbol
WheelsTurn = true;
break;
case 19: //Turn left 90 degrees
WheelResponses.append(TurnLft); //left angle symbol
WheelsTurn = true;
break;
case 20: //Turn around 180 degrees
WheelResponses.append(TurnArnd); //double arrow symbol
WheelsTurn = true;
break;
}
} else {
WheelResponses.append(NoMoveOrTurn);
}
}
}
WheelMovement = WheelResponses.toString(); //the same movements should be recognizable
//Setup a motion sense if WheelsConfig.AddAWheelSensor = 1 is checked
if (eq(BodySetting[4], "1")) {
MotionSense = 0;
//SetupSense(SenseNum, Sense_Name$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _
//Stimuli, LinOrCirc, IntOrLog, NumSensrs, SensorDependency);
SetupSense(MotionSense, "Motion", "Motion", "Mo", Symbolic, 1, 1, WheelMovement, Linear, IntegerValues, 1, Independent);
}
//SetupDevice(DeviceNum, DName$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _
//Responses, LinOrCirc, IntOrLog);
SetupDevice(WheelsDevice, "Wheels", "Wheels", "Wh", MS, 1, 1, WheelResponses.toString(), Linear, IntegerValues);
} //End of SetupWheels()
public final void SetupArms() {
} //End of SetupArms()
public void InitBodyToSmarty0(String[] Body) //Initialize the BodySetting$() or BodyValue$() to Smarty0 values
{
Body[0] = "21"; //Count of Body$() values
Body[1] = Smarty0;
Body[2] = "1"; //Vision.Value = 1 - checked
Body[3] = "0"; //Touch.Value
Body[4] = "0"; //WheelsConfig.AddAWheelSensor
Body[5] = "1"; //Wheels.Value
Body[6] = "0"; //Arms.Value
Body[7] = "1"; //VisionConfig.VisionDown
Body[8] = "0"; //VisionConfig.VisionLeft
Body[9] = "0"; //VisionConfig.VisionRight
Body[10] = "0"; //VisionConfig.VisionInFront
Body[11] = "0"; //VisionConfig.VisionBehind
Body[12] = "True"; //VisionConfig.VisionSymbolicOrMagnitude(0)
Body[13] = "False"; //VisionConfig.VisionSymbolicOrMagnitude(1)
Body[14] = "1"; //WheelsConfig.MoveForward
Body[15] = "1"; //WheelsConfig.MoveLeft
Body[16] = "1"; //WheelsConfig.MoveRight
Body[17] = "1"; //WheelsConfig.MoveBackward
Body[18] = "0"; //WheelsConfig.TurnRight
Body[19] = "0"; //WheelsConfig.TurnLeft
Body[20] = "0"; //WheelsConfig.TurnAround
Body[21] = "False"; //VisionConfig.VisionSymbolicOrMagnitude(2)
} //End of InitBodyToSmarty0()
public void InitBodySettingsToSmarty0() {
InitBodyToSmarty0(BodySetting);
}
public final void InitBodyValuesToSmarty0() {
InitBodyToSmarty0(BodyValue);
}
public final String SymbOrMagn(int SensOrDevc, int SensOrDevcNumber) {
String tempSymbOrMagn;
//called from SetupSense() & SetupDevice()
int SorG;
if (SensOrDevc == IsSense) {
SorG = Senses[SensOrDevcNumber][SymbolicOrMagnitude];
} else //Else SensOrDevc = IsDevice
{
SorG = Devices[SensOrDevcNumber][SymbolicOrMagnitude];
}
if (SorG == Symbolic) {
tempSymbOrMagn = "Symbolic";
} else {
tempSymbOrMagn = "Magnitude";
}
return tempSymbOrMagn;
} //End of SymbOrMagn$()
public final void SetupBinonTypes(int SenseOrDeviceNum, String BinNam, String BinAbb, int IsASense, Var BinonTypReturned) {
//Called by SetUpSense() and SetupDevice()
//After setting up a sense or device the binontypes() information must be updated correctly
//SenseOrDeviceNum could be one that already exists and is being reset
int BinTypNum = 0;
int PerceptBinTyp;
int DHabitBinTyp;
int FirstPtr;
int SecondPtr;
int ThisPercept;
int StartPercept;
int EndPercept;
int ThisLevel;
// '---- Binons[x][BType] - stimulus and response binon types
// TextBin = 1 ' = A letter (symbolic)
// ContBin = 2 ' = Contrast pattern - intensity (Magnitude)
// 'Parallel combinations should be put in the binons above the property type ones.
// NCBin = 3 ' = TextBin & ContBin combination
// ActBin = 4 ' = 2^N = NumPercepts+1, holds sequential binons.
// LetrBin = 5 ' = Response binon = letters
//------------------ Property and Percept combinations --------------------------
//The number of combinations at each level of complexity when combining independent senses.
//# of Sensors
// or Senses
// Stimuli @ P-Level 1 2 3 4 5 6 7 8 Total
// 1 1 1
// 2 2 1 3
// 3 3 3 1 7
// 4 4 6 4 1 15
// 5 5 10 10 5 1 31
// 6 6 15 20 15 6 1 63
// 7 7 21 35 35 21 7 1 127
// 8 8 28 56 70 56 28 8 1 255
// N 2^N - 1
// Public NumProperties 'N=2, The number of stimulus property binon types
// Public NumPercepts 'N=3, The number of property binons and Percept combinations of them
// Public NumBinonTypes '= 2^N+1, number of property binons, Percept combination binon types, Action type and
// ' the response type
// Public MaxBinonTypes 'with 2 senses and 1 device this is =5
// Public BinonTypeName$(1 To 31, 1 To 2) 'The names and abbreviations for the various binon types
// '---- BinonTypeName$() 2nd index values
// Public BinName '1
// Public BinAbbreviation '2
// 'The source types of property binons are 1=TextBin, 2=ContBin. There are N of these
// 'and all other Percept combinations such as Name&Cont.
// 'There are 2^N-1 Property plus Percept types
// 'There is just the one Action type - a sequential combination of the
// 'Property binons, Percept binons, response binon and/or Action binons.
// 'Added responses as LetrBin binons so NumBinonTypes = 2^N + 1
// Public BinonTypes[1 To 31][1 To 4] 'The binon types for stimuli, ActBin and responses
// '1st index = the type of binon (dimension = NumBinonTypes)
// '2nd index = binon type property
//
//---- BinonTypes() 2nd index values
// Public SensOrDevNum '1, Pointer points back to sense or device
// Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator
if (IsASense == IsSense) //If setting up a sense then
{
if (SenseOrDeviceNum <= NumProperties) //if it is an existing sense then resetting it
{
BinTypNum = SenseOrDeviceNum;
} else if (SenseOrDeviceNum == NumProperties + 1) //else if it is the next new sense then
{
NumProperties = SenseOrDeviceNum; //N=2, The number of stimulus property binon types
BinTypNum = NumProperties;
NumPercepts = (2 << (NumProperties - 1)) - 1; //N=3, The number of property binons and Percept combinations of them
for (PerceptBinTyp = NumProperties + 1; PerceptBinTyp <= NumPercepts; PerceptBinTyp++) { ping();
BinonTypeName[PerceptBinTyp][BinName] = "Percept";
BinonTypeName[PerceptBinTyp][BinAbbreviation] = "Pc";
}
//Setup the PerceptSources() to point at the correct source entries at the level below
ThisLevel = 2; //Filling in level 2 Percept information
ThisPercept = NumProperties + 1; //Position of 1st Percept combination of sense/property binons
StartPercept = ThisPercept; //Start of range of pairs - level-2 Percepts, level-1 Percepts=property binons
for (FirstPtr = 1; FirstPtr < NumProperties; FirstPtr++) //Create all the 2nd level pair pointers
{ ping();
for (SecondPtr = FirstPtr + 1; SecondPtr <= NumProperties; SecondPtr++) { ping();
PerceptSources[ThisPercept][FirstSource] = FirstPtr;
PerceptSources[ThisPercept][SecondSource] = SecondPtr;
PerceptSources[ThisPercept][PerceptLevel] = ThisLevel;
ThisPercept = ThisPercept + 1; //Next combination Percept will go in here
}
}
EndPercept = ThisPercept - 1; //End of range of level-2 Percepts - pairs of property binons
//Setup the level-3+ PerceptSources()
while (EndPercept - StartPercept > 0) { ping();
ThisLevel = ThisLevel + 1; //populate next level up
for (FirstPtr = StartPercept; FirstPtr < EndPercept; FirstPtr++) { ping();
for (SecondPtr = FirstPtr + 1; SecondPtr <= EndPercept; SecondPtr++) { ping();
if (PerceptSources[FirstPtr][SecondSource] == PerceptSources[SecondPtr][FirstSource]) //if share a common sub Percept
{
PerceptSources[ThisPercept][FirstSource] = FirstPtr;
PerceptSources[ThisPercept][SecondSource] = SecondPtr;
PerceptSources[ThisPercept][PerceptLevel] = ThisLevel;
ThisPercept = ThisPercept + 1; //Next combination Percept will go in here
}
}
}
StartPercept = EndPercept + 1; //Start next range after end of previous range
EndPercept = ThisPercept - 1; //End of range of this level Percepts
}
ActBin = NumPercepts + 1; //ActBin holds action and expectation binons = 2^N = NumPercepts + 1
BinonTypeName[ActBin][BinName] = "Action";
BinonTypeName[ActBin][BinAbbreviation] = "Ac";
NumBinonTypes = ActBin; //The number of types so far = 2^N
} else {
Stop(); //no other value allowed
}
} else //Else setting up a device
{
if (SenseOrDeviceNum + ActBin <= NumBinonTypes) //If it is an existing device then restting it
{
BinTypNum = SenseOrDeviceNum;
} else if (SenseOrDeviceNum + ActBin == NumBinonTypes + 1) //else if it is the next new device number then
{
NumBinonTypes = NumBinonTypes + 1; //= 2^N+x, number of property binons, Percept combination binon types,
BinTypNum = NumBinonTypes;
NumDHabits = (2 << (SenseOrDeviceNum - 1)) - 1; //N=3, The number of device response binons and D-Habit combinations of them
//VB TO JAVA CONVERTER NOTE: The ending condition of VB 'For' loops is tested only on entry to the loop. VB to Java Converter has created a temporary variable in order to use the initial value of ActBin + NumDHabits for every iteration:
var tempVar = ActBin + NumDHabits;
for (DHabitBinTyp = ActBin + 1 + SenseOrDeviceNum; DHabitBinTyp <= tempVar; DHabitBinTyp++) { ping();
BinonTypeName[DHabitBinTyp][BinName] = "D-Habit";
BinonTypeName[DHabitBinTyp][BinAbbreviation] = "DH";
}
NumBinonTypes = ActBin + NumDHabits;
} else {
Stop(); //no other value allowed
}
}
BinonTypeName[BinTypNum][BinName] = BinNam;
BinonTypeName[BinTypNum][BinAbbreviation] = BinAbb;
BinonTypes[BinTypNum][SensOrDevNum] = SenseOrDeviceNum; //points back to the device number
BinonTypes[BinTypNum][SymbolicOrMagnitude] = Senses[SenseOrDeviceNum][SymbolicOrMagnitude];
BinonTypReturned.set(BinTypNum);
} //End of SetupBinonTypes()
public final void SetupDevice(int DeviceNum, String DName, String BinonName, String BinonAbbrev, int MagnOrSymb, int LowerLimit, int UpperLimit, String Responses, int LinOrCirc, int IntOrLog) {
//This routine returns the Device number (DeviceNum) for the given Device type if none is provided
//DName$: is the name of the device type
//IntensityRange: is the range or number of response values for the device if it takes magnitude values
//Responses$: is a string of characters representing the possible movements
//BinonType: The response binon type
int UseDevice;
var BinTypNum = new Var<>(0);
String DisplayResponses;
//-------------------- Devices ------------------------------------------------
// Public NumDevices 'Number of output devices
// Public MaxDevices 'Maximum number of devices = max 8 devices
// Public Device$(1 To 8) 'Names of device, up to 8 devices
//
// Public Devices[1 To 8][1 To 5] 'Properties of the output / response devices
// '1st index = Device number
// '2nd index = Device property
// Public DeviceResponses$(1 To 4) 'A string of the possible symbolic responses for the devices
//---- Devices() - 2nd index values - Device Properties - DEFINED ABOVE
// Public PropertyBinonType '1, Response property binon type e.g. 1 = LetrBin
// Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator
// Public LowerRangeLimit '3, Lower limit of range of response values, zero is minimum (97 = "a")
// Public UpperRangeLimit '4, Upper limit of range of response values, 255 is maximum (122 = "z")
// Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Motor rotations are Circular (0 to 360)
// Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs
// Public Symbolic '1, Indicates that the values for this device are symbolic, Range a -> z
// Public Magnitude '2, Indicates that the values for this device are numeric, integers, range 0 -> limit
// Public Linear '1, Indicates that the values go from the lower limit to upper limit
// Public Circular '2, Indicates that the values rap around from the upper limit to 0
// Public IntegerValues '1, Indicates that the values are integer readings
// Public LogValues '2, Indicates that the values are already logs - orders of magnitude
if (NumDevices == MaxDevices) //Can't assign another new device number
{
Stop("NumDevices == MaxDevices (" + NumDevices + ")");
}
//There are only so many device types in DeviceValues array
//currently set to 8 in Adaptron.Initialize_Adaptron()
if (DeviceNum == 0) //don't have a device number yet so assign and return it
{
NumDevices = NumDevices + 1; //The new device number for this device
DeviceNum = NumDevices; //The returned device number
} else if (DeviceNum > MaxDevices) //else it is more than allowed
{
Stop("DeviceNum > MaxDevices (" + DeviceNum + "/" + MaxDevices + ")");
} else if (DeviceNum > NumDevices + 1) //else is it higher than the next one available
{
Stop("DeviceNum > NumDevices+1 (" + DeviceNum + "/" + (NumDevices+1) + ")");
} else if (DeviceNum <= NumDevices) //else use the one passed in - overriding an existing device
{
} else if (DeviceNum == NumDevices + 1) //next device number provided
{
NumDevices = DeviceNum; //The new device type number for this device = DeviceNum
}
UseDevice = DeviceNum;
if (IntensityRange > 256) //only 256 values allowed for response intensity
{
Stop("IntensityRange > 256 (" + IntensityRange + ")");
}
Device[UseDevice] = DName;
Devices[UseDevice][SymbolicOrMagnitude] = MagnOrSymb;
Devices[UseDevice][LowerRangeLimit] = LowerLimit; //lower limit number / range of response values
Devices[UseDevice][UpperRangeLimit] = UpperLimit; //upper limit number / range of response values
DeviceResponses[UseDevice] = Responses; //the symbolic responses
if (Devices[UseDevice][SymbolicOrMagnitude] == Magnitude) //Magnitude READINGS
{
Devices[UseDevice][LinearOrCircular] = LinOrCirc; //can be circular or linear
DeviceResponses[UseDevice] = ""; //no symbolic responses are possible
} else //Symbolic readings can not be circular
{
Devices[UseDevice][LinearOrCircular] = Linear; //non circular
}
Devices[UseDevice][IntegersOrLogs] = IntOrLog;
//SetupBinonTypes(SenseOrDeviceNum, BinNam$, BinAbb$, IsASense, BinonTypReturned)
SetupBinonTypes(UseDevice, BinonName, BinonAbbrev, IsDevice, BinTypNum);
Devices[UseDevice][PropertyBinonType] = BinTypNum.get(); //The binon number usually = highest number so far
//Fill in device info. on world page
StringBuilder deviceInfo = new StringBuilder();
for (int Dvc = 1; Dvc <= NumDevices; Dvc++) { ping();
if (Devices[Dvc][SymbolicOrMagnitude] == Magnitude) {
DisplayResponses = Devices[Dvc][LowerRangeLimit] + " to" + Devices[Dvc][UpperRangeLimit];
} else //symbolic values
{
DisplayResponses = DeviceResponses[Dvc];
DisplayResponses = mapCharacters(DisplayResponses, c -> eq(str(c), NoMoveOrTurn) ? ASpace : c);
}
deviceInfo.append(takeFirst(8, Device[Dvc] + ": ")
+ DisplayResponses + " " + SymbOrMagn(IsDevice, Dvc) + "\r\n");
}
World.showDeviceValues(str(deviceInfo));
} //End of SetupDevice()
public void Reset_Adaptron() //Called from DesignBody.FinalSetup(), & ResetWld_Click()
{
//Resets all changing info. to starting places.
//Must be called before setting up any senses/sensors.
int String;
int D;
int I;
ResetRnd(-1); //necessary to reset the sequence
OverLimit = false;
CreateAll = false; //True if create all combinations, False if use only familiar parts
// CreateAll = True '
BodyPointing = North; //always starts with body pointing North
World.PointUnder();
NumSenses = 0; //start with no senses
NumDevices = 0; //start with no devices
Motion = NoMove; //World.MoveDown() etc set this to indicate the direction the robot moved
//and it is used as the stimulus input of the Motion sense
for (I = 1; I <= MaxSenses; I++) //+1 so it covers the Percept sense too
{ ping();
Sense[I] = ""; //Names of sense
}
StoreAt = 0; //Initially the long term memory history is empty
//Initialize STMs
LIN = 0; //clear out memory display stuff - index into INPUTS$() and OUTPUTS$()
COUNTIN = 0; //Count of inputs
ClearMemory(); //This clears BinonDisplay.ChngResults.Text and LTM
for (I = 0; I <= 500; I++) { ping();
if (I > 0) {
}
for (String = 1; String <= MaxSenses; String++) { ping();
INPUTS[I][String] = "";
}
for (D = 1; D <= MaxDevices; D++) { ping();
OUTPUTS[I][D] = "";
}
}
//Adapt.IO.Text = "";
//Adapt.LTMem.Text = "";
//UNUSED TriggerObj = NullObject;
DoingReaction = false; //set true if last response was reflexive.
DoingRepeat = false;
//ActiveActon = NullAct; //no subconscious acton active
//UNUSED ExploreObj = NullObject; //will be set if reflexive response done.
//DoingAct1 = NullAct; //will be set if reflexive response done.
//UNUSED NumTrigLinks = 0; //Number of LTM episodic action links
//UNUSED NumActons = 0;
NumActs = 0; //The number of Acts entries in use
RotateActs = false; //Rotate through all reflexive acts
LastAct = 1; //initialized so next one will be #2 - not the Relax response = #1
if (RotateActs) //Rotation through acts starts with Relax
{
LastAct = 0;
}
change(); // persist changes
} //End of Reset-Adaptron()
private void ResetRnd(int i) {
// TODO
}
public void ClearMemory() {
//Called by Reset_Adaptron()
int Lk;
int T;
int I;
for (I = 1; I <= MaxBinons; I++) { ping();
Binons[I][OLv] = 0;
Binons[I][O1] = NullObject;
Binons[I][O2] = NullObject;
ZeroTheCounts(I);
}
NumBinons = 0; //there are no binons
for (T = 1; T <= MaxBinonTypes; T++) //For all property binons and their Percept combinations and Actions
{ ping();
BinonTypeName[T][BinName] = ""; //The names and abbreviations for the various binon types
BinonTypeName[T][BinAbbreviation] = "";
BinonTypes[T][SymbolicOrMagnitude] = Symbolic;
BinonTypes[T][SensOrDevNum] = 0; // Pointer points back to sense or device
}
ClearSenses(); //clear SensorValues() and SensedBinons()
ClearPerceptions(); //clear out all the perceptions in STM()
TopLevel = 0;
for (T = 1; T <= MaxPercepts; T++) //Clear perceived Parallel Percept and property binon entries
{ ping();
Percepts[T][BinId][Current] = NullObject;
Percepts[T][BinId][Fired] = NullObject;
Percepts[T][XQCnt][Current] = 0;
Percepts[T][XQCnt][Fired] = 0;
}
for (Lk = 1; Lk <= MaxTargets; Lk++) //Clear out all targets
{ ping();
Targets[Lk][NLnk] = NullTarget;
Targets[Lk][TargetBinon] = NullObject;
}
NumTargets = 0;
ClearExpectations();
World.setBinonDisplayObjList("");
World.setBinonDisplayChngResults("");
JND = 20; //Percent
AssignBases(); // SizeBase# = 1.2 for a 20% just noticeable difference
change(); // persist changes
} //End of ClearMemory()
public void ZeroTheCounts(int Habit) //Called by ClearMemory()
{
Binons[Habit][TQ] = 0;
Binons[Habit][GQ] = 0;
} //End ZeroTheCounts()
public void ClearSenses() //Called by ClearMemory()
{
for (int Sens = 1; Sens <= MaxSenses; Sens++) { ping();
SensorValues[Sens][XQCnt][Fired] = 0;
SensorValues[Sens][Valu][Fired] = 0;
SensorValues[Sens][XQCnt][Current] = 0;
SensorValues[Sens][Valu][Current] = 0;
SensedBinons[Sens] = NullObject;
}
NumProperties = 0;
} //End of ClearSenses()
public void ClearPerceptions() //Used by ClearMemory() and processing STM perceptions in PerceptionAction()
{
//Clear out all the Current and previous perceptions that are sources for Habits in the STM()
int Percpt;
int Lvl;
World.appendBinonDisplayChngResults(" ** Clearing Perceptions " + "\r\n");
for (Lvl = 1; Lvl <= MaxLevels; Lvl++) { ping();
for (Percpt = Fired; Percpt <= MaxLevels; Percpt++) { ping();
EmptySTM(Lvl, Percpt);
}
}
} //End of ClearPerceptions()
public void AssignBases() //Called by ClearMemory()
{
double Percnt;
Percnt = /*Microsoft.VisualBasic.Conversion.Val*/(JND) / 100.0;
SizeBase = 1 + Percnt; //1.2 for a 20% just noticeable difference
IntensityBase = 1 + Percnt; //If it is 2.0 then that is a 100% just noticeable difference
} //End of AssignBases()
public final int Buckit(double Valuu, double Base) {
// Base# = 1.2 'Ln(1.3) = 0.26, Ln(1.2) = 0.18
return (int) Math.round(100 * Math.log(Valuu) / Math.log(Base)); // XXX
} //End of Buckit()
public final void IdBinons(int OLvl, int Prt, int Obj1, int TQNum, int Obj2, int GQNum, int IDLRatio, int SeqOrPar, int ExpectIt, Var ObjId, Var NewOne) {
//OLvl = Level of the binon, 1 stimulus property binons and response binons, 2+ Percepts or Action patterns
//PrT = Property Type value
//Obj1 = The left source binon
//Obj2 = The right source binon
//IDLRatio = The IDL ratio value
//SeqOrPar = whether it is an Action sequence or a parallel Percept
//ObjId = The object / binon identifier returned, = NullObject if over the limit
//NewOne = Returned True if object newly created, False if it already existed.
//If a new binon is created it is Active but Idle - waiting to repeat
//---- Binon Properties - 2nd index values
// Public BType '1, The type of binon
// Public O1 '2, Left source binon pointer
// Public TQ '3, the count of times the trigger has fired
// Public O2 '4, Right source binon pointer
// Public GQ '5, the number of times the goal has fired
// Public IDL '6, The ratio value of the binon
// Public IntVl '7, Interest Value (NOVEL, INTERESTING, or Familiar)
// Public OLv '8, Level of object = number of lowest level parts involved
// Public SP '9, Sequential or Parallel property
// Public TriggerList '10, points to the linked list of target binons [Targets()]
// ' for which this binon is the left source binon (not the right source binon).
// Public TriggerCount '11, Count of its sequential right targets, >1 means it has more than one goal
// ' Used for prediction reliability, may be set >1 if needs to be combined with previous
// Public GoalList '12, points to the linked list of target binons [Targets()]
// ' for which this binon is the right source binon (not the left source binon)
// Public GoalCount '13, Count of its sequential left targets, >1 means can not predict its trigger
// ' Used for reliability of determining the cause, may be set >1 if needs to be combined with next
// Public AE '14, Action (Percept - Act) or Attention (Act - Percept) level 1 Sequential binon
//Given two objects/parts Obj1 and Obj2
//see if we have an object ObjId with the same values and the same Obj1 and Obj2.
//Return the found or newly created binon
if (Obj1 == 0) throw fail("obj1 = 0");
if (Obj2 == 0) throw fail("obj2 = 0");
if (NumBinons >= MaxBinons) //if can not find the exact match
{
ObjId.set(NullObject);
World.appendBinonDisplayChngResults("\r\n" + "Binon limit of " + MaxBinons + " reached!");
Stop();
return;
}
ObjId.set(NullObject); //Return no binon - none created by default
NewOne.set(true); //Assume we will not find it already exists and will create a new one
//First determine if we have any binons of the given type with the given ratio
if (NumBinons > 0) //if none then do not check if ExistBinon
{
//If the binons already exists then the ExistBinon routine sets the ObjId
//ExistBinon(OLvl, PrTyp, Bin1&, Bin2&, V1, ItsAE, ObjId&)
if (ExistBinon(OLvl, Prt, Obj1, Obj2, IDLRatio, ExpectIt, ObjId)) {
//This applies to Percept and property binons only when attended to
//DecreaseBinonInterest(BTyp, Bino&)
DecreaseBinonInterest(ObjId.get());
NewOne.set(false);
}
}
if (ObjId.get() == NullObject) //If it does not already exist then create it
{
ObjId.set(NumBinons + 1); //it was not found - so add it as a new one
Binons[ObjId.get()][BType] = Prt;
Binons[ObjId.get()][O1] = Obj1; //The left source binon
Binons[ObjId.get()][TQ] = TQNum;
Binons[ObjId.get()][O2] = Obj2; //The right source binon
Binons[ObjId.get()][GQ] = GQNum;
Binons[ObjId.get()][IDL] = IDLRatio; //stored object ratio values
//Do level 1 binons become familiar immediately? No they should also go from Novel to Interesting to Familiar
//Percepts start out Novel, then become Interesting and then Familiar
//Perceptual sequences start out Novel and each time attention is paid to them they become Interesting and Familiar
if (SeqOrPar == Parallel) //If it is a Property or Percept binon then
{
if (Prt <= NumProperties) //if it is a Property binon then
{
SetInterest(ObjId.get(), NOVEL); //Property binons start out Novel
SetInterest(ObjId.get(), FAMILIAR); //Familiar for testing purposes
} else //else it is a Percept binon
{
SetInterest(ObjId.get(), NOVEL); //Percept binons start out Novel
SetInterest(ObjId.get(), FAMILIAR); //Familiar for testing purposes
}
} else {
SetInterest(ObjId.get(), NOVEL); //Sequential binons start out Novel
//tmp Call SetInterest(ObjId, FAMILIAR) 'Familiar - for testing
}
Binons[ObjId.get()][OLv] = OLvl;
Binons[ObjId.get()][SP] = SeqOrPar; //Sequential or ParallelPrt,
if (SeqOrPar == Parallel && ExpectIt != 0) //AE value should be 0
{
Stop();
}
Binons[ObjId.get()][AE] = ExpectIt; //only used if SP=Sequential and OLvl=1, Action=1, Attention=2
Binons[ObjId.get()][TriggerList] = NullTarget; //=0, an NLnk pointer at end of linked list
Binons[ObjId.get()][TriggerCount] = 0; //Count of its sequential right targets, >1 means can not predict its goal
Binons[ObjId.get()][GoalList] = NullTarget; //=0, an NLnk pointer at end of linked list
Binons[ObjId.get()][GoalCount] = 0; //Count of its sequential left targets, >1 means can not predict its trigger
// '--- Linked List of Target Binons - for Percepts and Actions -------------
// Public NumTargets& 'The number of Target binon entries created so far
// Public MaxTargets& '10000 = the max number of Target binon entries possible
//
// Public Targets&(1 To 10000, 1 To 2) 'pointed to by Binons(Typ, ID, TriggerList) or by Binons(Typ, ID, GoalList)
// '---- Targets' 2nd index property values
// Public NLnk '1 = The pointer to the next Targets() entry in this linked list,
// ' may be a NullTarget at end of linked list
// Public TargetBinon '2 = a left or right Target binon
//
// Public NullTarget '=0, an NLnk pointer at end of linked list
//The target binon ObjId is triggered by source binon Obj1 so add it to the right target list for Obj1
if (Obj1 != NullObject) //cannot be property binon
{
NumTargets = NumTargets + 1; //create a new target
if (NumTargets > MaxTargets) //have we exeeded the maximum
{
Stop();
}
Targets[NumTargets][TargetBinon] = ObjId.get(); //The right target is the newly created binon
Targets[NumTargets][NLnk] = Binons[Obj1][TriggerList]; //It should point to the 1st one on existing list
Binons[Obj1][TriggerList] = NumTargets; //ObjId becomes the 1st one on the right target list of Obj1
if (SeqOrPar == Sequential) {
Binons[Obj1][TriggerCount] = Binons[Obj1][TriggerCount] + 1; //Count of right targets for Obj1
}
}
//The source binon Obj2 is the goal of this target binon ObjId so add it to the left target list of Obj2
if (Obj2 != NullObject) //cannot be property binon
{
NumTargets = NumTargets + 1; //create a new target
if (NumTargets > MaxTargets) //have we exeeded the maximum
{
Stop();
}
Targets[NumTargets][TargetBinon] = ObjId.get(); //The left target is the newly created binon
Targets[NumTargets][NLnk] = Binons[Obj2][GoalList]; //It should point to the 1st one on existing list
Binons[Obj2][GoalList] = NumTargets; //ObjId becomes the 1st one on the left target list of Obj2
if (SeqOrPar == Sequential) {
Binons[Obj2][GoalCount] = Binons[Obj2][GoalCount] + 1; //Count of left targets for Obj2
}
}
NumBinons = ObjId.get();
//tmp BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & " - Created New Binon = " & _
//DisplayStimulu[Prt][ObjId] + "\r\n";
} //End if not ExistBinon
} //End of IdBinons()
public final void DecreaseBinonInterest(int Bino) {
//Updates the interest in a stimulus, Novel -> Interesting -> Familiar
//called when the stimulus is added to the perception list
//unused int Intrst;
switch (InterestIn(Bino)) {
case NOVEL:
if (InterestLevels == 3) {
SetInterest(Bino, INTERESTING); //Novel -> Interesting
} else //Interestlevels=2
{
SetInterest(Bino, FAMILIAR); //Novel -> Familiar
}
break;
case INTERESTING:
SetInterest(Bino, FAMILIAR); //Interesting -> Familiar
break;
}
} //End of DecreaseBinonInterest()
public final void SetInterest(int Objct, int IntLvl) {
//Sets the interest level of the given object.
Binons[Objct][IntVl] = IntLvl;
} //End of SetInterest()
public final int InterestIn(int Objct) {
return Binons[Objct][IntVl];
} //End of Function InterestIn()
public final boolean ExistBinon(int OLvl, int PrTyp, int Bin1, int Bin2, int V1, int ItsAE, Var ObjId) {
boolean tempExistBinon = false;
//Given two objects numbered Bin1 and Bin2 etc. see if we have an object in Binons()
//that matches this combination, if so return its number in ObjId
//ObjID = 0 if not found and ExistBinon is set to False
//Ratios of Values are used for recognition of Time (duration) patterns
//Pairs of object / binon parts (Obj1 and Obj2) are used for recognition of:
//Sense patterns, sensor patterns and symbol patterns etc.
int OO;
int StartAt; //range of binons to search
int EndAt;
tempExistBinon = false; //assume it does not exist
ObjId.set(NullObject); //return NullObject if not found
StartAt = 1;
EndAt = NumBinons;
for (OO = StartAt; OO <= EndAt; OO++) //For all the known objects of this type
{ ping();
//Object level is an identifying property of a binon
if (Binons[OO][OLv] == OLvl) //If it is at the same level then
{
if (Binons[OO][BType] == PrTyp) //if it is the same binon type then
{
//O1 = Object Part 1 pointer and O2 = Object Part 2 pointer
//Given Id of the object - search for same pair of parts and AE
if (Binons[OO][O1] == Bin1 && Binons[OO][O2] == Bin2 && Binons[OO][AE] == ItsAE) {
if (V1 == Binons[OO][IDL]) //If it has the same quantity IDL Ratio?
{
ObjId.set(OO);
tempExistBinon = true;
OO = NumBinons; //terminate FindIt loop
}
}
}
}
}
return tempExistBinon;
} //End of ExistBinon()
public final void PerceptionAction(int[][][] SensorValues, Object[] DeviceValues) {
//Called by Adapt.Inpu_KeyPress() for each stimulus/response cycle.
//SensorValues() contains the stimuli from the senses/sensors
//DeviceValues() are output responses to the devices to change the body/environment
int ObjtLvl;
int NovelLvl;
String HabitIt = null;
int Pass;
boolean CheckIt = false;
int AEorEA = 0; //Action-Expectation (Response-Stimulus) or Expectation-Action (Stimulus-Response)
int SourceBinon;
//unused int SourceXQCnt;
//unused int SourceTQCnt;
// 0. INITIAL STATE: based on the variables: PracticingBinon and ConcentrationLevel, will be either;
// a) an Action being executed / practiced that identifies the expected Percept stimulus and
// a concentration level of novel or interesting. Plus zero or more other Actions that also match
// the attended-to past experience and have expectations of what will happen next.
//
// Or b) no Action being performed and concentration level of familiar but may have
// a previous attended-to stimulus that repeated a certain quantity of times and is expecting it to repeat again.
//
// Or c) no attended-to stimulus or practicing Perceptual sequence because it is the first time through
// In parallel there may be zero or more subconsciously executing Actions that will stop if they don't
// get their next expected stimulus or their source binons become idle and will continue otherwise.
StoreAt = StoreAt + 1;
if (StoreAt == MaxMemory) //stop further Go / Continue stepping
{
//XXX World.Go.Enabled = false;
}
World.setBinonDisplayChngResults("Step = " + StoreAt + "\r\n"); //display the cycle count
// 1. PERCEIVE PERCEPTS:
// Get stimuli from all senses / sensors and recognize / create all Percept binon combinations of
// familiar stimuli. Both source binons must be familiar before they can be combined.
// This happens when a change occurs on any sense / sensor. This includes all areas of sensors that
// attention is or is not focused on. This includes creation of stimuli that are expected and unexpected.
// Novel stimuli get created and are remembered in the novel state. Is it possible that novel ones are only
// kept if they have attention paid to them? When we sleep the novel ones are probably pruned.
// Otherwise you end up with too many of them. Maybe it is only Actions that have to be attended to so
// that their familiarity / interest is reduced. The interest of the Percept is reduced on occurrence repetition.
// For a three stage novelty reduction, if and when Percepts occur again they are changed to Interesting.
// The third time they occur they become familiar and can be combined with other familiar ones.
// An Action has to be practiced before its interest level is reduced.
//If there is a clock then
// If RecogThem is called for every time it ticks (on a regular interval even if nothing changed) then
// The sensor repeat count (Level1, XQCnt, Fired) should be set to 1.
// (this is the case for hand writen digits or anywhere the environment is polled)
// If the reading is Magnitude then level 1 needs to count the repeats of the same value within the JND
// level 2 wil contain ratio binons (symbolic)
// Else if RecogThem is called every time a change occurs on at least one sense then
// Put the value of the duration into the sensors repeat count (XQCnt). (as for Morse code)
//Else if there is no clock then
// RecogThem is event driven and called only when a change occurs on at least one sense then
// set the XQCnt to 1 and for any repeaters do as above for a clock.
// SensorValues[NameBin][Valu][Fired] = Asc(Letr$) 'The letter
// SensorValues[NameBin][XQCnt][Fired] = Durat 'the number of times it has repeated
// SensorValues[ContBin][Valu][Fired] = DitDah 'The contrast intensity
// SensorValues[ContBin][XQCnt][Fired] = Durat 'the number of times it has repeated
//Pay attention to the expected sensors if concentrating - a Percept,
//create the Percepts that attract attention and place the most interesting in STM(1,Fired)
//Set GotAttendedTo = true if got the expected/attendedto stimuli/Percept
ProcessStimuli(SensorValues); //Process the SensorValues()
//The Perception STM list has many binons at each level. The Fired one is the most recent fired binon
//before any processing has been done at that level. It is put in the Fired entry when
//the level below is processed.
//After the processing has been done the previous one contains what was in the Current and
//the Current contains what was in the Fired provided there was no repeat of an Action.
// 2. PERFORM ACTION RECOGNITION:
// High level algorithm - 30th December 2016
// Expectation = Expectation/Attention binon = A-R
// Action = Action Habit = R-A
// Perceptual sequence = Stimulus Habit (Percept at level 1) and = A-E at higher levels = R-A-R
// Action sequence = Response Habit (Device responses) and E-A higher up = A-R-A.
// Repeat the the algorithm below for these two situations:
// Pass 1/ Odd level Current Action sequence combined with Fired Perceptual sequence to produce next level up Fired Expectation,
// find out if right target Action of the Perceptual sequence is worth doing and then
// the even level Current Action is combined with just Fired Expectation to produce next level up Perceptual sequence,
// Find out if right target Action sequence of the Expectation is worth doing.
// Pass 2/ Odd level Current Perceptual sequence combined with Fired Action sequence to produce next level up Fired Action,
// find out if right target Expectation of the Action sequence is worth doing and then
// the even level Current Expectation is combined with just Fired Action to produce next level up Action sequence,
// find out if right target Perceptual sequence of the Action is worth doing.
// The algorithm: Repeat this for each level X of the STM() binon tree as long as the fired is not a null object
// If on an even level and doing pass 2/ then have a just Fired Action to process so
// check to see if the fired Action pattern matches the previous Action (X positions earlier) at this level
// If it repeats then increment the past entry for the repeat and move it up to current
// Else if it does not repeat or on an odd level or doing pass 1/ then
// combine the Current to the Fired at this level (if there is a current) and
// place it in the next level up Fired position
// end if
// If finished pass 1/ STM processing then use the highest level Action or Action sequence found worth doing and
// do its lowest level response. Put this response Action sequence in STM(level 1 Fired) and start pass 2
// If finished pass 2/ STM processing then use the highest level Expectation or Perceptual sequence found worth doing and
// attend to its lowest level expected Percept in ProcessStimuli().
// The stimulus Percept obtained will be the Fired Perceptual sequence to start this process again.
for (Pass = 1; Pass <= 2; Pass++) //For 1/ R-S & A-E combinations then 2/ S-R & E-A combinations
{ ping();
ObjtLvl = 1; //Start by processing level 1 perceptions - always assigned
NovelLvl = 0; //set to the level at which the fired STM is novel
MoveAmount = 0; //Move right amount to eliminate previous pattern
SourceBinon = STM[ObjtLvl][BinId][Fired]; //It may be a right source binon for some target binons
while (SourceBinon != NullObject) //While there is a Fired familiar binon in STM
{ ping();
World.appendBinonDisplayChngResults(StringHelper.trim(String.valueOf(ObjtLvl), ' ') + "-0/ Processing percepts at level" + vbToStr(ObjtLvl) + "\r\n");
//First move the STM entries right by the MoveAmount due to a repeater at a lower level
if (MoveAmount > 0) {
int Prcpt = 0; // declare undeclared variable
MoveRight(ObjtLvl, Current + MoveAmount, Current, 2 * Prcpt); //eliminates binon created with previous goal from STM
}
if (InterestIn(SourceBinon) > FAMILIAR) //If the STM fired binon is novel then
{
NovelLvl = ObjtLvl; //It can not be combined with a current
} else //else check for a repeat and combine with current in STM
{
CheckIt = false; //do not check for a repeat of an Action
if (Pass == 1) //If the Stimulus / Expectation processing pass
{
AEorEA = Attention;
HabitIt = "Percept";
if (ObjtLvl % 2 == 0) //Odd level = 1, Even level = 0
{
HabitIt = "Action";
CheckIt = true; //Check to see if it repeats - both A and E - even levels
}
} else if (Pass == 2) //else if the Action / Response processing pass
{
AEorEA = Action; //assume it will be an Action
HabitIt = "Action";
if (ObjtLvl % 2 == 0) //If fired entry is an Action then (Pass=2 and remainder =0)
{
HabitIt = "Expectation";
CheckIt = true; //Check to see if it repeats - both A and E - even levels
}
}
World.appendBinonDisplayChngResults(StringHelper.trim(String.valueOf(ObjtLvl), ' ')
+ "-0a/ Pass" + vbToStr(Pass) + " - " + HabitIt + " Processing" + "\r\n");
ProcessSTMLevel(ObjtLvl, SourceBinon, AEorEA, CheckIt);
} //End if STM Fired binon is Novel
MoveLeft(ObjtLvl); //Move all STM left, the fired entry into the current location
HighestPerceptLvl = ObjtLvl; //Remember the highest not null fired level in STM
if (HighestPerceptLvl > TopLevel) //track highest non-empty level
{
TopLevel = HighestPerceptLvl;
}
//Go up the pattern tree combining Fired and Currents if they are patterns and fired is not nullobject
ObjtLvl = ObjtLvl + 1; //check out the next level for current and fired
if (ObjtLvl <= MaxLevels) {
SourceBinon = STM[ObjtLvl][BinId][Fired]; //It may be a right source binon for some target binons or Null
} else {
SourceBinon = NullObject;
Stop();
}
}
//Move all higher levels left by one minus moveamount
MoveAmount = 1 - MoveAmount; //move left one but right based on repeater found
for (; ObjtLvl <= TopLevel; ObjtLvl++) //for all higher levels that have something in them
{ ping();
if (MoveAmount == 1) {
MoveLeft(ObjtLvl); //processed one more level 1 stimulus
} else if (MoveAmount < 0) {
MoveRight(ObjtLvl, Current - MoveAmount, Current, 2 * ObjtLvl);
}
}
ReportObjects1(); //Fill in the top part of BinonDisplay.ChngResults.Text
SourceBinon = STM[HighestPerceptLvl][BinId][Current]; //It may be a right source binon for some target binons
if (Pass == 1) {
//If finished pass 1/ STM processing then based on the recognized Perceptual sequence or Expectation find any
//predicted action and use this highest level Action or Action sequence found worth doing and
//do its lowest level response in PerformAction().
//Or if the predicted action is learnt / familiar then use thinking (deduction) and find one worth doing
//Put this response Action sequence in STM(level 1, Fired) and start pass 2
DetermineResponse(); //determine what response to produce - do thinking
//Keep a record of STM() binons for display of LTM
LTMEMORY[StoreAt][LtmESType] = BinonTypeOf(SourceBinon);
LTMEMORY[StoreAt][LtmESActBin] = SourceBinon;
World.appendBinonDisplayChngResults(DisplaySTM());
} else //else Pass = 2
{
//If finished pass 2/ STM processing then based on the recognized Action or Action sequence find any
//predicted perception and use this highest level Expectation or Perceptual sequence found worth doing and
//do its lowest level expected Percept and attend to it in ProcessStimuli().
//This effectively means DetermineStimulus() needs to determine what stimulus to attend to
//The stimulus Percept obtained will be the Fired Perceptual sequence to start this process again.
//Keep a record of STM() binons for display of LTM
LTMEMORY[StoreAt][LtmARType] = BinonTypeOf(SourceBinon);
LTMEMORY[StoreAt][LtmARActBin] = SourceBinon;
//The level 1 perceived stimulus could be a familiar stimulus but unexpected.
// It is unexpected because none of the active Perceptual sequences were expecting it.
ReportPerceptions(); //Reports on Percepts() and STM() & expectation
ReportObjects2(); //Report on Binons
} //End if Pass =1 or Pass = 2
}
} //End of PerceptionAction()
public final void ProcessStimuli(int[][][] SensorValues) //Called from PerceptionAction()
{
//SensorValues() contains the sensor readings for ProcessStimuli() to process.
//ProcessStimuli() is not currently provided with the Percept that it expects to get/should attend to.
//Instead ProcessStimuli() assumes that the previous stimuli will repeat and just delivers any changes.
//ProcessStimuli is asked to attend to the senses / sensors specified in the given Percept (not yet).
//After calling ProcessSenses() to put sensory stimuli from all senses into SensedBinons() it
//uses the SenseBinons() and puts the perceived ones in the Percepts(). Not yet based on what was being attended to.
//If nothing was attended to then all the sensory stimuli are used.
//It creates the parallel combinations (Percepts) of the property SensedBinons().
//Combinations are formed if the parts are both familiar and both changed or both familiar and not changed.
//The most interesting Percept is then the largest / highest level (most complex) one that changed or
//if there was no change then just the highest level one.
//The most interesting stimulus is then placed in STM(level 1, Fired).
//SenseBinons() consist of:
// TextBin = the symbolic value for the letter - symbolic
// ContBin = Intensity = the value for the sensor measurement - Magnitude
int Sens;
int PerceptType;
String GotWhat;
int TopType;
int TopBinon;
int TopInterest;
int OL;
boolean HaveAChange = false;
int RepeatCount;
int FirstBinon;
int IntInF = 0;
int SecondBinon;
int TheType;
OL = 1; //Property binons and their combinations are at level 1
HaveAChange = false; //Assume no change will take place on any sense
//The expectation is the previous stimulus will repeat
ReportPerceptions(); //Report on all Percepts, Actions and expectations
ProcessSenses(OL, SensorValues); //Obtain the SensedBinons() for all property types SensorValues()
// The expectation is a repeat of the previous stimuli (if there are any) Property and Percept binons.
// Magnitude stimuli values must change by a JND to be detected
// Symbolic stimuli values are always available because they are uniquely identified.
// Determine what attracts attention by combining the stimuli that have changed.
// If nothing has changed then a repeat of the previous stimuli has occurred.
//For all the senses/property and Percept types
// copy the SensedBinons() into the 1st level Fired Percepts (property binons level),
// the other Percept combinations of property binons are created below
for (Sens = 1; Sens <= NumSenses; Sens++) //For each property type = sense
{ ping();
TheType = Sens;
Percepts[TheType][XQCnt][Fired] = SensorValues[Sens][XQCnt][Fired];
Percepts[TheType][BinId][Fired] = SensedBinons[Sens]; //Property binons into Percepts Level 1
if (Percepts[TheType][BinId][Current] != NullObject) //use the previous SensedBinon
{
if (SensedBinons[Sens] != Percepts[TheType][BinId][Current]) {
HaveAChange = true; //This property binon has changed
}
} else //Else the Current entry is empty the first time through
{
if (StoreAt != 1) {
Stop();
}
}
} //end for each property binon
CreatePerceptCombos(); //Create all the combinations of Percepts
//Report on Percept perceptions
DisplayPercepts(Fired);
//------ What attracts attention and thus what to pay attention to / focus on
//The highest level, most interesting changed, not null current Percept binon
//captures attention for sequential processing
TopBinon = NullObject; //Will be the highest complexity if no changed one found
TopType = NullType;
if (HaveAChange) {
TopInterest = NoInterest; //The interest level of the highest changed binon
for (PerceptType = NumPercepts; PerceptType >= 1; PerceptType--) //For all the Percept binon types from complex to property binons
{ ping();
FirstBinon = Percepts[PerceptType][BinId][Fired]; //The Percept that fired of this type - maybe NullObject
SecondBinon = Percepts[PerceptType][BinId][Current]; //The previous or expected binon of this type - maybe NullObject
if (FirstBinon != SecondBinon) //If the fired one is different / changed then
{
//If have a perceived binon and an expected one then
if (FirstBinon != NullObject) {
IntInF = InterestIn(FirstBinon); //Interest level of this Percept
//If it is familiar and interest so far is also familiar then we use the largest changed combination
if (IntInF == FAMILIAR) {
if (TopInterest == NoInterest) //The first / highest familiar one
{
// subroutine UseThisOne
TopType = PerceptType;
TopBinon = FirstBinon; //Save the highest level changed interesting Percept
TopInterest = IntInF; //will be familiar - only used if HaveAChange=True
}
//Else if it is novel then use the lowest level highest interest that has changed
} else if (IntInF >= TopInterest) //If it is more or equal interest than the one so far then
{
// subroutine UseThisOne
TopType = PerceptType;
TopBinon = FirstBinon; //Save the highest level changed interesting Percept
TopInterest = IntInF; //will be familiar - only used if HaveAChange=True
}
} else //else one or both binons are NullObjects
{
} //End if it has a value
} else //else got expected - no difference / change
{
} //End if it has changed
}
//If there is no change then the largest (highest level) not null combination is focused on.
} else //else there is no change in stimuli
{
for (PerceptType = NumPercepts; PerceptType >= 1; PerceptType--) //For all the Percept binon types from complex to property binons
{ ping();
FirstBinon = Percepts[PerceptType][BinId][Fired]; //The Percept that fired of this type - maybe NullObject
if (FirstBinon != NullObject) {
// subroutine UseThisOne
TopType = PerceptType;
TopBinon = FirstBinon; //Save the highest level changed interesting Percept
TopInterest = IntInF; //will be familiar - only used if HaveAChange=True
PerceptType = 1; //terminate loop
}
}
}
if (HaveAChange) //report about a different stimulus then - unexpected
{
GotWhat = "Got UNEXPECTED: ";
} else //else we got what was expected
{
GotWhat = "Got EXPECTED: ";
}
World.appendBinonDisplayChngResults(rep(' ', 55) + GotWhat + DisplayPattern(TopBinon) + "\r\n");
ClearExpectations(); //Clears PracticingBinon, PerceivedBinon etc.
//Must have a property or Percept stimulus so place the value Percepts(..Fired)
//in the Fired entry of STM[) at level 1][set its XQ count][set ExpectLevel, Expcts(] etc.
RepeatCount = 0;
if (TopBinon != NullObject) {
RepeatCount = Percepts[TopType][XQCnt][Fired];
//FireTheBinon(PercptLvl, TheBinon&, TQCnt, XQCnt)
FireTheBinon(OL, TopBinon, 1, RepeatCount); //will set the XQ count and the Perceived etc.
RememberStimulus(TopBinon, StoreAt);
}
//Move the fired Percepts() actually sensed into the current entries and clear the Fired entries
for (PerceptType = 1; PerceptType <= NumPercepts; PerceptType++) //For all property and Percept binon types
{ ping();
Percepts[PerceptType][BinId][Current] = Percepts[PerceptType][BinId][Fired];
Percepts[PerceptType][BinId][Fired] = NullObject; //clear their entries
Percepts[PerceptType][XQCnt][Current] = Percepts[PerceptType][XQCnt][Fired];
Percepts[PerceptType][XQCnt][Fired] = 0;
}
} //End of ProcessStimuli()
public final void ProcessSenses(int OL, int[][][] SensorValues) //Called from ProcessStimuli()
{
//Goes through the Raw sensor data in SensorValues(), creates the property type SensedBinons().
//SensorValues consist of:
// Text = the symbolic value for the letter - symbolic
// Intensity = the value for the sensor measurement - Magnitude
var SensedBinon = new Var<>(0);
var NewBee = new Var<>(false);
int PropBinonType;
int PrevLogVal;
int FiredLogVal;
int ValuDiff;
//' -------------------------- Senses and Sensors --------------------------
//
// Public NumSenses 'The number of physical senses, Max of 8
// 'Currently equals the NumProperties since each sense currently = 1 property type
// Public MaxSenses 'Maximum number of senses = max 8 physical senses
//unused String[] Sense = new String[1 + 8]; //Names of senses, up to 8 physical senses
//
// Public Senses[1 To 8][1 To 6] 'Properties of the different senses
// '1st index = Sense number
// '2nd index = Sense property
//
// '---- Senses() - 2nd index values - Sense Properties
// Public PropertyBinonType '1, Stimulus property binon type e.g. 1 = TextBin or 2 = ContBin
// Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator
// Public LowerRangeLimit '3, Lower limit of range of values, zero is minimum (65 = "A")
// Public UpperRangeLimit '4, Upper limit of range of values, 255 is maximum (90 ="Z")
// Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Compass degrees are Circular (0 to 360)
// Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs
// Public NumberOfSensors '7 Number of sensors in sensor array
// Public SensorsDependentOrIndependent '8 are sensors adjacent (dependent) or independent
//
// Public Symbolic '1, Indicates that the values from this sense are symbolic, range A -> Z
// Public Magnitude '2, Indicates that the values from this sense are numeric, integers, range 0 -> Limit
//
// Public Linear '1, Indicates that the values go from the lower limit to upper limit
// Public Circular '2, Indicates that the values rap around from the upper limit to 0
//
// Public IntegerValues '1, Indicates that the values are integer readings
// Public LogValues '2, Indicates that the values are already logs - orders of magnitude
// '-------------------- Values of stimuli from senses / sensors ------------------------------
//
// Public SensorValues[1 To 8][1 To 2][0 To 1] 'Stimulus values from senses/sensors
// '1st index is sense number, currently = property binon type
// '2nd index is what type of information is in the SensorValues(), XQCnt or Valu
// '3rd index is Fired for the most recent stimulus value and Current for the previous
//
// '---- SensorValues 2nd index values - type of information in SensorValues()
// Public XQCnt '=1, the count of times the value has repeated, also used below
// Public Valu '=2, the value for the stimulus, if symbolic then value = Asc(Symbol$)
// Public NoName$ '"_", The character used when no letter provided for the IDL value of a TextBin binon
//
// '---- SensorValues 3rd index values - which past stimulus it is - also used below
// Public Fired '=0 'stimulus put in this level upon firing before being processed
// Public Current '=1 'The Fired one becomes the Current one after processing
//------ Create binons from Sensed values that have changed and put them in SensedBinons()
// and move the fired SensorValues to the previous entries for all senses = property types
for (int Sens = 1; Sens <= NumSenses; Sens++) //For each sense (TextBin and ContBin) = for each property type
{ ping();
PropBinonType = Sens; //In Morse code only one property per sense
if (Senses[Sens][SymbolicOrMagnitude] == Symbolic) //If symbolic then
{
//Symbolic values always put in SensedBinons() whether they changed or not.
//Create or find the binon for this symbolic value
//IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean)
IdBinons(OL, PropBinonType, NullObject, 0, NullObject, 0, SensorValues[Sens][Valu][Fired], Parallel, 0, SensedBinon, NewBee);
SensedBinons[Sens] = SensedBinon.get(); //Fired Symbolic value changed
} else //Else ValueType = Magnitude
{
FiredLogVal = Buckit(SensorValues[Sens][Valu][Fired], SizeBase); //Goal
//The first time though we will not have a previous (Current) sensor reading (PrevLogVal)
if (SensorValues[Sens][Valu][Current] == 0) //no previous value
{
ValuDiff = 1; //there is a change in the Magnitude reading
} else {
PrevLogVal = Buckit(SensorValues[Sens][Valu][Current], SizeBase); //Trigger
//Adjacent repeat quantities are used to produce a ratio - same as these two lines of code:
//ValuDiff = Int(Abs(PrevLogVal - FiredLogVal) / 100) 'the difference in the Logs = ratio of repeats
//If FiredLogVal > PrevLogVal Then ValuDiff = -ValuDiff 'keep the sign
ValuDiff = (PrevLogVal - FiredLogVal) / 100; //Trigger minus Goal Logs
}
//Using ValuDiff will produce values of 1 and -1 as the contrast (Intensity) SensorValues()
//IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, _
//IDLRatio, SeqOrPar, ExpectIt, ObjId, NewOne As boolean);
IdBinons(OL, PropBinonType, NullObject, 0, NullObject, 0, ValuDiff, Parallel, 0, SensedBinon, NewBee);
SensedBinons[Sens] = SensedBinon.get(); //Fired Magnitude value changed by a JND
}
SensorValues[Sens][Valu][Current] = SensorValues[Sens][Valu][Fired]; //save the previous value
SensorValues[Sens][XQCnt][Current] = SensorValues[Sens][XQCnt][Fired]; //save the previous repeat count
} //End of loop for each property type = sense
} //End of ProcessSenses()
public final void CreatePerceptCombos() //Create all the combinations of Percepts
{
var SensedBinon = new Var<>(0);
var NewBee = new Var<>(false);
int PropBinonType;
int OL;
int FirstType;
int FirstBinon;
int IntInF;
boolean FirstChanged = false;
int SecondType;
int SecondBinon;
int IntInS;
boolean SecondChanged = false;
//For all the possible pairs of not null 1st level Percepts() = Property binon level
// Create the 2nd and higher level combinations,
//combine changed with changed and no change with no change but only if both property binons are familiar.
//Fill in Percepts() with a NullObject if either source binon is a NullObject or novel
//Need to create the Percept combinations of property binons - data driven algorithm from PerceptSources()
for (PropBinonType = NumProperties + 1; PropBinonType <= NumPercepts; PropBinonType++) //PropBinonType used for position of the combination
{ ping();
FirstType = PerceptSources[PropBinonType][FirstSource];
SecondType = PerceptSources[PropBinonType][SecondSource];
OL = PerceptSources[PropBinonType][PerceptLevel];
// CombineThem; //Uses Percepts[TheType][BinId][Current] to determine change
// CombineThem:
FirstBinon = Percepts[FirstType][BinId][Fired];
SecondBinon = Percepts[SecondType][BinId][Fired];
Percepts[PropBinonType][BinId][Fired] = NullObject; //assume the combination will not be produced
if (FirstBinon != NullObject && SecondBinon != NullObject) //if both sources are not null
{
IntInF = InterestIn(FirstBinon);
IntInS = InterestIn(SecondBinon);
//Both source binons must be familiar before they can be combined
if (CreateAll || (IntInF == FAMILIAR && IntInS == FAMILIAR)) {
//Both source binons must have changed or both stayed the same before they can be combined
FirstChanged = false; //Percepts[TheType][BinId][Current]
if (Percepts[FirstType][BinId][Current] != FirstBinon) {
FirstChanged = true;
}
SecondChanged = false;
if (Percepts[SecondType][BinId][Current] != SecondBinon) {
SecondChanged = true;
}
if (FirstChanged == SecondChanged) //If both changed or both stayed the same then
{
//IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean)
IdBinons(OL, PropBinonType, FirstBinon, 0, SecondBinon, 0, 0, Parallel, 0, SensedBinon, NewBee);
//exp Call SetInterest(PropBinonType, SensedBinon, FAMILIAR) 'Percept binons always familiar
//The property combination binon has fired (been recognized) and is expecting to fire again
Percepts[PropBinonType][BinId][Fired] = SensedBinon.get();
//Need value in Fired because it will be moved into current
Percepts[PropBinonType][XQCnt][Fired] = Percepts[FirstType][XQCnt][Fired];
} else //else no combination binon created at level 1 - Source Percepts() are not familiar & changed
{
}
} else //else no combination binon created at level 1 - Source Percepts() are not familiar
{
}
} else //else no combination binon created at level 1 - Source Percepts() are NullObjects
{
}
// end of CombineThem
}
} //End CreatePerceptCombos()
public final void ActivateAction(int DoBinon) //called from PerceptionAction()
{
//DoBinon& is the PracticingBinon Action that is to be done
var DHabitBinon = new Var<>(0);
//GetDHabit returns the Action or D-Habit Binon
GetDHabit(DoBinon, DHabitBinon); //Get the level 1 D-Habit to perform
PerformDHabit(DHabitBinon.get());
} //End of ActivateAction()
public final void PerformDHabit(int DoBinon) //called from ActivateAction()
{
//DoBinon is a level 1 Binon (D-Habit) that contains the device response to perform.
// DoBinon after pass 1 has been done is the expected response.
// It calls PerformResponses() which performs the DoBinon.
// This means it outputs the LetrBin. Then it fires the binon so it is on the STM().
var Letter = new Var<>("");
//unused int LetterBinon = 0;
int DeviceNum = 0;
//unused boolean NewBee = false;
int OutType;
int OutBinon = 0;
// '-------------------- Devices ------------------------------------------------
//
// Public NumDevices 'Number of output devices
// Public MaxDevices 'Maximum number of devices = max 8 devices
// Public Device$(1 To 8) 'Names of device, up to 8 devices
//
// Public Devices[1 To 8][1 To 5] 'Properties of the output / response devices
// '1st index = Device number
// '2nd index = Device property
// Public DeviceResponses$(1 To 4) 'A string of the possible symbolic responses for the device
//---- Devices() - 2nd index values - Device Properties - DEFINED ABOVE
// Public PropertyBinonType '1, Response property binon type e.g. 1 = LetrBin
// Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator
// Public LowerRangeLimit '3, Lower limit of range of response values, zero is minimum (97 = "a")
// Public UpperRangeLimit '4, Upper limit of range of response values, 255 is maximum (122 = "z")
// Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Motor rotations are Circular (0 to 360)
// Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs
// Public Symbolic '1, Indicates that the values for this device are symbolic, Range a -> z
// Public Magnitude '2, Indicates that the values for this device are numeric, integers, range 0 -> limit
// Public Linear '1, Indicates that the values go from the lower limit to upper limit
// Public Circular '2, Indicates that the values rap around from the upper limit to 0
// Public IntegerValues '1, Indicates that the values are integer readings
// Public LogValues '2, Indicates that the values are already logs - orders of magnitude
//Find the response parts of DoBinon - should use Devices() to identify the binon types involved
if (DoBinon == NullObject) //If there was no response in DoBinon then
{
Stop(); //should always have one selected by DetermineResponse()
// DeviceNum = 1 'Letters = LetrBin
// OutType = Devices[DeviceNum][PropertyBinonType] 'Currently = LetrBin for device #1
// Letter$ = NoResp$
// 'Should distinguish between symbolic versus Magnitude responses
// 'Create or find the binon for this symbolic value
// 'IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean)
// Call IdBinons(1, OutType, NullObject, 0, NullObject, 0, Asc(Letter$), Parallel, 0, OutBinon, NewBee)
} else //else have a letter to output
{
OutBinon = DoBinon;
OutType = BinonTypeOf(DoBinon);
DeviceNum = BinonTypes[OutType][SensOrDevNum]; //the device number for this response type binon
}
//Output the response (if any) and setup the expectation
Letter.set(""); //GetValue adds text to 3rd parameter = Letter$ so empty it
GetValue(OutBinon, Letter);
Letter.set(StringHelper.trim(Letter.get(), ' '));
World.appendBinonDisplayChngResults(" OUTPUT response = " + Letter + "\r\n");
DeviceValues[DeviceNum][XQCnt] = 1;
DeviceValues[DeviceNum][Valu] = Binons[OutBinon][IDL];
ClearExpectations(); //Clears PerceivedBinon
//FireTheBinon(PercptLvl, TheBinon&, TQCnt, XQCnt)
FireTheBinon(1, OutBinon, 1, 1); //will set PerceivedBinon
RememberResponse(OutBinon, StoreAt);
} //End PerformDHabit()
public final void ReportPerceptions() {
//Display the Fired, Current and previous perceptions in Percepts()
//unused String OLvl = null;
//unused String Prcpt = null;
//unused String Pcpts = null;
DisplayPercepts(Current);
//Report on Perceptual sequence perceptions
World.appendBinonDisplayChngResults(DisplaySTM() + "\r\n");
} //End of ReportPerceptions()
public final void DisplayPercepts(int CurrOrFired) {
int BinType;
//Report on Percept recognitions
World.appendBinonDisplayChngResults(" Percepts = ");
for (BinType = 1; BinType <= NumPercepts; BinType++) //All binon types except Actions
{ ping();
World.appendBinonDisplayChngResults(DisplayPercept(BinType, CurrOrFired));
}
World.appendBinonDisplayChngResults("\r\n");
} //End of DisplayPercepts()
public final String DisplayPercept(int BType, int CurrOrFired) {
return StringHelper.trim(String.valueOf(Percepts[BType][XQCnt][CurrOrFired]), ' ') + "x" + DisplayPattern(Percepts[BType][BinId][CurrOrFired]) + " ";
} //End of DisplayPercept$()
public final String DisplaySTM() {
String tempDisplaySTM = "";
int OLvl;
int Prcpt;
String Pcpts;
//Report on perceptions in STM()
if (STM[1][BinId][Current] == NullObject) //No STM entries then
{
tempDisplaySTM = "STM is empty" + "\r\n";
} else {
for (OLvl = 1; OLvl <= MaxLevels; OLvl++) { ping();
//printVars_str DisplaySTM(+OLvl, +MaxLevels);
Pcpts = ""; //empty this line
for (Prcpt = OLvl + 2; Prcpt >= Fired; Prcpt--) //find out if any are not null at this level
{ ping();
if (STM[OLvl][BinId][Prcpt] != NullObject) {
Pcpts = Pcpts + DisplaySTMEntry(OLvl, Prcpt) + " ";
}
}
if (!Pcpts.equals("")) //Only if there was a fired entry
{
Pcpts = " " + "Lvl=" + StringHelper.trim(String.valueOf(OLvl), ' ') + " " + Pcpts; //Put level # at start of line
tempDisplaySTM = tempDisplaySTM + Pcpts + "\r\n";
} else //else no current entry at this level
{
OLvl = MaxLevels; //terminate the loop
}
}
tempDisplaySTM = tempDisplaySTM + "\r\n";
}
return tempDisplaySTM;
} //End of DisplaySTM$()
public final String DisplaySTMEntry(int Percpt, int CurrFired) {
int BinonId;
//unused String BinonSt = null;
var VL = new Var<>("");
BinonId = STM[Percpt][BinId][CurrFired];
GetValue(BinonId, VL);
VL.set(substring(substring(VL.get(), 0, 20) + " ", 0, 7)); //display 6 chars of pattern
return "#" + StringHelper.trim(vbToStr(CurrFired), ' ')
+ "=" + StringHelper.trim(String.valueOf(STM[Percpt][XQCnt][CurrFired]), ' ') + "x" + StringHelper.trim(String.valueOf(STM[Percpt][TQCnt][CurrFired]), ' ') + DisplayStimulu(BinonId) + " " + VL;
} //End of DisplaySTMEntry$()
public final String DisplayPattern(int StimBin) {
String tempDisplayPattern;
var BinonTyp = new Var<>("");
var VL = new Var<>("");
int NumChr;
int StimTyp;
StimTyp = BinonTypeOf(StimBin);
if (StimTyp == NullType) {
tempDisplayPattern = " ~ ";
} else if (StimBin == NullObject) //Have a type but no binon
{
GetTypeInfo(StimTyp, BinonTyp, VL);
tempDisplayPattern = VL.get().substring(0, 2) + " ~";
} else {
NumChr = 5 + 6 * (StimTyp - 1); //Level 2 is 11 characters, level 3 is 17 characters
GetValue(StimBin, VL);
tempDisplayPattern = DisplayStimulu(StimBin) + " " + substring(VL.get(), 0, NumChr);
}
return tempDisplayPattern;
} //End of DisplayPattern$()
public final String DisplayStimulu(int StimBin) {
String tempDisplayStimulu;
var BTyp = new Var<>("");
var Rdg = new Var<>("");
String Inf;
String Gl;
int StimTyp;
StimTyp = BinonTypeOf(StimBin);
if (StimBin == NullObject || StimTyp == NullType) {
tempDisplayStimulu = "-00";
} else {
GetTypeInfo(StimTyp, BTyp, Rdg);
Gl = StringHelper.trim(Rdg.get().substring(0, 2), ' ') + StringHelper.trim(String.valueOf(StimBin), ' ');
Inf = IntSymb(InterestIn(StimBin));
tempDisplayStimulu = Inf + Gl + AESR(StimBin);
}
return tempDisplayStimulu;
} //End of DisplayStimulu$()
public final String InterestSymbol(int BinNum) {
int IntIn;
IntIn = InterestIn(BinNum);
return IntSymb(IntIn);
} //End of InterestSymbol$()
public String IntSymb(Object Intrst) {
String tempIntSymb;
tempIntSymb = ASpace;
switch ((Integer) Intrst) {
case NOVEL:
tempIntSymb = chr(254);
break;
case INTERESTING:
tempIntSymb = "!";
break;
case FAMILIAR:
tempIntSymb = "-";
break;
}
return tempIntSymb;
} //End of IntSymb$()
public void ClearExpectations() //Called by ClearMemory(), ProcessStimuli() and PerformAction()
{
PerceivedBinon = NullObject;
} //End of ClearExpectations()
public final void FireTheBinon(int PercptLvl, int TheBinon, int TQCount, int XQCount) {
//Called from ProcessStimuli() for the most changed stimulus combination
//Called from CreateCombo which is called by ProcessSTMLevel() every time a familiar stimulus is experienced
//Called from PerformAction() after response produced
//The binon has fired so place it in the Fired entry at this level in the STM, increment its XQ count,
//idle it and make it the most recent target of its left and right source binons.
//A newly created binon can not fire - can not be put on the STM()
int Uselink;
//Make it the most recent target binon of its left and right source binons
ImYourMostRecent(TheBinon, TriggerList);
ImYourMostRecent(TheBinon, GoalList);
if (InterestIn(TheBinon) != NOVEL) {
if (TheBinon != NullObject) //If a valid binon has fired
{
STM[PercptLvl][BinId][Fired] = TheBinon;
if (STM[PercptLvl][XQCnt][Fired] != 0) //should be zero
{
Stop();
}
STM[PercptLvl][XQCnt][Fired] = XQCount; //It has fired this many times
STM[PercptLvl][TQCnt][Fired] = TQCount; //trigger firing count for comparison of size of repeaters
// BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & " + Binon " & _
// DisplayPattern$(TheType, TheBinon) & " Fired" & vbCrLf
//
//Want the PerceivedBinon to be the highest fired Perceptual or Action sequence binon
//that triggers at least one associating binon or the level-1 S or R that has no associating binon
if (PercptLvl == 1) //If at level-1 start with the S or R
{
PerceivedBinon = TheBinon; //Track the trigger of expected goal for the Action
} else {
if (isSorR(TheBinon)) //If on an odd level - Perceptual - or Action sequence then
{
Uselink = FloatingPointToInteger.ToInt32(MostRecentTriggerTargetLink(TheBinon)); //determine its first associating binon, if any
if (Uselink != NullTarget) //If the fired binon has at least one associating binon
{
PerceivedBinon = TheBinon; //Track the trigger of expected goal for the Action
} else //else use the previously assigned PerceivedBinon
{
}
} else //else we are on an even level - A- or Expectation
{
// Stop
}
}
} else {
Stop(); //The fired binon should never be null
}
} else //else it is novel and can not be put on STM()
{
String Res = (" " + PercptLvl).substring((" " + PercptLvl).length() - 5)
+ vbToStr(Binons[TheBinon][TriggerCount])
+ vbToStr(Binons[TheBinon][GoalCount])
+ " " + DisplayPattern(TheBinon) + " NEW" + "\r\n";
World.appendBinonDisplayChngResults("\r\n" + Res);
} //End If TheBinon is not novel
} //End of FireTheBinon()
public final void ImYourMostRecent(int HabBinon, int TriggerOrGoal) {
int SourceBinon;
int TgtLink;
int TgtBinon;
int PrevLink;
int FirstLink;
boolean FoundIt = false;
if (TriggerOrGoal == TriggerList) {
SourceBinon = Binons[HabBinon][O1]; //Left source binon - trigger
} else {
SourceBinon = Binons[HabBinon][O2]; //Right source binon - goal
}
if (SourceBinon != NullObject) {
//Find the target binon on the trigger or goal list of the source binon and move it to the front of the list
TgtLink = Binons[SourceBinon][TriggerOrGoal];
FirstLink = TgtLink;
FoundIt = false;
PrevLink = NullTarget;
while (!FoundIt) { ping();
if (TgtLink == NullTarget) //should have been on the list
{
Stop();
}
TgtBinon = Targets[TgtLink][TargetBinon]; //The target binon
if (TgtBinon == HabBinon) //If it matches the HabBinon then found the entry
{
FoundIt = true;
if (PrevLink != NullTarget) //If not at the start of the list already
{
Targets[PrevLink][NLnk] = Targets[TgtLink][NLnk]; //remove the TgtLink Targets() entry from linked list
Targets[TgtLink][NLnk] = FirstLink; //TgtLink Targets() entry points to old first one on list
Binons[SourceBinon][TriggerOrGoal] = TgtLink; //It is now the 1st one / most recent target of source binon
}
} else {
PrevLink = TgtLink; //Link for the previous Targets() entry
TgtLink = Targets[TgtLink][NLnk]; //go to the next link in Targets list
}
}
}
} //End of ImYourMostRecent()
public final double MostRecentTriggerTargetLink(int TheBinon) {
double tempMostRecentTriggerTargetLink;
//Called from FireTheBinon() when upadting STM() and DetermineResponse() when thinking
int TgtLink;
//Obtain the link to the most recent (first) target ActBin for the trigger
TgtLink = Binons[TheBinon][TriggerList]; //The list of all targets for which it is the trigger
tempMostRecentTriggerTargetLink = NullTarget;
if (Binons[TheBinon][TriggerCount] > 0) //If TheBinon has any sequential right targets then
{
while (TgtLink != NullTarget) { ping();
if (BinonTypeOf(Targets[TgtLink][TargetBinon]) == ActBin) //The type of right target binon of the the given stimulus
{
tempMostRecentTriggerTargetLink = TgtLink;
TgtLink = NullTarget; //found the first useful Perceptual sequence - terminate the loop
} else //else some of the right targets could be Percepts?
{
TgtLink = Targets[TgtLink][NLnk]; //skip Percepts
}
}
}
return tempMostRecentTriggerTargetLink;
} //End of MostRecentTriggerTargetLink()
public final void GetDHabit(int TheBinon, Var FoundBinon) {
//This finds the level-1 D-Habit or response binon for the given binon (TheBinon - may be an Action) and
//returns it as the expected binon (FoundBinon - may be a D-Habit or response binon)
//unused int NameBinon = 0;
FoundBinon.set(TheBinon); //If it is the NullObject then that is returned
while (BinonTypeOf(FoundBinon.get()) == ActBin) { ping();
FoundBinon.set(Binons[FoundBinon.get()][O2]);
}
//Now the Found binon type is a D-Habit binon
} //End of GetDHabit()
public final void ProcessSTMLevel(int ObjtLvl, int SourceBinon, int AorE, boolean CheckRepeat) //called by PerceptionAction()
{
//If CheckRepeat then determine if the Fired at this level is same as repeat position.
//If it is a repeater then increases its count.
//Then combines the Current and Fired entries and puts them at one level higher in STM
//The fired binon at ObjtLvl is still in Fired position in STM when done.
int Prcpt;
int TQFired;
int XQFired;
int OldPercBin;
int TQRepeat;
int TrgtLvl;
//tmp BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & Trim(Str$(ObjtLvl)) & "-0a/ Fired binon " & _
// DisplayPattern[SourceType][SourceBinon] + "\r\n";
//check to see if the pattern matches the previous pattern at this level
//if it matches then
// increment the past entry for the repeat and move it up to current
Prcpt = ObjtLvl; //Repeater at this level will be in this entry position
TrgtLvl = ObjtLvl + 1;
if (CheckRepeat) //If need to check if an Action or Expectation repeats then
{
World.appendBinonDisplayChngResults(StringHelper.trim(String.valueOf(ObjtLvl), ' ')
+ "-0c/ Check for repeater Action" + "\r\n");
OldPercBin = STM[ObjtLvl][BinId][Prcpt]; //Any repeater should be in the correct position = ObjtLvl
if (OldPercBin == SourceBinon) //If the old = Fired it is a repeat binon
{
TQFired = STM[ObjtLvl][TQCnt][Fired]; //Trigger quantity (size) of the SourceBinon just fired
TQRepeat = STM[ObjtLvl][TQCnt][Prcpt]; //Trigger quantity (size) for the older Prcpt binon
if (TQRepeat == TQFired) //If the repeater is the same size as the fired one then
{
//tmp BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & Trim(Str$(ObjtLvl)) & "-0b/ Pattern " & _
// DisplayPattern[SourceType][SourceBinon] + " Repeats" + "\r\n";
//Increment its repeat count by the number of time it fired (duration at level 1)
XQFired = STM[ObjtLvl][XQCnt][Fired];
STM[ObjtLvl][XQCnt][Prcpt] = STM[ObjtLvl][XQCnt][Prcpt] + XQFired;
MoveAmount = MoveAmount + ObjtLvl;
//MoveRight(ObLvl, FromEntry, ToEntry, UpTo)
MoveRight(ObjtLvl, Prcpt, Fired, 2 * Prcpt); //repeater ends up in Fired entry
EmptySTM(TrgtLvl, Fired); //clear the fired next level up
} else //same pattern but different size
{
//Stop 'OK - treat as not repeating
//tmp BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & Trim(Str$(ObjtLvl)) & "-0c/ Pattern " & _
// DisplayPattern(SourceType, SourceBinon) + " does Not repeat" + "\r\n";
}
} else {
//tmp BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & Trim(Str$(ObjtLvl)) & "-0c/ Pattern " & _
// DisplayPattern(SourceType, SourceBinon) + " does Not repeat" + "\r\n";
}
}
//If it does not repeat
// Then as a goal combine the trigger previous to it at this level
// (if there is a trigger) and place it in the next level up fired position
if (STM[ObjtLvl][BinId][Current] != NullObject) //If there is a trigger previous to the fired location
{
if (STM[ObjtLvl][BinId][Fired] != NullObject) //and there is a goal at the repeater position
{
if (ObjtLvl > 1 || STM[ObjtLvl][XQCnt][Current] != 0) //set to 0 if already used
{
CreateCombo(ObjtLvl, Current, AorE); //Place the result in Fired of level above
} else {
Stop(); // why?
}
if (Prcpt + 2 <= MaxLevels) {
EmptySTM(ObjtLvl, Prcpt + 2); //Remove used trigger binon
}
} else //The fired binon is NullObject
{
Stop();
}
}
} //End ProcessSTMLevel()
public final void MoveRight(int ObLvl, int FromEntry, int ToEntry, int UpTo) {
//Move all the entries at the ObLvl to the right so that the one at FromEntry ends up at ToEntry position
//Null out previous locations, stop when the From Entry reaches the UpTo position
int Prcpt;
int NewPrcpt;
int Distance;
Distance = FromEntry - ToEntry; //how far they have to move
if (UpTo > MaxLevels) {
UpTo = MaxLevels;
}
for (Prcpt = FromEntry; Prcpt <= UpTo; Prcpt++) { ping();
NewPrcpt = Prcpt - Distance;
MoveOnePerception(ObLvl, Prcpt, NewPrcpt);
EmptySTM(ObLvl, Prcpt); //Nullify where it came from
}
} //End MoveRight()
public final void MoveLeft(int ObLvl) {
//Move all the entries at this ObLvl to the left one position so the Fired is in the Current
int Prcpt;
boolean HaveAPercept = false;
int ToPrcpt;
HaveAPercept = false; //assume this level is empty
ToPrcpt = ObLvl + 2;
if (ToPrcpt >= MaxLevels) {
ToPrcpt = MaxLevels - 1;
}
for (Prcpt = ToPrcpt; Prcpt >= Fired; Prcpt--) { ping();
if (STM[ObLvl][BinId][Prcpt] != NullObject) {
HaveAPercept = true;
}
MoveOnePerception(ObLvl, Prcpt, Prcpt + 1); //Move it left one position
}
EmptySTM(ObLvl, Fired); //and clear the fired entry
if (!HaveAPercept) {
TopLevel = TopLevel - 1;
}
} //End MoveLeft()
public final void MoveOnePerception(int ObLvl, int FromEntry, int ToEntry) {
STM[ObLvl][BinId][ToEntry] = STM[ObLvl][BinId][FromEntry];
STM[ObLvl][XQCnt][ToEntry] = STM[ObLvl][XQCnt][FromEntry];
STM[ObLvl][TQCnt][ToEntry] = STM[ObLvl][TQCnt][FromEntry];
} //End of MoveOnePerception()
public void EmptySTM(int OLvl, int PrevCurrFired) {
STM[OLvl][BinId][PrevCurrFired] = NullObject;
STM[OLvl][XQCnt][PrevCurrFired] = 0;
STM[OLvl][TQCnt][PrevCurrFired] = 0;
} //End of EmptySTM()
public final void CreateCombo(int ObjtLvl, int TrigPrcpt, int AorE) {
//If it is possible, Combine the trigger (Current) and goal (Fired) binons in the STM()
int TriggerBinon;
int TQNum;
int IntInTrig;
int Bin12;
int TQCount;
int GoalBinon;
int GQNum;
int IntInGoal;
int Bin21;
int Prev1LogRpts;
int Prev2LogRpts;
int RptsDiff;
var ResultBinon = new Var<>(0);
int TgtLvl;
var NewBee = new Var<>(false);
int Bin11;
int Bin22;
boolean CombineThem = false;
ResultBinon.set(NullObject); //Returned NullObject if not found or created
TriggerBinon = STM[ObjtLvl][BinId][TrigPrcpt];
if (ObjtLvl == 1) {
STM[ObjtLvl][TQCnt][TrigPrcpt] = STM[ObjtLvl][XQCnt][TrigPrcpt]; //wait until it has stopped repeating
}
if (TriggerBinon != NullObject) //If have a trigger pattern then
{
GoalBinon = STM[ObjtLvl][BinId][TrigPrcpt - 1];
if (GoalBinon != NullObject) //and if have a goal pattern then
{
IntInTrig = InterestIn(TriggerBinon);
IntInGoal = InterestIn(GoalBinon);
if (IntInTrig == FAMILIAR && IntInGoal == FAMILIAR) //if both familiar then
{
Bin12 = Binons[TriggerBinon][O2];
Bin21 = Binons[GoalBinon][O1];
//If at source level 2 or higher they must overlap
//or they are adjacent at source level = 1
if ((ObjtLvl > 1 && Bin12 == Bin21) || ObjtLvl == 1) {
//When the 1st binon left source is specific enough to uniquely predict its next stimulus
//and the 2nd binon right source is specific enough to uniquely predict its previous stimulus and
//when the common source binon (Bin12 = Bin21) uniquely predicts both its goal and
//trigger binon then stop combining the trigger (TriggerBinon) with the goal (GoalBinon).
CombineThem = true;
if (ObjtLvl > 1) {
CombineThem = false;
Bin11 = Binons[TriggerBinon][O1];
Bin22 = Binons[GoalBinon][O2];
if (Binons[Bin11][TriggerCount] != 1 || Binons[Bin22][GoalCount] != 1 || Binons[Bin21][TriggerCount] != 1 || Binons[Bin21][GoalCount] != 1) //****** NOTE add True to the condition to turn off
{
CombineThem = true;
}
}
if (CombineThem) {
TQNum = STM[ObjtLvl][XQCnt][TrigPrcpt]; //the repeat value of the trigger - XQ count
GQNum = STM[ObjtLvl][XQCnt][TrigPrcpt - 1]; //the repeat value of the goal - XQ count
//Use the trigger and goal binons to create a new binon with
//the correct ratio and place it in the Fired perception at the TgtLvl
TgtLvl = ObjtLvl + 1;
Prev1LogRpts = Buckit(TQNum, SizeBase); //Trigger
Prev2LogRpts = Buckit(GQNum, SizeBase); //Goal
//Adjacent repeat quantities are used to produce a ratio - same as:
//QtyDiff = Int(Abs(Prev1LogRpts - Prev2LogRpts) / 100)
//the difference in the Logs = ratio of repeats
//If Prev2LogRpts > Prev1LogRpts Then RptsDiff = -RptsDiff 'keep the sign
RptsDiff = (Prev1LogRpts - Prev2LogRpts) / 100; //Trigger minus Goal Logs
//The new binon is Active but Idle - waiting for a repeat
//IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean)
IdBinons(TgtLvl, ActBin, TriggerBinon, TQNum, GoalBinon, GQNum, RptsDiff, Sequential, AorE, ResultBinon, NewBee);
//The binon has fired so place it in the Fired entry at the target level, increment its XQ count,
//idle it and make it the most recent target of its trigger and goal.
TQCount = STM[ObjtLvl][TQCnt][TrigPrcpt]; //The size of the lowest level left part
//Add the fired stimulus to the Perceived STM().
//FireTheBinon will set the XQ count and the PerceivedBinon.
//FireTheBinon(PercptLvl, TheBinon&, TQCnt, XQCnt)
FireTheBinon(TgtLvl, ResultBinon.get(), TQCount, 1); //will set the XQ count
}
} //End if they overlap properly
} //End if they are both familiar
} else //Else the fired one is Nullobject
{
Stop(); //It should not be possible for fired one to be NullObject '
} //End if the goal binon exists
} else //Else the trigger is NullObject
{
Stop(); //It should be not NullObject - already checked in ProcessSTMLevel()
} //End if the trigger binon exists
} //End of CreateCombo()
public final void ReportObjects1() {
//Report information after perception and attention - before practice
//Reports only the objects perceived in BinonDisplay.ChngResults
String Res;
String Ptrn;
int ExprObj;
// -------------------------- Status of perception before attending to the stimuli --------------
if (Processing50) {
return;
}
World.appendBinonDisplayChngResults("\r\n" + " # EObj Pattern - Fired Binon List" + "\r\n");
Res = "";
for (var J = 1; J <= HighestPerceptLvl; J++) { ping();
ExprObj = STM[J][BinId][Current];
if (ExprObj != NullObject) {
Ptrn = "";
if (ExprObj == PerceivedBinon) //If we have an expected binon at this level then
{
Ptrn += " This is the Perceived or Performed Binon";
}
Res = Res + (" " + J).substring((" " + J).length() - 5)
+ vbToStr(Binons[ExprObj][TriggerCount])
+ vbToStr(Binons[ExprObj][GoalCount])
+ " " + DisplayPattern(ExprObj) + " " + Ptrn + "\r\n";
}
}
World.appendBinonDisplayChngResults(Res + "\r\n");
} //End ReportObjects1()
public final void ReportObjects2() {
//Report after Pass 2 - after prerceiving stimulus, doing response and expecting a stimulus
//Reports on Objects in ObjList textbox
StringBuilder Res2 = new StringBuilder();
var Rdgs = new Var<>("");
StringBuilder Res1;
String Ptrn;
String IntInfo;
var VL = new Var<>("");
var Ty1 = new Var<>("");
var Ty2 = new Var<>("");
//unused String BN = null;
//unused String Brand = null;
int BnTyp;
int Objct;
var BinTyp = new Var<>("");
int ObjLvl;
//unused int Prcpt;
int TypInteger;
String Inf = null;
// -------------------- The binon list after being processed ------------
if (Processing50) {
return;
}
//Fill in Binon list in BinonDisplay.ObjList.Text
int NumChr;
for (BnTyp = 1; BnTyp <= NumBinonTypes; BnTyp++) //Property binons and Percept combinations, Perceptual sequences and Responses
{ ping();
GetTypeInfo(BnTyp, BinTyp, Rdgs); //Rdgs$ = abbreviation - not used - use BinTyp$ only
Res2.append(BnTyp).append(", ").append(Rdgs).append(BinTyp).append("\r\n");
for (ObjLvl = 1; ObjLvl <= MaxLevels; ObjLvl++) //For each level of binons
{ ping();
Res1 = new StringBuilder();
for (Objct = 1; Objct <= NumBinons; Objct++) //For all binons
{ ping();
Ptrn = "";
if (Binons[Objct][OLv] == ObjLvl) //if have a binon at this level then
{
if (BinonTypeOf(Objct) == BnTyp) {
Inf = "";
VL.set("");
GetValue(Objct, VL);
NumChr = 5 + 6 * (Binons[Objct][OLv] - 1); //Level 2 is 11 characters, level 3 is 17 characters
Ptrn = substring(VL.get(), 0, NumChr); //display 14 chars of pattern
if ((Ptrn == null ? 0 : Ptrn.length()) == 1) {
Ptrn = " " + Ptrn;
}
TypInteger = BinonTypeOf(Binons[Objct][O1]);
GetTypeInfo(TypInteger, Ty1, Ty1);
TypInteger = BinonTypeOf(Binons[Objct][O2]);
GetTypeInfo(TypInteger, Ty2, Ty2);
IntInfo = InterestSymbol(Objct);
Res1.append(substring(" " + Objct, (" " + Objct).length() - 3))
.append(substring((" " + Binons[Objct][OLv]), (" " + Binons[Objct][OLv]).length() - 3))
.append(AESR(Objct)).append(" ")
.append(substring(Ty1.get(), 0, 2))
.append(substring(" " + Binons[Objct][O1], (" " + Binons[Objct][O1]).length() - 3))
.append(" ").append(substring(Ty2.get(), 0, 2))
.append(substring(" " + Binons[Objct][O2], (" " + Binons[Objct][O2]).length() - 3))
.append(substring(" " + Binons[Objct][IDL], (" " + Binons[Objct][IDL]).length() - 4))
.append(takeLast(2, vbToStr(Binons[Objct][TriggerCount])))
.append(takeLast(2, vbToStr(Binons[Objct][GoalCount])))
.append(substring(" " + IntInfo, (" " + IntInfo).length() - 3))
.append(substring(" " + Binons[Objct][TQ], (" " + Binons[Objct][TQ]).length() - 3))
.append(substring(" " + Binons[Objct][GQ], (" " + Binons[Objct][GQ]).length() - 3))
//.append("*X*")
.append(" ").append(Ptrn).append(" ")
.append(DisplayHabit(Objct)).append("\r\n");
}
} //End if it is this Binon type
}
if (!StringHelper.isNullOrEmpty(Res1.toString())) {
Res2.append(Res1).append("\r\n");
}
}
Res2.append("\r\n");
}
World.setBinonDisplayObjList(Res2.toString()); //value set above
} //End of ReportObjects2()
public final String AESR(int Objct) {
String tempAESR;
if (BinonTypeOf(Objct) <= NumPercepts) //AE property is 0 for parallel binons
{
tempAESR = " P"; //Level 1 Percept or property binon
} else {
tempAESR = " A"; //level 1 Response binon = LetrBin
}
if (Binons[Objct][AE] == Action) //AE not assigned for level 1 Stimuli or Responses
{
if (!isSorR(Objct)) //two letters refer to types/roles of source binons
{
tempAESR = " A"; //Action binon
} else {
tempAESR = " AA"; //Action sequence
}
} else if (Binons[Objct][AE] == Attention) {
if (!isSorR(Objct)) {
tempAESR = " E"; //Expectation binon
} else {
tempAESR = " PP"; //Perceptual sequence
}
}
return tempAESR;
} //End of AESR$()
public final boolean isSorR(int Objct) {
//If the binon is at an odd sequential level then it is either an S or R
//If the binon is at an even sequential level then it is either an A or an E
//If the binon is not sequential (an ActBin) then it is either an S or R
//remainder is 1 if odd level, 0 if even level
return Binons[Objct][OLv] % 2 == 1 || BinonTypeOf(Objct) != ActBin;
}
public final String DisplayHabit(int ObjBin) {
StringBuilder tempDisplayHabit;
//Displays the list of target binons for which this one is the left source and / or right source
int Link;
//unused int Bin = 0;
tempDisplayHabit = new StringBuilder();
//Display the list of target binons this one triggers
Link = Binons[ObjBin][TriggerList]; //does the binon trigger at least one target binon
while (Link != NullTarget) { ping();
//add target binon type and objID
tempDisplayHabit.append("l").append(DisplayStimulu(Targets[Link][TargetBinon]));
Link = Targets[Link][NLnk]; //go to the next one on the list
if (Link != NullTarget) {
tempDisplayHabit.append(", ");
}
}
Link = Binons[ObjBin][GoalList]; //does the binon goal at least one target binon
if (Link != NullObject && !StringHelper.isNullOrEmpty(tempDisplayHabit.toString())) {
tempDisplayHabit.append(", ");
}
while (Link != NullTarget) { ping();
//add target binon type and objID
tempDisplayHabit.append("r").append(DisplayStimulu(Targets[Link][TargetBinon]));
Link = Targets[Link][NLnk]; //go to the next one on the list
if (Link != NullTarget) {
tempDisplayHabit.append(", ");
}
}
return tempDisplayHabit.toString();
} //End of DisplayHabit()
public final void DetermineResponse() //Called from PerceptionAction()
{
//Enter here if finished pass 1/ STM processing then based on the recognized Perceptual sequence or Expectation find any
//predicted action and use this highest level Action or Action sequence found worth doing and
//do its lowest level response in PerformAction().
//Or if the predicted action is learnt / familiar then use thinking (deduction) and find one worth doing
//Put this response Action sequence in STM(level 1, Fired) and start pass 2
int FirstLink;
int Thinklink;
int ThinkBinon;
//unused int EndLink = 0;
String Reason = null;
//unused int GoalBinon = 0;
//unused int TrigTargetBinon = 0;
var PracticingBinon = new Var<>(0); //The binon being practiced. Concentration Level is based upon it.
int DoneBinon;
var NewBee = new Var<>(false);
int OutType;
int UL;
int ll;
int NextResponse;
var ResponseBinon = new Var<>(0);
int I;
int CurrentResponse;
int UseResponse;
int HaveResponse;
int NumberOfResponses;
String ThisResponse = null;
//FireTheBinon() will have found any response worth doing and PerceivedBinon will be the level
//for the Perceptual sequence trigger to find the response to do.
//The Practicing binon may be the NullObject because no Actions were being performed.
//This happens when there are no Actions for the stimulus as the trigger.
//This means no expectation. After a stimulus is familiar and the one following it is also familiar then
//we have a novel Action for the trigger and at least have one expectation
//Note: it should be just the perceived binon that is used based on any number >0 triggercount
//the interest in redoing its most recent determines if need to practice it. triggercount=1 needed to
//do deductions - certain / reliable inference, if >1 then just the most recent possible goal is used
//and this gives induction reasoning - no certainty because sometime in the past at least one different goal has happened
PracticingBinon.set(NullObject); //even after thinking then babble
//If have a perceived binon (it is an Perceptual sequence) with associating Action binons then
//check to see if it is worth doing - if not then think
FirstLink = FloatingPointToInteger.ToInt32(MostRecentTriggerTargetLink(PerceivedBinon)); //The right target binon link - if any
if (FirstLink != NullTarget) //If have a link to a recent right target Action binon then
{
PracticingBinon.set(Targets[FirstLink][TargetBinon]); //This must be an Action
if (InterestIn(PracticingBinon.get()) > FAMILIAR) //If it is worth doing then
{
Reason = " STM Perceived binon is the trigger of its most recent novel Action";
//use PracticingBinon below by calling ActivateAction()
} else //else the binon is not worth practicing so think about it
{
//#1 Approach: ----------------------------
//An alternate approach here is to go up the most recent right target binons of the tree
//looking for an Action that is novel and if found then activate all the right targets traversed so
//that the sequence is done at a concentration level to repeat / learn the novel one.
//Let us just try one traversal up this right target binon tree via the intermediate Perceptual sequence.
Thinklink = FloatingPointToInteger.ToInt32(MostRecentTriggerTargetLink(PracticingBinon.get())); //The right target binon link - if any
//This will be an Perceptual sequence - but we need to go up one more level to the Action - if any
if (Thinklink != NullTarget) //If there is a right target link to an associating binon then
{
ThinkBinon = Targets[Thinklink][TargetBinon];
Thinklink = FloatingPointToInteger.ToInt32(MostRecentTriggerTargetLink(ThinkBinon)); //The right target Action binon link - if any
} else //Else no right target Perceptual sequence binon
{
}
//#2 Approach: ----------------------------
//Obtain the response that could be performed and see if it triggers an Expectation (stimulus) worth expecting
//2 GoalBinon = Binons[PracticingBinon][O2] 'The goal that could be done - Action sequence
//2 Thinklink = MostRecentTriggerTargetLink(GoalBinon) 'Does it have a right target - an Expectation
//2 Reason$ = " Thought about associated goal of STM perceived is trigger of a most recent novel Expectation"
// -----------------------------------------
if (Thinklink != NullTarget) //If there is a right target link to an associating binon then
{
ThinkBinon = Targets[Thinklink][TargetBinon]; //The Approach#1 Action or Approach#2 Expectation to practice
if (InterestIn(ThinkBinon) > FAMILIAR) //if the next A- or Expectation is worth expecting then
{
//there is a next Perceptual sequence to expect so do the current Action - PracticingBinon
//use PracticingBinon below by calling ActivateAction()
Reason = " Thought about right target of STM perceived is trigger of a most recent novel Action";
} else //Else the next Action sequence (goal of PracticingBinon) is not worth doing so
{
PracticingBinon.set(NullObject); //do not do the practicing binon - it is familiar / learnt
} //End if the next binon was worth doing
} else //else there is no next possible stimulus - no associating Expectation so
{
PracticingBinon.set(NullObject); //do not do the practicing binon - it is familiar / learnt
} //End if there was no next Perceptual sequence to expect
} //End if the associating Action (PracticingBinon) is worth doing
} else //Else no right target link of PerceivedBinon - no PracticingBinon
{
} //End of Is there a right target link of Perceived binon
//If don't have a binon to practice, even after thinking, then find something to do or babble
if (PracticingBinon.get() == NullObject) //If the PracticingBinon is still a NullObject then
{
Reason = "";
//If the Practicing Binon is null because the highest STM recognized Perceptual sequence (PerceivedBinon)
//has no associating Action binons (is novel or familiar but followed by a novel binon) then
//we do nothing to see if it repeats
int DeviceNum;
if (FirstLink == NullTarget) //If there is no associating binons for the perception
{
//so use the 1st device and its first symbolic or range response, PracticingBinon must be set
DeviceNum = 1; //Letters = LetrBin
OutType = Devices[DeviceNum][PropertyBinonType]; //Currently = Wheels for device #1
if (Devices[DeviceNum][SymbolicOrMagnitude] == Magnitude) //Use Range of values
{
NextResponse = Devices[DeviceNum][LowerRangeLimit];
//IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean)
IdBinons(1, OutType, NullObject, 0, NullObject, 0, NextResponse, Parallel, 0, PracticingBinon, NewBee);
} else //If Devices[DeviceNum][SymbolicOrMagnitude] = Symbolic Then 'Use first response values
{
String Letter = DeviceResponses[DeviceNum].substring(0, 1); //Will be a NoResp$
// Letter$ = NoResp$
//Create or find the binon for this symbolic value
//IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean)
IdBinons(1, OutType, NullObject, 0, NullObject, 0, asc(Letter), Parallel, 0, PracticingBinon, NewBee);
}
Reason = " First response of first action device - Babbling";
} else //else have an associating Action sequence for PerceivedBinon then
{
//Find the most recent response at the lowest level and use the next one
DoneBinon = Targets[FirstLink][TargetBinon]; //The Action most recently practiced at the next level up
//GetDHabit returns the lowest level response binon in ResponseBinon
GetDHabit(DoneBinon, ResponseBinon); //Get the level 1 most recent response done
DeviceNum = BinonTypes[BinonTypeOf(ResponseBinon.get())][SensOrDevNum]; //the device number for this response type binon
if (Devices[DeviceNum][SymbolicOrMagnitude] == Magnitude) //Use Range of values
{
ll = Devices[DeviceNum][LowerRangeLimit];
UL = Devices[DeviceNum][UpperRangeLimit];
if (Binons[ResponseBinon.get()][IDL] == NoResp) //If it is the no response then
{
NextResponse = ll;
} else {
NextResponse = Binons[ResponseBinon.get()][IDL] + 1;
if (NextResponse > UL) //if off end of valid values then
{
NextResponse = ll; //wrap around to start again
}
}
//Create or find the binon for this symbolic value
//IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean)
IdBinons(1, BinonTypeOf(ResponseBinon.get()), NullObject, 0, NullObject, 0, NextResponse, Parallel, 0, PracticingBinon, NewBee);
} else //If Devices[DeviceNum][SymbolicOrMagnitude] = Symbolic Then 'Use given response values
{
//Find the last one used
CurrentResponse = 0;
NumberOfResponses = DeviceResponses[DeviceNum].length();
for (I = 1; I <= NumberOfResponses; I++) //go through the response string
{ ping();
if (Binons[ResponseBinon.get()][IDL] == asc(DeviceResponses[DeviceNum].substring(I - 1, I - 1 + 1))) {
CurrentResponse = I;
I = NumberOfResponses; //terminate the loop
}
}
//Find the next non "z" entry
UseResponse = CurrentResponse;
HaveResponse = 0; //will be set to the next response entry position
// 'A random response generator
// While HaveResponse = 0
// UseResponse = Int(NumberOfResponses * Rnd + 1) 'generate a number between 1 and and NumberofResponses
// ThisResponse$ = Mid$(DeviceResponses$(DeviceNum), UseResponse, 1)
// 'if it is a response that can be done and not a repeat of the last one chosen then
// If ThisResponse$ <> NoMoveOrTurn$ And UseResponse <> CurrentResponse Then
// HaveResponse = UseResponse 'a non-zero value will terminate the loop
// End If
// Wend
//Sequentially go through the available responses
while (HaveResponse == 0) { ping();
UseResponse = UseResponse + 1;
if (UseResponse > NumberOfResponses) //if off the end of the string then
{
UseResponse = 1; //start at the beginning again
}
ThisResponse = DeviceResponses[DeviceNum].substring(UseResponse - 1, UseResponse - 1 + 1);
if (!ThisResponse.equals(NoMoveOrTurn)) //if it is a response that can be done then
{
HaveResponse = UseResponse; //a non-zero value will terminate the loop
}
}
//Create or find the binon for this symbolic value
//IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean)
IdBinons(1, BinonTypeOf(ResponseBinon.get()), NullObject, 0, NullObject, 0, asc(ThisResponse), Parallel, 0, PracticingBinon, NewBee);
}
Reason = " Babbling";
} //End if have no associating Action sequence
} else //Else have a binon to practice so do that one
{
} //End if do not have a PracticingBinon
//Report on what is being practiced - if anything
if (PracticingBinon.get() != NullObject) //If practicing then
{
World.appendBinonDisplayChngResults(" * Practicing " + DisplayPattern(PracticingBinon.get()) + Reason + "\r\n");
} else {
Stop();
World.appendBinonDisplayChngResults(" * Not Practicing anything" + "\r\n");
}
//If have no action to practice at this point then PerformAction() will respond with nothing
ActivateAction(PracticingBinon.get()); //Perform the response and fire the binon to STM(1, Fired)
//Old notes
// If we are practicing (concentrating on) an Action then this active sequence will have a goal
// that it is trying to achieve. This is the goal of the most recent target binon (Action) triggered by the
// previously perceived/attended-to stimulus. It is the prediction, the expectation.
// The concentration level will be based on the wanted / pleasant (desirability) level of the goal or
// interest level (novel, interesting or familiar) of the redo interest of the Action being practiced.
// When practicing / concentrating we will only attend to the expected goal of the Action being practiced.
// All of the triggered target binons of the attended to stimulus are active / expecting but only the most recent one
// is being practiced, goal expected.
// If any expecting Action (including the one being practiced) does not get its expected goal then it becomes inactive.
// The binon recognized (fired) instead will be on the Percepts() list and attract attention.
// Thus the possible outcomes are:
// O1 - Get the expected goal of the practicing Action binon (PracticingResult$ = "Matched"
// O2 - Get the goal of a different triggered Expecting target Action binon (same triggering / attended-to binon)
// O3 - All expecting Actions could fail
// O3a - get a familiar goal stimulus but it is a novel sequence for the attended-to as the trigger
// O3b - get a novel or interesting stimulus at the AttendToLevel or lower.
// Note: you can be attending to a stimulus but not practicing because there are no right target Action binons
// of the attended-to stimulus.
// Note: only target Sequence / Action binons can be performed / practiced - not target property binons
//If concentrating - no expecting binon got its goal so - Outcome O3
// we find the "got-instead" goal
// This "got-instead" goal binon is the one obtained instead of the expected goal
// or if that is not available (a NullObject) then it is the next attended-to stimulus (the novel one produced).
// The logic should be:
//1 If practicing an Action then (PracticingResult$ will be set Matched or Failed)
// When practicing an Action you are paying attention / focusing on / expecting a stimulus from sense of its goal
//2 If it matched its goal and the goal has finished repeating then focus / pay attention to its goal. [set as AttendTo]
// Reduce its interest / novelty level.
// Can not be distracted because paying attention to the goal sense (change blindness) and got the goal?
// Or will any stimulus not expected by any of the other Actions (not being practiced) distract you? [set AttendTo]
// else it failed to match / get the goal of the practicing binon so
// the one being practiced stays at the same interest level.
// The actual sequence experienced becomes the most recent one (but no change in its interest level).
// Attention is paid to the stimulus "got-instead" of the goal at the same sense as the goal unless
// there is a stimulus that distracts you from this. [set AttendTo]
// Else not practicing so
// Pay attention to the most interesting - attractive? stimulus [set AttendTo]
// End
//
//' The interest in a sequence is only reduced if it is the one being practiced and the goal is matched.
//' What about another sequence that has the same trigger and its goal is expected but it is not the one being
//' practiced but it is the one that is matched? It stays novel. If it becomes the most recent it will be practiced
//' the next time its trigger occurs.
// 'If not practicing (e.g. due to a novel or interesting attended-to stimulus) then
// ' Attend to the most attractive perception
// ' If the attendto is novel or interesting, it can not be the left source for any target binons
// ' and has no goals.
// ' If the attendto is a novel Percept then we must remain not practicing (ConcentrationLevel = NoInterest).
// ' If the attendto is an Action then pay attention to the goal stimulus that caused the novel
// ' sequence. It will be familiar. Start practicing any
// ' If the attendto is familiar then
// ' use it as the trigger and its most recent sequential right target as an Action worth practicing.
// ' Set the concentration level based on the wanted (pleasant) goal (must be familiar) or
// ' the interest level of the most recent Action right target to practice.
// ' Its goal is the expectation. That is what is being predicted.
// ' If the interest / concentration level is familiar then use thinking to search for something
// ' more interesting to do
// ' end if
// 'end if
//
//' If was practicing - failed or matched will have no AttendTo and Expected = goal set, PracticingBinon = NullObject
//' - repeating trigger or goal and not interrupted then PracticingBinon will be set
//' If not practicing AttendTo is not set, PracticingBinon = NullObject and ExpectedBinon = NullObject
//' 10a. THINKING:
//' If still no Action worth practicing then find one through thinking.
//' Find an Action that will lead to one that needs practicing or that will produce a
//' rewarding final goal stimulus.
//' Pay attention to the goal stimulus of the most recent Action of the attended-to stimulus and
//' treat it as though it was the attended-to stimulus and repeat steps 8 and 9 above.
//' This is thinking of the goal by traversing the Actions for this stimulus as the trigger.
//' This repeats until we come across an Action that has a desirable redo interest or
//' a pleasant expected goal stimulus.
//' There will be a limit on this looping to begin with. Some other criterion is required
//' to stop this thinking. It must stop if it loops around to an already thought about Action.
//' If it is successful the first thought about Action will be selected for performing in step 11
//' as the active practicing Action at the appropriate concentration level.
//' In a real-time system a thinking loop may continue until it is interrupted by an unexpected stimulus.
//' Should the thinking loop also select additional Actions or should they only be started by a conscious stimulus?
//' Where does boredom fit in - results from repetition of a conscious stimulus?
//' Or if we have a limited number of thinking steps we may not find an Action worth doing.
//' Should thinking be done after or before investigating the parts of the attended-to in step 9?
//' Thinking is based on recalling the goal stimulus of the most recent Action
//' for the attended-to stimulus and letting the interest in this goal stimulus determine whether to
//' perform the Action. Should we store the thought as a thought so that it can be repeated
//' if successful and learnt?
//' We are bored when the only Action we have to do is a familiar one or there is no Action to do.
//' If we get the expected goal of a familiar Action then the sequence is the next trigger.
//
//' Also might consider the situation where do have a conscious active Action but it is being done at the
//' interesting level and thinking produces a novel one to practice - if this is logically possible.
} //End of DetermineResponse()
public class Bodies {
//
// Called to assign the different body configuration parameters
// Called to perform each sense/response action cycle by World.Go_Click()
//
//
//World data moved here because it can't be put in World form
String[][] WP = new String[40 + 1][40 + 1]; //The positions of the world as appearing
//in the Current World grid, a ABlock$ = "#" indicates
//the location is a blacked out square
// Label NG(0 To 383)
//Number Grid is stored in linear array of Labels NG(0) to NG(383)
//that have no borders. These contain the location letters that can be displayed.
// Label CWP(0 To 511)
//World Grid is stored in linear array of Labels CWP(0)->CWP(511)
//that have borders and can contain letters. The background colour is black for a block and light blue
//for the cursor. The CWP.Caption = "S" for where Smarty is.
String MaxBodies;
String BExternal;
int InputSense;
void BodyAssignStimuli() {
//Fills in the Values$() with KIN$() from last response
int Sens;
var Stimuli = new Var<>("");
// Public NumSenses 'The number of physical senses, Max of 8, set in SetUpSense()
// 'Currently equals the NumProperties since each sense currently = 1 property type
// Public MaxSenses 'Maximum number of senses = max 8 physical senses
// Public Sense$(1 To 8) 'Names of senses, up to 8 physical senses
// Public IsSense '1, Flag for Senses versus Devices
//
// Public Senses(1 To 8, 1 To 8) 'Properties of the different senses
// '1st index = Sense number
// '2nd index = Sense property
//
// '---- Senses() - 2nd index values - Sense Properties
// Public PropertyBinonType '1, Stimulus property binon type e.g. 1 = TextBin or 2 = ContBin
// Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator
// Public LowerRangeLimit '3, Lower limit of range of values, zero is minimum (65 = "A")
// Public UpperRangeLimit '4, Upper limit of range of values, 255 is maximum (90 ="Z")
// Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Compass degrees are Circular (0 to 360)
// Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs
// Public NumberOfSensors '7 Number of sensors in sensor array
// Public SensorsDependentOrIndependent '8 are sensors adjacent (dependent) or independent
// Public SensorValues[1 To 8][1 To 2][0 To 1] 'Stimulus values from senses/sensors
// '1st index is sense number, currently = property binon type
// '2nd index is what type of information is in the SensorValues(), XQCnt or Valu
// '3rd index is Fired for the most recent stimulus value and Current for the previous
//
// '---- SensorValues 2nd index values - type of information in SensorValues()
// Public XQCnt '=1, the count of times the value has repeated, also used below
// Public Valu '=2, the value for the stimulus, if symbolic then value = Asc(Symbol$)
// Public NoName$ '"_", The character used when no letter provided for the IDL value of a TextBin binon
//
// '---- SensorValues 3rd index values - which past stimulus it is - also used below
// Public Fired '=0 'stimulus put in this level upon firing before being processed
// Public Current '=1 'The Fired one becomes the Current one after processing
LIN = LIN + 1;
for (Sens = 1; Sens <= NumSenses; Sens++) //For each sense
{ ping();
if (Senses[Sens][SymbolicOrMagnitude] == Magnitude) {
GetStimuli(Sens, Stimuli); //get the stimuli from body senses
//Stimuli$ = Chr$(of the range to far wall)
SensorValues[Sens][XQCnt][Fired] = 1;
SensorValues[Sens][Valu][Fired] = asc(Stimuli.get()); //one character per sense
INPUTS[LIN][Sens] = chr(SensorValues[Sens][Valu][Fired] + 48); //convert to "1" to "8"
} else //Else Symbolic input
{
//Setup a motion sense if WheelsConfig.AddAWheelSensor = 1 is checked
if (Sense[Sens].equals("Motion")) //If its name is the sense of motion then
{
SensorValues[Sens][XQCnt][Fired] = 1;
SensorValues[Sens][Valu][Fired] = asc(Motion);
} else //else it is some other symbolic sense
{
GetStimuli(Sens, Stimuli); //get the stimuli from body senses
SensorValues[Sens][XQCnt][Fired] = 1;
SensorValues[Sens][Valu][Fired] = asc(Stimuli.get()); //one character per sense
}
INPUTS[LIN][Sens] = chr(SensorValues[Sens][Valu][Fired]);
}
}
} //End of BodyAssignStimuli()
public final void BodyFunction2() //called from World.Go to perform a cycle
{
//This routine determines the current stimuli and changes the body's state
//based on which body is currently being used.
String CurrentPlace = null;
char Kn;
char Resp;
//Smarty0$ body has a sensor that looks under at the current square and
//moves Up, Down, Left or Right. Always displayed as an O
//If a body can turn and change the direction it is pointing
//then it is displayed as an ^, >, <, or v
CurrentPlace = World.LookUnder();
// Public DeviceValues(1 To 8, 1 To 2) 'Response values for devices
// '1st index is device number, currently = response property binon type
// '2nd index is what type of information is in the DeviceValues(), XQCnt or Valu
//
// '---- DeviceValues 2nd index values - type of information in DeviceValues() - DEFINED ABOVE
//' Public XQCnt '=1, the count of times the value needs repeating, also used below
//' Public Valu '=2, the value for the response, if symbolic then Symbol$ = Chr$(value)
// Public NoResp$ '"-", The character representing no response for a LetrBin binon
BodyAssignStimuli(); //fills in the Values$() from the senses and
//the Motion$ from last response if turned on
PerceptionAction(SensorValues, DeviceValues);
if (NumDevices > 1) {
Stop();
}
Resp = (char) DeviceValues[1][Valu];
Kn = Resp;
switch (Resp) //Motion$ will be set by the World.Move routines
{
case NoResp:
Motion = NoMove; //= Mid$(WheelMovement$, 1, 1)
break;
case MoveForward:
switch (BodyPointing) {
case East:
World.MoveEast();
break;
case South:
World.MoveSouth();
break;
case West:
World.MoveWest();
break;
case North:
World.MoveNorth();
break;
}
if (Motion.equals("Y")) {
Motion = WheelMovement.substring(1, 2);
}
break;
case MoveToLeft:
switch (BodyPointing) {
case East:
World.MoveNorth();
break;
case South:
World.MoveEast();
break;
case West:
World.MoveSouth();
break;
case North:
World.MoveWest();
break;
}
if (Motion.equals("Y")) {
Motion = WheelMovement.substring(2, 3);
}
break;
case MoveToRight:
switch (BodyPointing) {
case East:
World.MoveSouth();
break;
case South:
World.MoveWest();
break;
case West:
World.MoveNorth();
break;
case North:
World.MoveEast();
break;
}
// WheelMovement$ = "-flrb" & rotate left, right and around 180 degrees
if (Motion.equals("Y")) {
Motion = WheelMovement.substring(3, 4);
}
break;
case MoveBackward:
switch (BodyPointing) {
case East:
World.MoveWest();
break;
case South:
World.MoveNorth();
break;
case West:
World.MoveEast();
break;
case North:
World.MoveSouth();
break;
}
if (Motion.equals("Y")) {
Motion = WheelMovement.substring(4, 5);
}
break;
case TurnRght: //rotate right 90 degrees
BodyPointing = BodyPointing + 1;
if (BodyPointing == 4) {
BodyPointing = 0;
}
Motion = WheelMovement.substring(5, 6); //a rotate always happens
break;
case TurnLft: //rotate left 90 dgrees
BodyPointing = BodyPointing - 1;
if (BodyPointing == -1) {
BodyPointing = 3;
}
Motion = WheelMovement.substring(6, 7); //a rotate always happens
break;
case TurnArnd: //rotate around 180 degrees
BodyPointing = BodyPointing + 2;
if (BodyPointing == 4) {
BodyPointing = 0;
}
if (BodyPointing == 5) {
BodyPointing = 1;
}
Motion = WheelMovement.substring(7, 8); //a rotate always happens
break;
} //Case Resp$
//Orient body pointer on world view if wheels turn
if (WheelsTurn) {
switch (BodyPointing) //direction body is pointing, 0=East, 1=South, 2=West, 3=North
{
case East:
World.PointEast(); // >
break;
case South:
World.PointSouth(); // v
break;
case West:
World.PointWest(); // <
break;
case North:
World.PointNorth(); // ^
// Case 4
// Call World.RangeSymbol ' "+" sign
break;
}
} else //else the wheels don't turn so display an A
{
World.PointUnder(); //"A" = Adaptron pointing North
}
OUTPUTS[LIN][1] = OUTPUTS[LIN][1] + Kn; //for HistoryDisplay of outputs
change(); // persist any changes in this object
World.Update_View(); //dump all the history and LTMem()
//do this for each sense
World.DisplayStimuliAndResponse(SensorValues, Resp); //fillin the World.VB() value
} //End of BodyFunction2()
public final void GetStimuli(int Sens, Var ReturnedStimuli) {
//Get the stimulus value for each Sens.
//Currently each Sense is a single sensor
ReturnedStimuli.set("");
if (Senses[Sens][SymbolicOrMagnitude] == Magnitude) {
switch (Sense[Sens]) //Based on the name of the sense
{
case "VisionD": //Looking down at cell - distance 1 cell away
ReturnedStimuli.set(ReturnedStimuli.get() + (char) 1);
break;
case "VisionL": //looking left based on body direction
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeWest()));
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeNorth()));
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeEast()));
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeSouth()));
break;
}
break;
case "VisionR": //looking right
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeEast()));
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeSouth()));
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeWest()));
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeNorth()));
break;
}
break;
case "VisionF": //looking forward
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeNorth()));
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeEast()));
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeSouth()));
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeWest()));
break;
}
break;
case "VisionB": //looking behind
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeSouth()));
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeWest()));
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeNorth()));
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeEast()));
break;
}
break;
}
} else //Sense is symbolic
{
if (Senses[Sens][LowerRangeLimit] == asc(Wall)) //If vision just looking at next square then
{
switch (Sense[Sens]) //Based on the name of the sense
{
case "VisionD": //Looking down at cell floor
ReturnedStimuli.set(Wall);
break;
case "VisionL": //looking left based on body direction
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest());
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth());
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast());
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth());
break;
}
break;
case "VisionR": //looking right
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast());
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth());
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest());
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth());
break;
}
break;
case "VisionF": //looking forward
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth());
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast());
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth());
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest());
break;
}
break;
case "VisionB": //looking behind
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth());
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest());
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth());
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast());
break;
}
break;
}
if (!ReturnedStimuli.get().equals(Wall)) //if it's not a wall then the square is empty
{
ReturnedStimuli.set(EmptySquare);
}
} else //Else vision looking at symbolic location value in next square
{
switch (Sense[Sens]) //Based on the name of the sense
{
case "VisionD": //Looking down at cell
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookUnder());
break;
case "VisionL": //looking left based on body direction
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest());
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth());
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast());
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth());
break;
}
break;
case "VisionR": //looking right
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast());
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth());
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest());
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth());
break;
}
break;
case "VisionF": //looking forward
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth());
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast());
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth());
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest());
break;
}
break;
case "VisionB": //looking behind
switch (BodyPointing) {
case North:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth());
break;
case East:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest());
break;
case South:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth());
break;
case West:
ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast());
break;
}
break;
}
} //end if its looking for wall or space or looking for square location letter
} //end if sense is magnitude or symbolic
} //End of GetStimuli()
}
} // end of Smarty
static final class StringHelper {
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'Substring' when 'start' is a method
// call or calculated value to ensure that 'start' is obtained just once.
//------------------------------------------------------------------------------------
public static String substring(String string, int start, int length) {
if (length < 0)
throw new IndexOutOfBoundsException("Parameter length cannot be negative.");
return string.substring(start, start + length);
}
//------------------------------------------------------------------------------------
// This method replaces the .NET static string method 'IsNullOrEmpty'.
//------------------------------------------------------------------------------------
public static boolean isNullOrEmpty(String string) {
return string == null || string.length() == 0;
}
//------------------------------------------------------------------------------------
// This method replaces the .NET static string method 'IsNullOrWhiteSpace'.
//------------------------------------------------------------------------------------
public static boolean isNullOrWhiteSpace(String string) {
if (string == null)
return true;
for (int index = 0; index < string.length(); index++) { ping();
if (!Character.isWhitespace(string.charAt(index)))
return false;
}
return true;
}
//------------------------------------------------------------------------------------
// This method replaces the .NET static string method 'Join' (2 parameter version).
//------------------------------------------------------------------------------------
public static String join(String separator, String[] stringArray) {
if (stringArray == null)
return null;
else
return join(separator, stringArray, 0, stringArray.length);
}
//------------------------------------------------------------------------------------
// This method replaces the .NET static string method 'Join' (4 parameter version).
//------------------------------------------------------------------------------------
public static String join(String separator, String[] stringArray, int startIndex, int count) {
if (stringArray == null)
return null;
StringBuilder sb = new StringBuilder();
for (int index = startIndex; index < stringArray.length && index - startIndex < count; index++) { ping();
if (separator != null && index > startIndex)
sb.append(separator);
if (stringArray[index] != null)
sb.append(stringArray[index]);
}
return sb.toString();
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'Remove' (1 parameter version).
//------------------------------------------------------------------------------------
public static String remove(String string, int start) {
return string.substring(0, start);
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'Remove' (2 parameter version).
//------------------------------------------------------------------------------------
public static String remove(String string, int start, int count) {
return string.substring(0, start) + string.substring(start + count);
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'TrimEnd'.
//------------------------------------------------------------------------------------
public static String trimEnd(String string, Character... charsToTrim) {
if (string == null || charsToTrim == null)
return string;
int lengthToKeep = string.length();
for (int index = string.length() - 1; index >= 0; index--) { ping();
boolean removeChar = false;
if (charsToTrim.length == 0) {
if (Character.isWhitespace(string.charAt(index))) {
lengthToKeep = index;
removeChar = true;
}
} else {
for (int trimCharIndex = 0; trimCharIndex < charsToTrim.length; trimCharIndex++) { ping();
if (string.charAt(index) == charsToTrim[trimCharIndex]) {
lengthToKeep = index;
removeChar = true;
break;
}
}
}
if (!removeChar)
break;
}
return string.substring(0, lengthToKeep);
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'TrimStart'.
//------------------------------------------------------------------------------------
public static String trimStart(String string, Character... charsToTrim) {
if (string == null || charsToTrim == null)
return string;
int startingIndex = 0;
for (int index = 0; index < string.length(); index++) { ping();
boolean removeChar = false;
if (charsToTrim.length == 0) {
if (Character.isWhitespace(string.charAt(index))) {
startingIndex = index + 1;
removeChar = true;
}
} else {
for (int trimCharIndex = 0; trimCharIndex < charsToTrim.length; trimCharIndex++) { ping();
if (string.charAt(index) == charsToTrim[trimCharIndex]) {
startingIndex = index + 1;
removeChar = true;
break;
}
}
}
if (!removeChar)
break;
}
return string.substring(startingIndex);
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'Trim' when arguments are used.
//------------------------------------------------------------------------------------
public static String trim(String string, Character... charsToTrim) {
return trimEnd(trimStart(string, charsToTrim), charsToTrim);
}
//------------------------------------------------------------------------------------
// This method is used for string equality comparisons when the option
// 'Use helper 'stringsEqual' method to handle null strings' is selected
// (The Java String 'equals' method can't be called on a null instance).
//------------------------------------------------------------------------------------
public static boolean stringsEqual(String s1, String s2) {
if (s1 == null && s2 == null)
return true;
else
return s1 != null && s1.equals(s2);
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'PadRight' (1 parameter version).
//------------------------------------------------------------------------------------
public static String padRight(String string, int totalWidth) {
return padRight(string, totalWidth, ' ');
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'PadRight' (2 parameter version).
//------------------------------------------------------------------------------------
public static String padRight(String string, int totalWidth, char paddingChar) {
StringBuilder sb = new StringBuilder(string);
while (sb.length() < totalWidth) { ping();
sb.append(paddingChar);
}
return sb.toString();
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'PadLeft' (1 parameter version).
//------------------------------------------------------------------------------------
public static String padLeft(String string, int totalWidth) {
return padLeft(string, totalWidth, ' ');
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'PadLeft' (2 parameter version).
//------------------------------------------------------------------------------------
public static String padLeft(String string, int totalWidth, char paddingChar) {
StringBuilder sb = new StringBuilder();
while (sb.length() + string.length() < totalWidth) { ping();
sb.append(paddingChar);
}
sb.append(string);
return sb.toString();
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string constructor which repeats a character.
//------------------------------------------------------------------------------------
public static String repeatChar(char charToRepeat, int count) {
String newString = "";
for (int i = 1; i <= count; i++) { ping();
newString += charToRepeat;
}
return newString;
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'LastIndexOf' (char version).
//------------------------------------------------------------------------------------
public static int lastIndexOf(String string, char value, int startIndex, int count) {
int leftMost = startIndex + 1 - count;
int rightMost = startIndex + 1;
String substring = string.substring(leftMost, rightMost);
int lastIndexInSubstring = substring.lastIndexOf(value);
if (lastIndexInSubstring < 0)
return -1;
else
return lastIndexInSubstring + leftMost;
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'LastIndexOf' (string version).
//------------------------------------------------------------------------------------
public static int lastIndexOf(String string, String value, int startIndex, int count) {
int leftMost = startIndex + 1 - count;
int rightMost = startIndex + 1;
String substring = string.substring(leftMost, rightMost);
int lastIndexInSubstring = substring.lastIndexOf(value);
if (lastIndexInSubstring < 0)
return -1;
else
return lastIndexInSubstring + leftMost;
}
}
static final class FloatingPointToInteger {
public static byte ToSByte(double source) {
byte floor = (byte) Math.floor(source);
if (Math.abs(source - floor) == 0.5) {
if (floor % 2 == 0)
return floor;
else
return (byte) Math.ceil(source);
} else if (Math.abs(source - floor) < 0.5)
return floor;
else
return (byte) Math.ceil(source);
}
public static short ToInt16(double source) {
short floor = (short) Math.floor(source);
if (Math.abs(source - floor) == 0.5) {
if (floor % 2 == 0)
return floor;
else
return (short) Math.ceil(source);
} else if (Math.abs(source - floor) < 0.5)
return floor;
else
return (short) Math.ceil(source);
}
public static int ToInt32(double source) {
int floor = (int) Math.floor(source);
if (Math.abs(source - floor) == 0.5) {
if (floor % 2 == 0)
return floor;
else
return (int) Math.ceil(source);
} else if (Math.abs(source - floor) < 0.5)
return floor;
else
return (int) Math.ceil(source);
}
public static long ToInt64(double source) {
long floor = (long) Math.floor(source);
if (Math.abs(source - floor) == 0.5) {
if (floor % 2 == 0)
return floor;
else
return (long) Math.ceil(source);
} else if (Math.abs(source - floor) < 0.5)
return floor;
else
return (long) Math.ceil(source);
}
}
static boolean debugValues = false; // debug sensor output
static int defaultSpacing = 10, spacing;
static JFrame mainFrame;
static List> gridComponents;
static JComponent mainGrid;
static JCheckBoxMenuItem miShowLocations;
static SingleComponentPanel scpMainGrid, scpVisionConfig, scpWheelsConfig, scpCurrentSmarty,
scpStimuliAndResponse;
static JFrame historyFrame, memoryFrame;
static JSpinner worldSizeSpinner;
static JTextArea historyTextArea1, historyTextArea2;
static JTextArea taSensorValues, taDeviceValues;
// originally: BinonDisplay.ObjList.Text
static JTextArea memoryTextArea1;
// originally: BinonDisplay.ChngResults.Text
static JTextArea memoryTextArea2;
static Smarty smarty; // AI instance
static Q smartyQ = startQ("Smarty Q"); // queue for Smarty operations
static String wallSymbol = unicode_blackSquare(), noWallSymbol = unicode_dottedSquare();
static Color lightBlue = colorFromHex("4169e1");
static String locationLetters = charRange('A', 'Z') + "[\\]^_`" + charRange('a', 'z') + charRange(123, 128);
static String smartyUnicode = unicode_slightlySmilingFace();
static int smartyFontSize = 40;
static String windowsFontID = "#1400468";
static String emojiFontID = "#1400470";
static String frameIconID = "#1102983";
static String monospacedFontID = /*#1400479*/"#1400483";
static double monospacedFontSize = 12;
static boolean smartyBrainPersistence = false;
static String smartyImageID = "#1102987";
static String helpTextID = "#1031105";
static String worldFileExtension = "WLD";
static String bodyFileExtension = "BDY";
static String historyHelp = unindent_mls("\r\n A percept is the stimulus or simultaneous combination of stimuli observed.\r\n An action is the response or simultaneous combination of responses produced.\r\n Binon # numbers refer to the binons in memory that represent the percepts, actions, expectations, and perceptual or action sequences.\r\n P = Percept, E = Expectation, PP = Perceptual sequence A = Action, AA = Action sequence\r\n Read the paper: \"The Perception-Action Hierarchy and its Implementation Using Binons (Binary Neurons)\" on the www.adaptroninc.com website for more information.\r\n");
// translate Smarty's windows characters to unicode
static Map winToUnicode = litmap(
Smarty.Smarty, unicode_slightlySmilingFace(),
Smarty.UpArrow, unicode("2191"),
Smarty.LeftArrow, unicode("2190"),
Smarty.RightArrow, unicode("2192"),
Smarty.DownArrow, unicode("2193"),
Smarty.Wall, unicode_blackVerticalRectangle(),
Smarty.EmptySquare, unicode_whiteVerticalRectangle(),
Smarty.chr(Smarty.TurnRght), unicode("21B1"),
Smarty.chr(Smarty.TurnLft), unicode("21B0"),
Smarty.chr(Smarty.TurnArnd), unicode("21B7"),
Smarty.chr(254), unicode_blackSmallSquare());
static boolean showTabs = true;
static int defaultWorldSize = 7, maxWorldSize = 8;
static ReliableSingleThread rstUpdateChngResults = rstWithPreDelay(250, new Runnable() { public void run() { try {
setText(memoryTextArea2, winToUnicode(state.binonDisplayChngResults));
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "setText(memoryTextArea2, winToUnicode(state.binonDisplayChngResults));"; }});
static void rearrangeLetters() {
int iLetter = 0;
for (int y = 0; y < state.gridRows; y++)
for (int x = 0; x < state.gridCols; x++) {
JCell cell = getCell(x, y);
if (cell.obstacle())
cell.letter = ' ';
else
cell.letter = locationLetters.charAt(iLetter++);
}
}
static class VisionMode {
static String nextSquare = "next square";
static String distanceToWall = "distance to wall";
static String wallOrNot = "wall or not";
}
static class CameraDirection {
static String down = "down";
static String left = "left";
static String right = "right";
static String inFront = "in front";
static String behind = "behind";
static List all = ll(down, left, right, inFront, behind);
}
static class SmartyBody extends Concept {
static final String _fieldOrder = "name cameraDirections visionMode wheels changed used";
String name = "Smarty0";
Set cameraDirections = litset(CameraDirection.down);
String visionMode = VisionMode.nextSquare; // see VisionMode
Set wheels = litset("MoveForward", "MoveLeft", "MoveRight", "MoveBackward");
boolean changed = false; // changed w.r.t. file
boolean used = false; // used in Smarty execution
// for saving
String wheelsFlag(String flag) { return wheels.contains(flag) ? "1" : "0"; }
void userCausedChange() {
print("Body: User caused change");
changed = true;
change();
}
}
static class State extends Concept {
static final String _fieldOrder = "fontScale worldName gridRows gridCols showLocations worldChanged startX startY smartyX smartyY smartyDirection selection cursorDirection obstacles history1 history2 memory1 sensorValuesText deviceValuesText binonDisplayChngResults body recentWorldFiles recentBodyFiles";
float fontScale = 1.5f;
String worldName = "Empty";
int gridRows = defaultWorldSize, gridCols = defaultWorldSize; // actually these are always identical, could merge into one
boolean showLocations = false;
boolean worldChanged = false;
int startX, startY; // Smarty's start position
int smartyX, smartyY;
String smartyDirection = Smarty.Smarty; // which way Smarty is looking - this or smarty.LeftArrow etc.
Rect selection = rect(1, 1, 1, 1);
Pt cursorDirection = pt(1, 0);
BitSet obstacles = new BitSet();
String history1 = "", history2 = "", memory1 = "", sensorValuesText = "", deviceValuesText = "";
String binonDisplayChngResults = ""; // memory2
Ref body = new Ref();
// value is just true
Map recentWorldFiles = synchronizedMRUCache(5);
Map recentBodyFiles = synchronizedMRUCache(5);
void setSelection(Rect r) {
if (!cset_trueIfChanged(this, "selection" , r)) return;
if (selection.h == 1 && selection.w > 1) _setField("cursorDirection" , pt(1, 0));
else if (selection.w == 1 && selection.h > 1) _setField("cursorDirection" , pt(0, 1));
repaintGrid();
}
void clearSelectedArea() {
fillSelection(false);
}
void invertSelection() {
JCell cell1 = getCell(selection.x, selection.y);
fillSelection(!cell1.obstacle());
}
void fillSelection(boolean b) {
for (Pt p : pointsInRect(selection))
if (!(b && state.smartyX == p.x && state.smartyY == p.y)) // don't put an obstacle over Smarty
getCell(p.x, p.y).setObstacle(b);
rearrangeLetters();
moveCursor();
}
void moveCursor() {
setCursor(selection.x+cursorDirection.x, selection.y+cursorDirection.y);
}
void setCursor(int x, int y) {
setSelection(rect(mod(x, gridCols), mod(y, gridRows), 1, 1));
}
void moveCursor(int dx, int dy) {
_setField("cursorDirection" , pt(dx, dy));
setCursor(selection.x+cursorDirection.x, selection.y+cursorDirection.y);
}
void placeSmarty() {
getCell(selection.x, selection.y).setObstacle(false);
cset(state, "startX" , selection.x, "startY" , selection.y);
moveSmarty(selection.x, selection.y);
moveCursor();
}
void moveSmarty(int x, int y) {
if (!inRange(x, 0, gridCols) || !inRange(y, 0, gridRows))
throw fail("Smarty position not in range: " + x + "/" + y);
if (cset_trueIfChanged(this, "smartyX" , x, "smartyY" , y)) {
cset(this, "worldChanged" , true);
repaintGrid();
}
}
void moveSmartyRelative(int x, int y) {
moveSmarty(smartyX+x, smartyY+y);
}
} // end of State
static State state;
static class JCell extends JComponent {
int x, y;
char letter;
JCell(int x, int y) {
this.y = y;
this.x = x;}
public void paint(Graphics _g) {
Graphics2D g = (Graphics2D) _g;
int w = getWidth(), h = getHeight();
Color color = Color.white;
if (state.selection.contains(x, y)) color = lightBlue;
else if (obstacle()) color = Color.black;
fillRect(g, 0, 0, w, h, color);
if (state.showLocations && !obstacle()) {
AutoCloseable __5 = tempSetFont(g, loadFont_cached(windowsFontID)); try {
drawTextWithTopLeftCornerAt(g, str(letter), new Pt(2, 0), Color.black);
} finally { _close(__5); }}
if (state.smartyX == x && state.smartyY == y) {
AutoCloseable __6 = tempSetFontSize(g, smartyFontSize); try {
/*temp tempSetFont(g, loadFont_cached(emojiFontID));
drawCenteredText(g, smartyUnicode, 0, 0, w, h, Color.black);*/
double size = 0.6;
int dx = iround((1-size)/2*w);
int dy = iround((1-size)/2*h);
if (eq(state.smartyDirection, smarty.Smarty))
drawScaledImage(g, loadImage2_cached(smartyImageID), rectFromPoints(dx, dy, w-dx, h-dy));
else {
//temp tempSetFont(g, loadFont_cached(windowsFontID));
String icon = lookupOrKeep(winToUnicode, state.smartyDirection);
drawCenteredText(g, icon, 0, 0, w, h, Color.black);
}
} finally { _close(__6); }}
}
int index() { return y*state.gridCols+x; }
boolean obstacle() { return main.contains(state.obstacles, index()); }
void setObstacle(boolean b) {
if (setBit_trueIfChanged(state.obstacles, index(), b)) {
cset(state, "worldChanged" , true);
state.change();
}
}
{
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
main.requestFocus(mainGrid);
if (!isLeftButton(e)) return;
state.setSelection(new Rect(x, y, 1, 1));
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
//_print("Drag in " + x + "/" + y + ": " + e.getPoint());
Component dest = componentAtScreenLocationInWindow(mainFrame, e);
if (dest instanceof JCell) {
//_print("Target: " + dest);
state.setSelection(rectFromPointsInclusiveSorted(x, y, ((JCell) dest).x, ((JCell) dest).y));
}
}
});
}
public String toString() { return x + "/" + y; }
}
static JCell getCell(int x, int y) {
return gridComponents.get(y).get(x);
}
static JCell smartyCell() {
return getCell(state.smartyX, state.smartyY);
}
static boolean inGrid(int x, int y) {
return inRange(y, state.gridRows) && inRange(x, state.gridCols);
}
static void makeMainGrid() {
gridComponents = map(iotaZeroList(state.gridRows), y
-> map(iotaZeroList(state.gridCols), x
-> new JCell(x, y)));
mainGrid = setFocusable(setBackground(Color.black, hvgrid(gridComponents, 1)));
scpMainGrid.setComponent(mainGrid);
rearrangeLetters();
}
// always clears the world
static void setWorldSize(int size) {
state.obstacles.clear();
state.gridCols = state.gridRows = size;
setSpinnerValue(worldSizeSpinner, size);
state.selection = rect(1, 1);
cset(state, "startX" , 0, "startY" , 0);
state.moveSmarty(0, 0);
cset(state, "worldChanged" , false);
state.change();
makeMainGrid();
resetSmarty();
}
static void repaintGrid() {
repaint(mainGrid);
}
// add more functions here
static void smartyMain() {
System.out.println("Main class: " + strWithIdentityHashCode(mc()) + ", class loader: " + getClassLoader(mc()));
autoRestart(2.0);
// print all vm bus msgs from concepts
//vmBus_snoopToPrint((msg, arg) -> firstOfArrayOrSame(arg) instanceof Concepts);
setProgramDir(print("Using directory: ", mainDir()));
logProgramOutput();
_handleException_showThreadCancellations = true;
if (!isDevVersion()) hideConsole();
else veryBigConsole();
db();
uniq(SmartyBody.class); // make at least one instance
state = uniq(State.class);
smarty = uniq(Smarty.class);
initSmarty();
if (!state.body.has()) cset(state, "body" , conceptWhere(SmartyBody.class)); // default body
//cset(state.body, used := false); // XXX
// prep GUI
jtattoo_mcWin(); // styling
//set swingFontScale_debug;
updateFontScale(state.fontScale); // scaling
disableSpaceBarForAllButtons(); // no space bar for buttons
loadLibrary(windowsFontID);
defaultFrameIcon(frameIconID);
mainFrame = showFrame("Smarty");
//exitOnClose(mainFrame);
onWindowClosing(mainFrame, runnableThread(new Runnable() { public void run() { try {
cleanUp(mc()); // proper clean-up for standalone mode
cleanKillVM();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cleanUp(mc()); // proper clean-up for standalone mode\r\n cleanKillVM();"; }}));
historyTextArea1 = monospaced(uneditableBlackTextArea_noUndo());
historyTextArea2 = monospaced(uneditableBlackTextArea_noUndo());
memoryTextArea1 = /*withTypeWriterFont*/monospaced(uneditableBlack(swing(() -> new JLineHeightTextArea(0.8))));
memoryTextArea2 = monospaced(uneditableBlackTextArea_noUndo(winToUnicode(state.binonDisplayChngResults)));
makeMenus();
registerCtrlKey(mainFrame, KeyEvent.VK_N, "New world", new Runnable() { public void run() { try { print("new") ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "print(\"new\")"; }});
registerCtrlKey(mainFrame, KeyEvent.VK_R, "Retrieve world", new Runnable() { public void run() { try { ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return ""; }});
registerCtrlKey(mainFrame, KeyEvent.VK_S, "Save world", new Runnable() { public void run() { try { ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return ""; }});
addMenu(mainFrame, "View",
miShowLocations = jCheckBoxMenuItem("Locations (Ctrl+L)", state.showLocations, b -> {
cset(state, "showLocations" , b);
repaintGrid();
}),
jMenu("UI Zoom",
"100%", new Runnable() { public void run() { try { uiZoom(100) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "uiZoom(100)"; }},
"112%", new Runnable() { public void run() { try { uiZoom(112) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "uiZoom(112)"; }},
"125%", new Runnable() { public void run() { try { uiZoom(125) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "uiZoom(125)"; }},
"140%", new Runnable() { public void run() { try { uiZoom(140) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "uiZoom(140)"; }}),
"---",
"Self-Test", runnableThread(new Runnable() { public void run() { try { selfTest();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "selfTest();"; }}),
"Console", new Runnable() { public void run() { try { activateConsole();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "activateConsole();"; }});
registerCtrlKey(mainFrame, KeyEvent.VK_L, "Locations", new Runnable() { public void run() { try {
cset(state, "showLocations" , !state.showLocations);
setChecked(miShowLocations, state.showLocations);
repaintGrid();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cset(state, showLocations := !state.showLocations);\r\n setChecked(miShowL..."; }});
JMenuBar menuBar = getMenuBar(mainFrame);
JMenuItem helpItem = jMenuItem("Help F1", runnableThread(new Runnable() { public void run() { try { showHelp();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showHelp();"; }}));
/*print(minSize := getMinimumSize(helpItem));
print(preferredSize := getPreferredSize(helpItem));*/
addMenuItem(menuBar, jPreferredWidthToMaxWidth(helpItem));
addAndRevalidate(menuBar, jHorizontalGlue()); // spacer
registerFunctionKey(mainFrame, 1, runnableThread(new Runnable() { public void run() { try { showHelp();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showHelp();"; }}));
registerKeyCode(mainFrame, KeyEvent.VK_SPACE, new Runnable() { public void run() { try { state.invertSelection() ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.invertSelection()"; }});
registerKeyCode(mainFrame, KeyEvent.VK_UP, new Runnable() { public void run() { try { state.moveCursor(0, -1) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.moveCursor(0, -1)"; }});
registerKeyCode(mainFrame, KeyEvent.VK_LEFT, new Runnable() { public void run() { try { state.moveCursor(-1, 0) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.moveCursor(-1, 0)"; }});
registerKeyCode(mainFrame, KeyEvent.VK_DOWN, new Runnable() { public void run() { try { state.moveCursor(0, 1) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.moveCursor(0, 1)"; }});
registerKeyCode(mainFrame, KeyEvent.VK_RIGHT, new Runnable() { public void run() { try { state.moveCursor(1, 0) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.moveCursor(1, 0)"; }});
// react to any letter from A to Z
for (int key = KeyEvent.VK_A; key <= KeyEvent.VK_Z; key++)
registerKeyCode(mainFrame, key, new Runnable() { public void run() { try { state.placeSmarty() ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.placeSmarty()"; }});
worldSizeSpinner = jSpinner(state.gridCols, 1, maxWorldSize);
onChange(worldSizeSpinner, new Runnable() { public void run() { try {
int size = intFromSpinner(worldSizeSpinner);
if (state.gridCols != size) {
if (state.worldChanged) {
int result = swingShowConfirmDialog(mainFrame,
"World has changed! - Save it before resizing?", "Smarty",
JOptionPane.YES_NO_CANCEL_OPTION);
if (result == JOptionPane.YES_OPTION) {
saveWorldDialog(new Runnable() { public void run() { try { newWorldWithoutConfirmation(size) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "newWorldWithoutConfirmation(size)"; }});
return;
} else if (result == JOptionPane.CANCEL_OPTION) {
setSpinnerValue(worldSizeSpinner, state.gridCols);
return;
}
}
newWorldWithoutConfirmation(size);
}
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "int size = intFromSpinner(worldSizeSpinner);\r\n if (state.gridCols != size)..."; }});
scpCurrentSmarty = singleComponentPanel();
JComponent middleArea = westAndCenterWithMargin(spacing,
jvstackWithSpacing(spacing,
withTitle(("World size (max=" + maxWorldSize + ")"), worldSizeSpinner),
jbutton("Clear Selected Area", runnableThread(new Runnable() { public void run() { try { state.clearSelectedArea() ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.clearSelectedArea()"; }})),
withTitle("Current world", disableTextField(jLiveValueTextField(conceptFieldLiveValue("worldName",state)))),
showTabs ? null : fontSizePlus(2, setForeground(Color.ORANGE, jCenteredLabel("Design or Select a body for Smarty"))),
showTabs ? null : jbutton("Design or Select Smarty's Body", new Runnable() { public void run() { try { showSmartyConfig();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showSmartyConfig();"; }}),
withTitle("Current Smarty", scpCurrentSmarty)),
jvgridWithSpacing(spacing,
withTitle(monospaced(jLabel("Sensors: Values: are:")), taSensorValues = monospaced(uneditableBlackTextArea_noUndo())),
withTitle(monospaced(jLabel("Devices: Values: are:")), taDeviceValues = monospaced(uneditableBlackTextArea_noUndo())))
);
JComponent controlArea = northAndCenterWithMargin(spacing,
vstackWithSpacing(
fontSizePlus(2, setForeground(Color.blue, jlabel("Design the World - Read the Help F1"))),
jMinHeight(swingScale(200), middleArea)),
jCenteredSection("Run Smarty",
jflow(
jbutton("Go / Continue", runnableThread(new Runnable() { public void run() { try { goCmd();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "goCmd();"; }})),
jButton("See History", new Runnable() { public void run() { try { showHistory();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showHistory();"; }}),
jbutton("See Memory", new Runnable() { public void run() { try { showMemory();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showMemory();"; }}),
jbutton("Reset", new Runnable() { public void run() { try { resetSmarty();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "resetSmarty();"; }}),
jbutton("EXIT", runnableThread(new Runnable() { public void run() { try { killVM();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "killVM();"; }}))))
);
scpMainGrid = singleComponentPanel();
makeMainGrid();
var mainPanel = westAndCenterWithMargins(spacing,
jvstackWithSpacing(spacing,
jFixedSize(500, scpMainGrid),
scpStimuliAndResponse = singleComponentPanel()
),
controlArea);
if (showTabs) {
scpVisionConfig = singleComponentPanel();
scpWheelsConfig = singleComponentPanel();
updateTabs();
setFrameContents(mainFrame, jtabs(
"Smarty", mainPanel,
"Vision", scpVisionConfig,
"Wheels", scpWheelsConfig));
} else
setFrameContents(mainFrame, mainPanel);
centerPackFrame(mainFrame);
// set minimum width
jMinWidth_pure(mainFrame, max(1000, swingScale(800)));
centerFrameWithMinWidth(mainFrame);
// set min frame height
jMinHeight_pure(mainFrame, getHeight(mainFrame));
// disable height changes entirely (not good, may cut off at the bottom)
//frameMaxHeight(mainFrame, getHeight(mainFrame));
//smarty.World.Update_View();
setText(historyTextArea1, winToUnicode(state.history1));
setText(historyTextArea2, winToUnicode(state.history2));
setText(memoryTextArea1, winToUnicode(state.memory1));
setText(taSensorValues, winToUnicode(state.sensorValuesText));
setText(taDeviceValues, winToUnicode(state.deviceValuesText));
enableBodyControls(!state.body.get().used);
if (!smartyBrainPersistence)
resetSmarty();
if (!isDevVersion()) showHelp();
else {
//goCmd();
//selfTest();
}
} // end of main function
static boolean isDevVersion() {
return isProgramID("#1031104");
}
static void updateTabs() {
scpVisionConfig.setComponent(visionConfigPanel(state.body.get()));
scpWheelsConfig.setComponent(wheelsConfigPanel(state.body.get()));
scpCurrentSmarty.setComponent(disableTextField(jLiveValueTextField(conceptFieldLiveValue("name",state.body.get()))));
updateFrameTitles();
}
static void enableBodyControls(boolean b) {
var panels = ll(scpVisionConfig, scpWheelsConfig);
for (var c : concatMap(panel -> allChildrenOfType(JComponent.class,panel), panels))
if (isInstanceOfAny(c, JCheckBox.class, JRadioButton.class, JTextField.class)
&& !(c instanceof BodyNameField))
setEnabled(c, b);
// Modify body button is enabled iff controls are not enabled
for (var c : concatMap(panel -> allChildrenOfType(ModifyBodyButton.class,panel), panels))
setEnabled(c, !b);
}
static void showHelp() {
String text = loadSnippet(helpTextID);
String heading = firstLine(text);
trim(dropFirstLine(text));
showCenterFrame(swingScale(650), swingScale(500), heading, makeUneditableWithTextColor(Color.black, wordWrapTextArea(text)));
}
// run in Swing thread
static void showHistory() {
Font ttFont = loadFont_cached(monospacedFontID, 12), helpFont = sansSerifFont(13);
if (historyFrame == null)
historyFrame = getFrame(showCenterFrame(maxPt(pt(800, 600), scalePt(600, 350, swingFontScale())),
"History",
withMargin(centerAndSouthWithMargin(spacing,
centerAndSouthWithMargin(
historyTextArea1,
westAndCenterWithMargin(spacing, setFont(ttFont, topAlignLabel(jMultiLineLabel(
linesLL("Step #", "Percept", "Binon #", "", "Expect", "Binon #",
"", "Action", "Binon #", "", "Action", "Binon #", "")))),
setFont(ttFont, historyTextArea2))
),
centerAndEastWithMargin(
setFont(helpFont, jMultiLineLabel(historyHelp)),
jvstackWithSpacing(
jButton("See World", new Runnable() { public void run() { try { showWorld();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showWorld();"; }}),
jButton("See Memory", new Runnable() { public void run() { try { showMemory();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showMemory();"; }}))
)))));
else
frameToFront(historyFrame);
updateFrameTitles();
}
// run in Swing thread
static void showMemory() {
Font ttFont = typeWriterFont(12), helpFont = sansSerifFont(13);
String Interestng;
if (smarty.InterestLevels == 3)
Interestng = smarty.IntSymb(smarty.INTERESTING) + "=Interesting, ";
else // Only 2 interest levels
Interestng = "";
String IntSymbol = " " + smarty.IntSymb(smarty.NOVEL) + " = Novel, " + Interestng + smarty.IntSymb(smarty.FAMILIAR) + " = Familiar";
// originally: BinonDisplay.ObjListTitle.Caption
String title = "Bn# OL Ty TL BL TR BR V L R In LQ RQ Pattern "
+ " l = Left target, r = Right target," + IntSymbol;
if (memoryFrame == null)
memoryFrame = getFrame(showCenterFrame(scalePt(600, 350, swingFontScale()),
"Smarty's Memory",
jvsplit(0.5, 100,
centerAndEastWithMargins(
northAndCenterWithMargin(
setFont(ttFont, jLabel(title)),
setFont(ttFont, memoryTextArea1)),
jvstackWithSpacing(
jButton("See World", new Runnable() { public void run() { try { showWorld();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showWorld();"; }}),
jButton("See History", new Runnable() { public void run() { try { showHistory();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showHistory();"; }}))
),
memoryTextArea2)
));
else
frameToFront(memoryFrame);
updateFrameTitles();
}
static void showWorld() {
frameToFront(mainFrame);
}
static JRadioButton visionModeRadioButton(SmartyBody body, ButtonGroup buttonGroup, String visionMode, String text) {
var rb = jradiobutton(buttonGroup, text, eq(body.visionMode, visionMode));
onChange(rb, new Runnable() { public void run() { try { if (isChecked(rb)) { cset(body, "visionMode", visionMode); body.userCausedChange(); }
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (isChecked(rb)) { cset(body, +visionMode); body.userCausedChange(); }"; }});
return rb;
}
static class ModifyBodyButton extends JButton {
ModifyBodyButton() {
super("Modify Smarty's Body");
main.addActionListener(this, new Runnable() { public void run() { try { modifyBody();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "modifyBody();"; }});
}
}
// enable the controls to edit the body, after confirmation
static void modifyBody() {
if (state.body.get().used) {
if (!confirmOKCancel("Modifying Smarty's body will reset its state. Do you wish to continue?"))
return;
resetSmarty();
cset(state.body, "used" , false);
}
enableBodyControls(true);
}
static class BodyNameField extends JTextField {
BodyNameField() {
setEnabled(false);
}
}
static JComponent bodyNamePanel(SmartyBody body) {
SimpleLiveValue lv = conceptFieldLiveValue("name",body);
lv.onChange(new Runnable() { public void run() { try { body.userCausedChange() ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "body.userCausedChange()"; }});
return hstackWithSpacing(
jMinWidth(swingScale(250), withLabel("Body name:",
bindTextComponentToLiveValue(lv, swing(() -> new BodyNameField())))),
swing(() -> new ModifyBodyButton()));
}
static JComponent visionConfigPanel(SmartyBody body) {
var buttonGroup = buttonGroup();
return northAndCenterWithMargins(spacing,
bodyNamePanel(body),
westAndCenterWithMargin(spacing,
jCenteredSection("Camera",
withLeftMargin(spacing, jvstackWithSpacing(spacing,
itemPlus(jlabel("Select the camera directions"),
map(CameraDirection.all, direction -> {
var cb = jCheckBox(direction, body.cameraDirections.contains(direction));
onChange(cb, new Runnable() { public void run() { try { addOrRemove(body.cameraDirections, direction, isChecked(cb)); body.userCausedChange();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addOrRemove(body.cameraDirections, direction, isChecked(cb)); body.userCaused..."; }});
return cb;
}))))),
jCenteredSection("Vision mode",
jvstack(
withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS(replaceSymbols("\r\n Square locations are identified with a letter.\r\n Looking down provides the letter of the current square.\r\n Looking in other directions provides the letter in the next square\r\n depending on the direction Smarty is facing.\r\n If it is a wall then the symbolic stimulus is a $wallSymbol\r\n ")))),
visionModeRadioButton(body, buttonGroup, VisionMode.nextSquare,
"Looking at the next square (symbolic values = letter in square)"),
verticalStrut(20),
withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS("\r\n Looking at the distance to the nearest wall will provide the\r\n number of squares from the current position to the wall in\r\n the direction the camera is facing. A wall next to the robot\r\n is one square away. Looking down will always return 1.\r\n "))),
visionModeRadioButton(body, buttonGroup, VisionMode.distanceToWall,
"Distance to wall (magnitude values = number of squares)"),
verticalStrut(20),
withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS("\r\n Looking at the next square will either see a wall or an empty square\r\n "))),
visionModeRadioButton(body, buttonGroup, VisionMode.wallOrNot,
replaceSymbols("Wall or not (symbolic values = $wallSymbol for a wall and $noWallSymbol for no wall)"))))));
}
static void showVisionConfig(SmartyBody body) {
showPackedFrame("Configure Smarty's Vision",
visionConfigPanel(body));
}
static JCheckBox wheelsConfigCheckBox(SmartyBody body, String symbol, String text) {
var cb = jCheckBox(text, body.wheels.contains(symbol));
onChange(cb, new Runnable() { public void run() { try { addOrRemove(body.wheels, symbol, isChecked(cb)); body.userCausedChange();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addOrRemove(body.wheels, symbol, isChecked(cb)); body.userCausedChange();"; }});
return cb;
}
static JComponent wheelsConfigPanel(SmartyBody body) {
return northAndCenterWithMargins(spacing,
bodyNamePanel(body),
vstackWithSpacing(spacing,
westAndCenterWithMargin(spacing,
jCenteredSection("Movement",
withLeftMargin(spacing, jvstackWithSpacing(
jlabel("Select the wheel motions"),
wheelsConfigCheckBox(body, "MoveForward", "Forward = f"),
wheelsConfigCheckBox(body, "MoveLeft", "Left = l"),
wheelsConfigCheckBox(body, "MoveRight", "Right = r"),
wheelsConfigCheckBox(body, "MoveBackward", "Backward = b")))),
jCenteredSection("Help", withLeftMargin(
jTopLabel(hhtml(nlToBr(mls_replaceDollarVars(winToUnicode("\r\n Motion in any direction will move one square.\r\n If there is a wall in the way it will not move. A \"-\" indicates no motion.\r\n The direction moved depends on the direction Smarty is facing.\r\n Smarty will appear as a $smiley if it cannot turn. It will then always be\r\n facing North (up) so moving right will move to the East (right).\r\n "), "smiley" , himgForJLabel("#1102987", "width" , swingScale(15), "height" , swingScale(15), "align" , "middle")))))))),
westAndCenterWithMargin(spacing,
jCenteredSection("Turning",
withLeftMargin(spacing, vstackWithSpacing(
wheelsConfigCheckBox(body, "TurnRight", "Turn to the right = Rotate clockwise 90 degrees = " + winToUnicode(Smarty.TurnRght)),
wheelsConfigCheckBox(body, "TurnLeft", "Turn to the left = Rotate anti-clockwise 90 degrees = " + winToUnicode(Smarty.TurnLft)),
wheelsConfigCheckBox(body, "TurnAround", "Turn around = Rotate 180 degrees = " + winToUnicode(Smarty.TurnArnd))))),
jCenteredSection("Help", withLeftMargin(jMultiLineLabel(winToUnicode(mls_replaceDollarVars("\r\n Turning will stay on the same square. If Smarty is able to turn then it will appear as $left, $right, $up or $down to indicate the direction it is facing.\r\n ",
"left" , Smarty.LeftArrow,
"right" , Smarty.RightArrow,
"up" , Smarty.UpArrow,
"down" , Smarty.DownArrow)))))),
jCenteredSection("Sensing",
withLeftMargin(spacing, wheelsConfigCheckBox(body, "AddAWheelSensor", "Add a wheel sensor to detect if it moved or failed because it was up against a wall"))
)
));
}
static void showWheelsConfig(SmartyBody body) {
var buttonGroup = buttonGroup();
showPackedFrame("Configure Smarty's Wheels",
wheelsConfigPanel(body));
}
static void showSmartyConfig() {
showPackedFrameMinWidth(400, "Design or Select a body for Smarty",
withMargin(centeredButtons(
"Vision", new Runnable() { public void run() { try { showVisionConfig(state.body.get()) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showVisionConfig(state.body.get())"; }},
"Wheels", new Runnable() { public void run() { try { showWheelsConfig(state.body.get()) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showWheelsConfig(state.body.get())"; }}))
);
}
// e.g. $wallSymbol and $noWallSymbol
static String replaceSymbols(String s) {
return replaceDollarVars(s, "wallSymbol", wallSymbol, "noWallSymbol", noWallSymbol);
}
static String exportWorldForSaving() {
List lines = new ArrayList();
lines.add(" " + state.gridRows);
for (int y = 0; y < state.gridRows; y++)
for (int x = 0; x < state.gridCols; x++) {
JCell cell = getCell(x, y);
lines.add(state.smartyX == x && state.smartyY == y ? "A" : cell.obstacle() ? "#" : " ");
}
return lines(lines);
}
static void saveWorld(File f) {
String text = exportWorldForSaving();
saveTextFile(f, text);
infoBox("World saved: " + fileName(f));
cset(state, "worldName" , fileNameWithoutExtension(f), "worldChanged" , false);
addRecentWorldFile(f);
}
static void addRecentWorldFile(File f) { swing(new Runnable() { public void run() { try {
removeAndPut(state.recentWorldFiles, f, true);
state.change();
makeMenus();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "removeAndPut(state.recentWorldFiles, f, true);\r\n state.change();\r\n makeMenu..."; }}); }
static void addRecentBodyFile(File f) { swing(new Runnable() { public void run() { try {
removeAndPut(state.recentBodyFiles, f, true);
state.change();
makeMenus();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "removeAndPut(state.recentBodyFiles, f, true);\r\n state.change();\r\n makeMenus();"; }}); }
static void loadWorld(File f) {
try {
List lines = linesFromFile_list(f);
if (eqAfterRtrim(lines(lines), exportWorldForSaving()))
{ infoBox("World is the same as current one"); return; }
int i = 0;
int gridRows = parseInt(trim(lines.get(i++)));
if (gridRows < 1 || gridRows > maxWorldSize) throw fail("Bad world size: " + gridRows);
setWorldSize(gridRows);
for (int y = 0; y < gridRows; y++)
for (int x = 0; x < gridRows; x++) {
String line = lines.get(i++);
JCell cell = getCell(x, y);
if (eq(line, "#"))
cell.setObstacle(true);
else if (eq(line, "A"))
state.moveSmarty(x, y);
}
rearrangeLetters();
repaintGrid();
cset(state, "worldName" , fileNameWithoutExtension(f));
cset(state, "worldChanged" , false);
infoBox("World loaded: " + fileName(f));
addRecentWorldFile(f);
} catch (Throwable __e) { messageBox(__e); }
}
static void saveWorldDialog() { saveWorldDialog(null); }
static void saveWorldDialog(Runnable whenDone) {
{ swing(new Runnable() { public void run() { try {
JFileChooser fileChooser = new JFileChooser(mainDir());
fileChooser.setFileFilter(new FileNameExtensionFilter(("Smarty World files (*." + worldFileExtension + ")"), worldFileExtension));
if (fileChooser.showSaveDialog(mainFrame) == JFileChooser.APPROVE_OPTION) {
File f = defaultExtension(worldFileExtension, fileChooser.getSelectedFile());
saveWorld(f);
infoBox("World saved as " + f.getName());
} else
messageBox("World NOT saved");
callF(whenDone);
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JFileChooser fileChooser = new(mainDir());\r\n fileChooser.setFileFilter(new..."; }}); }
}
static void withWorldSave(Runnable r) {
if (state.worldChanged) {
int result = swingShowConfirmDialog(mainFrame,
"World has changed! - Save it?", "Smarty",
JOptionPane.YES_NO_CANCEL_OPTION);
if (result == JOptionPane.YES_OPTION) {
saveWorldDialog(r);
return;
} else if (result == JOptionPane.CANCEL_OPTION)
return;
else
cset(state, "worldChanged" , false);
}
r.run();
}
static void loadWorldDialog() {
withWorldSave(new Runnable() { public void run() { try { loadWorldDialogWithoutConfirmation();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadWorldDialogWithoutConfirmation();"; }});
}
static void loadWorldDialogWithoutConfirmation() { swing(new Runnable() { public void run() { try {
JFileChooser fileChooser = new JFileChooser(mainDir());
fileChooser.setFileFilter(new FileNameExtensionFilter(("Smarty World files (*." + worldFileExtension + ")"), worldFileExtension));
if (fileChooser.showOpenDialog(mainFrame) == JFileChooser.APPROVE_OPTION)
loadWorld(fileChooser.getSelectedFile());
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JFileChooser fileChooser = new(mainDir());\r\n fileChooser.setFileFilter(new F..."; }}); }
static void newWorld() {
withWorldSave(new Runnable() { public void run() { try { newWorldWithoutConfirmation();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "newWorldWithoutConfirmation();"; }});
}
static void newWorldWithoutConfirmation() { newWorldWithoutConfirmation(defaultWorldSize); }
static void newWorldWithoutConfirmation(int size) {
setWorldSize(size);
cset(state, "worldName" , "Empty", "worldChanged" , false);
updateFrameTitles();
}
static File mainDir() {
return mkdirs(userDir("Adaptron/Smarty"));
}
static String exportBodyForSaving() {
String[] Body = new String[22];
bodyToArray(state.body.get(), Body);
return lines(dropFirst(Body));
}
static void saveBody(File f) {
String text = exportBodyForSaving();
saveTextFile(f, text);
cset(state.body.get(), "changed" , false);
addRecentBodyFile(f);
}
static void bodyToArray(SmartyBody b, String[] Body) {
Body[1] = escapeNewLines(b.name);
// TODO: remaining values from AI?
Body[2] = "1"; //Vision.Value = 1 - checked
Body[3] = "0"; //Touch.Value
Body[4] = b.wheelsFlag("AddAWheelSensor");
Body[5] = "1"; //Wheels.Value
Body[6] = "0"; //Arms.Value
Body[7] = b.cameraDirections.contains(CameraDirection.down) ? "1" : "0"; //VisionConfig.VisionDown
Body[8] = b.cameraDirections.contains(CameraDirection.left) ? "1" : "0"; //VisionConfig.VisionLeft
Body[9] = b.cameraDirections.contains(CameraDirection.right) ? "1" : "0"; //VisionConfig.VisionRight
Body[10] = b.cameraDirections.contains(CameraDirection.inFront) ? "1" : "0"; //VisionConfig.VisionInFront
Body[11] = b.cameraDirections.contains(CameraDirection.behind) ? "1" : "0"; //VisionConfig.VisionBehind
Body[12] = eq(b.visionMode, VisionMode.nextSquare) ? "True" : "False"; //VisionConfig.VisionSymbolicOrMagnitude(0)
Body[13] = eq(b.visionMode, VisionMode.distanceToWall) ? "True" : "False"; //VisionConfig.VisionSymbolicOrMagnitude(1)
Body[14] = b.wheelsFlag("MoveForward");
Body[15] = b.wheelsFlag("MoveLeft");
Body[16] = b.wheelsFlag("MoveRight");
Body[17] = b.wheelsFlag("MoveBackward");
Body[18] = b.wheelsFlag("TurnRight");
Body[19] = b.wheelsFlag("TurnLeft");
Body[20] = b.wheelsFlag("TurnAround");
Body[21] = eq(b.visionMode, VisionMode.wallOrNot) ? "True" : "False"; //VisionConfig.VisionSymbolicOrMagnitude(2)
}
static void withBodySave(Runnable r) {
if (state.body.get().changed) {
int result = swingShowConfirmDialog(mainFrame,
"Body has changed! - Save it?", "Smarty",
JOptionPane.YES_NO_CANCEL_OPTION);
if (result == JOptionPane.YES_OPTION) {
saveBodyDialog(r);
return;
} else if (result == JOptionPane.CANCEL_OPTION)
return;
else
cset(state.body, "changed" , false);
}
r.run();
}
static void newBody() {
withBodySave(new Runnable() { public void run() { try { newBodyWithoutConfirmation();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "newBodyWithoutConfirmation();"; }});
}
static void newBodyWithoutConfirmation() {
cdelete(state.body.get());
cset(state, "body" , cnew(SmartyBody.class));
finishBodySetup();
}
static void loadBody(File f) {
try {
List lines = linesFromFile_list(f);
if (eqAfterRtrim(lines(lines), exportBodyForSaving()))
{ infoBox("Body is the same as current one"); return; }
String[] Body = asStringArray(itemPlusList("", lines));
newBody();
var b = state.body.get();
// TODO: remaining values
cset(b, "name" , Body[1]);
if (eq(Body[4], "1")) b.wheels.add("AddAWheelSensor");
if (eq(Body[7], "1")) b.cameraDirections.add(CameraDirection.down);
if (eq(Body[8], "1")) b.cameraDirections.add(CameraDirection.left);
if (eq(Body[9], "1")) b.cameraDirections.add(CameraDirection.right);
if (eq(Body[10], "1")) b.cameraDirections.add(CameraDirection.inFront);
if (eq(Body[11], "1")) b.cameraDirections.add(CameraDirection.behind);
if (eq(Body[12], "True")) b.visionMode = VisionMode.nextSquare;
if (eq(Body[13], "True")) b.visionMode = VisionMode.distanceToWall;
if (eq(Body[14], "1")) b.wheels.add("MoveForward");
if (eq(Body[15], "1")) b.wheels.add("MoveLeft");
if (eq(Body[16], "1")) b.wheels.add("MoveRight");
if (eq(Body[17], "1")) b.wheels.add("MoveBackward");
if (eq(Body[18], "1")) b.wheels.add("TurnRight");
if (eq(Body[19], "1")) b.wheels.add("TurnLeft");
if (eq(Body[20], "1")) b.wheels.add("TurnAround");
if (eq(Body[21], "True")) b.visionMode = VisionMode.wallOrNot;
cset(b, "changed" , false);
b.change();
updateTabs();
infoBox("Body loaded: " + fileName(f));
addRecentBodyFile(f);
finishBodySetup();
} catch (Throwable __e) { messageBox(__e); }
}
static void saveBodyDialog() { saveBodyDialog(null); }
static void saveBodyDialog(Runnable whenDone) {
{ swing(new Runnable() { public void run() { try {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setSelectedFile(newFile(mainDir(), sanitizeFileName(state.body.get().name)));
fileChooser.setFileFilter(new FileNameExtensionFilter(("Smarty Body files (*." + bodyFileExtension + ")"), bodyFileExtension));
if (fileChooser.showSaveDialog(mainFrame) == JFileChooser.APPROVE_OPTION) {
File f = defaultExtension(bodyFileExtension, fileChooser.getSelectedFile());
cset(state.body, "name" , fileNameWithoutExtension(f));
updateTabs();
saveBody(f);
infoBox("Body saved as " + f.getName());
}
callF(whenDone);
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "new JFileChooser fileChooser;\r\n fileChooser.setSelectedFile(newFile(mainDi..."; }}); }
}
static void loadBodyDialog() {
withBodySave(new Runnable() { public void run() { try { loadBodyDialogWithoutConfirmation();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadBodyDialogWithoutConfirmation();"; }});
}
static void loadBodyDialogWithoutConfirmation() { swing(new Runnable() { public void run() { try {
JFileChooser fileChooser = new JFileChooser(mainDir());
fileChooser.setFileFilter(new FileNameExtensionFilter(("Smarty Body files (*." + bodyFileExtension + ")"), bodyFileExtension));
if (fileChooser.showOpenDialog(mainFrame) == JFileChooser.APPROVE_OPTION)
loadBody(fileChooser.getSelectedFile());
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JFileChooser fileChooser = new(mainDir());\r\n fileChooser.setFileFilter(new F..."; }}); }
static String infosForWindowTitle() {
return " - World= " + state.worldName + ", Body= " + state.body.get().name
+ ", Run done on " + simpleDateFormat_defaultTZ_now("MM-dd-YYYY") + " (mm-dd-yyyy) "
+ simpleDateFormat_defaultTZ_now("HH:mm:ss");
}
static void updateFrameTitles() {
frameTitle(mainFrame, "Smarty's World" + infosForWindowTitle());
frameTitle(historyFrame, "Stimulus/Response, Percept/Action History" + infosForWindowTitle());
frameTitle(memoryFrame, "Smarty's Memory" + infosForWindowTitle());
}
// Make the dynamic menus
static void makeMenus() {
addMenu(mainFrame, "Worlds",
"New... (Ctrl+N)", new Runnable() { public void run() { try { newWorld();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "newWorld();"; }},
"Retrieve... (Ctrl+R)", new Runnable() { public void run() { try { loadWorldDialog();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadWorldDialog();"; }},
"Save... (Ctrl+S)", new Runnable() { public void run() { try { saveWorldDialog();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "saveWorldDialog();"; }},
"---",
mapWithIndexStartingAt1(reversed(keys(state.recentWorldFiles)), (idx, f)
-> jMenuItem(idx + " " + fileName(f), new Runnable() { public void run() { try { withWorldSave(new Runnable() { public void run() { try { loadWorld(f) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadWorld(f)"; }}) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "withWorldSave(r { loadWorld(f) })"; }})),
empty(state.recentWorldFiles) ? null : "---",
"Exit", runnableThread(new Runnable() { public void run() { try { killVM();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "killVM();"; }}));
addMenu(mainFrame, "Bodies",
"New... (Ctrl+N)", new Runnable() { public void run() { try { newBody();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "newBody();"; }},
"Retrieve... (Ctrl+R)", new Runnable() { public void run() { try { loadBodyDialog();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadBodyDialog();"; }},
"Save... (Ctrl+S)", new Runnable() { public void run() { try { saveBodyDialog();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "saveBodyDialog();"; }},
"---",
mapWithIndexStartingAt1(reversed(keys(state.recentBodyFiles)), (idx, f)
-> jMenuItem(idx + " " + fileName(f), new Runnable() { public void run() { try { withBodySave(new Runnable() { public void run() { try { loadBody(f) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadBody(f)"; }}) ;
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "withBodySave(r { loadBody(f) })"; }})),
empty(state.recentBodyFiles) ? null : "---",
"Exit", runnableThread(new Runnable() { public void run() { try { killVM();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "killVM();"; }}));
}
static void goCmd() { smartyQ.add(new Runnable() { public void run() { try { goCmd_impl();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "goCmd_impl();"; }}); }
static void goCmd_impl() {
try {
evalWithTimeout(10.0, new Runnable() { public void run() { try {
print("goCmd");
if (!state.body.get().used) {
finishBodySetup();
cset(state.body, "used" , true);
enableBodyControls(false);
}
smarty.bodies.BodyFunction2();
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "print(\"goCmd\");\r\n \r\n if (!state.body.get().used) {\r\n finishB..."; }});
} catch (Throwable __e) { messageBox(__e); }
}
static int Indx(int row, int col) {
// C is the across / column location - 0 based
// R is the down / row location - 0 based
// the function gives the index into NG and CWP linear arrays - 0 based
// can not be greater than 199 because 200+ used for wall letters
return state.gridCols * row + col;
}
// NG(I).Caption is contents of cell x/y
// with I = WallNo(x, y, direction)
// NG Caption is either "" or smarty.Smarty
// or Chr$(64 + InNG - 200) [location letter?]
// WP$ seems to hold the playing field
// WP$(R, C) can be ABlock$
/* From Brett:
WP$ contains either a space, a block or the smarty symbol.
The smarty symbol may be an S, >, <, ^, v or + depending on which way smarty is pointing.
NG().captions contain the letter for each location. The LookUnder$() routine returns the letter
for the camera that looks down at the current square. LookNorth$() etc. and other Look routines
return the cell letter that is one cell away.
The higher index values into NG() can contain letter for the walls set by the IDWalls() routine.
But this feature is not in use and the higher index entries of NG are invisible so a mouse down
cannot be done on them.
Note also that ScopeLeft$() and other Scope routines that would return wall letters are not in use.
*/
static int InRow() { return state.smartyY; }
static int InCol() { return state.smartyX; }
static void setSmartyDirection(String smartyDirection) {
if (cset_trueIfChanged(state, "smartyDirection", smartyDirection))
repaintGrid();
}
// query cell for Smarty's brain
static String WP(int y, int x) {
if (x == InCol() && y == InRow())
return state.smartyDirection;
else
return getCell(x, y).obstacle() ? smarty.ABlock : smarty.ASpace;
}
// put more static functions here
static class TheWorld extends Smarty.TheWorld {
// find what letter we are standing on
public String LookUnder() {
return str(smartyCell().letter);
}
void moveRelative(int x, int y) {
x += state.smartyX; y += state.smartyY;
if (!inGrid(x, y) || getCell(x, y).obstacle())
smarty.Motion = smarty.NoMove;
else {
smarty.Motion = "Y";
state.moveSmarty(x, y);
}
}
public void MoveWest() {
moveRelative(-1, 0);
}
public void MoveSouth() {
moveRelative(0, 1);
}
public void MoveEast() {
moveRelative(1, 0);
}
public void MoveNorth() {
moveRelative(0, -1);
}
public void DisplayStimuliAndResponse(int[][][] inputValues, char response) {
List leftStack = new ArrayList();
List rightStack = new ArrayList();
for (int Sens = 1; Sens <= smarty.NumSenses; Sens++) {
int NumSensors = smarty.Senses[Sens][smarty.NumberOfSensors];
if (NumSensors == 0) continue;
if (NumSensors != 1) warn("More than one sensor in sense");
String label = smarty.Sense[Sens] + ":";
var inputValue = inputValues[Sens][smarty.Valu][smarty.Fired];
String text;
if (smarty.Senses[Sens][smarty.SymbolicOrMagnitude] == smarty.Magnitude)
text = str(charPlus(inputValue , '0'))
+ (debugValues ? " [magn " + inputValue + "]" : "");
else
text = lookupOrKeep(winToUnicode, str((char) inputValue))
+ (debugValues ? " [char " + inputValue + "]" : ""); // A, B, C etc
leftStack.add(withLabel(withTypeWriterFont(jlabel(label)), jlabel(text)));
}
for (int Devs = 1; Devs <= smarty.NumDevices; Devs++) {
String label = smarty.Device[Devs] + ":";
rightStack.add(withLabel(withTypeWriterFont(jlabel(label)), jlabel(winToUnicode(response))));
}
scpStimuliAndResponse.set(jhgridWithSpacing(
vstack(leftStack),
vstack(rightStack)));
}
public void Update_View() { // called by World.LookInside_Click() to SeeHistory and Bodies.BodyFunction2()
// refreshes all the subwindows
historyDisplay();
dumpLTM();
}
public void setBinonDisplayObjList(String text) {
cset(state, "memory1" , text);
setText(memoryTextArea1, winToUnicode(text));
}
public void setBinonDisplayChngResults(String text) {
cset(state, "binonDisplayChngResults" , text);
rstUpdateChngResults.trigger();
}
public void appendBinonDisplayChngResults(String text) {
cset(state, "binonDisplayChngResults" , state.binonDisplayChngResults+text);
rstUpdateChngResults.trigger();
}
String lookDirection(int dx, int dy) {
int x = InCol()+dx, y = InRow()+dy;
// If off top of board or next one is a block
if (inGrid(x, y)) // must be on board
if (eq(WP(y, x), smarty.ABlock))
return smarty.Wall; // looking at a wall
else // valid square to move into
return str(getCell(x, y).letter);
else // looking beyond grid
return smarty.Wall;
}
public String LookNorth() { return lookDirection(0, -1); }
public String LookSouth() { return lookDirection(0, 1); }
public String LookWest() { return lookDirection(-1, 0); }
public String LookEast() { return lookDirection( 1, 0); }
public void PointUnder() {
setSmartyDirection(smarty.Smarty);
}
public void PointNorth() {
setSmartyDirection(smarty.UpArrow);
}
public void PointSouth() {
setSmartyDirection(smarty.DownArrow);
}
public void PointWest() {
setSmartyDirection(smarty.LeftArrow);
}
public void PointEast() {
setSmartyDirection(smarty.RightArrow);
}
public int RangeNorth() { return rangeDirection(0, -1); }
public int RangeSouth() { return rangeDirection(0, 1); }
public int RangeWest() { return rangeDirection(-1, 0); }
public int RangeEast() { return rangeDirection( 1, 0); }
public int rangeDirection(int dx, int dy) { // Distance to wall
int x = InCol(), y = InRow();
int i = 0;
do {
++i;
x += dx;
y += dy;
// End if off rightside of board or next one is a block
} while (inGrid(x, y) && !getCell(x, y).obstacle());
return i;
}
public void showSensorValues(String text) {
cset(state, "sensorValuesText" , text);
setText(taSensorValues, winToUnicode(text));
}
public void showDeviceValues(String text) {
cset(state, "deviceValuesText" , text);
setText(taDeviceValues, winToUnicode(text));
}
} // end of TheWorld
static void initSmarty() {
smarty.World = new TheWorld();
smarty.Initialize_Adaptron();
}
static void finishBodySetup() { resetSmarty(); }
static void resetSmarty() {
print("Finishing body setup");
ResetSmartyLocation();
smarty.Reset_Adaptron(); // set all memory, S-List, Habit stack
cset(state, "history1" , "", "history2" , "", "memory1" , "");
setText(historyTextArea1, "");
setText(historyTextArea2, "");
setText(memoryTextArea1, "");
setText(memoryTextArea2, "");
bodyToArray(state.body.get(), smarty.BodySetting);
//pnl("BodySetting", smarty.BodySetting);
/*if (Vision.Value = 1)*/ smarty.SetupVision();
//if (Touch.Value = 1) smarty.SetupTouch();
/*if (Wheels.Value = 1)*/ smarty.SetupWheels();
//if (Arms.Value = 1) smarty.SetupArms();
SetupStimulusResponseDisplay(); //Setup display of stimuli at bottom of World screen
updateTabs();
}
// not needed
static void SetupStimulusResponseDisplay() {}
// from Adapt.frm / HISTORYDISPLAY
static void historyDisplay() {
List lines = new ArrayList();
StringBuilder[] ILines$ = new StringBuilder[10+1];
int GroupSize = 250; // After 250 events the IO.Text area wraps the lines
StringBuilder NumberLine$ = new StringBuilder();
StringBuilder OLine1$ = new StringBuilder();
for (int Group = 0; Group <= (smarty.LIN - 1) / GroupSize; Group++) {
int EndLIN = min(GroupSize * Group + GroupSize, smarty.LIN);
for (int E = GroupSize * Group + 1; E <= EndLIN; E++) {
if (E == GroupSize * Group + 1) { // If it is the 1st position / event in the line then
NumberLine$ = new StringBuilder("Step # : ");
for (int Sn = 1; Sn <= smarty.NumSenses; Sn++) // Add labels to start of lines
ILines$[Sn] = new StringBuilder(takeFirst(smarty.Sense[Sn] + ": ", 9)); // The name of the sense
OLine1$ = new StringBuilder(takeFirst(smarty.Device[1] + ": ", 9)); // The name of the action device
}
String E_str = " " + E; // visual-basic style int-to-string!
NumberLine$.append(E_str); // the event number
int Wdth = l(E_str); // the space taken up by the event number
for (int Sn = 1; Sn <= smarty.NumSenses; Sn++)
ILines$[Sn].append(takeLast(" " + smarty.INPUTS[E][Sn], Wdth));
OLine1$.append(takeLast(" " + smarty.OUTPUTS[E][1], Wdth));
}
lines.add(str(NumberLine$));
for (int Sn = 1; Sn <= smarty.NumSenses; Sn++)
lines.add(str(ILines$[Sn]));
lines.add(str(OLine1$));
lines.add("");
}
String text = rtrim(lines(lines));
cset(state, "history1" , text);
setText(historyTextArea1, winToUnicode(text));
} // end of historyDisplay
static void dumpLTM() { //Called by Update_View
String MemValT = null;
int[] MemSize = new int[2000 + 1];
String Sen = null;
String Att = null;
String Pe = null;
String Ob = null;
Object BinTyp = null;
boolean DisplayIt = false; //a Spac$,
//'-------------------- Long Term Memory (LTM) - Monitoring Info. -------------------------
// 'For Display purposes only by Adapt.DUMPLTM in Adapt.LTMem
// 'Long term memory contains a list of the stimuli that have been paid attention to.
// 'It stores Perceptual sequences as a pair of sequential memory locations.
//
// Public LTMEMORY&(1 To 2000, 1 To 6)
// '1st index is StoreAt cycle number
// '2nd index is what type of information is in the LTM
//
// '---- LTMEMORY() 2nd index values - type of information in LTMEMORY()
// Public LtmPerceptTyp '1 Percept binon type
// Public LtmPerceptBin '2 Percept binon
// Public LtmESType '3 Type of ES Binon - may be an SS
// Public LtmESActBin '4 ES Actbin
// Public LtmARType '5 Type of AR Binon - may be an RR
// Public LtmARActBin '6 AR ActBin
// Public LtmActionTyp '7 Action binon type
// Public LtmActionBin '8 Action binon
for (var I = 1; I <= smarty.StoreAt; I++) //find the widest binon # for all the StoreAt positions
{
MemSize[I] = intMax(
l(str(I))+1,
3,
l(vbToStr(smarty.LTMEMORY[I][smarty.LtmPerceptBin])),
l(vbToStr(smarty.LTMEMORY[I][smarty.LtmESActBin])),
l(vbToStr(smarty.LTMEMORY[I][smarty.LtmARActBin])),
l(vbToStr(smarty.LTMEMORY[I][smarty.LtmActionBin])));
}
StringBuffer text = new StringBuffer();
int GroupSize = 250;
var tempVar = (smarty.StoreAt - 1) / GroupSize;
for (int Group = 0; Group <= (smarty.StoreAt - 1) / GroupSize; Group++) {
int EndLIN = GroupSize * Group + GroupSize; //Only put up the available values
if (EndLIN > smarty.StoreAt) EndLIN = smarty.StoreAt;
StringBuilder MemLine = new StringBuilder();
for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM display the event number
MemLine.append(pad(MemSize[E], str(E)));
text.append(MemLine + "\r\n");
//------Percepts(.., Fired) Type
MemLine = new StringBuilder();
for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
{
Att = smarty.BinonTypeName[smarty.LTMEMORY[E][smarty.LtmPerceptTyp]][smarty.BinAbbreviation]; //Att$ = Str$(STM(1, BinTp, Current))
MemLine.append(pad(MemSize[E], Att));
}
text.append(MemLine + "\r\n");
//------Percepts(.., Fired) Binon
MemLine = new StringBuilder(); //Trigger STIMULUS intensity
for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
{
Att = str(smarty.LTMEMORY[E][smarty.LtmPerceptBin]); //Att$ = Str$(STM(1, BinId, Current))
MemLine.append(pad(MemSize[E], Att));
}
text.append(MemLine + "\r\n\r\n");
//------ES ActBin type
MemLine = new StringBuilder();
for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
{
Att = smarty.AESR(smarty.LTMEMORY[E][smarty.LtmESActBin]);
MemLine.append(pad(MemSize[E], Att));
}
text.append(MemLine + "\r\n");
//------ LTMEMORY ActBin Object binon
MemLine = new StringBuilder();
for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
{
Att = String.valueOf(smarty.LTMEMORY[E][smarty.LtmESActBin]);
MemLine.append(pad(MemSize[E], Att));
}
text.append(MemLine + "\r\n\r\n");
//------AR ActBin type
MemLine = new StringBuilder();
for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
{
Att = smarty.AESR(smarty.LTMEMORY[E][smarty.LtmARActBin]);
MemLine.append(pad(MemSize[E], Att));
}
text.append(MemLine + "\r\n");
//------ LTMEMORY ActBin Object binon
MemLine = new StringBuilder();
for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
{
Att = String.valueOf(smarty.LTMEMORY[E][smarty.LtmARActBin]);
MemLine.append(pad(MemSize[E], Att));
}
text.append(MemLine + "\r\n\r\n");
//------Actions(.., Fired) Type
MemLine = new StringBuilder();
for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
{
Att = smarty.BinonTypeName[smarty.LTMEMORY[E][smarty.LtmActionTyp]][smarty.BinAbbreviation];
MemLine.append(pad(MemSize[E], Att));
}
text.append(MemLine + "\r\n");
//------Actions(.., Fired) Binon
MemLine = new StringBuilder();
for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
{
Att = String.valueOf(smarty.LTMEMORY[E][smarty.LtmActionBin]);
MemLine.append(pad(MemSize[E], Att));
}
text.append(MemLine + "\r\n\r\n");
}
String s = rtrim(str(text));
cset(state, "history2" , s);
setText(historyTextArea2, winToUnicode(s));
} //End of dumpLTM
static void uiZoom(double percent) {
if (cset_trueIfChanged(state, "fontScale" , toFloat(percent/100)))
restart();
}
static void updateFontScale(float scale) {
swingFontScale(scale);
spacing = iround(defaultSpacing*scale);
}
static void selfTest() { new SelfTest().run(); }
static class SelfTest {
Scorer scorer = new Scorer();
void loadWorldAndBody(String worldText, String bodyText) {
File bodyFile = programFile("body.tmp");
File worldFile = programFile("world.tmp");
saveTextFile(worldFile, dropLeadingEmptyLines(worldText));
loadWorld(worldFile);
saveTextFile(bodyFile, dropLeadingEmptyLines(bodyText));
loadBody(bodyFile);
}
public void run() {
activateConsole();
print("Self-Test START");
String text = loadSnippet("#1031220");
List parts = splitAtMultipleEqualsLines(text);
assertEqualsVerbose(6, l(parts));
loadWorldAndBody(parts.get(0), parts.get(1));
List outputTexts = subList(parts, 2);
do {
// step 1
if (!step(outputTexts)) break;
text = loadSnippet("#1031228");
outputTexts = getMulti(splitAtMultipleEqualsLines(text), 2, 3, 0, 1);
// step 2
if (!step(outputTexts)) break;
// step 10
text = loadSnippet("#1031229");
outputTexts = getMulti(splitAtMultipleEqualsLines(text), 0, 1, 2, 3);
for (int _repeat_0 = 0; _repeat_0 < 7; _repeat_0++) { goCmd_impl(); }
if (!step(outputTexts)) break;
// step 50
text = loadSnippet("#1031230");
outputTexts = getMulti(splitAtMultipleEqualsLines(text), 2, 3, 0, 1);
for (int _repeat_1 = 0; _repeat_1 < 39; _repeat_1++) { goCmd_impl(); }
if (!step(outputTexts)) break;
} while (false);
// second test case
text = loadSnippet("#1031231");
parts = splitAtMultipleEqualsLines(text);
assertEqualsVerbose(6, l(parts));
loadWorldAndBody(parts.get(0), parts.get(1));
do {
// step 30
outputTexts = getMulti(subList(parts, 2), 2, 3, 0, 1);
for (int _repeat_2 = 0; _repeat_2 < 29; _repeat_2++) { goCmd_impl(); }
if (!step(outputTexts)) break;
} while (false);
// third test case
text = loadSnippet("#1031238");
parts = splitAtMultipleEqualsLines(text);
assertEqualsVerbose(6, l(parts));
loadWorldAndBody(parts.get(0), parts.get(1));
do {
// step 50
outputTexts = getMulti(subList(parts, 2), 2, 3, 0, 1);
for (int _repeat_3 = 0; _repeat_3 < 49; _repeat_3++) { goCmd_impl(); }
if (!step(outputTexts)) break;
} while (false);
print("SELF-TEST RESULT: " + scorer);
}
// returns false if something failed
boolean step(List outputTexts) {
goCmd_impl();
List diffs = new ArrayList();
printAsciiHeading("HISTORY 1");
print(addAndReturn(diffs, unidiff2(historyTextArea1, outputTexts.get(2))));
printAsciiHeading("HISTORY 2");
print(addAndReturn(diffs, unidiff2(historyTextArea2, outputTexts.get(3))));
printAsciiHeading("MEMORY 1");
print(addAndReturn(diffs, unidiff2(memoryTextArea1, outputTexts.get(0))));
printAsciiHeading("MEMORY 2");
print(addAndReturn(diffs, unidiff2(state.binonDisplayChngResults, outputTexts.get(1))));
boolean ok = allStringsEmpty(diffs);
scorer.add(ok, nOutputs(nempties(diffs)) + " differ");
return ok;
}
}
static String unidiff2(JTextComponent ta, String text) {
return unidiff2(getText(ta), text);
}
static String unidiff2(String actual, String text) {
return unidiff(cleanUpForDiff(text), cleanUpForDiff(actual));
}
static String cleanUpForDiff(String text) {
return fixNewLines(rtrim(dropLeadingEmptyLines(text)));
}
static void ResetSmartyLocation() {
if (!getCell(state.startX, state.startY).obstacle())
state.moveSmarty(state.startX, state.startY);
}
static String winToUnicode(Object text) {
return mapCharacters(str(text), c -> lookupOrKeep(winToUnicode, str(c)));
}
static A monospaced(A a) {
return setFont(monospacedFontID, swingScale(monospacedFontSize), a);
}
public static void main(final String[] args) throws Exception {
File mainJar = getMainJarLocation();
File unpackDir = newFile(mainDir(), "code");
programID = "#1031123";
{ if (standalone_start(new String[0], "Smarty", null, mainJar, unpackDir, programID())) return; }
smartyMain();
}
static int strL(String s) {
return s == null ? 0 : s.length();
}
static int lCharSequence(CharSequence s) {
return s == null ? 0 : s.length();
}
static String str(Object o) {
return o == null ? "null" : o.toString();
}
static String str(char[] c) {
return new String(c);
}
static Object first(Object list) {
return first((Iterable) list);
}
static A first(List list) {
return empty(list) ? null : list.get(0);
}
static A first(A[] bla) {
return bla == null || bla.length == 0 ? null : bla[0];
}
static A first(IterableIterator i) {
return first((Iterator) i);
}
static A first(Iterator i) {
return i == null || !i.hasNext() ? null : i.next();
}
static A first(Iterable i) {
if (i == null) return null;
Iterator it = i.iterator();
return it.hasNext() ? it.next() : null;
}
static Character first(String s) { return empty(s) ? null : s.charAt(0); }
static Character first(CharSequence s) { return empty(s) ? null : s.charAt(0); }
static A first(Pair p) {
return p == null ? null : p.a;
}
static Byte first(byte[] l) {
return empty(l) ? null : l[0];
}
static int min(int a, int b) {
return Math.min(a, b);
}
static long min(long a, long b) {
return Math.min(a, b);
}
static float min(float a, float b) { return Math.min(a, b); }
static float min(float a, float b, float c) { return min(min(a, b), c); }
static double min(double a, double b) {
return Math.min(a, b);
}
static double min(double[] c) {
double x = Double.MAX_VALUE;
for (double d : c) x = Math.min(x, d);
return x;
}
static float min(float[] c) {
float x = Float.MAX_VALUE;
for (float d : c) x = Math.min(x, d);
return x;
}
static byte min(byte[] c) {
byte x = 127;
for (byte d : c) if (d < x) x = d;
return x;
}
static short min(short[] c) {
short x = 0x7FFF;
for (short d : c) if (d < x) x = d;
return x;
}
static int min(int[] c) {
int x = Integer.MAX_VALUE;
for (int d : c) if (d < x) x = d;
return x;
}
static int l(Object[] a) { return a == null ? 0 : a.length; }
static int l(boolean[] a) { return a == null ? 0 : a.length; }
static int l(byte[] a) { return a == null ? 0 : a.length; }
static int l(short[] a) { return a == null ? 0 : a.length; }
static int l(long[] a) { return a == null ? 0 : a.length; }
static int l(int[] a) { return a == null ? 0 : a.length; }
static int l(float[] a) { return a == null ? 0 : a.length; }
static int l(double[] a) { return a == null ? 0 : a.length; }
static int l(char[] a) { return a == null ? 0 : a.length; }
static int l(Collection c) { return c == null ? 0 : c.size(); }
static int l(Iterator i) { return iteratorCount_int_close(i); } // consumes the iterator && closes it if possible
static int l(Map m) { return m == null ? 0 : m.size(); }
static int l(CharSequence s) { return s == null ? 0 : s.length(); }
static long l(File f) { return f == null ? 0 : f.length(); }
static int l(Object o) {
return o == null ? 0
: o instanceof String ? l((String) o)
: o instanceof Map ? l((Map) o)
: o instanceof Collection ? l((Collection) o)
: o instanceof Object[] ? l((Object[]) o)
: o instanceof boolean[] ? l((boolean[]) o)
: o instanceof byte[] ? l((byte[]) o)
: o instanceof char[] ? l((char[]) o)
: o instanceof short[] ? l((short[]) o)
: o instanceof int[] ? l((int[]) o)
: o instanceof float[] ? l((float[]) o)
: o instanceof double[] ? l((double[]) o)
: o instanceof long[] ? l((long[]) o)
: (Integer) call(o, "size");
}
static int l(MultiSet ms) { return ms == null ? 0 : ms.size(); }
static boolean eq(Object a, Object b) {
return a == b || a != null && b != null && a.equals(b);
}
static String rep(int n, char c) {
return repeat(c, n);
}
static String rep(char c, int n) {
return repeat(c, n);
}
static List rep(A a, int n) {
return repeat(a, n);
}
static List rep(int n, A a) {
return repeat(n, a);
}
static void change() {
//mainConcepts.allChanged();
// safe version for now cause function is sometimes included unnecessarily (e.g. by EGDiff)
callOpt(getOptMC("mainConcepts"), "allChanged");
}
//sbool ping_actions_shareable = true;
static volatile boolean ping_pauseAll = false;
static int ping_sleep = 100; // poll pauseAll flag every 100
static volatile boolean ping_anyActions = false;
static Map ping_actions = newWeakHashMap();
static ThreadLocal ping_isCleanUpThread = new ThreadLocal();
// always returns true
static boolean ping() {
if (ping_pauseAll || ping_anyActions) ping_impl(true /* XXX */);
//ifndef LeanMode ping_impl(); endifndef
return true;
}
// returns true when it slept
static boolean ping_impl(boolean okInCleanUp) { try {
if (ping_pauseAll && !isAWTThread()) {
do
Thread.sleep(ping_sleep);
while (ping_pauseAll);
return true;
}
if (ping_anyActions) { // don't allow sharing ping_actions
if (!okInCleanUp && !isTrue(ping_isCleanUpThread.get()))
failIfUnlicensed();
Object action = null;
synchronized(ping_actions) {
if (!ping_actions.isEmpty()) {
action = ping_actions.get(currentThread());
if (action instanceof Runnable)
ping_actions.remove(currentThread());
if (ping_actions.isEmpty()) ping_anyActions = false;
}
}
if (action instanceof Runnable)
((Runnable) action).run();
else if (eq(action, "cancelled"))
throw fail("Thread cancelled.");
}
return false;
} catch (Exception __e) { throw rethrow(__e); } }
static String vbToStr(long l) {
return l < 0 ? str(l) : " " + l;
}
// Use like this: printVars_str(+x, +y);
// Or: printVars("bla", +x);
// Or: printVars bla(+x);
static void printVars_str(Object... params) {
String s = "";
if (odd(l(params))) {
s = str(first(params));
if (endsWithLetterOrDigit(s)) s += ": ";
params = dropFirst(params);
}
print(s + renderVars_str(params));
}
static List replace(List l, A a, A b) {
for (int i = 0; i < l(l); i++)
if (eq(l.get(i), a))
l.set(i, b);
return l;
}
static List replace(A a, A b, List l) {
return replace(l, a, b);
}
// replace all occurrences of a in s with b
static String replace(String s, String a, String b) {
return s == null ? null : a == null || b == null ? s : s.replace(a, b);
}
static String replace(String s, char a, char b) {
return s == null ? null : s.replace(a, b);
}
static List takeFirst(List l, int n) {
return l(l) <= n ? l : newSubListOrSame(l, 0, n);
}
static List takeFirst(int n, List l) {
return takeFirst(l, n);
}
static String takeFirst(int n, String s) { return substring(s, 0, n); }
static String takeFirst(String s, int n) { return substring(s, 0, n); }
static CharSequence takeFirst(int n, CharSequence s) { return subCharSequence(s, 0, n); }
static List takeFirst(int n, Iterable i) {
if (i == null) return null;
List l = new ArrayList();
Iterator it = i.iterator();
for (int _repeat_0 = 0; _repeat_0 < n; _repeat_0++) { if (it.hasNext()) l.add(it.next()); else break; }
return l;
}
static int[] takeFirst(int n, int[] a) {
return takeFirstOfIntArray(n, a);
}
static boolean isTrue(Object o) {
if (o instanceof Boolean)
return ((Boolean) o).booleanValue();
if (o == null) return false;
if (o instanceof ThreadLocal) // TODO: remove this
return isTrue(((ThreadLocal) o).get());
throw fail(getClassName(o));
}
static boolean isTrue(Boolean b) {
return b != null && b.booleanValue();
}
static boolean empty(Collection c) { return c == null || c.isEmpty(); }
static boolean empty(Iterable c) { return c == null || !c.iterator().hasNext(); }
static boolean empty(CharSequence s) { return s == null || s.length() == 0; }
static boolean empty(Map map) { return map == null || map.isEmpty(); }
static boolean empty(Object[] o) { return o == null || o.length == 0; }
static boolean empty(Object o) {
if (o instanceof Collection) return empty((Collection) o);
if (o instanceof String) return empty((String) o);
if (o instanceof Map) return empty((Map) o);
if (o instanceof Object[]) return empty((Object[]) o);
if (o instanceof byte[]) return empty((byte[]) o);
if (o == null) return true;
throw fail("unknown type for 'empty': " + getType(o));
}
static boolean empty(Iterator i) { return i == null || !i.hasNext(); }
static boolean empty(double[] a) { return a == null || a.length == 0; }
static boolean empty(float[] a) { return a == null || a.length == 0; }
static boolean empty(int[] a) { return a == null || a.length == 0; }
static boolean empty(long[] a) { return a == null || a.length == 0; }
static boolean empty(byte[] a) { return a == null || a.length == 0; }
static boolean empty(short[] a) { return a == null || a.length == 0; }
static boolean empty(MultiSet ms) { return ms == null || ms.isEmpty(); }
static boolean empty(File f) { return getFileSize(f) == 0; }
static String mapCharacters(String s, IF1 f) {
return join(map(characters(s), f));
}
static String mapCharacters(IF1 f, String s) {
return mapCharacters(s, f);
}
static RuntimeException fail() { throw new RuntimeException("fail"); }
static RuntimeException fail(Throwable e) { throw asRuntimeException(e); }
static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); }
static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); }
static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); }
static List takeLast(List l, int n) {
return newSubList(l, l(l)-n);
}
static List takeLast(int n, List l) {
return takeLast(l, n);
}
static String takeLast(int n, String s) {
return substring(s, l(s)-n);
}
static String takeLast(String s, int n) {
return substring(s, l(s)-n);
}
static Q startQ() {
return new Q();
}
static Q startQ(String name) {
return new Q(name);
}
static String unicode_blackSquare() {
return "\u25A0";
}
static String unicode_dottedSquare() {
return "\u2B1A";
}
static java.awt.Color colorFromHex(String hex) {
return awtColor(hex);
}
static String charRange(char first, char last) {
StringBuilder buf = new StringBuilder();
while (first <= last) buf.append(first++);
return str(buf);
}
static String charRange(int first, int last) {
return charRange((char) first, (char) last);
}
static String unicode_slightlySmilingFace() {
return codePointToString(0x1F642);
}
static String unindent_mls(String s) {
return autoUnindent_mls(s);
}
static HashMap litmap(Object... x) {
HashMap map = new HashMap();
litmap_impl(map, x);
return map;
}
static void litmap_impl(Map map, Object... x) {
if (x != null) for (int i = 0; i < x.length-1; i += 2)
if (x[i+1] != null)
map.put(x[i], x[i+1]);
}
static String unicode(String hex) {
return codePointToString(parseHexInt(hex));
}
static String unicode_blackVerticalRectangle() {
return unicode("25AE");
}
static String unicode_whiteVerticalRectangle() {
return unicode("25AF");
}
static String unicode_blackSmallSquare() {
return "\u25AA";
}
static ReliableSingleThread rstWithPreDelay(int delay, Runnable r) {
return rstWithDelay(delay, r);
}
static ReliableSingleThread rstWithPreDelay(double seconds, Runnable r) {
return rstWithDelay(seconds, r);
}
static boolean setText_opt = true; // optimize by calling getText first
static A setText(A c, Object text) {
setText((JComponent) c, text);
return c;
}
static A setText(final A c, Object text) {
// only for editable combo boxes at this point
final String s = strUnnull(text);
{ swing(new Runnable() { public void run() { try {
c.getEditor().setItem(s);
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.getEditor().setItem(s);"; }}); }
return c;
}
static void setText(JLabel c, Object text) {
setText((JComponent) c, text);
}
static JButton setText(JButton c, Object text) {
setText((JComponent) c, jlabel_textAsHTML_center_ifNeeded(strUnnull(text)));
return c;
}
static A setText(final A c, Object text) {
if (c == null) return null;
final String s = strUnnull(text);
{ swing(new Runnable() { public void run() { try {
if (!setText_opt || neq(callOpt(c, "getText"), s))
call(c, "setText", s);
} catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!setText_opt || neq(callOpt(c, \"getText\"), s))\r\n call(c, \"setText\", s);"; }}); }
return c;
}
static RuntimeException rethrow(Throwable t) {
if (t instanceof Error)
_handleError((Error) t);
throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t);
}
static RuntimeException rethrow(String msg, Throwable t) {
throw new RuntimeException(msg, t);
}
static List ll(A... a) {
ArrayList l = new ArrayList(a.length);
if (a != null) for (A x : a) l.add(x);
return l;
}
static HashSet litset(A... items) {
return lithashset(items);
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static volatile Appendable print_log = local_log; // might be redirected, e.g. to main bot
// in bytes - will cut to half that
static volatile int print_log_max = 1024*1024;
static volatile int local_log_max = 100*1024;
static boolean print_silent = false; // total mute if set
static Object print_byThread_lock = new Object();
static volatile ThreadLocal