const [lineTurtle, textTurtle] = [new Turtle(), new Turtle()];
textTurtle.radians();

const text = new Text();
const prev = {x: 0, y: 0};
const scaleX = 8; // min=1, max=20, step=0.5
const scaleY = 8; // min=1, max=20, step=0.5

const mode = 3; // min=0, max=3, step=1 (Both, Text only, Lines Only, Prime Numbers)

function walk(i) {
    let nr = i+1; // 1 based
    let {x, y} = spiral(nr);
    
    x *= scaleX;
    y *= scaleY;
    
    if (mode != 1) lineTurtle.goto(x, y);
    
    const angle = Math.atan2(prev.y - y, prev.x - x);
    if (mode <= 1) {
        textTurtle.jump(x, y);
        textTurtle.setheading(angle);
        text.print(textTurtle, `${i}`, .1, 0, 0.875);
    }
    
    if (mode == 3 && isPrime(nr)) {
        textTurtle.jump(x, y-0.75);
        textTurtle.circle(0.75);
    }
    
    prev.x = x;
    prev.y = y;
    
    return Math.abs(x) < 125 || Math.abs(y) < 125;
}

function isPrime(number) {
    if (number < 2) return false;
    for (let i = 2; i <= Math.sqrt(number); i++) {
        if (number % i === 0) return false;
    }
    return true;
}

// source from https://medium.com/acrossthegalaxy/grid-spiral-search-formula-3b476bfdd2df
function spiral(n) {
    const k = Math.ceil((Math.sqrt(n) - 1.0) / 2.0);
    const t = 2.0 * k;
    let m = (t + 1) * (t + 1);
    if (n >= m - t) {
        return {x: k - (m - n), y: -k};
    } else {
        m = m - t;
    }
    
    if (n >= m - t) {
        return {x: -k, y: -k + (m - n)};
    } else {
        m = m - t;
    }
    
    if (n >= m - t) {
        return {x: -k + (m - n), y: k};
    } else {
        return {x: k, y: k - (m - n - t)};
    }
}


////////////////////////////////////////////////////////////////
// Text utility code. Created by Reinder Nijhoff 2019
// https://turtletoy.net/turtle/1713ddbe99
// Jurgen 2021: Fixed Text.print() to restore turtle._fullCircle
//.             if was in e.g. degrees mode (or any other)
////////////////////////////////////////////////////////////////
function Text() {class Text {print (t, str, scale = 1, italic = 0, kerning = 1) {let fc = t._fullCircle;t.radians();let pos = [t.x(), t.y()], h = t.h(), o = pos;str.split('').map(c => {const i = c.charCodeAt(0) - 32;if (i < 0 ) {pos = o = this.rotAdd([0, 48*scale], o, h);} else if (i > 96 ) {pos = this.rotAdd([16*scale, 0], o, h);} else {const d = dat[i], lt = d[0]*scale, rt = d[1]*scale, paths = d[2];paths.map( p => {t.up();p.map( s=> {t.goto(this.rotAdd([(s[0]-s[1]*italic)*scale - lt, s[1]*scale], pos, h));t.down();});});pos = this.rotAdd([(rt - lt)*kerning, 0], pos, h);}});t._fullCircle = fc;}rotAdd (a, b, h) {return [Math.cos(h)*a[0] - Math.sin(h)*a[1] + b[0], Math.cos(h)*a[1] + Math.sin(h)*a[0] + b[1]];}}const dat = ('br>eoj^jl<jqirjskrjq>brf^fe<n^ne>`ukZdz<qZjz<dgrg<cmqm>`thZhw<lZlw<qao_l^h^e_caccdeefggmiojpkqmqporlshsercp>^vs^as<f^h`hbgdeeceacaab_d^f^h_k`n`q_s^<olmmlolqnspsrrspsnqlol>]wtgtfsereqfphnmlpjrhsdsbraq`o`makbjifjekckaj_h^f_eaecffhimporqssstrtq>eoj`i_j^k_kajcid>cqnZl\\j_hcghglhqjulxnz>cqfZh\\j_lcmhmllqjuhxfz>brjdjp<egom<ogem>]wjajs<ajsj>fnkojpiojnkokqis>]wajsj>fnjniojpkojn>_usZaz>`ti^f_dbcgcjdofrisksnrpoqjqgpbn_k^i^>`tfbhak^ks>`tdcdbe`f_h^l^n_o`pbpdofmicsqs>`te^p^jfmfogphqkqmppnrkshserdqco>`tm^clrl<m^ms>`to^e^dgefhekenfphqkqmppnrkshserdqco>`tpao_l^j^g_ebdgdlepgrjsksnrppqmqlpingkfjfggeidl>`tq^gs<c^q^>`th^e_dadceegfkgnhpjqlqopqorlshserdqcocldjfhigmfoepcpao_l^h^>`tpeohmjjkikfjdhcecddaf_i^j^m_oapepjoomrjshserdp>fnjgihjikhjg<jniojpkojn>fnjgihjikhjg<kojpiojnkokqis>^vrabjrs>]wagsg<amsm>^vbarjbs>asdcdbe`f_h^l^n_o`pbpdofngjijl<jqirjskrjq>]xofndlcicgdfeehekfmhnknmmnk<icgefhfkgmhn<ocnknmpnrntluiugtdsbq`o_l^i^f_d`bbad`g`jambodqfrislsorqqrp<pcokompn>asj^bs<j^rs<elol>_tc^cs<c^l^o_p`qbqdpfoglh<chlhoipjqlqopqorlscs>`urcqao_m^i^g_eadccfckdnepgrismsorqprn>_tc^cs<c^j^m_oapcqfqkpnopmrjscs>`sd^ds<d^q^<dhlh<dsqs>`rd^ds<d^q^<dhlh>`urcqao_m^i^g_eadccfckdnepgrismsorqprnrk<mkrk>_uc^cs<q^qs<chqh>fnj^js>brn^nnmqlrjshsfreqdndl>_tc^cs<q^cl<hgqs>`qd^ds<dsps>^vb^bs<b^js<r^js<r^rs>_uc^cs<c^qs<q^qs>_uh^f_daccbfbkcndpfrhslsnrppqnrkrfqcpan_l^h^>_tc^cs<c^l^o_p`qbqepgohlici>_uh^f_daccbfbkcndpfrhslsnrppqnrkrfqcpan_l^h^<koqu>_tc^cs<c^l^o_p`qbqdpfoglhch<jhqs>`tqao_l^h^e_caccdeefggmiojpkqmqporlshsercp>brj^js<c^q^>_uc^cmdpfrisksnrppqmq^>asb^js<r^js>^v`^es<j^es<j^os<t^os>`tc^qs<q^cs>asb^jhjs<r^jh>`tq^cs<c^q^<csqs>cqgZgz<hZhz<gZnZ<gznz>cqc^qv>cqlZlz<mZmz<fZmZ<fzmz>brj\\bj<j\\rj>asazsz>fnkcieigjhkgjfig>atpeps<phnfleiegfehdkdmepgrislsnrpp>`sd^ds<dhffhekemfohpkpmopmrkshsfrdp>asphnfleiegfehdkdmepgrislsnrpp>atp^ps<phnfleiegfehdkdmepgrislsnrpp>asdkpkpiognfleiegfehdkdmepgrislsnrpp>eqo^m^k_jbjs<gene>atpepuoxnylzizgy<phnfleiegfehdkdmepgrislsnrpp>ate^es<eihfjemeofpips>fni^j_k^j]i^<jejs>eoj^k_l^k]j^<kekvjyhzfz>are^es<oeeo<ikps>fnj^js>[y_e_s<_ibfdegeifjijs<jimfoeretfuius>ateees<eihfjemeofpips>atiegfehdkdmepgrislsnrppqmqkphnfleie>`sdedz<dhffhekemfohpkpmopmrkshsfrdp>atpepz<phnfleiegfehdkdmepgrislsnrpp>cpgegs<gkhhjfleoe>bsphofleieffehfjhkmlompopporlsisfrep>eqj^jokrmsos<gene>ateeeofrhsksmrpo<peps>brdejs<pejs>_ubefs<jefs<jens<rens>bseeps<pees>brdejs<pejshwfydzcz>bspees<eepe<esps>cqlZj[i\\h^h`ibjckekgii<j[i]i_jakbldlfkhgjkllnlpkrjsiuiwjy<ikkmkojqirhthvixjylz>fnjZjz>cqhZj[k\\l^l`kbjcieigki<j[k]k_jaibhdhfihmjilhnhpirjskukwjy<kkimiojqkrltlvkxjyhz>^vamakbhdgfghhlknlplrksi<akbidhfhhillnmpmrlsisg>brb^bscsc^d^dsese^f^fsgsg^h^hsisi^j^jsksk^l^lsmsm^n^nsoso^p^psqsq^r^rs').split('>').map(r=> { return [r.charCodeAt(0)-106,r.charCodeAt(1)-106, r.substr(2).split('<').map(a => {const ret = []; for (let i=0; i<a.length; i+=2) {ret.push(a.substr(i, 2).split('').map(b => b.charCodeAt(0)-106));} return ret; })]; });return new Text();}