├── favicon.png ├── img ├── car.png └── background.png ├── screenshot.png ├── css └── main.css ├── manifest.json ├── js ├── aux.js ├── Perceptron.js ├── main.js └── data.js ├── LICENSE ├── index.html ├── sw.js └── README.md /favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victorqribeiro/carGamePerceptron/HEAD/favicon.png -------------------------------------------------------------------------------- /img/car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victorqribeiro/carGamePerceptron/HEAD/img/car.png -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victorqribeiro/carGamePerceptron/HEAD/screenshot.png -------------------------------------------------------------------------------- /img/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victorqribeiro/carGamePerceptron/HEAD/img/background.png -------------------------------------------------------------------------------- /css/main.css: -------------------------------------------------------------------------------- 1 | html, body{ 2 | margin: 0; 3 | padding: 0; 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | height: 100%; 8 | } 9 | canvas{ 10 | max-width: 100%; 11 | background: url('../img/background.png') center center no-repeat; 12 | background-size: cover; 13 | } 14 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carGamePerceptron", 3 | "short_name": "carGamePerceptron", 4 | "description": "A Neural Network experiment", 5 | "start_url": "index.html", 6 | "display": "standalone", 7 | "orientation": "portrait", 8 | "background_color": "#FFF", 9 | "theme_color": "#FFF", 10 | "icons": [ 11 | { 12 | "src": "favicon.png", 13 | "sizes": "256x256", 14 | "type": "image/png", 15 | "density": 1 16 | }, 17 | { 18 | "src": "favicon.png", 19 | "sizes": "512x512", 20 | "type": "image/png", 21 | "density": 1 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /js/aux.js: -------------------------------------------------------------------------------- 1 | if('serviceWorker' in navigator) { 2 | navigator.serviceWorker 3 | .register('/carGamePerceptron/sw.js', {scope: './'}) 4 | .then(response => response) 5 | .catch(reason => reason); 6 | } 7 | 8 | let deferredPrompt; 9 | const addBtn = document.createElement('button'); 10 | 11 | window.addEventListener('beforeinstallprompt', (e) => { 12 | e.preventDefault(); 13 | deferredPrompt = e; 14 | addBtn.style.display = 'block'; 15 | addBtn.addEventListener('click', (e) => { 16 | addBtn.style.display = 'none'; 17 | deferredPrompt.prompt(); 18 | deferredPrompt.userChoice.then((choiceResult) => { 19 | deferredPrompt = null; 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /js/Perceptron.js: -------------------------------------------------------------------------------- 1 | class Perceptron { 2 | 3 | constructor(size, learningRate, iterations){ 4 | this.weights = Array(++size).fill(0); 5 | this.lr = learningRate || 0.01; 6 | this.it = iterations || 10; 7 | } 8 | 9 | predict(inputs){ 10 | let activation = this.weights[0]; 11 | for(let i = 0; i < inputs.length; i++){ 12 | activation += this.weights[i+1] * inputs[i]; 13 | } 14 | return activation >= 0 ? 1 : 0; 15 | } 16 | 17 | fit(input, target){ 18 | let prediction, error, it = 0; 19 | while(it < this.it){ 20 | for(let i=0; i < input.length; i++){ 21 | prediction = this.predict( input[i] ); 22 | error = target[i] - prediction; 23 | this.weights[0] += this.lr * error; 24 | for(let j=0; j < input[i].length; j++){ 25 | this.weights[j+1] += this.lr * error * input[i][j]; 26 | } 27 | } 28 | it += 1; 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Victor Ribeiro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | carGamePerceptron 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /sw.js: -------------------------------------------------------------------------------- 1 | const filesToCache = [ 2 | './', 3 | './index.html', 4 | './js/main.js', 5 | './js/data.js', 6 | './js/Perceptron.js', 7 | './css/main.css', 8 | './img/car.png', 9 | './img/background.png', 10 | './favicon.png', 11 | './manifest.json' 12 | ]; 13 | 14 | const staticCacheName = 'carGamePerceptron-v1'; 15 | 16 | self.addEventListener('install', event => { 17 | event.waitUntil( 18 | caches.open(staticCacheName) 19 | .then(cache => { 20 | return cache.addAll(filesToCache); 21 | }) 22 | ); 23 | }); 24 | 25 | self.addEventListener('fetch', event => { 26 | event.respondWith( 27 | caches.match(event.request) 28 | .then(response => { 29 | if (response) { 30 | return response; 31 | } 32 | 33 | return fetch(event.request) 34 | 35 | .then(response => { 36 | return caches.open(staticCacheName).then(cache => { 37 | cache.put(event.request.url, response.clone()); 38 | return response; 39 | }); 40 | }); 41 | 42 | }).catch(error => {}) 43 | ); 44 | }); 45 | 46 | self.addEventListener('activate', event => { 47 | 48 | const cacheWhitelist = [staticCacheName]; 49 | 50 | event.waitUntil( 51 | caches.keys().then(cacheNames => { 52 | return Promise.all( 53 | cacheNames.map(cacheName => { 54 | if (cacheWhitelist.indexOf(cacheName) === -1) { 55 | return caches.delete(cacheName); 56 | } 57 | }) 58 | ); 59 | }) 60 | ); 61 | }); 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Excuse me, would you let my Neural Network drive? 3 | 4 | A Neural Network experiment involving a JavaScript game: can a perceptron drive a car? 5 | 6 | [![Scrap](http://img.youtube.com/vi/g0WV3qWcVuA/0.jpg)](http://www.youtube.com/watch?v=g0WV3qWcVuA) 7 | 8 | A live version of the code is hosted [here](https://victorribeiro.com/carGamePerceptron) 9 | 10 | # About 11 | 12 | Not so long ago I published the [simplest perceptron you'll ever see](https://github.com/victorqribeiro/perceptron), code I wrote after a machine learning class, a while back. Ever since that I've been meaning to do something cool with it. So, browsing some [more old codes](http://jsfiddle.net/user/victorqribeiro) I found a [little game](https://github.com/victorqribeiro/carGame) I made when I was studing fake 3D perspective, so I thought: can my perceptron play this game? 13 | 14 | So I gave the game code a little brushing, wrote some more code to capture the data of me playing it (I played until I got a score of 33 points) and feed it to my neural net. After that I just played with the learning rate and iterations and let it play the game on it's own. 15 | 16 | A [Neuroevolution](https://en.wikipedia.org/wiki/Neuroevolution) you say? Yes, I thought about that. I have a fully conected multilayer perceptron, that I'm about to realease, So I'm saving the ideia of evolving a neural net with genetic algorithm for that. 17 | 18 | Quick reminder that the game is not fair. Sometimes two cars comes in parallel with each other, so not even a human could beat it. 19 | 20 | # Questions? 21 | 22 | If you have any questions about the code or how I implemented it, or even how I got the data to feed the neural network (features), please feel free to contact me. (I left some comments on the code) 23 | -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | /* nn stuff */ 2 | 3 | const nn = new Perceptron( x[0].length, 0.01, 15000 ); 4 | 5 | nn.fit( x, y ); 6 | 7 | /* game stuff */ 8 | 9 | const size = Math.min(innerWidth, innerHeight); 10 | const canvas = document.createElement("canvas"); 11 | canvas.width = w = size; 12 | canvas.height = h = size; 13 | const c = canvas.getContext("2d"); 14 | 15 | c.translate(w/2,h-h/2.5); 16 | 17 | document.body.appendChild(canvas); 18 | const car = new Image(), fov = 300; 19 | 20 | let points = [], score = 0, p, colide; 21 | 22 | /* 23 | let i, _x, _y; 24 | */ 25 | 26 | function init(){ 27 | 28 | /* 29 | i = 0; 30 | _x = []; 31 | _y = []; 32 | */ 33 | 34 | car.src = 'img/car.png'; 35 | car.onload = ()=>draw(); 36 | 37 | points = []; 38 | score = 0; 39 | 40 | for(let i = 0; i < 2; i++){ 41 | points.push({ 42 | x: Math.random() > 0.5 ? -40 : 5, 43 | y: 0, 44 | z: Math.random()*200, 45 | w: 30, 46 | speed: Math.random() + 0.5 47 | }); 48 | } 49 | 50 | p = { 51 | x: 0, 52 | y: 0, 53 | z: -230, 54 | lane: 1, 55 | laneToBe: 1, 56 | isChangingLane: false, 57 | collide: function(r){ 58 | return ( (this.x > r.x && this.x < r.x+r.w) || 59 | (this.x+r.w > r.x && this.x+r.w < r.x+r.w) ) && 60 | (r.z > this.z && r.z < this.z+5); 61 | } 62 | }; 63 | 64 | 65 | } 66 | 67 | const _sort = (a,b)=>{ 68 | if(a.z < b.z){ 69 | return 1; 70 | }else if(b.z < a.z){ 71 | return -1; 72 | }else{ 73 | return 0; 74 | } 75 | }; 76 | 77 | function draw(){ 78 | 79 | points.sort( _sort ); 80 | 81 | /* this portion of the code get the data for training the neural network every 30 frames 82 | if(i % 30 == 0){ 83 | _x.push( [ points[1].x < 0 ? 0 : 1, points[1].z, points[1].speed, points[0].x < 0 ? 0 : 1, points[0].z, points[0].speed ] ); 84 | _y.push( p.lane ) 85 | } 86 | i++; 87 | */ 88 | 89 | if( p.lane != p.laneToBe){ 90 | p.isChangingLane = true; 91 | let x; 92 | if( p.laneToBe == 0 ){ 93 | x = -1; 94 | }else{ 95 | x = 1; 96 | } 97 | p.x += x; 98 | if( p.x == -35 ){ 99 | p.lane = 0; 100 | p.isChangingLane = false; 101 | }else if( p.x == 4 ){ 102 | p.lane = 1; 103 | p.isChangingLane = false; 104 | } 105 | } 106 | 107 | c.clearRect(-w,-h,w*2,h*2); 108 | colide = false; 109 | for(let i = 0; i < points.length; i++){ 110 | points[i].z -= points[i].speed; 111 | let s = fov / (fov+points[i].z); 112 | c.save(); 113 | c.scale(s,s); 114 | c.translate(points[i].x,points[i].y); 115 | c.drawImage(car,0,0,30,30); 116 | c.restore(); 117 | if(points[i].z < p.z-20){ 118 | points[i].z = 200; 119 | points[i].x = Math.random() > 0.5 ? -40 : 5; 120 | score++; 121 | } 122 | if(p.collide(points[i])){ 123 | colide = true; 124 | break; 125 | } 126 | } 127 | c.save(); 128 | let sp = fov / (fov + p.z); 129 | c.scale(sp,sp); 130 | c.translate(p.x,p.y); 131 | c.drawImage(car,0,0,30,30); 132 | c.restore(); 133 | c.font = "30px Arial"; 134 | c.fillText("Score: "+score, -w/2+10, -h/2 ); 135 | 136 | const move = nn.predict( [ points[1].x < 0 ? 0 : 1, points[1].z, points[1].speed, points[0].x < 0 ? 0 : 1, points[0].z, points[0].speed ] ); 137 | 138 | if(!p.isChangingLane) 139 | p.laneToBe = move; 140 | 141 | if(!colide) 142 | requestAnimationFrame(draw); 143 | } 144 | 145 | document.body.addEventListener('click', function(){ 146 | if( colide ) 147 | init(); 148 | }); 149 | 150 | init(); 151 | -------------------------------------------------------------------------------- /js/data.js: -------------------------------------------------------------------------------- 1 | const x = [[0,104.98653759724385,0.508096235591929,0,169.88276536858967,1.1732416053556067], 2 | [0,89.74365052948579,0.508096235591929,0,134.6855172079217,1.1732416053556067], 3 | [0,74.50076346172773,0.508096235591929,0,99.48826904725335,1.1732416053556067], 4 | [0,59.25787639396974,0.508096235591929,0,64.29102088658495,1.1732416053556067], 5 | [0,29.09377272591675,1.1732416053556067,0,44.01498932621189,0.508096235591929], 6 | [0,-6.103475434751446,1.1732416053556067,0,28.77210225845404,0.508096235591929], 7 | [0,-41.30072359541965,1.1732416053556067,0,13.529215190696192,0.508096235591929], 8 | [0,-76.49797175608792,1.1732416053556067,0,-1.7136718770616728,0.508096235591929], 9 | [0,-111.69521991675633,1.1732416053556067,0,-16.956558944819534,0.508096235591929], 10 | [0,-146.8924680774245,1.1732416053556067,0,-32.19944601257738,0.508096235591929], 11 | [0,-182.08971623809248,1.1732416053556067,0,-47.44233308033523,0.508096235591929], 12 | [0,-217.28696439876046,1.1732416053556067,0,-62.68522014809308,0.508096235591929], 13 | [0,-77.92810721585113,0.508096235591929,1,197.6535167892888,1.1732416053556067], 14 | [0,-93.17099428360919,0.508096235591929,1,162.45626862862082,1.1732416053556067], 15 | [0,-108.41388135136725,0.508096235591929,1,127.25902046795282,1.1732416053556067], 16 | [0,-123.65676841912531,0.508096235591929,1,92.06177230728441,1.1732416053556067], 17 | [0,-138.89965548688306,0.508096235591929,1,56.864524146616056,1.1732416053556067], 18 | [0,-154.1425425546407,0.508096235591929,1,21.66727598594786,1.1732416053556067], 19 | [0,-169.38542962239833,0.508096235591929,1,-13.529972174720337,1.1732416053556067], 20 | [0,-184.62831669015597,0.508096235591929,1,-48.72722033538854,1.1732416053556067], 21 | [0,-199.8712037579136,0.508096235591929,1,-83.92446849605685,1.1732416053556067], 22 | [0,-215.11409082567124,0.508096235591929,1,-119.12171665672525,1.1732416053556067], 23 | [0,-230.35697789342888,0.508096235591929,1,-154.31896481739335,1.1732416053556067], 24 | [0,-245.5998649611865,0.508096235591929,1,-189.51621297806133,1.1732416053556067], 25 | [1,-224.71346113872931,1.1732416053556067,1,189.32997905256966,0.508096235591929], 26 | [1,174.08709198481202,0.508096235591929,0,190.6140671571552,1.1732416053556067], 27 | [0,155.41681899648722,1.1732416053556067,1,158.84420491705438,0.508096235591929], 28 | [0,120.21957083581914,1.1732416053556067,1,143.60131784929675,0.508096235591929], 29 | [0,85.02232267515073,1.1732416053556067,1,128.3584307815391,0.508096235591929], 30 | [0,49.82507451448242,1.1732416053556067,1,113.11554371378105,0.508096235591929], 31 | [0,14.627826353814221,1.1732416053556067,1,97.87265664602299,0.508096235591929], 32 | [0,-20.569421806853978,1.1732416053556067,1,82.62976957826493,0.508096235591929], 33 | [0,-55.766669967522176,1.1732416053556067,1,67.38688251050687,0.508096235591929], 34 | [0,-90.96391812819053,1.1732416053556067,1,52.143995442748974,0.508096235591929], 35 | [0,-126.16116628885894,1.1732416053556067,1,36.901108374991125,0.508096235591929], 36 | [0,-161.35841444952695,1.1732416053556067,1,21.658221307233276,0.508096235591929], 37 | [0,-196.55566261019493,1.1732416053556067,1,6.415334239475424,0.508096235591929], 38 | [0,-231.7529107708629,1.1732416053556067,1,-8.827552828282448,0.508096235591929], 39 | [1,-24.0704398960403,0.508096235591929,1,183.5746175250216,1.1732416053556067], 40 | [1,-39.31332696379815,0.508096235591929,1,148.37736936435363,1.1732416053556067], 41 | [1,-54.556214031555996,0.508096235591929,1,113.18012120368546,1.1732416053556067], 42 | [1,-69.79910109931393,0.508096235591929,1,77.98287304301705,1.1732416053556067], 43 | [1,-85.04198816707199,0.508096235591929,1,42.78562488234878,1.1732416053556067], 44 | [1,-100.28487523483005,0.508096235591929,1,7.588376721680582,1.1732416053556067], 45 | [1,-115.52776230258812,0.508096235591929,1,-27.608871438987617,1.1732416053556067], 46 | [1,-130.7706493703461,0.508096235591929,1,-62.806119599655815,1.1732416053556067], 47 | [1,-146.01353643810373,0.508096235591929,1,-98.00336776032421,1.1732416053556067], 48 | [1,-161.25642350586136,0.508096235591929,1,-133.20061592099256,1.1732416053556067], 49 | [1,-176.499310573619,0.508096235591929,1,-168.39786408166054,1.1732416053556067], 50 | [1,-203.59511224232853,1.1732416053556067,1,-191.74219764137663,0.508096235591929], 51 | [1,-238.7923604029965,1.1732416053556067,1,-206.98508470913427,0.508096235591929], 52 | [1,-222.2279717768919,0.508096235591929,1,176.535167892888,1.1732416053556067], 53 | [1,-237.47085884464954,0.508096235591929,1,141.33791973222003,1.1732416053556067], 54 | [1,106.14067157155178,1.1732416053556067,0,197.4595188220404,0.508096235591929], 55 | [1,70.94342341088337,1.1732416053556067,0,182.21663175428276,0.508096235591929], 56 | [1,35.74617525021514,1.1732416053556067,0,166.97374468652512,0.508096235591929], 57 | [1,0.5489270895469427,1.1732416053556067,0,151.7308576187675,0.508096235591929], 58 | [1,-34.64832107112126,1.1732416053556067,0,136.48797055100985,0.508096235591929], 59 | [1,-69.84556923178948,1.1732416053556067,0,121.24508348325202,0.508096235591929], 60 | [1,-105.04281739245789,1.1732416053556067,0,106.00219641549396,0.508096235591929], 61 | [1,-140.24006555312616,1.1732416053556067,0,90.7593093477359,0.508096235591929], 62 | [1,-175.43731371379414,1.1732416053556067,0,75.51642227997783,0.508096235591929], 63 | [1,-210.63456187446212,1.1732416053556067,0,60.27353521221983,0.508096235591929], 64 | [1,-245.8318100351301,1.1732416053556067,0,45.03064814446198,0.508096235591929], 65 | [0,29.78776107670413,0.508096235591929,0,169.49571826075442,1.1732416053556067], 66 | [0,14.54487400894628,0.508096235591929,0,134.29847010008643,1.1732416053556067], 67 | [0,-0.6980130588115832,0.508096235591929,0,99.1012219394181,1.1732416053556067], 68 | [0,-15.940900126569444,0.508096235591929,0,63.903973778749695,1.1732416053556067], 69 | [0,-31.183787194327294,0.508096235591929,0,28.7067256180815,1.1732416053556067], 70 | [0,-46.42667426208514,0.508096235591929,0,-6.490522542586697,1.1732416053556067], 71 | [0,-61.66956132984299,0.508096235591929,0,-41.6877707032549,1.1732416053556067], 72 | [0,-76.91244839760103,0.508096235591929,0,-76.88501886392316,1.1732416053556067], 73 | [0,-112.08226702459157,1.1732416053556067,0,-92.15533546535909,0.508096235591929], 74 | [0,-147.27951518525975,1.1732416053556067,0,-107.39822253311715,0.508096235591929], 75 | [0,-182.47676334592774,1.1732416053556067,0,-122.64110960087521,0.508096235591929], 76 | [0,-217.67401150659572,1.1732416053556067,0,-137.883996668633,0.508096235591929], 77 | [0,-153.12688373639062,0.508096235591929,0,197.6535167892888,1.1732416053556067], 78 | [0,-168.36977080414826,0.508096235591929,0,162.45626862862082,1.1732416053556067], 79 | [0,-183.6126578719059,0.508096235591929,0,127.25902046795282,1.1732416053556067], 80 | [0,-198.85554493966353,0.508096235591929,0,92.06177230728441,1.1732416053556067], 81 | [0,-214.09843200742117,0.508096235591929,0,56.864524146616056,1.1732416053556067], 82 | [0,-229.3413190751788,0.508096235591929,0,21.66727598594786,1.1732416053556067], 83 | [0,-244.58420614293644,0.508096235591929,0,-13.529972174720337,1.1732416053556067], 84 | [0,-48.72722033538854,1.1732416053556067,1,190.3461715237535,0.508096235591929], 85 | [0,-83.92446849605685,1.1732416053556067,1,175.10328445599586,0.508096235591929], 86 | [0,-119.12171665672525,1.1732416053556067,1,159.86039738823823,0.508096235591929], 87 | [0,-154.31896481739335,1.1732416053556067,1,144.6175103204806,0.508096235591929], 88 | [0,-189.51621297806133,1.1732416053556067,1,129.37462325272296,0.508096235591929], 89 | [0,-224.71346113872931,1.1732416053556067,1,114.13173618496492,0.508096235591929], 90 | [1,98.88884911720686,0.508096235591929,1,190.6140671571552,1.1732416053556067], 91 | [1,83.6459620494488,0.508096235591929,1,155.41681899648722,1.1732416053556067], 92 | [1,68.40307498169074,0.508096235591929,1,120.21957083581914,1.1732416053556067], 93 | [1,53.16018791393283,0.508096235591929,1,85.02232267515073,1.1732416053556067], 94 | [1,37.91730084617498,0.508096235591929,1,49.82507451448242,1.1732416053556067], 95 | [1,14.627826353814221,1.1732416053556067,1,22.674413778417133,0.508096235591929], 96 | [1,-20.569421806853978,1.1732416053556067,1,7.431526710659282,0.508096235591929], 97 | [1,-55.766669967522176,1.1732416053556067,1,-7.811360357098591,0.508096235591929], 98 | [1,-90.96391812819053,1.1732416053556067,1,-23.05424742485644,0.508096235591929], 99 | [1,-126.16116628885894,1.1732416053556067,1,-38.29713449261429,0.508096235591929], 100 | [1,-161.35841444952695,1.1732416053556067,1,-53.54002156037214,0.508096235591929], 101 | [1,-196.55566261019493,1.1732416053556067,1,-68.78290862813006,0.508096235591929], 102 | [1,-231.7529107708629,1.1732416053556067,1,-84.02579569588812,0.508096235591929], 103 | [1,-99.26868276364618,0.508096235591929,1,183.5746175250216,1.1732416053556067], 104 | [1,-114.51156983140424,0.508096235591929,1,148.37736936435363,1.1732416053556067], 105 | [1,-129.75445689916225,0.508096235591929,1,113.18012120368546,1.1732416053556067], 106 | [1,-144.99734396691989,0.508096235591929,1,77.98287304301705,1.1732416053556067], 107 | [1,-160.24023103467752,0.508096235591929,1,42.78562488234878,1.1732416053556067], 108 | [1,-175.48311810243516,0.508096235591929,1,7.588376721680582,1.1732416053556067], 109 | [1,-190.7260051701928,0.508096235591929,1,-27.608871438987617,1.1732416053556067], 110 | [1,-205.96889223795043,0.508096235591929,1,-62.806119599655815,1.1732416053556067], 111 | [1,-221.21177930570806,0.508096235591929,1,-98.00336776032421,1.1732416053556067], 112 | [1,-236.4546663734657,0.508096235591929,1,-133.20061592099256,1.1732416053556067], 113 | [1,-168.39786408166054,1.1732416053556067,1,198.47571129322424,0.508096235591929], 114 | [1,-203.59511224232853,1.1732416053556067,1,183.2328242254666,0.508096235591929], 115 | [1,-238.7923604029965,1.1732416053556067,1,167.98993715770897,0.508096235591929], 116 | [1,152.74705008995133,0.508096235591929,1,176.535167892888,1.1732416053556067], 117 | [1,137.5041630221937,0.508096235591929,1,141.33791973222003,1.1732416053556067], 118 | [1,106.14067157155178,1.1732416053556067,1,122.26127595443589,0.508096235591929], 119 | [1,70.94342341088337,1.1732416053556067,1,107.01838888667783,0.508096235591929], 120 | [1,35.74617525021514,1.1732416053556067,1,91.77550181891976,0.508096235591929], 121 | [1,0.5489270895469427,1.1732416053556067,1,76.5326147511617,0.508096235591929], 122 | [1,-34.64832107112126,1.1732416053556067,1,61.28972768340368,0.508096235591929], 123 | [1,-69.84556923178948,1.1732416053556067,1,46.046840615645834,0.508096235591929], 124 | [1,-105.04281739245789,1.1732416053556067,1,30.803953547887986,0.508096235591929], 125 | [1,-140.24006555312616,1.1732416053556067,1,15.561066480130137,0.508096235591929], 126 | [1,-175.43731371379414,1.1732416053556067,1,0.31817941237227476,0.508096235591929], 127 | [1,-210.63456187446212,1.1732416053556067,1,-14.924707655385587,0.508096235591929], 128 | [1,-245.8318100351301,1.1732416053556067,1,-30.167594723143438,0.508096235591929], 129 | [1,-45.41048179090129,0.508096235591929,1,169.49571826075442,1.1732416053556067], 130 | [1,-60.653368858659135,0.508096235591929,1,134.29847010008643,1.1732416053556067], 131 | [1,-75.89625592641715,0.508096235591929,1,99.1012219394181,1.1732416053556067], 132 | [1,-91.13914299417522,0.508096235591929,1,63.903973778749695,1.1732416053556067], 133 | [1,-106.38203006193328,0.508096235591929,1,28.7067256180815,1.1732416053556067], 134 | [1,-121.62491712969134,0.508096235591929,1,-6.490522542586697,1.1732416053556067], 135 | [1,-136.86780419744915,0.508096235591929,1,-41.6877707032549,1.1732416053556067], 136 | [1,-152.11069126520678,0.508096235591929,1,-76.88501886392316,1.1732416053556067], 137 | [1,-167.35357833296442,0.508096235591929,1,-112.08226702459157,1.1732416053556067], 138 | [1,-182.59646540072205,0.508096235591929,1,-147.27951518525975,1.1732416053556067], 139 | [1,-197.8393524684797,0.508096235591929,1,-182.47676334592774,1.1732416053556067], 140 | [1,-217.67401150659572,1.1732416053556067,1,-213.08223953623732,0.508096235591929], 141 | [1,-228.32512660399496,0.508096235591929,0,197.6535167892888,1.1732416053556067], 142 | [1,-243.5680136717526,0.508096235591929,0,162.45626862862082,1.1732416053556067], 143 | [0,127.25902046795282,1.1732416053556067,0,191.36236399493734,0.508096235591929], 144 | [0,92.06177230728441,1.1732416053556067,0,176.1194769271797,0.508096235591929], 145 | [0,56.864524146616056,1.1732416053556067,0,160.87658985942207,0.508096235591929], 146 | [0,21.66727598594786,1.1732416053556067,0,145.63370279166443,0.508096235591929], 147 | [0,-13.529972174720337,1.1732416053556067,0,130.3908157239068,0.508096235591929], 148 | [0,-48.72722033538854,1.1732416053556067,0,115.14792865614879,0.508096235591929], 149 | [0,-83.92446849605685,1.1732416053556067,0,99.90504158839073,0.508096235591929], 150 | [0,-119.12171665672525,1.1732416053556067,0,84.66215452063267,0.508096235591929], 151 | [0,-154.31896481739335,1.1732416053556067,0,69.4192674528746,0.508096235591929], 152 | [0,-189.51621297806133,1.1732416053556067,0,54.17638038511669,0.508096235591929], 153 | [0,-224.71346113872931,1.1732416053556067,0,38.93349331735884,0.508096235591929], 154 | [0,23.69060624960099,0.508096235591929,1,190.6140671571552,1.1732416053556067], 155 | [0,8.44771918184314,0.508096235591929,1,155.41681899648722,1.1732416053556067], 156 | [0,-6.795167885914733,0.508096235591929,1,120.21957083581914,1.1732416053556067], 157 | [0,-22.038054953672585,0.508096235591929,1,85.02232267515073,1.1732416053556067], 158 | [0,-37.280942021430434,0.508096235591929,1,49.82507451448242,1.1732416053556067], 159 | [0,-52.52382908918828,0.508096235591929,1,14.627826353814221,1.1732416053556067], 160 | [0,-67.76671615694619,0.508096235591929,1,-20.569421806853978,1.1732416053556067], 161 | [0,-83.00960322470425,0.508096235591929,1,-55.766669967522176,1.1732416053556067], 162 | [0,-98.25249029246231,0.508096235591929,1,-90.96391812819053,1.1732416053556067], 163 | [1,-126.16116628885894,1.1732416053556067,0,-113.49537736022037,0.508096235591929], 164 | [1,-161.35841444952695,1.1732416053556067,0,-128.7382644279784,0.508096235591929], 165 | [1,-196.55566261019493,1.1732416053556067,0,-143.98115149573604,0.508096235591929], 166 | [1,-231.7529107708629,1.1732416053556067,0,-159.22403856349368,0.508096235591929], 167 | [0,-174.4669256312513,0.508096235591929,1,183.5746175250216,1.1732416053556067], 168 | [0,-189.70981269900895,0.508096235591929,1,148.37736936435363,1.1732416053556067], 169 | [0,-204.95269976676659,0.508096235591929,1,113.18012120368546,1.1732416053556067], 170 | [0,-220.19558683452422,0.508096235591929,1,77.98287304301705,1.1732416053556067], 171 | [0,-235.43847390228186,0.508096235591929,1,42.78562488234878,1.1732416053556067], 172 | [1,7.588376721680582,1.1732416053556067,0,199.49190376440808,0.508096235591929], 173 | [1,-27.608871438987617,1.1732416053556067,0,184.24901669665044,0.508096235591929], 174 | [1,-62.806119599655815,1.1732416053556067,0,169.0061296288928,0.508096235591929], 175 | [1,-98.00336776032421,1.1732416053556067,0,153.76324256113517,0.508096235591929], 176 | [1,-133.20061592099256,1.1732416053556067,0,138.52035549337754,0.508096235591929], 177 | [1,-168.39786408166054,1.1732416053556067,0,123.27746842561976,0.508096235591929], 178 | [1,-203.59511224232853,1.1732416053556067,0,108.0345813578617,0.508096235591929], 179 | [1,-238.7923604029965,1.1732416053556067,0,92.79169429010364,0.508096235591929], 180 | [0,77.54880722234557,0.508096235591929,0,176.535167892888,1.1732416053556067], 181 | [0,62.30592015458754,0.508096235591929,0,141.33791973222003,1.1732416053556067], 182 | [0,47.06303308682969,0.508096235591929,0,106.14067157155178,1.1732416053556067], 183 | [0,31.820146019071842,0.508096235591929,0,70.94342341088337,1.1732416053556067], 184 | [0,16.577258951313993,0.508096235591929,0,35.74617525021514,1.1732416053556067], 185 | [0,0.5489270895469427,1.1732416053556067,0,1.3343718835561327,0.508096235591929], 186 | [0,-34.64832107112126,1.1732416053556067,0,-13.90851518420173,0.508096235591929], 187 | [0,-69.84556923178948,1.1732416053556067,0,-29.15140225195958,0.508096235591929], 188 | [0,-105.04281739245789,1.1732416053556067,0,-44.39428931971743,0.508096235591929], 189 | [0,-140.24006555312616,1.1732416053556067,0,-59.63717638747528,0.508096235591929], 190 | [0,-175.43731371379414,1.1732416053556067,0,-74.88006345523328,0.508096235591929], 191 | [0,-210.63456187446212,1.1732416053556067,0,-90.12295052299135,0.508096235591929], 192 | [0,-245.8318100351301,1.1732416053556067,0,-105.36583759074941,0.508096235591929], 193 | [0,-120.60872465850747,0.508096235591929,0,169.49571826075442,1.1732416053556067], 194 | [0,-135.8516117262653,0.508096235591929,0,134.29847010008643,1.1732416053556067], 195 | [0,-151.09449879402294,0.508096235591929,0,99.1012219394181,1.1732416053556067], 196 | [0,-166.33738586178058,0.508096235591929,0,63.903973778749695,1.1732416053556067], 197 | [0,-181.5802729295382,0.508096235591929,0,28.7067256180815,1.1732416053556067], 198 | [0,-196.82315999729585,0.508096235591929,0,-6.490522542586697,1.1732416053556067], 199 | [0,-212.06604706505348,0.508096235591929,0,-41.6877707032549,1.1732416053556067], 200 | [0,-227.30893413281112,0.508096235591929,0,-76.88501886392316,1.1732416053556067], 201 | [0,-242.55182120056875,0.508096235591929,0,-112.08226702459157,1.1732416053556067], 202 | [0,-147.27951518525975,1.1732416053556067,0,192.37855646612118,0.508096235591929], 203 | [0,-182.47676334592774,1.1732416053556067,0,177.13566939836355,0.508096235591929], 204 | [0,-217.67401150659572,1.1732416053556067,0,161.8927823306059,0.508096235591929], 205 | [0,146.64989526284828,0.508096235591929,0,197.6535167892888,1.1732416053556067], 206 | [0,131.40700819509064,0.508096235591929,0,162.45626862862082,1.1732416053556067], 207 | [0,116.16412112733266,0.508096235591929,0,127.25902046795282,1.1732416053556067], 208 | [0,92.06177230728441,1.1732416053556067,0,100.9212340595746,0.508096235591929], 209 | [0,56.864524146616056,1.1732416053556067,0,85.67834699181654,0.508096235591929], 210 | [0,21.66727598594786,1.1732416053556067,0,70.43545992405848,0.508096235591929], 211 | [0,-13.529972174720337,1.1732416053556067,0,55.19257285630054,0.508096235591929], 212 | [0,-48.72722033538854,1.1732416053556067,0,39.949685788542695,0.508096235591929], 213 | [0,-83.92446849605685,1.1732416053556067,0,24.706798720784846,0.508096235591929], 214 | [0,-119.12171665672525,1.1732416053556067,0,9.463911653026997,0.508096235591929], 215 | [0,-154.31896481739335,1.1732416053556067,0,-5.7789754147308745,0.508096235591929], 216 | [0,-189.51621297806133,1.1732416053556067,0,-21.02186248248873,0.508096235591929], 217 | [0,-224.71346113872931,1.1732416053556067,0,-36.26474955024658,0.508096235591929], 218 | [0,-51.507636618004426,0.508096235591929,0,190.6140671571552,1.1732416053556067], 219 | [0,-66.75052368576232,0.508096235591929,0,155.41681899648722,1.1732416053556067], 220 | [0,-81.99341075352038,0.508096235591929,0,120.21957083581914,1.1732416053556067], 221 | [0,-97.23629782127844,0.508096235591929,0,85.02232267515073,1.1732416053556067], 222 | [0,-112.4791848890365,0.508096235591929,0,49.82507451448242,1.1732416053556067], 223 | [0,-127.72207195679457,0.508096235591929,0,14.627826353814221,1.1732416053556067], 224 | [0,-142.9649590245522,0.508096235591929,0,-20.569421806853978,1.1732416053556067], 225 | [0,-158.20784609230984,0.508096235591929,0,-55.766669967522176,1.1732416053556067], 226 | [0,-173.45073316006747,0.508096235591929,0,-90.96391812819053,1.1732416053556067], 227 | [0,-188.6936202278251,0.508096235591929,0,-126.16116628885894,1.1732416053556067], 228 | [0,-203.93650729558274,0.508096235591929,0,-161.35841444952695,1.1732416053556067], 229 | [0,-219.17939436334038,0.508096235591929,0,-196.55566261019493,1.1732416053556067], 230 | [0,-234.422281431098,0.508096235591929,0,-231.7529107708629,1.1732416053556067], 231 | [0,-249.66516849885565,0.508096235591929,1,183.5746175250216,1.1732416053556067], 232 | [1,148.37736936435363,1.1732416053556067,0,185.26520916783429,0.508096235591929], 233 | [1,113.18012120368546,1.1732416053556067,0,170.02232210007665,0.508096235591929], 234 | [1,77.98287304301705,1.1732416053556067,0,154.77943503231901,0.508096235591929], 235 | [1,42.78562488234878,1.1732416053556067,0,139.53654796456138,0.508096235591929], 236 | [1,7.588376721680582,1.1732416053556067,0,124.29366089680363,0.508096235591929], 237 | [1,-27.608871438987617,1.1732416053556067,0,109.05077382904557,0.508096235591929], 238 | [1,-62.806119599655815,1.1732416053556067,0,93.8078867612875,0.508096235591929], 239 | [1,-98.00336776032421,1.1732416053556067,0,78.56499969352944,0.508096235591929], 240 | [1,-133.20061592099256,1.1732416053556067,0,63.322112625771396,0.508096235591929], 241 | [1,-168.39786408166054,1.1732416053556067,0,48.07922555801355,0.508096235591929], 242 | [1,-203.59511224232853,1.1732416053556067,0,32.8363384902557,0.508096235591929], 243 | [1,-238.7923604029965,1.1732416053556067,0,17.59345142249785,0.508096235591929], 244 | [0,2.3505643547399906,0.508096235591929,1,176.535167892888,1.1732416053556067], 245 | [0,-12.892322713017874,0.508096235591929,1,141.33791973222003,1.1732416053556067], 246 | [0,-28.135209780775725,0.508096235591929,1,106.14067157155178,1.1732416053556067], 247 | [0,-43.37809684853357,0.508096235591929,1,70.94342341088337,1.1732416053556067], 248 | [0,-58.62098391629142,0.508096235591929,1,35.74617525021514,1.1732416053556067], 249 | [0,-73.86387098404941,0.508096235591929,1,0.5489270895469427,1.1732416053556067], 250 | [0,-89.10675805180747,0.508096235591929,1,-34.64832107112126,1.1732416053556067], 251 | [0,-104.34964511956554,0.508096235591929,1,-69.84556923178948,1.1732416053556067], 252 | [0,-119.5925321873236,0.508096235591929,1,-105.04281739245789,1.1732416053556067], 253 | [1,-140.24006555312616,1.1732416053556067,0,-134.83541925508146,0.508096235591929], 254 | [1,-175.43731371379414,1.1732416053556067,0,-150.0783063228391,0.508096235591929], 255 | [1,-210.63456187446212,1.1732416053556067,0,-165.32119339059673,0.508096235591929], 256 | [1,-245.8318100351301,1.1732416053556067,0,-180.56408045835437,0.508096235591929], 257 | [0,-195.806967526112,0.508096235591929,0,169.49571826075442,1.1732416053556067], 258 | [0,-211.04985459386964,0.508096235591929,0,134.29847010008643,1.1732416053556067], 259 | [0,-226.29274166162728,0.508096235591929,0,99.1012219394181,1.1732416053556067], 260 | [0,-241.5356287293849,0.508096235591929,0,63.903973778749695,1.1732416053556067], 261 | [0,28.7067256180815,1.1732416053556067,0,193.39474893730502,0.508096235591929], 262 | [0,-6.490522542586697,1.1732416053556067,0,178.1518618695474,0.508096235591929], 263 | [0,-41.6877707032549,1.1732416053556067,0,162.90897480178975,0.508096235591929], 264 | [0,-76.88501886392316,1.1732416053556067,0,147.66608773403212,0.508096235591929], 265 | [0,-112.08226702459157,1.1732416053556067,0,132.42320066627448,0.508096235591929], 266 | [0,-147.27951518525975,1.1732416053556067,0,117.18031359851653,0.508096235591929], 267 | [0,-182.47676334592774,1.1732416053556067,0,101.93742653075847,0.508096235591929], 268 | [0,-217.67401150659572,1.1732416053556067,0,86.69453946300041,0.508096235591929], 269 | [0,71.45165239524235,0.508096235591929,0,197.6535167892888,1.1732416053556067], 270 | [0,56.2087653274844,0.508096235591929,0,162.45626862862082,1.1732416053556067], 271 | [0,40.96587825972655,0.508096235591929,0,127.25902046795282,1.1732416053556067], 272 | [0,25.722991191968703,0.508096235591929,0,92.06177230728441,1.1732416053556067], 273 | [0,10.480104124210854,0.508096235591929,0,56.864524146616056,1.1732416053556067], 274 | [0,-4.762782943547016,0.508096235591929,0,21.66727598594786,1.1732416053556067], 275 | [0,-20.005670011304872,0.508096235591929,0,-13.529972174720337,1.1732416053556067], 276 | [0,-48.72722033538854,1.1732416053556067,0,-35.24855707906272,0.508096235591929], 277 | [0,-83.92446849605685,1.1732416053556067,0,-50.49144414682057,0.508096235591929], 278 | [0,-119.12171665672525,1.1732416053556067,0,-65.73433121457845,0.508096235591929], 279 | [0,-154.31896481739335,1.1732416053556067,0,-80.97721828233651,0.508096235591929], 280 | [0,-189.51621297806133,1.1732416053556067,0,-96.22010535009457,0.508096235591929], 281 | [0,-224.71346113872931,1.1732416053556067,0,-111.46299241785263,0.508096235591929], 282 | [0,-126.7058794856107,0.508096235591929,1,190.6140671571552,1.1732416053556067], 283 | [0,-141.94876655336836,0.508096235591929,1,155.41681899648722,1.1732416053556067], 284 | [0,-157.191653621126,0.508096235591929,1,120.21957083581914,1.1732416053556067], 285 | [0,-172.43454068888363,0.508096235591929,1,85.02232267515073,1.1732416053556067], 286 | [0,-187.67742775664126,0.508096235591929,1,49.82507451448242,1.1732416053556067], 287 | [0,-202.9203148243989,0.508096235591929,1,14.627826353814221,1.1732416053556067], 288 | [0,-218.16320189215654,0.508096235591929,1,-20.569421806853978,1.1732416053556067], 289 | [0,-233.40608895991417,0.508096235591929,1,-55.766669967522176,1.1732416053556067], 290 | [0,-248.6489760276718,0.508096235591929,1,-90.96391812819053,1.1732416053556067], 291 | [1,-126.16116628885894,1.1732416053556067,1,186.28140163901813,0.508096235591929], 292 | [1,-161.35841444952695,1.1732416053556067,1,171.0385145712605,0.508096235591929], 293 | [1,-196.55566261019493,1.1732416053556067,1,155.79562750350286,0.508096235591929], 294 | [1,-231.7529107708629,1.1732416053556067,1,140.55274043574522,0.508096235591929], 295 | [1,125.3098533679875,0.508096235591929,1,183.5746175250216,1.1732416053556067], 296 | [1,110.06696630022944,0.508096235591929,1,148.37736936435363,1.1732416053556067], 297 | [1,94.82407923247138,0.508096235591929,1,113.18012120368546,1.1732416053556067], 298 | [1,77.98287304301705,1.1732416053556067,1,79.58119216471331,0.508096235591929], 299 | [1,42.78562488234878,1.1732416053556067,1,64.33830509695525,0.508096235591929], 300 | [1,7.588376721680582,1.1732416053556067,1,49.095418029197404,0.508096235591929], 301 | [1,-27.608871438987617,1.1732416053556067,1,33.852530961439555,0.508096235591929], 302 | [1,-62.806119599655815,1.1732416053556067,1,18.609643893681707,0.508096235591929], 303 | [1,-98.00336776032421,1.1732416053556067,1,3.366756825923849,0.508096235591929], 304 | [1,-133.20061592099256,1.1732416053556067,1,-11.876130241834018,0.508096235591929], 305 | [1,-168.39786408166054,1.1732416053556067,1,-27.119017309591868,0.508096235591929], 306 | [1,-203.59511224232853,1.1732416053556067,1,-42.36190437734972,0.508096235591929], 307 | [1,-238.7923604029965,1.1732416053556067,1,-57.604791445107566,0.508096235591929], 308 | [1,-72.84767851286554,0.508096235591929,0,176.535167892888,1.1732416053556067], 309 | [1,-88.0905655806236,0.508096235591929,0,141.33791973222003,1.1732416053556067], 310 | [1,-103.33345264838167,0.508096235591929,0,106.14067157155178,1.1732416053556067], 311 | [1,-118.57633971613973,0.508096235591929,0,70.94342341088337,1.1732416053556067], 312 | [1,-133.81922678389762,0.508096235591929,0,35.74617525021514,1.1732416053556067], 313 | [1,-149.06211385165525,0.508096235591929,0,0.5489270895469427,1.1732416053556067], 314 | [1,-164.3050009194129,0.508096235591929,0,-34.64832107112126,1.1732416053556067], 315 | [1,-179.54788798717053,0.508096235591929,0,-69.84556923178948,1.1732416053556067], 316 | [1,-194.79077505492816,0.508096235591929,0,-105.04281739245789,1.1732416053556067], 317 | [1,-210.0336621226858,0.508096235591929,0,-140.24006555312616,1.1732416053556067], 318 | [1,-225.27654919044343,0.508096235591929,0,-175.43731371379414,1.1732416053556067]]; 319 | 320 | const y = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, 321 | 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, 322 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 323 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 324 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1, 325 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 326 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1, 327 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, 328 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; 329 | --------------------------------------------------------------------------------