!7 static CirclesAndLines cal; p-pretty { cal = new CirclesAndLines; Circle a = cal.circle_autoVis("PLAYER", "Chess Player", 0.25, 0.75); Circle b = cal.circle_autoVis("PLAYER", "Chess Player", 0.75, 0.75); cal.arrow(a, "VS", b); cal.circle_autoVis("MAGNUS CARLSEN", 0.25, 0.25); cal.circle_autoVis("HIKARU NAKAMURA", 0.75, 0.25); Canvas canvas = cal.show(700, 600); nu(Thinker, +cal, +canvas, think := f think).init(); } bool think() { true; } sclass Thinker { double delay = 2; // 2 seconds CirclesAndLines cal; Canvas canvas; JTextArea textArea; JButton btnThink, btnStartOver; volatile bool thinking; S status, initialStatus = "Set up."; int step; bool inited; O think; // func -> bool void init { if (inited) ret; inited = true; addControls(); thread "Think" { Thinker.this.run(); } } void addControls { swing { addToWindowRight(canvas, withMargin(vstackWithSpacing( jMaxWidth(167, jMinHeight(180, jscroll(textArea = setFontSize(16, makeBold(wordWrapTypeWriterTextArea()))))), btnThink = fatButton(100, "Think!", r { thinkOrStop() }), btnStartOver = fatButton(60, "Start over", r { startOver() }) ))); increaseFrameWidth(canvas, 180); status = initialStatus; status(); } } void startOver { // todo } void run { repeat { sleepSeconds(delay); if (thinking) pcall { print("Thinking"); bool t; time { t = think(); } if (!t) { thinking(false); print("Done"); } else { print("Updating"); canvas.update(); } } } } void thinking(bool b) { thinking = b; status(); setText(btnThink, b ? "
Stop
thinking
" : "Think!"); } void thinkOrStop { thinking(!thinking); } bool think() { if (think == null) false; cal.lock.lock(); try { step++; status(); ret !isFalse(pcallF(think)); } finally { cal.lock.unlock(); } } JButton fatButton(int h, S text, O action) { JButton btn = jbutton(text, action); btn.setFont(sansSerifBold(16)); ret jMinSize(167, h, btn); } void status { setText(textArea, status + "\n\n" + (thinking ? "Thinking...\n\n" : "") + (step == 0 ? "No thoughts made yet." : "Thoughts made: " + step)); } }