!7 !include #1007303 // CirclesAndLines static CirclesAndLines cal; extend Base { new L traits; bool hasTrait(S t) { ret containsIC(traits(), t); } L traits() { if (text != null && neq(first(traits), text)) traits.add(0, text); ret traits; } } p-substance { cal = new CirclesAndLines; Circle a = cal.addCircle(#1007291, 1/3.0, 0.25, "DONALD"); Circle b = cal.addCircle(#1007292, 2/3.0, 0.25, "BOMBS"); Circle c = cal.addCircle(#1007314, 1/3.0, 0.75, "GOOD"); Circle d = cal.addCircle(#1007319, 2/3.0, 0.75, "BAD"); cal.addArrow(a, b, "MAKES"); cal.addArrow(b, d, "ARE"); Canvas canvas = cal.showAsFrame(); repeat { sleepSeconds(5); if (!think()) ret; print("Updating"); canvas.update(); } } // for (X is Y): addTrait(X, Y); && for (X makes bad): addLink(X is bad); sbool think() { bool change = false; for (Line l : cal.lines) { if (l.hasTrait("is") || l.hasTrait("are")) { int n = l(l.a.traits()); l.a.traits().addAll(b.traits()); change |= l(l.a.traits()) > n; } if (eqic(l.text, "makes") && l.b.hasTrait("bad")) { change |= addLink(l.a, "IS", cal.findCircle("bad")); } } ret change; } sbool addLink(Circle a, S link, Circle b) { Arrow arrow = cal.findArrow(a, b); if (arrow == null) { arrow = cal.addArrow(a, b, text); true; } else { if (arrow.hasTrait(link)) false; arrow.traits().add(link); true; } }