Guess the country Game 🐢

Every day you can guess a different country.

#game

Log in to post a comment.

const turtle = new Turtle();
const text = new Text();

const charDistance = (a, b) => a&&b ? Math.abs(a.charCodeAt(0) - b.charCodeAt(0)) / 25 : 1;
let guess = ''; // type=string, Guess the country 
guess = guess.toLowerCase();
const country = getCountry().toLowerCase();
const correct = guess === country;

const player = `M-38,54C-38,59 -41,65 -39,69C-37,72 -32,77 -29,74C-27,72 -25,69 -24,66C-22,63 -27,58 -24,55C-22,53 -19,55 -16,56C-13,57 -10,56 -7,56C-3,56 2,56 6,56C8,56 10,55 11,56C12,57 11,59 10,60C9,62 10,64 11,66C11,67 10,69 11,70C14,73 18,76 21,74C24,73 27,71 28,68C29,66 28,63 28,61C28,59 29,57 28,56C27,55 26,54 27,53C29,51 30,51 32,49C33,48 32,45 34,44C38,42 43,40 45,36C46,33 47,29 49,27C52,24 56,23 60,21C63,20 66,22 69,21C70,20 71,18 70,17C69,16 65,17 66,16C68,14 71,10 70,7C68,2 59,3 54,3C50,3 45,1 42,4C35,11 31,22 24,29C22,31 22,24 22,21C22,17 19,12 16,9C12,5 6,5 1,3C-9,-2 -21,-2 -31,0C-38,1 -44,6 -49,11C-54,16 -54,25 -56,32C-58,38 -58,46 -54,50C-49,55 -58,59 -58,59C-58,59 -55,59 -54,58C-50,56 -45,54 -40,54`; /// type=path, Draw your own player
const checkmark = `M-45,-22C-45,-15 -47,-7 -48,0C-49,9 -47,17 -48,26C-49,31 -49,35 -49,40C-49,41 -50,43 -49,44C-46,47 -40,44 -36,44C-27,44 -17,43 -8,43C-0,43 7,43 15,43C20,43 26,47 30,43C33,40 30,35 30,31C30,21 30,10 30,0C30,-5 30,-9 31,-14C32,-17 36,-23 33,-24C20,-27 6,-24 -8,-24C-16,-24 -24,-24 -32,-24C-36,-24 -43,-26 -45,-22C-46,-19 -43,-16 -41,-13C-37,-7 -32,-2 -27,4C-24,8 -21,13 -16,16C-14,17 -11,22 -10,20C-1,2 10,-17 24,-31C30,-37 35,-42 40,-48C42,-51 43,-56 47,-56`; /// type=path, Draw your own player

Canvas.setpenopacity(correct ? -1 : 1);
function walk() {
    let playerShape = new Shape(player);
    let checkmarkShape = new Shape(checkmark);
    
    let at = 0;
    if (!correct) {
        turtle.jump(-55, -85);
        text.print(turtle, 'Guess the country', 0.32);
        turtle.jump(-55, -75);
        text.print(turtle, `(${country.length} characters)`, 0.32/2);
        
        for(let char of country) {
            let guessChar = guess.charAt(at);
            let t = (at+1) / (country.length+1);
            let distance = charDistance(guessChar, char);
            let charIsCorrect = distance == 0;
            let charPos = [-55, 180 * (-0.5 + t) + 15]
            const charEndPos = [55, charPos[1]];
            let playerPos =  lerp2(charEndPos, charPos, distance);
            
            if (charIsCorrect) checkmarkShape.draw(add(playerPos, [5, -5]), 8, turtle);
            else playerShape.draw(add(playerPos, [0, -5]), lerp(8, 10, distance), turtle);
            
            if (!correct) for(let i=1;i<25;i++) {
                 let pos = lerp2(charEndPos, charPos, i/25);
                 turtle.jump(pos);
                 turtle.circle(charDistance(guessChar, char) > i/25 ? .3 : .5)
            }
            at++
        }
    }
    
    if (correct) {
        let finalPlayerPos = [0,0]
        checkmarkShape.draw(finalPlayerPos, 16, turtle);
        for(let a = 0;a<Math.PI*2;a+=0.001) {
            let d = 20 + (1-Math.random()*Math.random()) * 175;
            let ang = a - 3;
            let ang2 = ang + (-0.5 + (Math.random()*Math.random()))*0.03;
            let dist = Math.random() + 4.5;
            turtle.jump(add(finalPlayerPos, [Math.sin(ang) * d, Math.cos(ang) * d]));
            turtle.goto(add(finalPlayerPos, [Math.sin(ang2) * (d+dist), Math.cos(ang2) * (d+dist)]));
            turtle.goto(add(finalPlayerPos, [Math.sin(ang) * (d+dist), Math.cos(ang) * (d+dist)]));
            turtle.goto(add(finalPlayerPos, [Math.sin(ang) * d, Math.cos(ang) * d]));
        }
    }
}

function getCountry() {                                                                                                                             // lol, just dont look here ok?
    const all =                                                                                                                                     ["Afghanistan", "Albania", "Algeria", "Argentina", "Australia", "Austria", "Bangladesh", "Belgium", "Bolivia", "Brazil", "Bulgaria", "Canada", "Chile", "China", "Colombia", "Costa Rica", "Croatia", "Cuba", "Czech Republic", "Denmark", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Estonia", "Ethiopia", "Finland", "France", "Germany", "Ghana", "Greece", "Guatemala", "Haiti", "Honduras", "Hungary", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica", "Japan", "Jordan", "Kenya", "Kuwait", "Lebanon", "Libya", "Lithuania", "Malaysia", "Mexico", "Morocco", "Nepal", "Netherlands", "New Zealand", "Nigeria", "North Korea", "Norway", "Pakistan", "Panama", "Peru", "Philippines", "Poland", "Portugal", "Romania", "Russia", "Saudi Arabia", "Senegal", "Serbia", "Singapore", "South Africa", "South Korea", "Spain", "Sri Lanka", "Sweden", "Switzerland", "Syria", "Thailand", "Turkey", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Venezuela", "Vietnam", "Yemen", "Zimbabwe"];
    let random = Random(new Date().setHours(0, 0, 0, 0));
    return all[random()*all.length|0];
}

function Random(seed = Math.random()) {
    let rseed = seed;
    return () => {
        let r = 1103515245 * (((rseed) >> 1) ^ (rseed++));
        r = 1103515245 * (r ^ (r>>3));
        r = r ^ (r >> 16);
        return r / 1103515245 % 1;	
    }
}

////////////////////////////////////////////////////////////////
// Shape utility code. Created by Reinder Nijhoff 2024
// https://turtletoy.net/turtle/e4b2bf3db6
////////////////////////////////////////////////////////////////
class Shape {
    constructor(svg) {
        this.path = new Path(svg);
        let points = this.getPoints();
        
        // center
        const center = scale(points.reduce((a,c) => add(a, c), [0,0]), 1/points.length);
        points = points.map(p => sub(p, center));

        // normalize
        let radius = 0;
        points.forEach( p => radius = Math.max(radius, Math.hypot(p[0], p[1])));
        this.points = points.map(p => scale(p, 1/radius));
    }
    
    getPoints(count = 200) {
        return [...new Array(count)].map( (_, i) => this.path.p(i/(count-1)) );
    }
    
    // Gift wrapping algorithm
    // https://en.wikipedia.org/wiki/Gift_wrapping_algorithm
    getConvexHull(S) {
        S = S.filter( (p, i) => i % 4 === 0);
        S = [...S].sort( (a,b) => a[0] - b[0]);
        let pointOnHull = S[0], endpoint, i = 0;
        const P = [];
        
        do {
            P[i] = pointOnHull;
            endpoint = S[0]; 
            for (let j = 0; j < S.length; j++) {
                if( equal(endpoint, pointOnHull) || cross(sub(S[j], P[i]), sub(endpoint, P[i])) < 0 ) {
                    endpoint = S[j];   // found greater left turn, update endpoint
                }
            }
            i++;
            pointOnHull = [...endpoint];
        } while (!equal(endpoint, P[0]) && i < S.length);

        return P;
    }
    
    draw(center, size, turtle) {
        let points = this.points.map(p => add(scale(p, size), center));
        points.forEach((p,idx) => !idx ? turtle.jump(...p) : turtle.goto(...p));
    }
}

////////////////////////////////////////////////////////////////
// Path utility code. Created by Reinder Nijhoff 2023
// Parses a single SVG path (only M, C and L statements are
// supported). The p-method will return
// [...position, ...derivative] for a normalized point t.
//
// https://turtletoy.net/turtle/46adb0ad70
////////////////////////////////////////////////////////////////
function Path(svg) {
    class MoveTo {
        constructor(p) { this.p0 = p; }
        p(t, s) { return [...this.p0, 1, 0]; }
        length() { return 0; }
    }
    class LineTo {
        constructor(p0, p1) { this.p0 = p0, this.p1 = p1; }
        p(t, s = 1) {
            const nt = 1 - t, p0 = this.p0, p1 = this.p1;
            return [ 
                nt*p0[0] + t*p1[0],
                nt*p0[1] + t*p1[1],
                (p1[0] - p0[0]) * s,
                (p1[1] - p0[1]) * s,
            ];
        }
        length() { 
            const p0 = this.p0, p1 = this.p1;
            return Math.hypot(p0[0]-p1[0], p0[1]-p1[1]);
        }
    }
    class BezierTo {
        constructor(p0, c0, c1, p1) { this.p0 = p0, this.c0 = c0, this.c1 = c1, this.p1 = p1; }
        p(t, s = 1) {
            const nt = 1 - t, p0 = this.p0, c0 = this.c0, c1 = this.c1, p1 = this.p1;
            return [ 
                nt*nt*nt*p0[0] + 3*t*nt*nt*c0[0] + 3*t*t*nt*c1[0] + t*t*t*p1[0],
                nt*nt*nt*p0[1] + 3*t*nt*nt*c0[1] + 3*t*t*nt*c1[1] + t*t*t*p1[1],
                (3*nt*nt*(c0[0]-p0[0]) + 6*t*nt*(c1[0]-c0[0]) + 3*t*t*(p1[0]-c1[0])) * s,
                (3*nt*nt*(c0[1]-p0[1]) + 6*t*nt*(c1[1]-c0[1]) + 3*t*t*(p1[1]-c1[1])) * s,
            ];
        }
        length() {
            return this._length || (
                this._length = Array.from({length:25}, (x, i) => this.p(i/25)).reduce( 
                    (a,c,i,v) => i > 0 ? a + Math.hypot(c[0]-v[i-1][0], c[1]-v[i-1][1]) : a, 0));
        }
    }
    class Path {
        constructor(svg) {
            this.segments = [];
            this.parsePath(svg);
        }
        parsePath(svg) {
            const t = svg.match(/([0-9.-]+|[MLC])/g);
            for (let s, i=0; i<t.length;) {
                switch (t[i++]) {
                    case 'M': this.add(new MoveTo(s=[t[i++],t[i++]]));
                              break;
                    case 'L': this.add(new LineTo(s, s=[t[i++],t[i++]]));
                              break;
                    case 'C': this.add(new BezierTo(s, [t[i++],t[i++]], [t[i++],t[i++]], s=[t[i++],t[i++]]));
                              break;
                    default:  i++;
                }
            }
        }
        add(segment) {
            this.segments.push(segment);
            this._length = 0;
        }
        length() {
            return this._length || (this._length = this.segments.reduce((a,c) => a + c.length(), 0));
        }
        p(t) {
            t = Math.max(Math.min(t, 1), 0) * this.length();
            for (let l=0, i=0, sl=0; i<this.segments.length; i++, l+=sl) {
                sl = this.segments[i].length();
                if (t > l && t <= l + sl) {
                    return this.segments[i].p((t-l)/sl, sl/this.length());
                }
            }
            return this.segments[Math.min(1, this.segments.length-1)].p(0);
        }
    }
    return new Path(svg);
}


// 
// 2D Vector math
//
function cross(a, b) { return a[0]*b[1]-a[1]*b[0]; }
function equal(a,b) { return .001>dist_sqr(a,b); }
function scale(a,b) { return [a[0]*b,a[1]*b]; }
function add(a,b) { return [a[0]+b[0],a[1]+b[1]]; }
function sub(a,b) { return [a[0]-b[0],a[1]-b[1]]; }
function dot(a,b) { return a[0]*b[0]+a[1]*b[1]; }
function dist_sqr(a,b) { return (a[0]-b[0])**2+(a[1]-b[1])**2; }
function dist(a,b) { return Math.sqrt(dist_sqr(a,b)); }
function length(a) { return Math.sqrt(dot(a,a)); }
function lerp(a,b,t) { return a + (b-a) * t }
function lerp2(a,b,t) { return [lerp(a[0],b[0],t),lerp(a[1],b[1],t)] }
function normalize(a) { return scale(a, 1/length(a)); }
function transform(a, mat) { return [a[0] * mat[0] + a[1] * mat[2], a[0] * mat[1] + a[1] * mat[3]]; }


////////////////////////////////////////////////////////////////
// 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();}