Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

4788
LINES

< > BotCompany Repo | #1031138 // Smarty AI Include

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (7897L) is out of date.

// AI begins here

do not include class Letter.

!include once #1002637 // substring
!include once #1000810 // join
!include once #1007089 // lastIndexOf
!include once #1003421 // padLeft
!include once #1002071 // trim

// copied from main.java in preliminary IDEA project
// from "static class Smarty" to
// "JavaX standard functions & classes"

concept Smarty {
    int IntensityRange;
    String[] Sense = new[10+1];
    boolean Processing50;
    int MaxBodies;

    transient TheWorld World;
    new Bodies 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 S LookSouth() {
            return "";
        }

        public S LookNorth() {
            return "";
        }

        public S LookEast() {
            return "";
        }

        public S LookWest() {
            return "";
        }

        public void Update_View() {}

        public void setBinonDisplayObjList(S text) {}

        public void setBinonDisplayChngResults(S text) {}
        
        public void appendBinonDisplayChngResults(S text) {}

        public void showSensorValues(S text) {}
        
        public void showDeviceValues(S 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[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; //If it is false then Smarty displays as an O else it displays as ^><v

    //  Relax$ = NoResp$         '"-", used for Relaxing response - currently the same as NoResp$

    transient final char MoveForward = 'f';
    transient final char MoveToLeft = 'l';
    transient final char MoveToRight = 'r';
    transient final char MoveBackward = 'b'; // f, l, r, b
    static final char TurnRght = 187; //right angle in Terminal font
    static final char TurnLft = 188; //left angle
    static final char TurnArnd = 18; //double arrow

    String NoMoveOrTurn; //"z" indicates Smarty does not have this move ability

// ---------------------------Primitive responses  --------------------------------------

    //unused String[][] Acts = new String[100 + 1][2]; //Primitive responses per device per device type
    int NumActs; //The number of Acts entries in use
    //unused Public MaxActs; //Max is 100
    //Acts properties
    //unused Public DvcType; //0 = The device type number for this device
    //unused Public DvcID; //1 = The device number for this device of the device type
    //unused Public Respns; //2 = The response for this device

    //static Public NullAct; //-1 Used only for Act2 - Indicates that Act1 points to a primitive Acts()
    //unused Public RelaxAct; //1, The 1st act = 1st response in 1st device of 1st device type = a relax

    boolean RotateActs; //Set true if GetNxtResponse rotates through all acts

    //--------------------  The Stimulus Objects (Binons)  -------------------------

    //This is a tree of all stimulus and response representations - Parallel ones from multiple sensors and devices.
    //A binon is made up of 2 source binons (left and right) at the next level down.
    //A binon has many right target and left target binons.
    //For parallel recognition it stimulates both targets when it fires (recognizes its source combination)
    //For sequential performance it is activated by its left target, waits to be triggered by its left source,
    //then activates/does its right source and fires its right target.

    int NumBinons; //Number of objects so far in Binons(), incremented before its use
    //to determine the place where the next new binon will be placed in Binons()
    int MaxBinons; //5000, Max number of binons per type
    boolean OverLimit; //Global flag set when over Binon or Path limit

    int[][] Binons = new int[5000 + 1][14 + 1]; //Objects, parts, percepts, stimuli, responses
    //1st index = binon number
    //2nd index = binon property

    //---- Binon Properties - 2nd index values
    int BType; //1, The type of binon
    int O1; //2, Left source binon pointer
    int TQ; //3, the count of times the trigger has fired
    int O2; //4, Right source binon pointer
    int GQ; //5, the number of times the goal has fired
    int IDL; //6, The ratio value of the binon
    int IntVl; //7, Interest Value (NOVEL, INTERESTING, or Familiar)
    int OLv; //8, Level of object = number of lowest level parts involved
    int SP; //9, Sequential or Parallel property
    int 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).
    int 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
    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; //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; //set true if last response was reactive / reflex
    boolean DoingRepeat; //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<String> BinonTyp, ISetter<String> 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<String> 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 ping (BinonTypeOf(TheBinon) == ActBin) //While we have an Action
            {
                LeftBinon = TheBinon;
                //Go down the left side to the bottom Property or Percept binon
                while ping (BinonTypeOf(LeftBinon) == ActBin) //While we have an Action
                {
                    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 ping (BinonTypeOf(TheBinon) > NumProperties) //While we have a Percept
            {
                LeftBinon = TheBinon;
                //Go down the left side to the bottom property binon
                while ping (BinonTypeOf(LeftBinon) > NumProperties) //While we have a Percept
                {
                    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, +Sense_Name, +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

        new StringBuilder sensorInfo;
        for ping (Sns = 1; Sns <= NumSenses; Sns++) {
            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(S msg default "STOP") {
        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 ping (var I = 14; I <= 20; I++) {
                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<Integer> 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 ping (PerceptBinTyp = NumProperties + 1; PerceptBinTyp <= NumPercepts; PerceptBinTyp++) {
                    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 ping (FirstPtr = 1; FirstPtr < NumProperties; FirstPtr++) //Create all the 2nd level pair pointers
                {
                    for ping (SecondPtr = FirstPtr + 1; SecondPtr <= NumProperties; SecondPtr++) {
                        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 ping (EndPercept - StartPercept > 0) {
                    ThisLevel = ThisLevel + 1; //populate next level up
                    for ping (FirstPtr = StartPercept; FirstPtr < EndPercept; FirstPtr++) {
                        for ping (SecondPtr = FirstPtr + 1; SecondPtr <= EndPercept; SecondPtr++) {
                            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 ping (DHabitBinTyp = ActBin + 1 + SenseOrDeviceNum; DHabitBinTyp <= tempVar; DHabitBinTyp++) {
                    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
        new StringBuilder deviceInfo;
        for ping (int Dvc = 1; Dvc <= NumDevices; Dvc++) {
            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 S;
        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 ping (I = 1; I <= MaxSenses; I++) //+1 so it covers the Percept sense too
        {
            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 ping (I = 0; I <= 500; I++) {
            if (I > 0) {
            }
            for ping (S = 1; S <= MaxSenses; S++) {
                INPUTS[I][S] = "";
            }
            for ping (D = 1; D <= MaxDevices; D++) {
                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 ping (I = 1; I <= MaxBinons; I++) {
            Binons[I][OLv] = 0;
            Binons[I][O1] = NullObject;
            Binons[I][O2] = NullObject;
            ZeroTheCounts(I);
        }

        NumBinons = 0; //there are no binons

        for ping (T = 1; T <= MaxBinonTypes; T++) //For all property binons and their Percept combinations and Actions
        {
            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 ping (T = 1; T <= MaxPercepts; T++) //Clear perceived Parallel Percept and property binon entries
        {
            Percepts[T][BinId][Current] = NullObject;
            Percepts[T][BinId][Fired] = NullObject;
            Percepts[T][XQCnt][Current] = 0;
            Percepts[T][XQCnt][Fired] = 0;
        }

        for ping (Lk = 1; Lk <= MaxTargets; Lk++) //Clear out all targets
        {
            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 ping (int Sens = 1; Sens <= MaxSenses; Sens++) {
            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 ping (Lvl = 1; Lvl <= MaxLevels; Lvl++) {
            for ping (Percpt = Fired; Percpt <= MaxLevels; Percpt++) {
                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<Integer> ObjId, Var<Boolean> 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) fail("obj1 = 0");
        if (Obj2 == 0) 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<Integer> ObjId) {
        boolean tempExistBinon;

        //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 ping (OO = StartAt; OO <= EndAt; OO++) //For all the known objects of this type
        {
            //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;
        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 ping (Pass = 1; Pass <= 2; Pass++) //For 1/ R-S & A-E combinations then 2/ S-R & E-A combinations
        {
            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 ping (SourceBinon != NullObject) //While there is a Fired familiar binon in STM
            {
                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 ping (; ObjtLvl <= TopLevel; ObjtLvl++) //for all higher levels that have something in them
            {
                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;
        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 ping (Sens = 1; Sens <= NumSenses; Sens++) //For each property type = sense
        {
            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 ping (PerceptType = NumPercepts; PerceptType >= 1; PerceptType--) //For all the Percept binon types from complex to property binons
            {
                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 ping (PerceptType = NumPercepts; PerceptType >= 1; PerceptType--) //For all the Percept binon types from complex to property binons
            {
                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 ping (PerceptType = 1; PerceptType <= NumPercepts; PerceptType++) //For all property and Percept binon types
        {
            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 ping (int Sens = 1; Sens <= NumSenses; Sens++) //For each sense (TextBin and ContBin) = for each property type
        {
            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;
        int SecondType;
        int SecondBinon;
        int IntInS;
        boolean SecondChanged;

        //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 ping (PropBinonType = NumProperties + 1; PropBinonType <= NumPercepts; PropBinonType++) //PropBinonType used for position of the combination
        {
            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 ping (BinType = 1; BinType <= NumPercepts; BinType++) //All binon types except Actions
        {
            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 ping (OLvl = 1; OLvl <= MaxLevels; OLvl++) {
                //printVars_str DisplaySTM(+OLvl, +MaxLevels);
              
                Pcpts = ""; //empty this line

                for ping (Prcpt = OLvl + 2; Prcpt >= Fired; Prcpt--) //find out if any are not null at this level
                {
                    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;

        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 ping (!FoundIt) {
                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 ping (TgtLink != NullTarget) {
                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<Integer> 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 ping (BinonTypeOf(FoundBinon.get()) == ActBin) {
            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 ping (Prcpt = FromEntry; Prcpt <= UpTo; Prcpt++) {
            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;
        int ToPrcpt;

        HaveAPercept = false; //assume this level is empty

        ToPrcpt = ObLvl + 2;
        if (ToPrcpt >= MaxLevels) {
            ToPrcpt = MaxLevels - 1;
        }

        for ping (Prcpt = ToPrcpt; Prcpt >= Fired; Prcpt--) {
            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;

        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 ping (var J = 1; J <= HighestPerceptLvl; J++) {
            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 ping (BnTyp = 1; BnTyp <= NumBinonTypes; BnTyp++) //Property binons and Percept combinations, Perceptual sequences and Responses
        {
            GetTypeInfo(BnTyp, BinTyp, Rdgs); //Rdgs$ = abbreviation - not used - use BinTyp$ only
            Res2.append(BnTyp).append(", ").append(Rdgs).append(BinTyp).append("\r\n");

            for ping (ObjLvl = 1; ObjLvl <= MaxLevels; ObjLvl++) //For each level of binons
            {
                Res1 = new StringBuilder();

                for ping (Objct = 1; Objct <= NumBinons; Objct++) //For all binons
                {
                    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 ping (Link != NullTarget) {
            //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 ping (Link != NullTarget) {
            //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 ping (I = 1; I <= NumberOfResponses; I++) //go through the response string
                    {
                        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 ping (HaveResponse == 0) {
                        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 ping (Sens = 1; Sens <= NumSenses; Sens++) //For each sense
            {
                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<String> 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 ping (int index = 0; index < string.length(); index++) {
            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 ping (int index = startIndex; index < stringArray.length && index - startIndex < count; index++) {
            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 ping (int index = string.length() - 1; index >= 0; index--) {
            boolean removeChar = false;
            if (charsToTrim.length == 0) {
                if (Character.isWhitespace(string.charAt(index))) {
                    lengthToKeep = index;
                    removeChar = true;
                }
            } else {
                for ping (int trimCharIndex = 0; trimCharIndex < charsToTrim.length; trimCharIndex++) {
                    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 ping (int index = 0; index < string.length(); index++) {
            boolean removeChar = false;
            if (charsToTrim.length == 0) {
                if (Character.isWhitespace(string.charAt(index))) {
                    startingIndex = index + 1;
                    removeChar = true;
                }
            } else {
                for ping (int trimCharIndex = 0; trimCharIndex < charsToTrim.length; trimCharIndex++) {
                    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 ping (sb.length() < totalWidth) {
            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 ping (sb.length() + string.length() < totalWidth) {
            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 ping (int i = 1; i <= count; i++) {
            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);
    }
}

download  show line numbers  debug dex  old transpilations   

Travelled to 5 computer(s): bhatertpkbcr, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, vouqrxazstgt

No comments. add comment

Snippet ID: #1031138
Snippet name: Smarty AI Include
Eternal ID of this version: #1031138/86
Text MD5: e53061da5c94530c974d9ff61f668039
Author: stefan
Category: javax / smarty
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-05-27 23:42:05
Source code size: 239042 bytes / 4788 lines
Pitched / IR pitched: No / No
Views / Downloads: 325 / 1176
Version history: 85 change(s)
Referenced in: [show references]