@shlomil/turtlejs
Version:
A feature-rich JavaScript implementation of turtle graphics inspired by Python's turtle module
1 lines • 75.2 kB
JavaScript
var e,t,n={width:.5,height:.75,canvwidth:400,canvheight:300,leftright:null,topbottom:null,mode:"standard",colormode:1,colormode_keep_names:!1,delay:10,undobuffersize:1e3,shape:"classic",pencolor:"black",fillcolor:"black",resizemode:"noresize",visible:!0,x:0,y:0,angle:0,isDown:!0,drawSpeed:1,penSize:1,filling:!1,fillRule:"evenodd",tiltAngle:0,turtleSize:10,stretchFactors:{width:1,length:1,outline:1},fullcircle:360,maxUndoSteps:10,shapes:{turtle:[[0,16],[-2,14],[-1,10],[-4,7],[-7,9],[-9,8],[-6,5],[-7,1],[-5,-3],[-8,-6],[-6,-8],[-4,-5],[0,-7],[4,-5],[6,-8],[8,-6],[5,-3],[7,1],[6,5],[9,8],[7,9],[4,7],[1,10],[2,14]],arrow:[[0,10],[-5,0],[5,0]],circle:[...Array(36)].map(((e,t)=>{const n=10*t*Math.PI/180;return[10*Math.sin(n),10*Math.cos(n)]})),square:[[10,10],[10,-10],[-10,-10],[-10,10]],triangle:[[0,10],[-10,-10],[10,-10]],classic:[[0,0],[-5,-9],[0,-7],[5,-9]]},imageRendering:"pixelated",imageSmoothing:!1,imageSmoothingQuality:"low"};const i={space:" ",return:"Enter",tab:"Tab",backspace:"Backspace",delete:"Delete",escape:"Escape",up:"ArrowUp",down:"ArrowDown",left:"ArrowLeft",right:"ArrowRight"};const s="undefined"!=typeof window&&"undefined"!=typeof document,a="undefined"!=typeof self&&"undefined"==typeof window||"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope;let r=s?window:null,o=s?document:null;class l{#e=0;#t;#n;#i;#s;#a;#r;#o;#l;#h;#c;#u;#d=null;#g={turtle:[[0,16],[-2,14],[-1,10],[-4,7],[-7,9],[-9,8],[-6,5],[-7,1],[-5,-3],[-8,-6],[-6,-8],[-4,-5],[0,-7],[4,-5],[6,-8],[8,-6],[5,-3],[7,1],[6,5],[9,8],[7,9],[4,7],[1,10],[2,14]],arrow:[[0,10],[-5,0],[5,0]],circle:[...Array(36)].map(((e,t)=>{const n=10*t*Math.PI/180;return[10*Math.sin(n),10*Math.cos(n)]})),square:[[10,10],[10,-10],[-10,-10],[-10,10]],triangle:[[0,10],[-10,-10],[10,-10]],classic:[[0,0],[-5,-9],[0,-7],[5,-9]]};#y;#p;#w=null;#f;#m=1;#k=new Map;#S;#b;#v=[];#x;#_;#P;#T=new Map;#M=Promise.resolve();#D;#C=!1;#z="low";#q;#B;#O=[];#L=!1;#G;#R=null;#A=null;imageSmoothing(e=null){if(null===e)return this.#C;this.#C=e}imageSmoothingQuality(e=null){if(null===e)return this.#z;if(!["low","medium","high"].includes(e))throw new Error("imageSmoothingQuality() expects 'low', 'medium', or 'high'");this.#z=e}get#I(){return this.#q.colormode()}#E(e){return this.#q._user_color(e)}#W(e){return this.#q._color_arg_normalize(e)}constructor(e,t=n){e instanceof h?(this.#q=e,this.#t=e.getcanvas()):e instanceof l?(this.#q=e.getscreen(),this.#t=this.#q.getcanvas(),t=e._getstate()):(this.#q=new h(e),this.#t=e),this.#q.addTurtle(this),this.#n=this.#t.getContext("2d",{willReadFrequently:!0}),this.#n.imageSmoothingEnabled=this.#C,this.#n.imageSmoothingQuality=this.#z,this._setstate(t),this.#G=this.#q.getWorldCoordinates(),this.#V()}async#F(e){return this.#M=this.#M.then((()=>new Promise((async t=>{t(await e())})))),this.#M}#Y(e,t){return this.#q._worldToScreen(e,t)}#H(e,t){return this.#q._screenToWorld(e,t)}async screensize(e=null,t=null,n=null){return this.#F((()=>(null!==e&&null!==t&&(this.#t.width=e,this.#t.height=t),null!==n&&(this.#t.style.backgroundColor=this.#W(n)),[this.#t.width,this.#t.height])))}async begin_poly(){return this.#F((()=>(this.#R=[],this.#R.push([this.#i,this.#s]),Promise.resolve())))}async end_poly(){return this.#F((()=>{if(!this.#R)throw new Error("end_poly() without matching begin_poly()");return this.#R.push([this.#i,this.#s]),this.#A=[...this.#R],this.#R=null,Promise.resolve()}))}async get_poly(){return this.#F((()=>{if(!this.#A)throw new Error("No polygon has been recorded yet. Use begin_poly() and end_poly() first.");return[...this.#A]}))}async resizemode(e=null){if(!["noresize","auto","user"].includes(e))throw new Error("resizemode() expects 'noresize', 'auto', or 'user'");return this.#F((()=>(null===e||(this.#_===e&&(this.#X(),this.#_=e,this.#V()),this.#_=e),this.#_)))}async setundobuffer(e=null){return this.#F((()=>(this.#B=null!==e?e:0,this.#B)))}async setworldcoordinates(e,t,n,i){return this.#F((()=>{this.#q.setworldcoordinates(e,t,n,i)}))}_setworldcoordinates(){const e=this.#c;this.#c=!1,this.#X(),this.#U(this.#q.getWorldCoordinates(),this.#G)||(this._clear(!1),this._pensize(this.#h),this.#L=!0,this.#G=this.#q.getWorldCoordinates(),this._update()),this.#c=e,e&&this.#V()}#X(){this.#d&&this.#n.putImageData(this.#d.imageData,this.#d.x,this.#d.y),this.#d=null}async forward(e){return this.#F((async()=>{await this._forward(e)}))}async _forward(e){this.#X();const t=this.#N("forward",[e]),n=this.#i,i=this.#s,s=performance.now(),a=this.#a*Math.PI/180,r=0===this.#o?0:50*(11-this.#o);this.#j(t,n,i);const o=t=>{this.#X();const o=t-s,l=Math.max(0,Math.min(o/r,1)),h=this.#i,c=this.#s;if(this.#i=n+e*Math.cos(a)*l,this.#s=i+e*Math.sin(a)*l,this.#r){const[e,t]=this.#Y(h,c),[n,i]=this.#Y(this.#i,this.#s);this.#n.beginPath(),this.#n.moveTo(e,t),this.#n.lineTo(n,i),this.#n.stroke()}this.#V()};if(this.#o<10){let e=this;return new Promise((n=>{requestAnimationFrame((function i(a){o(a),a-s>=r?(e.#j(t,e.#i,e.#s),e.#R&&e.#R.push([e.#i,e.#s]),n()):requestAnimationFrame(i)}))}))}if(this.#i=n+e*Math.cos(a),this.#s=i+e*Math.sin(a),this.#r){const[e,t]=this.#Y(n,i),[s,a]=this.#Y(this.#i,this.#s);this.#n.beginPath(),this.#n.moveTo(e,t),this.#n.lineTo(s,a),this.#n.stroke()}this.#j(t,this.#i,this.#s),this.#R&&this.#R.push([this.#i,this.#s]),this.#V()}getworld(){return{...this.#G}}async backward(e){return this.forward(-e)}async right(e){return this.#F((async()=>{await this._right(e)}))}async _right(e){let t=this;this.#X();let n=this.#N("right",[e]);const i=this.#a,s=performance.now(),a=0===this.#o?0:50*(11-this.#o),r=t=>{this.#X();const n=t-s,r=Math.min(n/a,1);this.#a=i-e*r,this.#V()};if(this.#o<10)return new Promise((e=>{requestAnimationFrame((function i(o){r(o),o-s>=a?(t.#Q(n),e()):requestAnimationFrame(i)}))}));this.#a=i-e,this.#Q(n),this.#V()}async left(e){return this.right(-e)}async penup(){return this.#F((()=>{this.#r=!1,this.#N("penup",[])}))}async pendown(){return this.#F((()=>{this.#r=!0,this.#N("pendown",[])}))}async color(...e){return this.#F((()=>this._color(...e)))}_color(...e){if(0==e.length)return[this.#l,this.#f].map((e=>this.#E(e)));let t,n;this.#X(),3==e.length?n=t=this.#W(e):2==e.length?(t=this.#W(e[0]),n=this.#W(e[1])):1==e.length&&(t=n=this.#W(e[0])),this.#l=t,this.#f=n,this.#n.strokeStyle=t,this.#N("color",e),this.#V()}async pensize(e=null){return this.#F((()=>{this._pensize(e)}))}async width(e=null){return await this.pensize(e)}_pensize(e=null){if(null==e)return this.#h;if(this.#h=e,"noresize"===this.#_){const t=this.#t.width/(this.#G.right-this.#G.left),n=this.#t.height/(this.#G.top-this.#G.bottom),i=(Math.abs(t)+Math.abs(n))/2;this.#n.lineWidth=e/i}else this.#n.lineWidth=e;this.#N("pensize",[e])}async clear(){return this.#F((()=>{this._clear()}))}_clear(e=!0){this.#X(),this.#n.clearRect(0,0,this.#t.width,this.#t.height),this.#c&&this.#V(),e&&this.#N("clear",[])}async home(){return this.#F((()=>{this._home()}))}_home(){this.#i=0,this.#s=0,this.#a=0,this.#N("home",[])}async goto(e,t=null){return this.#F((async()=>{await this._goto(e,t)}))}async teleport(e,t=null,n=!1){return this.#F((async()=>{this._teleport(e,t,n)}))}async _teleport(e,t=null,n=!1){if(null===t){if(!Array.isArray(e))throw new Error("If only one argument is provided, it must be a [x,y] array");[e,t]=e}if(this.#X(),this.#i=e,this.#s=t,this.#N("teleport",[e,t]),this.#r&&n){const[e,t]=this.#Y(this.#i,this.#s);this.#n.beginPath(),this.#n.arc(e,t,this.#h/2,0,2*Math.PI),this.#n.fillStyle=this.#W(this.#l),this.#n.fill()}this.#c&&this.#V()}async _goto(e,t){let n=this;this.#X();const i=this.#N("goto",[e,t]),s=this.#i,a=this.#s;this.#j(i,e,t);const r=performance.now(),o=0===this.#o?0:50*(11-this.#o),l=n=>{this.#X();const i=n-r,l=Math.min(i/o,1);if(this.#i=s+(e-s)*l,this.#s=a+(t-a)*l,this.#r){const[e,t]=this.#Y(s,a),[n,i]=this.#Y(this.#i,this.#s);this.#n.beginPath(),this.#n.moveTo(e,t),this.#n.lineTo(n,i),this.#n.stroke()}this.#V()};if(this.#o<10)return new Promise((e=>{requestAnimationFrame((function t(s){l(s),s-r>=o?(n.#j(i,n.#i,n.#s),n.#R&&n.#R.push([n.#i,n.#s]),e()):requestAnimationFrame(t)}))}));if(this.#i=e,this.#s=t,this.#r){const[e,t]=this.#Y(s,a),[n,i]=this.#Y(this.#i,this.#s);this.#n.beginPath(),this.#n.moveTo(e,t),this.#n.lineTo(n,i),this.#n.stroke()}return this.#j(i,this.#i,this.#s),this.#R&&this.#R.push([this.#i,this.#s]),this.#V(),Promise.resolve()}async setheading(e){return this.#F((()=>{this._setheading(e)}))}async setpos(e,t=null){return this.goto(e,t)}async setposition(e,t=null){return this.goto(e,t)}async fd(e){return this.forward(e)}async bk(e){return this.backward(e)}async back(e){return this.backward(e)}async rt(e){return this.right(e)}async lt(e){return this.left(e)}async seth(e){return this.setheading(e)}async pu(){return this.penup()}async pd(){return this.pendown()}async down(){return this.pendown()}async up(){return this.penup()}async position(){return this.#F((()=>[this.#i,this.#s]))}async pos(){return this.position()}async xcor(){return this.#F((()=>this.#i))}async ycor(){return this.#F((()=>this.#s))}async heading(){return this.#F((()=>this.#a))}async towards(e,t=null){return this.#F((()=>{let n,i;if(null===t){if(!Array.isArray(e))throw new Error("If only one argument is provided, it must be a [x,y] array");[n,i]=e}else n=e,i=t;const s=n-this.#i,a=i-this.#s;return(180*Math.atan2(a,s)/Math.PI+360)%360}))}#$(e,t=1,n=0){const i=this.#q.getShape(e);if(!i)return;const[s,a]=this.#Y(this.#i,this.#s);this.#n.beginPath();const r=i.map((([e,n])=>{const i=e*t*this.#P.width,r=n*t*this.#P.length,o=(-this.#a-90)*Math.PI/180,l=i*Math.cos(o)-r*Math.sin(o),h=i*Math.sin(o)+r*Math.cos(o);return[s+l,a+h]}));this.#n.moveTo(r[0][0],r[0][1]);for(const[e,t]of r.slice(1))this.#n.lineTo(e,t);this.#n.closePath(),this.#n.fillStyle=this.#l,this.#n.fill(),this.#n.strokeStyle=this.#l,this.#n.stroke()}#V(e=!1){if(!this.#c&&!e)return;this.#X();const[t,n]=this.#Y(this.#i,this.#s),i=this.#t.width/(this.#G.right-this.#G.left),s=this.#t.height/(this.#G.top-this.#G.bottom),a=(this.#u+this.#h)*Math.max(i,s)*2,r=2*a;e||(this.#d={imageData:this.#n.getImageData(t-a,n-a,r,r),x:t-a,y:n-a}),this.#$(this.#y,1,this.#a)}async hideturtle(){return this.#F((()=>{this.#X(),this.#c=!1}))}async showturtle(){return this.#F((()=>{this.#c=!0,this.#V()}))}async isvisible(){return this.#F((()=>this.#c))}async ht(){return this.hideturtle()}async st(){return this.showturtle()}#N(e,t=[]){const n={x:this.#i,y:this.#s,angle:this.#a,isDown:this.#r,color:this.#l,penSize:this.#h,isVisible:this.#c,worldCoordinates:{...this.#G},resizeMode:this.#_,stretchFactors:{...this.#P},path:null,action:e,parameters:t,filling:this.#p,fillColor:this.#f,fillPath:this.#p&&this.#w?new Path2D(this.#w):null,points:[]};if(this.#v.push(n),this.#v.length>this.#B){const e=this.#v.shift();(e.path||e.fillPath)&&0===this.#O.length&&this.#O.push({type:"snapshot",imageData:this.#n.getImageData(0,0,this.#t.width,this.#t.height)})}return n}#K(e){this.#d=null,this.#i=e.x,this.#s=e.y,this.#a=e.angle,this.#r=e.isDown,this.#l=e.color,this.#h=e.penSize,this.#c=e.isVisible,this.#G={...e.worldCoordinates},this.#_=e.resizeMode,this.#P={...e.stretchFactors},e.canvasState&&this.#n.putImageData(e.canvasState,0,0),this.#n.strokeStyle=this.#l,this._pensize(this.#h),this.#c&&this.#V()}async setx(e){return this.#F((()=>{this.goto(e,this.#s)}))}async sety(e){return this.#F((()=>{this.goto(this.#i,e)}))}async distance(e,t=null){return this.#F((()=>{let n,i;if(null===t){if(!Array.isArray(e))throw new Error("If only one argument is provided, it must be a [x,y] array");[n,i]=e}else n=e,i=t;return Math.sqrt((this.#i-n)**2+(this.#s-i)**2)}))}onclick(e,t=1,n=null){let i=this;if(!e)return this.#t.onclick=null,void(this.#t.onauxclick=null);const s=t=>{const n=i.#t.getBoundingClientRect(),s=t.clientX-n.left,a=t.clientY-n.top,[r,o]=i.#H(s,a);e(r,o)};if(1===t)if(n){const e=this.#t.onclick;this.#t.onclick=t=>{e&&e(t),s(t)}}else this.#t.onclick=s;else if(2===t)if(n){const e=this.#t.onauxclick;this.#t.onauxclick=t=>{1===t.button&&(e&&e(t),s(t))}}else this.#t.onauxclick=e=>{1===e.button&&s(e)};else if(3===t)if(n){const e=this.#t.onauxclick;this.#t.onauxclick=t=>{2===t.button&&(e&&e(t),s(t))}}else this.#t.onauxclick=e=>{2===e.button&&s(e)}}onscreenclick(e,t=1,n=null){return this.onclick(e,t,n)}onkey(e,t){if(null===e){if(t)document.removeEventListener("keyup",this.#T?.get(t)),this.#T?.delete(t);else{for(const[e,t]of this.#T)document.removeEventListener("keyup",t);this.#T.clear()}return}const n=i[t.toLowerCase()]||t.toLowerCase(),s=t=>{t.key.toLowerCase()===n.toLowerCase()&&e()};this.#T.set(t,s),document.addEventListener("keyup",s)}onkeyrelease(e,t){return this.onkey(e,t)}onkeypress(e,t=null){if(null===e)return void this.onkey(null,t);const n=i[t.toLowerCase()]||t.toLowerCase(),s=t=>{t.key.toLowerCase()===n.toLowerCase()&&e()};this.#T.set(t,s),document.addEventListener("keydown",s)}world_width(){return this.#G.right-this.#G.left}world_height(){return this.#G.top-this.#G.bottom}window_width(){return this.#t.width}window_height(){return this.#t.height}async delay(e=null){return this.#F((()=>{if(null===e)return this.#e;this.#e=e}))}async bgcolor(e){return this.#F((()=>{this.#t.style.backgroundColor=this.#W(e)}))}async shape(e=null){return this.#F((()=>{if(null===e)return this.#y;if(!this.#q.getShape(e))throw new Error(`Shape ${e} is not available`);this.#y=e,this.#V()}))}async shapesize(e=null,t=null,n=null){return this.#F((()=>{null!==e&&null!==t&&(this.#P.width=e,this.#P.length=t),null!==n&&(this.#P.outline=n)}))}async turtlesize(e=null,t=null,n=null){return await this.shapesize(e,t,n)}async circle(e,t=360,n=null){return this.#F((async()=>{await this._circle(e,t,n)}))}async _circle(e,t=360,n=null){this.#X();const i=this.#N("circle",[e,t,n]);null===n&&(n=Math.max(4,Math.floor(Math.abs(e)/5)));const s=(this.#a-90)*Math.PI/180,a=this.#i-Math.abs(e)*Math.cos(s),r=this.#s-Math.abs(e)*Math.sin(s),o=s,l=e<0;if(this.#r){const n=Math.max(2,Math.ceil(Math.abs(t)%360*100/360)),s=[];s.push([this.#i,this.#s]);for(let l=1;l<=n;l++){const h=o+t*(l/n)*Math.PI/180,c=a+Math.abs(e)*Math.cos(h),u=r+Math.abs(e)*Math.sin(h);s.push([c,u]),this.#j(i,c,u,!1,!1),this.#R&&this.#R.push([c,u])}i.path=this.#J(s),i.points=s}const h=performance.now(),c=0===this.#o?0:200*(11-this.#o),u=n=>{this.#X();const i=n-h,s=Math.min(i/c,1),u=o+t*s*Math.PI/180;if(this.#r){const n=100,i=Math.floor(n*s);for(let s=0;s<=i;s++){const i=o+t*(s/n)*Math.PI/180,l=a+Math.abs(e)*Math.cos(i),h=r+Math.abs(e)*Math.sin(i),[c,u]=this.#Y(l,h);0===s?(this.#n.beginPath(),this.#n.moveTo(c,u)):(this.#n.lineTo(c,u),this.#n.stroke(),this.#n.beginPath(),this.#n.moveTo(c,u))}}this.#i=a+Math.abs(e)*Math.cos(u),this.#s=r+Math.abs(e)*Math.sin(u);const d=180*u/Math.PI+(l?-90:90);this.#a=d,this.#V()};if(this.#o<10)return new Promise((e=>{requestAnimationFrame((function t(n){u(n),n-h>=c?e():requestAnimationFrame(t)}))}));{const n=o+t*Math.PI/180;if(this.#r){const n=100;for(let i=0;i<=n;i++){const s=o+t*(i/n)*Math.PI/180,l=a+Math.abs(e)*Math.cos(s),h=r+Math.abs(e)*Math.sin(s);0===i?(this.#n.beginPath(),this.#n.moveTo(l,h)):(this.#n.lineTo(l,h),this.#n.stroke(),this.#n.beginPath(),this.#n.moveTo(l,h))}}this.#i=a+Math.abs(e)*Math.cos(n),this.#s=r+Math.abs(e)*Math.sin(n);const s=180*n/Math.PI+(l?-90:90);this.#a=s,this.#Q(i),this.#V()}return Promise.resolve()}async dot(e=null,t=null){return this.#F((()=>{this.#X(),this.#N();const n=this.#l,i=this.#h;t&&(this.#l=this.#W(t)),null===e&&(e=Math.max(this.#h+4,2*this.#h));const[s,a]=this.#Y(this.#i,this.#s);this.#n.beginPath(),this.#n.arc(s,a,e/2,0,2*Math.PI),this.#n.fillStyle=this.#l,this.#n.fill(),this.#l=this.#W(n),this._pensize(i),this.#V()}))}async begin_fill(){return this.#F((()=>{this.#p=!0,this.#w=new Path2D;const[e,t]=this.#Y(this.#i,this.#s);this.#w.moveTo(e,t),this.#N("begin_fill",[])}))}async end_fill(e=n.fillRule){return this.#F((()=>{let t=this.#N("end_fill",[e]);this.#X(),this.#p&&this.#w&&(this.#w.closePath(),this.#n.fillStyle=this.#f,this.#n.fill(this.#w,e),t.filling=this.#p=!1,t.do_fill_path=new Path2D(this.#w),t.fillPath=this.#w=null),this.#V()}))}async filling(){return this.#F((()=>this.#p))}async pencolor(...e){return this.#F((()=>{if(0===e.length)return this.#E(this.#l);this.#X(),3===e.length?this.#l=this.#W(e):1===e.length&&(this.#l=this.#W(e[0])),this.#n.strokeStyle=this.#l,this.#N("pencolor",e),this.#V()}))}async fillcolor(...e){return this.#F((()=>{if(0===e.length)return this.#E(this.#f);this.#X(),3===e.length?this.#f=this.#W(e):1===e.length&&(this.#f=this.#W(e[0])),this.#n.fillStyle=this.#f,this.#N("fillcolor",e),this.#V()}))}async reset(){return this.#F((async()=>{this._reset()}))}_reset(){this._clear(),this.#i=0,this.#s=0,this.#a=0,this.#r=!0,this.#o=1,this.#l="black",this.#f="black",this.#h=1,this.#c=!0,this.#y=n.shape,this.#n.strokeStyle="black",this.#n.fillStyle="black",this.#n.lineWidth=1;const e=this.#q.naturalWorldCoordinates();this._setworldcoordinates(e.left,e.bottom,e.right,e.top),this.#v=[],this.#O=[],this.#V()}async write(e,t=!1,n="left",i=["Arial",8,"normal"]){return this.#F((()=>{this._write(e,t,n,i)}))}_write(e,t=!1,n="left",i=["Arial",8,"normal"]){this.#X();const[s,a]=this.#Y(this.#i,this.#s);this.#n.fillStyle=this.#l,this.#n.textAlign=n,this.#n.font=`${i[2]} ${i[1]}px ${i[0]}`;const r=-this.#a*Math.PI/180;if(this.#n.save(),this.#n.translate(s,a),this.#n.rotate(r),this.#n.fillText(e,0,0),this.#n.restore(),t){const t=this.#n.measureText(e).width*Math.cos(r),n=this.#t.width/(this.#G.right-this.#G.left);this.#i+=t/n}this.#N("write",[e,t,n,i]),this.#V()}async stamp(){return this.#F((()=>{const e=this.#m++;return this.#k.set(e,{x:this.#i,y:this.#s,angle:this.#a,shape:this.#y}),this.#V(!0),e}))}async clearstamp(e){return this.#F((()=>{this.#k.delete(e),this.#Z()}))}async clearstamps(e=null){return this.#F((()=>{if(null===e)this.#k.clear();else if(e>0){Array.from(this.#k.entries()).slice(-e).forEach((([e])=>this.#k.delete(e)))}else{Array.from(this.#k.entries()).slice(0,-e).forEach((([e])=>this.#k.delete(e)))}this.#Z()}))}async tilt(e){return this.#F((()=>{this.#S=(this.#S+e)%360,this.#N("tilt",[e])}))}tiltangle(e=null){return this.#F((()=>{if(null===e)return this.#S;this.#S=e,this.#N("tiltangle",[e])}))}async speed(e=null){return this.#F((()=>{this._speed(e)}))}_speed(e=null){if(null===e)return this.#o;if("string"==typeof e)switch(e.toLowerCase()){case"fastest":e=0;break;case"fast":e=10;break;case"normal":e=6;break;case"slow":e=3;break;case"slowest":e=1;break;default:throw new Error("Invalid speed string")}this.#o=Math.max(0,Math.min(10,e)),this.#N("speed",[e])}mode(e=null){if(null===e)return this.#b;if(!["standard","logo","world"].includes(e))throw new Error('Mode must be "standard", "logo", or "world"');this.#b=e}#Z(){this.#X(),this.#n.clearRect(0,0,this.#t.width,this.#t.height);for(const[e,t]of this.#k){const[e,n]=this.#Y(t.x,t.y),i=this.#g[t.shape].map((([i,s])=>{const a=t.angle*Math.PI/180,r=i*Math.cos(a)-s*Math.sin(a),o=i*Math.sin(a)+s*Math.cos(a);return[e+r,n+o]}));this.#n.beginPath(),this.#n.moveTo(i[0][0],i[0][1]);for(const[e,t]of i.slice(1))this.#n.lineTo(e,t);this.#n.closePath(),this.#n.fillStyle=this.#l,this.#n.fill(),this.#n.strokeStyle=this.#l,this.#n.stroke()}this.#c&&this.#V()}async undo(){return this.#F((()=>{if(0===this.#v.length)return;const e=this.#v.pop();if("end_fill"===e.action){this.#p=!0;let t=-1;for(let e=this.#v.length-1;e>=0;e--)if("begin_fill"===this.#v[e].action){t=e;break}if(t>=0)this.#w=new Path2D(this.#v[t].fillPath);else{this.#w=new Path2D;const[t,n]=this.#Y(e.x,e.y);this.#w.moveTo(t,n)}}else"begin_fill"===e.action?(this.#p=!1,this.#w=null):e.filling&&e.fillPath&&(this.#p=!0,this.#w=new Path2D(e.fillPath));if(this.#v.length>0){const t=this.#v[this.#v.length-1];this.#i=t.x,this.#s=t.y,this.#a=t.angle,this.#r=t.isDown,this.#l=t.color,this.#h=t.penSize,this.#c=t.isVisible,this.#G={...t.worldCoordinates},this.#_=t.resizeMode,this.#P={...t.stretchFactors},"begin_fill"!==e.action&&"end_fill"!==e.action&&(this.#p=t.filling,this.#f=t.fillColor)}else this.#i=0,this.#s=0,this.#a=0,this.#r=!0,this.#l="black",this.#h=1,this.#c=!0,this.#p=!1,this.#f="black",this.#w=null;this.#L=!0,this._update()}))}async listen(e=null,t=null){return this.#F((()=>{this.#q.listen()}))}get#ee(){return this.#a*this.#D/360}set#ee(e){this.#a=360*e/this.#D}async degrees(e=360){return this.#F((()=>{this.#D=e}))}async radians(){return this.#F((()=>{this.#D=2*Math.PI}))}async heading(){return this.#F((()=>this.#ee))}_setheading(e){this.#ee=e}async isdown(){return this.#F((()=>this.#r))}async pen(){return this.#F((()=>({shown:this.#c,pendown:this.#r,pencolor:this.#l,fillcolor:this.#f,pensize:this.#h,speed:this.#o,resizemode:this.#_,stretchfactor:{...this.#P},outline:this.#P.outline})))}async getpen(){return this}async getturtle(){return this}getscreen(){return this.#q}async clone(){return this.#F((()=>new l(this)))}async title(e=null){return this.#F((()=>null===e?document.title:(document.title=e,e)))}async _getstate(){return this.#F((()=>({width:this.#t.width,height:this.#t.height,canvwidth:this.#t.width,canvheight:this.#t.height,leftright:n.leftright,topbottom:n.topbottom,colormode:this.#I,undobuffersize:this.#B,delay:this.#e,x:this.#i,y:this.#s,angle:this.#a,isDown:this.#r,drawSpeed:this.#o,pencolor:this.#l,penSize:this.#h,visible:this.#c,turtleSize:this.#u,shape:this.#y,filling:this.#p,fillcolor:this.#f,tiltAngle:this.#S,mode:this.#b,resizeMode:this.#_,stretchFactors:{...this.#P},fullcircle:this.#D,maxUndoSteps:this.#x,world:this.#G?{left:this.#G.left,right:this.#G.right,top:this.#G.top,bottom:this.#G.bottom,scaleX:this.#G.scaleX,scaleY:this.#G.scaleY}:null,canvas:{width:this.#t.width,height:this.#t.height,imageSmoothing:this.#C,imageSmoothingQuality:this.#z}})))}_setstate(e){this.#i=e.x,this.#s=e.y,this.#a=e.angle,this.#r=e.isDown,this.#o=e.drawSpeed,this.#l=e.pencolor,this.#h=e.penSize,this.#c=e.visible,this.#u=e.turtleSize,this.#y=e.shape,this.#p=e.filling,this.#f=e.fillcolor,this.#S=e.tiltAngle,this.#_=e.resizeMode,this.#D=e.fullcircle,this.#B=e.undobuffersize,this.#P=e.stretchFactors,this.#x=e.maxUndoSteps}async update(){return this.#F((()=>{this._update()}))}#te(e,t,n="none"){const i=(t.right-t.left)/(e.right-e.left),s=(t.bottom-t.top)/(e.bottom-e.top);let a=0,r=0;return"origin"===n?n=[0,0]:"center"===n?n=[(e.right-e.left)/2,(e.bottom-e.top)/2]:"topleft"===n?n=[e.left,e.top]:"bottomright"===n?n=[e.right,e.bottom]:"bottomleft"===n?n=[e.left,e.bottom]:"topright"===n&&(n=[e.right,e.top]),"none"!==n&&(a=(n[0]-e.left)*i-n[0],r=(n[1]-e.top)*s-n[1]),{scaleX:i,scaleY:s,translateX:a,translateY:r}}#U(e,t){return!(!e||!t)&&(e.left===t.left&&e.right===t.right&&e.top===t.top&&e.bottom===t.bottom)}#ne(e,t,n="none"){const{scaleX:i,scaleY:s,translateX:a,translateY:r}=this.#te(e,t,n);return{scaleX:i,scaleY:s,translateX:a,translateY:r}}_update(){if(this.#L){this.#X(),this.#n.clearRect(0,0,this.#t.width,this.#t.height),this.#O.length>0&&"snapshot"===this.#O[0].type&&this.#n.putImageData(this.#O[0].imageData,0,0),this.#q.naturalWorldCoordinates(),this.#n.save();for(const e of this.#v)this.#U(e.worldCoordinates,this.#G)||(e.path=this.#J(e.points),e.worldCoordinates={...this.#G}),e.path&&(this.#n.strokeStyle=e.color,this.#n.lineWidth=e.penSize,this.#n.stroke(e.path)),e.do_fill_path&&(this.#n.fillStyle=e.fillColor,this.#n.fill(e.do_fill_path));this.#n.restore(),this.#c&&this.#V(),this.#L=!1}}#J(e){if(!e||e.length<2)return null;const t=new Path2D,[n,i]=this.#Y(e[0][0],e[0][1]);t.moveTo(n,i);for(let n=1;n<e.length;n++){const[i,s]=this.#Y(e[n][0],e[n][1]);t.lineTo(i,s)}return t}#ie(e,t,n,i){return this.#J([[e,t],[n,i]])}#j(e,t,n,i=!1,s=!1){if(!e)return;const[a,r]=s?[t,n]:this.#Y(t,n);let o=i;e.path||(e.path=new Path2D,o=!0),this.#r||(o=!0),o?e.path.moveTo(a,r):e.path.lineTo(a,r),this.#p&&this.#w&&(i?this.#w.moveTo(a,r):this.#w.lineTo(a,r),e.fillPath=new Path2D(this.#w)),e.x=this.#i,e.y=this.#s,e.angle=this.#a,e.isDown=this.#r,e.color=this.#l,e.penSize=this.#h,e.isVisible=this.#c,e.fillcolor=this.#f,e.filling=this.#p,e.points=e.points||[],e.isDown&&e.points.push([t,n])}#Q(e){e.x=this.#i,e.y=this.#s,e.angle=this.#a,e.isDown=this.#r,e.color=this.#l,e.penSize=this.#h,e.isVisible=this.#c,e.worldCoordinates={...this.#G},e.resizeMode=this.#_,e.stretchFactors={...this.#P},e.fillcolor=this.#f,e.filling=this.#p}}class h{#t;#n;#se=new Set;#e=n.delay;#I=n.colormode;#ae=n.colormode_keep_names;#b=n.mode;#re=n.title;#G=null;#T=new Map;#g;#oe;#le=null;constructor(e,t=n){this.#t=e,this.#n=e.getContext("2d",{willReadFrequently:!0});const i=this.naturalWorldCoordinates();this.#G={left:i.left,bottom:i.bottom,right:i.right,top:i.top,scaleX:i.scaleX,scaleY:i.scaleY},this.#b=t.mode,this.#e=t.delay,this.#I=t.colormode,this.#ae=t.colormode_keep_names,this.#re=t.title,this.#g=t.shapes,this.#oe=t.imageRendering,this.imageRendering(this.#oe)}naturalWorldCoordinates(){return{left:-this.#t.width/2,bottom:-this.#t.height/2,right:this.#t.width/2,top:this.#t.height/2,scaleX:1,scaleY:1}}canvasWorldCoordinates(){return{left:0,top:0,right:this.#t.width,bottom:this.#t.height,scaleX:1,scaleY:1}}imageRendering(e=null){if(null===e)return this.#oe;if(!["auto","high-performance","crisp-edges","pixelated"].includes(e))throw new Error("imageRendering() expects 'auto', 'high-performance', 'crisp-edges', or 'pixelated'");this.#oe=e,this.#t.style.imageRendering&&this.#t.style.imageRendering===e||(this.#t.style.imageRendering=e)}async bgcolor(...e){if(0===e.length)return this._user_color(this.#t.style.backgroundColor);if(3===e.length)this.#t.style.backgroundColor=this._color_arg_normalize(e);else{if(1!==e.length)throw new Error("bgcolor() expects 0, 1, or 3 arguments");this.#t.style.backgroundColor=this._color_arg_normalize(e[0])}}async bgpic(e=null){return null===e?this.#le?this.#le.src:"nopic":"nopic"===e?(this.#le&&(this.#le=null),"nopic"):new Promise(((t,n)=>{const i=new Image;i.onload=()=>{this.#le=i,t(e)},i.onerror=()=>{n(new Error(`Failed to load image: ${e}`))},i.src=e}))}async screensize(e=null,t=null,n=null){return null!==e&&null!==t&&(this.#t.width=e,this.#t.height=t),null!==n&&(this.#t.style.backgroundColor=n),[this.#t.width,this.#t.height]}async setworldcoordinates(e,t,n,i){this.#G={left:e,bottom:t,right:n,top:i,scaleX:this.#t.width/(n-e),scaleY:this.#t.height/(i-t)},this.#se.forEach((e=>e._setworldcoordinates()))}listen(){this.#t.tabIndex=0,this.#t.focus()}onkey(e=null,t=null){if(null===e)return void(t?(document.removeEventListener("keyup",this.#T.get(t)),this.#T.delete(t)):(this.#T.forEach(((e,t)=>{document.removeEventListener("keyup",e)})),this.#T.clear()));const n={space:" ",return:"Enter",tab:"Tab",backspace:"Backspace",delete:"Delete",escape:"Escape",up:"ArrowUp",down:"ArrowDown",left:"ArrowLeft",right:"ArrowRight"}[t.toLowerCase()]||t.toLowerCase(),i=t=>{t.key.toLowerCase()===n.toLowerCase()&&e()};this.#T.set(t,i),document.addEventListener("keyup",i)}mode(e=null){if(null===e)return this.#b;["standard","logo","world"].includes(e)&&(this.#b=e,this.#se.forEach((t=>t._updateMode(e))))}colormode(e=null){if(null===e)return this.#I;this.#I=e}colormode_keep_names(e=null){if(null===e)return this.#ae;this.#ae=e}getcanvas(){return this.#t}getshapes(){return Object.keys(this.#g)}register_shape(e,t){this.#g[e]=t}addshape(e,t){return this.register_shape(e,t)}turtles(){return Array.from(this.#se)}window_height(){return this.#t.height}window_width(){return this.#t.width}title(e=null){return null===e?document.title:(document.title=e,e)}addTurtle(e){this.#se.add(e)}removeTurtle(e){this.#se.delete(e)}getShape(e){return this.#g[e]}getWorldCoordinates(){return{...this.#G}}async delay(e=null){if(null===e)return this.#e;this.#e=e}async tracer(e=null,t=null){console.warn("tracer() is not yet implemented")}async update(){console.warn("update() is not yet implemented")}async clearscreen(){this.#n.clearRect(0,0,this.#t.width,this.#t.height),this.#se.forEach((e=>e._home()))}async resetscreen(){await this.clearscreen();const e=this.naturalWorldCoordinates();this.setworldcoordinates(e.left,e.top,e.right,e.bottom)}async onclick(e,t=1,n=null){if(!e)return this.#t.onclick=null,void(this.#t.onauxclick=null);const i=t=>{const n=this.#t.getBoundingClientRect(),i=t.clientX-n.left,s=t.clientY-n.top,[a,r]=this._screenToWorld(i,s);e(a,r)};if(1===t)if(n){const e=this.#t.onclick;this.#t.onclick=t=>{e&&e(t),i(t)}}else this.#t.onclick=i;else if(2===t||3===t)if(n){const e=this.#t.onauxclick;this.#t.onauxclick=n=>{n.button===(2===t?1:2)&&(e&&e(n),i(n))}}else this.#t.onauxclick=e=>{e.button===(2===t?1:2)&&i(e)}}onrelease(e,t=1,n=!1){let i=this;if(!e)return void(this.#t.onmouseup=null);const s=n=>{if(n.button!==t-1)return;const s=i.#t.getBoundingClientRect(),a=n.clientX-s.left,r=n.clientY-s.top,[o,l]=i._screenToWorld(a,r);e(o,l)};if(n){const e=this.#t.onmouseup;this.#t.onmouseup=t=>{e&&e(t),s(t)}}else this.#t.onmouseup=s}onscreenclick(e,t=1,n=null){return this.onclick(e,t,n)}ondrag(e,t=1,n=!1){let i=this;if(!e)return void(this.#t.onmousemove=null);const s=n=>{if(!(n.buttons&1<<t-1))return;const s=i.#t.getBoundingClientRect(),a=n.clientX-s.left,r=n.clientY-s.top,[o,l]=i._screenToWorld(a,r);e(o,l)};if(n){const e=this.#t.onmousemove;this.#t.onmousemove=t=>{e&&e(t),s(t)}}else this.#t.onmousemove=s}ontimer(e,t=0){setTimeout(e,t)}async textinput(e,t){return t(t,"")}async numinput(e,t,n=null,i=null,s=null){let a;for(;;){const e=t(t,null!==n?n.toString():"");if(null===e)return null;if(a=parseFloat(e),isNaN(a))alert("Not a number");else if(null!==i&&a<i)alert(`Minimum value is ${i}`);else{if(!(null!==s&&a>s))break;alert(`Maximum value is ${s}`)}}return a}async bye(){this.#se.clear(),this.#T.clear(),this.#t.parentNode&&this.#t.parentNode.removeChild(this.#t)}async exitonclick(){let e=this;const t=()=>{e.bye(),e.#t.removeEventListener("click",t)};this.#t.addEventListener("click",t)}async setup(e=n.width,t=n.height,i=null,s=null){"number"==typeof e&&e<=1&&(e=Math.floor(window.innerWidth*e)),"number"==typeof t&&t<=1&&(t=Math.floor(window.innerHeight*t)),this.#t.width=e,this.#t.height=t,null!==i&&null!==s&&(this.#t.style.position="absolute",this.#t.style.left=`${i}px`,this.#t.style.top=`${s}px`),this.setworldcoordinates(-e/2,-t/2,e/2,t/2)}_screenToWorld(e,t){return[e/this.#G.scaleX+this.#G.left,-(t/this.#G.scaleY-this.#G.top)]}_worldToScreen(e,t){return[(e-this.#G.left)*this.#G.scaleX,(this.#G.top-t)*this.#G.scaleY]}_color_arg_normalize(t){if(null===t)return null;let n;if(Array.isArray(t)){if(3!==t.length)throw new Error("Color arrays must have exactly 3 elements");n=1===this.#I?t.map((e=>Math.round(255*e))):t.map(Math.floor)}else if("string"==typeof t){if(t=t.trim(),e[t])return e[t];if((t=t.replace(" ","")).startsWith("#")&&7===t.length)return t;if(!t.startsWith("rgb"))return t;n=t.slice(4,-1).split(",").map((e=>parseInt(e.trim())))}else{if("number"!=typeof t)return"#000000";n=[255&t,t>>8&255,t>>16&255]}return n=n.map((e=>Math.max(0,Math.min(255,e)))),"#"+n.map((e=>e.toString(16).padStart(2,"0"))).join("")}_user_color(e){if("string"==typeof e&&!e.startsWith("#"))return e;if("string"!=typeof e)throw new Error("_user_color() expects a string");if(this.#ae)return t[e];let n=e.slice(1).match(/.{1,2}/g).map((e=>parseInt(e,16)));return 1===this.#I?n.map((e=>Math.round(1e4*e/255)/1e4)):n}}let c,u=null,d=null;function g(){return null===d&&(d=new h(function(e=!1){let t;if(s)t=o.createElement("canvas"),t.width=n.canvwidth,t.height=n.canvheight,t.style.backgroundColor=n.bgcolor,e&&o.body.appendChild(t);else{if(!a&&void 0===OffscreenCanvas)throw new Error("No canvas support in this environment");t=new OffscreenCanvas(n.width,n.height)}return t}(!0),n)),d}function y(){return null===u&&(u=new l(g())),u}function p(e){if(!(e instanceof l))throw new Error("setDefaultTurtle() expects a Turtle instance");u=e,w(e.getscreen())}function w(e){if(!(e instanceof h))throw new Error("setDefaultScreen() expects a Screen instance");d=e}function f(e=r){for(const[t,n]of Object.entries(c))"function"!=typeof n&&"class"!=typeof n||(e[t]=n)}const m={Turtle:l,Screen:h,forward:async e=>await y().forward(e),fd:async e=>await y().fd(e),backward:async e=>await y().backward(e),bk:async e=>await y().bk(e),back:async e=>await y().back(e),right:async e=>await y().right(e),rt:async e=>await y().rt(e),left:async e=>await y().left(e),lt:async e=>await y().left(e),goto:async(e,t)=>await y().goto(e,t),setpos:async(e,t)=>await y().setpos(e,t),setposition:async(e,t)=>await y().setposition(e,t),teleport:async(e,t)=>await y().teleport(e,t),setx:async e=>await y().setx(e),sety:async e=>await y().sety(e),setheading:async e=>await y().setheading(e),seth:async e=>await y().seth(e),home:async()=>await y().home(),circle:async(e,t)=>await y().circle(e,t),dot:async(e,t)=>await y().dot(e,t),stamp:async()=>await y().stamp(),clearstamp:async e=>await y().clearstamp(e),clearstamps:async e=>await y().clearstamps(e),undo:async()=>await y().undo(),speed:async e=>await y().speed(e),position:async()=>await y().position(),pos:async()=>await y().pos(),towards:async(e,t)=>await y().towards(e,t),xcor:async()=>await y().xcor(),ycor:async()=>await y().ycor(),heading:async()=>await y().heading(),distance:async(e,t)=>await y().distance(e,t),degrees:async()=>await y().degrees(),radians:async()=>await y().radians(),pendown:async()=>await y().pendown(),pd:async()=>await y().pd(),down:async()=>await y().down(),penup:async()=>await y().penup(),pu:async()=>await y().pu(),up:async()=>await y().up(),pensize:async e=>y().pensize(e),width:async e=>y().width(e),pen:async e=>await y().pen(e),isdown:async()=>await y().isdown(),color:async(...e)=>await y().color(...e),pencolor:async(...e)=>await y().pencolor(...e),fillcolor:async(...e)=>await y().fillcolor(...e),filling:async()=>await y().filling(),begin_fill:async()=>await y().begin_fill(),end_fill:async()=>await y().end_fill(),reset:async()=>await y().reset(),clear:async()=>await y().clear(),write:async(e,t,n,i)=>await y().write(e,t,n,i),showturtle:async()=>await y().showturtle(),st:async()=>await y().st(),hideturtle:async()=>await y().hideturtle(),ht:async()=>await y().ht(),isvisible:async()=>await y().isvisible(),shape:async e=>await y().shape(e),resizemode:async e=>await y().resizemode(e),shapesize:async(e,t,n)=>await y().shapesize(e,t,n),turtlesize:async(e,t,n)=>await y().turtlesize(e,t,n),shearfactor:async(e,t)=>await y().shearfactor(e,t),tiltangle:async e=>await y().tiltangle(e),tilt:async e=>await y().tilt(e),shapetransform:async(e,t)=>await y().shapetransform(e,t),get_shapepoly:async e=>await y().get_shapepoly(e),onclick:async(e,t,n)=>await y().onclick(e,t,n),onrelease:async(e,t,n)=>await g().onrelease(e,t,n),ondrag:async(e,t,n)=>await g().ondrag(e,t,n),begin_poly:async()=>await y().begin_poly(),end_poly:async()=>await y().end_poly(),get_poly:async()=>await y().get_poly(),clone:async()=>await y().clone(),getturtle:async()=>await y().getturtle(),getpen:async()=>await y().getpen(),getscreen:async()=>await y().getscreen(),setundobuffer:async e=>await y().setundobuffer(e),undobufferentries:async()=>await y().undobufferentries(),bgcolor:async(...e)=>await g().bgcolor(...e),bgpic:async e=>await g().bgpic(e),clearscreen:async()=>await g().clearscreen(),resetscreen:async()=>await g().resetscreen(),screensize:async(e,t,n)=>await g().screensize(e,t,n),setworldcoordinates:async(e,t,n,i)=>await g().setworldcoordinates(e,t,n,i),delay:async e=>await g().delay(e),tracer:async(e,t)=>await g().tracer(e,t),update:async()=>await g().update(),listen:async()=>await g().listen(),onkey:async(e,t)=>await g().onkey(e,t),onkeyrelease:async(e,t)=>await g().onkeyrelease(e,t),onkeypress:async(e,t)=>await g().onkeypress(e,t),onscreenclick:async(e,t,n)=>await g().onscreenclick(e,t,n),ontimer:async(e,t)=>await g().ontimer(e,t),mainloop:async()=>Promise.accept(),done:async()=>Promise.accept(),mode:async e=>await g().mode(e),colormode:async e=>await g().colormode(e),getcanvas:async()=>await g().getcanvas(),getshapes:async()=>await g().getshapes(),register_shape:async(e,t)=>await g().register_shape(e,t),addshape:async(e,t)=>await g().addshape(e,t),turtles:async()=>await g().turtles(),window_height:async()=>await g().window_height(),window_width:async()=>await g().window_width(),textinput:async(e,t)=>await g().textinput(e,t),numinput:async(e,t,n,i,s)=>await g().numinput(e,t,n,i,s),bye:async()=>await g().bye(),exitonclick:async()=>await g().exitonclick(),setup:async(e,t,n,i)=>await g().setup(e,t,n,i),title:async e=>await g().title(e),colormode_keep_names:async e=>await g().colormode_keep_names(e),imageRendering:async e=>await g().imageRendering(e),setDefaultTurtle:p,setDefaultScreen:w,export_turtle_globals:f,getShape:async e=>await g().getShape(e),getWorldCoordinates:async()=>await g().getWorldCoordinates(),addTurtle:async e=>await g().addTurtle(e),removeTurtle:async e=>await g().removeTurtle(e)};c=m;const k=m.forward,S=m.fd,b=m.backward,v=m.bk,x=m.back,_=m.right,P=m.rt,T=m.left,M=m.lt,D=m.goto,C=m.setpos,z=m.setposition,q=m.teleport,B=m.setx,O=m.sety,L=m.setheading,G=m.seth,R=m.home,A=m.pendown,I=m.pd,E=m.down,W=m.penup,V=m.pu,F=m.up,Y=m.pensize,H=m.width,X=m.pen,U=m.isdown,N=m.color,j=m.pencolor,Q=m.fillcolor,$=m.filling,K=m.begin_fill,J=m.end_fill,Z=m.circle,ee=m.dot,te=m.stamp,ne=m.clearstamp,ie=m.clearstamps,se=m.write,ae=m.position,re=m.pos,oe=m.towards,le=m.xcor,he=m.ycor,ce=m.heading,ue=m.distance,de=m.degrees,ge=m.radians,ye=m.reset,pe=m.clear,we=m.showturtle,fe=m.st,me=m.hideturtle,ke=m.ht,Se=m.isvisible,be=m.shape,ve=m.resizemode,xe=m.shapesize,_e=m.turtlesize,Pe=m.tiltangle,Te=m.tilt,Me=m.onclick,De=m.onrelease,Ce=m.ondrag,ze=m.listen,qe=m.onkey,Be=m.onkeyrelease,Oe=m.onkeypress,Le=m.onscreenclick,Ge=m.ontimer,Re=m.begin_poly,Ae=m.end_poly,Ie=m.get_poly,Ee=m.clone,We=m.getturtle,Ve=m.getpen,Fe=m.getscreen,Ye=m.setundobuffer,He=m.undobufferentries,Xe=m.undo,Ue=m.bgcolor,Ne=m.bgpic,je=m.clearscreen,Qe=m.resetscreen,$e=m.screensize,Ke=m.setworldcoordinates,Je=m.delay,Ze=m.tracer,et=m.update,tt=m.mode,nt=m.colormode,it=m.getcanvas,st=m.getshapes,at=m.register_shape,rt=m.addshape,ot=m.turtles,lt=m.window_height,ht=m.window_width,ct=m.title,ut=m.textinput,dt=m.numinput,gt=m.bye,yt=m.exitonclick,pt=m.setup,wt=m.mainloop,ft=m.done,mt=m.colormode_keep_names,kt=m.imageRendering;"undefined"!=typeof module&&module.exports&&(module.exports=m),e="\nalice blue 240 248 255\nAliceBlue 240 248 255\nantique whi 250 235 215\nAntiqueWhit 250 235 215\nAntiqueWhit 255 239 219\nAntiqueWhit 238 223 204\nAntiqueWhit 205 192 176\nAntiqueWhit 139 131 120\nagua 0 255 255\naquamarine 127 255 212\naquamarine1 127 255 212\naquamarine2 118 238 198\naquamarine3 102 205 170\naquamarine4 69 139 116\nazure 240 255 255\nazure1 240 255 255\nazure2 224 238 238\nazure3 193 205 205\nazure4 131 139 139\nbeige 245 245 220\nbisque 255 228 196\nbisque1 255 228 196\nbisque2 238 213 183\nbisque3 205 183 158\nbisque4 139 125 107\nblack 0 0 0\nblanched al 255 235 205\nBlanchedAlm 255 235 205\nblue 0 0 255\nblue violet 138 43 226\nblue1 0 0 255\nblue2 0 0 238\nblue3 0 0 205\nblue4 0 0 139\nBlueViolet 138 43 226\nbrown 165 42 42\nbrown1 255 64 64\nbrown2 238 59 59\nbrown3 205 51 51\nbrown4 139 35 35\nburlywood 222 184 135\nburlywood1 255 211 155\nburlywood2 238 197 145\nburlywood3 205 170 125\nburlywood4 139 115 85\ncadet blue 95 158 160\nCadetBlue 95 158 160\nCadetBlue1 152 245 255\nCadetBlue2 142 229 238\nCadetBlue3 122 197 205\nCadetBlue4 83 134 139\nchartreuse 127 255 0\nchartreuse1 127 255 0\nchartreuse2 118 238 0\nchartreuse3 102 205 0\nchartreuse4 69 139 0\nchocolate 210 105 30\nchocolate1 255 127 36\nchocolate2 238 118 33\nchocolate3 205 102 29\nchocolate4 139 69 19\ncoral 255 127 80\ncoral1 255 114 86\ncoral2 238 106 80\ncoral3 205 91 69\ncoral4 139 62 47\ncornflower 100 149 237\nCornflowerB 100 149 237\ncornsilk 255 248 220\ncornsilk1 255 248 220\ncornsilk2 238 232 205\ncornsilk3 205 200 177\ncornsilk4 139 136 120\ncrymson 220 20 60\ncyan 0 255 255\ncyan1 0 255 255\ncyan2 0 238 238\ncyan3 0 205 205\ncyan4 0 139 139\ndark blue 0 0 139\ndark cyan 0 139 139\ndark golden 184 134 11\ndark gray 169 169 169\ndark green 0 100 0\ndark grey 169 169 169\ndark khaki 189 183 107\ndark magent 139 0 139\ndark olive 85 107 47\ndark orange 255 140 0\ndark orchid 153 50 204\ndark red 139 0 0\ndark salmon 233 150 122\ndark sea gr 143 188 143\ndark slate 72 61 139\ndark slate 47 79 79\ndark slate 47 79 79\ndark turquo 0 206 209\ndark violet 148 0 211\nDarkBlue 0 0 139\nDarkCyan 0 139 139\nDarkGoldenr 184 134 11\nDarkGoldenr 255 185 15\nDarkGoldenr 238 173 14\nDarkGoldenr 205 149 12\nDarkGoldenr 139 101 8\nDarkGray 169 169 169\nDarkGreen 0 100 0\nDarkGrey 169 169 169\nDarkKhaki 189 183 107\nDarkMagenta 139 0 139\nDarkOliveGr 85 107 47\nDarkOliveGr 202 255 112\nDarkOliveGr 188 238 104\nDarkOliveGr 162 205 90\nDarkOliveGr 110 139 61\nDarkOrange 255 140 0\nDarkOrange1 255 127 0\nDarkOrange2 238 118 0\nDarkOrange3 205 102 0\nDarkOrange4 139 69 0\nDarkOrchid 153 50 204\nDarkOrchid1 191 62 255\nDarkOrchid2 178 58 238\nDarkOrchid3 154 50 205\nDarkOrchid4 104 34 139\nDarkRed 139 0 0\nDarkSalmon 233 150 122\nDarkSeaGree 143 188 143\nDarkSeaGree 193 255 193\nDarkSeaGree 180 238 180\nDarkSeaGree 155 205 155\nDarkSeaGree 105 139 105\nDarkSlateBl 72 61 139\nDarkSlateGr 47 79 79\nDarkSlateGr 151 255 255\nDarkSlateGr 141 238 238\nDarkSlateGr 121 205 205\nDarkSlateGr 82 139 139\nDarkSlateGr 47 79 79\nDarkTurquoi 0 206 209\nDarkViolet 148 0 211\ndeep pink 255 20 147\ndeep sky bl 0 191 255\nDeepPink 255 20 147\nDeepPink1 255 20 147\nDeepPink2 238 18 137\nDeepPink3 205 16 118\nDeepPink4 139 10 80\nDeepSkyBlue 0 191 255\nDeepSkyBlue 0 191 255\nDeepSkyBlue 0 178 238\nDeepSkyBlue 0 154 205\nDeepSkyBlue 0 104 139\ndim gray 105 105 105\ndim grey 105 105 105\nDimGray 105 105 105\nDimGrey 105 105 105\ndodger blue 30 144 255\nDodgerBlue 30 144 255\nDodgerBlue1 30 144 255\nDodgerBlue2 28 134 238\nDodgerBlue3 24 116 205\nDodgerBlue4 16 78 139\nfirebrick 178 34 34\nfirebrick1 255 48 48\nfirebrick2 238 44 44\nfirebrick3 205 38 38\nfirebrick4 139 26 26\nfloral whit 255 250 240\nFloralWhite 255 250 240\nforest gree 34 139 34\nForestGreen 34 139 34\nfuchsia 255 0 255\ngainsboro 220 220 220\nghost white 248 248 255\nGhostWhite 248 248 255\ngold 255 215 0\ngold1 255 215 0\ngold2 238 201 0\ngold3 205 173 0\ngold4 139 117 0\ngoldenrod 218 165 32\ngoldenrod1 255 193 37\ngoldenrod2 238 180 34\ngoldenrod3 205 155 29\ngoldenrod4 139 105 20\ngray 128 128 128\ngray0 0 0 0\ngray1 3 3 3\ngray2 5 5 5\ngray3 8 8 8\ngray4 10 10 10\ngray5 13 13 13\ngray6 15 15 15\ngray7 18 18 18\ngray8 20 20 20\ngray9 23 23 23\ngray10 26 26 26\ngray11 28 28 28\ngray12 31 31 31\ngray13 33 33 33\ngray14 36 36 36\ngray15 38 38 38\ngray16 41 41 41\ngray17 43 43 43\ngray18 46 46 46\ngray19 48 48 48\ngray20 51 51 51\ngray21 54 54 54\ngray22 56 56 56\ngray23 59 59 59\ngray24 61 61 61\ngray25 64 64 64\ngray26 66 66 66\ngray27 69 69 69\ngray28 71 71 71\ngray29 74 74 74\ngray30 77 77 77\ngray31 79 79 79\ngray32 82 82 82\ngray33 84 84 84\ngray34 87 87 87\ngray35 89 89 89\ngray36 92 92 92\ngray37 94 94 94\ngray38 97 97 97\ngray39 99 99 99\ngray40 102 102 102\ngray41 105 105 105\ngray42 107 107 107\ngray43 110 110 110\ngray44 112 112 112\ngray45 115 115 115\ngray46 117 117 117\ngray47 120 120 120\ngray48 122 122 122\ngray49 125 125 125\ngray50 127 127 127\ngray51 130 130 130\ngray52 133 133 133\ngray53 135 135 135\ngray54 138 138 138\ngray55 140 140 140\ngray56 143 143 143\ngray57 145 145 145\ngray58 148 148 148\ngray59 150 150 150\ngray60 153 153 153\ngray61 156 156 156\ngray62 158 158 158\ngray63 161 161 161\ngray64 163 163 163\ngray65 166 166 166\ngray66 168 168 168\ngray67 171 171 171\ngray68 173