!7 sbool showHelpOnStart; static int spacing = 20; static JFrame mainFrame; static LL gridComponents; static JComponent mainGrid; static JCheckBoxMenuItem miShowLocations; static SingleComponentPanel scpMainGrid; static JFrame historyFrame, memoryFrame; sS wallSymbol = unicode_blackSquare(), noWallSymbol = unicode_dottedSquare(); static Color lightBlue = colorFromHex("4169e1"); sS locationLetters = charRange('A', 'Z') + "[\\]^_`" + charRange('a', 'z') + charRange(123, 128); sS smartyUnicode = basicUnicodeSmiley(); static int smartyFontSize = 40; sS windowsFontID = #1400468; sS frameIconID = #1102983; sS historyHelp = unindent_mls([[ A percept is the stimulus or simultaneous combination of stimuli observed. An action is the response or simultaneous combination of responses produced. Binon # numbers refer to the binons in memory that represent the percepts, actions, expectations, and perceptual or action sequences. P = Percept, E = Expectation, PP = Perceptual sequence A = Action, AA = Action sequence Read the paper: "The Perception-Action Hierarchy and its Implementation Using Binons (Binary Neurons)" on the www.adaptroninc.com website for more information. ]]); svoid rearrangeLetters { int iLetter = 0; for (int y = 0; y < state.gridRows; y++) for (int x = 0; x < state.gridCols; x++) { JCell cell = getCell(x, y); if (cell.obstacle()) cell.letter = ' '; else cell.letter = locationLetters.charAt(iLetter++); } } sclass VisionMode { sS nextSquare = "next square"; sS distanceToWall = "distance to wall"; sS wallOrNot = "wall or not"; } sclass CameraDirection { sS down = "down"; sS left = "left"; sS right = "right"; sS inFront = "in front"; sS behind = "behind"; static LS all = ll(down, left, right, inFront, behind); } concept SmartyBody { S name = "Smarty0"; new Set cameraDirections; S visionMode = VisionMode.nextSquare; // see VisionMode } concept State { float fontScale = 1.25f; int gridRows = 8, gridCols = 8; bool showLocations = true; int smartyX, smartyY; Rect selection = rect(1, 1, 1, 1); Pt cursorDirection = pt(1, 0); new BitSet obstacles; new Ref body; void setSelection(Rect r) { if (!cset_trueIfChanged(this, selection := r)) ret; if (selection.h == 1 && selection.w > 1) _setField(cursorDirection := pt(1, 0)); else if (selection.w == 1 && selection.h > 1) _setField(cursorDirection := pt(0, 1)); repaint(mainGrid); } void clearSelectedArea { fillSelection(false); } void invertSelection { JCell cell1 = getCell(selection.x, selection.y); fillSelection(!cell1.obstacle()); } void fillSelection(bool b) { for (Pt p : pointsInRect(selection)) getCell(p.x, p.y).setObstacle(b); rearrangeLetters(); moveCursor(); } void moveCursor { setCursor(selection.x+cursorDirection.x, selection.y+cursorDirection.y); } void setCursor(int x, int y) { setSelection(rect(mod(x, gridCols), mod(y, gridRows), 1, 1)); } void moveCursor(int dx, int dy) { _setField(cursorDirection := pt(dx, dy)); setCursor(selection.x+cursorDirection.x, selection.y+cursorDirection.y); } void placeSmarty { getCell(selection.x, selection.y).setObstacle(false); cset(this, smartyX := selection.x, smartyY := selection.y); moveCursor(); } } // end of State static State state; sclass JCell > JComponent { int x, y; char letter; *(int *x, int *y) {} public void paint(Graphics _g) { Graphics2D g = cast _g; int w = getWidth(), h = getHeight(); Color color = Color.white; if (state.selection.contains(x, y)) color = lightBlue; else if (obstacle()) color = Color.black; fillRect(g, 0, 0, w, h, color); if (state.showLocations && !obstacle()) { temp tempSetFont(g, loadFont_cached(windowsFontID)); drawTextWithTopLeftCornerAt(g, str(letter), Pt(2, 0), Color.black); } if (state.smartyX == x && state.smartyY == y) { temp tempSetFontSize(g, smartyFontSize); drawCenteredText(g, smartyUnicode, 0, 0, w, h, Color.black); } } int index() { ret y*state.gridCols+x; } bool obstacle() { ret main contains(state.obstacles, index()); } void setObstacle(bool b) { setBit(state.obstacles, index(), b); state.change(); } { addMouseListener(new MouseAdapter { public void mousePressed(MouseEvent e) { main requestFocus(mainGrid); if (!isLeftButton(e)) ret; state.setSelection(new Rect(x, y, 1, 1)); } }); addMouseMotionListener(new MouseMotionAdapter { public void mouseDragged(MouseEvent e) { _print("Drag in " + x + "/" + y + ": " + e.getPoint()); Component dest = componentAtScreenLocationInWindow(mainFrame, e); if (dest cast JCell) { _print("Target: " + dest); state.setSelection(rectFromPointsInclusiveSorted(x, y, dest.x, dest.y)); } } }); } toString { ret x + "/" + y; } } static JCell getCell(int x, int y) { ret gridComponents.get(y).get(x); } svoid makeMainGrid { gridComponents = map(iotaZeroList(state.gridRows), y -> map(iotaZeroList(state.gridCols), x -> new JCell(x, y))); mainGrid = setFocusable(setBackground(Color.black, hvgrid(gridComponents, 1))); scpMainGrid.setComponent(mainGrid); rearrangeLetters(); } svoid setWorldSize(int size) { state.obstacles.clear(); state.gridCols = state.gridRows = size; state.selection = rect(1, 1); state.smartyX = state.smartyY = 0; state.change(); makeMainGrid(); } p { autoRestart(2.0); db(); uniq(SmartyBody); // make at least one instance state = uniq(State); if (!state.body.has()) cset(state, body := conceptWhere(SmartyBody)); // default body jtattoo_mcWin(); state.fontScale = 1.5f; // XXX //set swingFontScale_debug; swingFontScale(state.fontScale); loadLibrary(windowsFontID); defaultFrameIcon(frameIconID); mainFrame = showFrame("Smarty"); addMenu(mainFrame, "Worlds", "New... (Ctrl+N)", r {}, "Retrieve... (Ctrl+R)", r {}, "Save... (Ctrl+S)", r {}, "---", "Exit", rThread killVM); registerCtrlKey(mainFrame, KeyEvent.VK_N, "New world", r { print("new") }); registerCtrlKey(mainFrame, KeyEvent.VK_R, "Retrieve world", r {}); registerCtrlKey(mainFrame, KeyEvent.VK_S, "Save world", r {}); addMenu(mainFrame, "View", miShowLocations = jCheckBoxMenuItem("Locations (Ctrl+L)", state.showLocations, b -> { cset(state, showLocations := b); repaint(mainGrid); })); registerCtrlKey(mainFrame, KeyEvent.VK_L, "Locations", r { cset(state, showLocations := !state.showLocations); setChecked(miShowLocations, state.showLocations); repaint(mainGrid); }); JMenuBar menuBar = getMenuBar(mainFrame); JMenuItem helpItem = jMenuItem("Help F1", rThread showHelp); /*print(minSize := getMinimumSize(helpItem)); print(preferredSize := getPreferredSize(helpItem));*/ addMenuItem(menuBar, jPreferredWidthToMaxWidth(helpItem)); addAndRevalidate(menuBar, jHorizontalGlue()); // spacer registerFunctionKey(mainFrame, 1, rThread showHelp); registerKeyCode(mainFrame, KeyEvent.VK_SPACE, r { state.invertSelection() }); registerKeyCode(mainFrame, KeyEvent.VK_UP, r { state.moveCursor(0, -1) }); registerKeyCode(mainFrame, KeyEvent.VK_LEFT, r { state.moveCursor(-1, 0) }); registerKeyCode(mainFrame, KeyEvent.VK_DOWN, r { state.moveCursor(0, 1) }); registerKeyCode(mainFrame, KeyEvent.VK_RIGHT, r { state.moveCursor(1, 0) }); for (int key = KeyEvent.VK_A; key <= KeyEvent.VK_Z; key++) registerKeyCode(mainFrame, key, r { state.placeSmarty() }); JSpinner worldSizeSpinner = jSpinner(state.gridCols, 1, 8); onChange(worldSizeSpinner, r { setWorldSize(intFromSpinner(worldSizeSpinner)); }); JComponent middleArea = westAndCenterWithMargin(spacing, jvstackWithSpacing(spacing, withTitle("World size (max=8)", worldSizeSpinner), jbutton("Clear Selected Area", rThread { state.clearSelectedArea() }), withTitle("Current world", jdisabledtextfield("empty")), fontSizePlus(2, setForeground(Color.ORANGE, jCenteredLabel("Design or Select a body for Smarty"))), jbutton("Design or Select Smarty's Body", r showSmartyConfig), withTitle("Current Smarty", jdisabledtextfield("Smarty0")), ), jvgridWithSpacing(spacing, withTitle("Sensors Values are", jTextArea()), withTitle("Devices Values are", jTextArea()) ) ); JComponent controlArea = northCenterAndSouthWithMargin(spacing, fontSizePlus(2, setForeground(Color.blue, jlabel("Design the World - Read the Help F1"))), middleArea, jCenteredSection("Run Smarty", jflow( jbutton("Go / Continue"), jButton("See History", r showHistory), jbutton("Reset"), jbutton("EXIT", rThread killVM), jbutton("See Memory", r showMemory))) ); scpMainGrid = singleComponentPanel(); makeMainGrid(); setFrameContents(mainFrame, westAndCenterWithMargins(spacing, jvstackWithSpacing(spacing, jFixedSize(500, scpMainGrid), jhgridWithSpacing(spacing, jlabel("VisionD:"), jlabel("Wheels:")) ), controlArea)); centerPackFrame(mainFrame); if (showHelpOnStart) showHelp(); //hideConsole(); } svoid showHelp() { S text = loadSnippet(#1031105); S heading = firstLine(text); trim(dropFirstLine(text)); showFrame(heading, fontSizePlus(4, makeUneditableWithTextColor(Color.black, wordWrapTextArea(text)))); } // run in Swing thread svoid showHistory { Font ttFont = typeWriterFont(12), helpFont = sansSerifFont(13); if (historyFrame == null) historyFrame = getFrame(showCenterFrame(scalePt(600, 350, swingFontScale()), "Stimulus/Response, Percept/Action History", withMargin(centerAndSouthWithMargin(spacing, jvsplit(0.5, 100, jTextArea(), westAndCenterWithMargin(spacing, setFont(ttFont, topAlignLabel(jMultiLineLabel( linesLL("Step #", "Percept", "Binon #", "", "Expect", "Binon #", "", "Action", "Binon #", "", "Action", "Binon #", "")))), setFont(ttFont, jTextArea())) ), centerAndEastWithMargin( setFont(helpFont, jMultiLineLabel(historyHelp)), jvstackWithSpacing( jButton("See World", r showWorld), jButton("See Memory", r showMemory)) ))))); else frameToFront(historyFrame); } // run in Swing thread svoid showMemory { Font ttFont = typeWriterFont(12), helpFont = sansSerifFont(13); if (memoryFrame == null) memoryFrame = getFrame(showCenterFrame(scalePt(600, 350, swingFontScale()), "Smarty's Memory", jvsplit(0.5, 100, centerAndEastWithMargins( northAndCenterWithMargin( setFont(ttFont, jLabel("bla bla bla")), setFont(ttFont, jTextArea())), jvstackWithSpacing( jButton("See World", r showWorld), jButton("See History", r showHistory)) ), jTextArea(), ) )); else frameToFront(memoryFrame); } svoid showWorld { frameToFront(mainFrame); } static JRadioButton visionModeRadioButton(SmartyBody body, ButtonGroup buttonGroup, S visionMode, S text) { var rb = jradiobutton(buttonGroup, text, eq(body.visionMode, visionMode)); onChange(rb, r { if (isChecked(rb)) cset(body, +visionMode); }); ret rb; } svoid showVisionConfig(SmartyBody body) { var buttonGroup = buttonGroup(); showPackedFrame("Configure Smarty's Vision", northAndCenterWithMargins(spacing, jlabel("Body name: " + body.name), westAndCenterWithMargin(spacing, jCenteredSection("Camera", withLeftMargin(spacing, jvstackWithSpacing(spacing, itemPlus(jlabel("Select the camera directions"), map(CameraDirection.all, direction -> { var cb = jCheckBox(direction, body.cameraDirections.contains(direction)); onChange(cb, r { addOrRemove(body.cameraDirections, direction, isChecked(cb)); body.change(); }); ret cb; }))))), jCenteredSection("Vision mode", jvstackWithSpacing(spacing, visionModeRadioButton(body, buttonGroup, VisionMode.nextSquare, "Looking at the next square (symbolic values = letter in square)"), withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS(replaceSymbols([[ Square locations are identified with a letter. Looking down provides the letter of the current square. Looking in other directions provides the letter in the next square depending on the direction Smarty is facing. If it is a wall then the symbolic stimulus is a $wallSymbol ]])))), visionModeRadioButton(body, buttonGroup, VisionMode.distanceToWall, "Distance to wall (magnitude values = number of squares)"), withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS([[ Looking at the distance to the nearest wall will provide the number of squares from the current position to the wall in the direction the camera is facing. A wall next to the robot is one square away. Looking down will always return 1. ]]))), visionModeRadioButton(body, buttonGroup, VisionMode.wallOrNot, replaceSymbols("Wall or not (symbolic values = $wallSymbol for a wall and $noWallSymbol for no wall)")), withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS([[ Looking at the next square will either see a wall or an empty square ]]))), )) ))); } svoid showWheelsConfig(SmartyBody body) { var buttonGroup = buttonGroup(); showPackedFrame("Configure Smarty's Wheels", northAndCenterWithMargins(spacing, jlabel("Body name: " + body.name), vstackWithSpacing(spacing, jCenteredSection("Movement", withLeftMargin(spacing, jvstackWithSpacing(spacing, jlabel("Select the wheel motions:"), jCheckBox("Forward = f"), jCheckBox("Left = l"), jCheckBox("Right = r"), jCheckBox("Backward = b"), ))), jCenteredSection("Turning", vstackWithSpacing(spacing, jCheckBox("Turn to the right = Rotate clockwise 90 degrees = X"), jCheckBox("Turn to the left = Rotate anti-clockwise 90 degrees = X"), jCheckBox("Turn around = Rotate 180 degrees = X"), )), jCenteredSection("Sensing", jCheckBox("Add a wheel sensor to detect if it moved or failed because it was up against a wall") ) ) )); } svoid showSmartyConfig { showPackedFrameMinWidth(400, "Design or Select a body for Smarty", withMargin(centeredButtons( "Vision", r { showVisionConfig(state.body!) }, "Wheels", r { showWheelsConfig(state.body!) }, )) ); } // e.g. $wallSymbol and $noWallSymbol sS replaceSymbols(S s) { ret replaceDollarVars(s, +wallSymbol, +noWallSymbol); }