Spaces:
Sleeping
Sleeping
| // const API_URL = "http://127.0.0.1:8000/intelli-snake-2/" | |
| const API_URL = "https://intelli-snake-2-api.herokuapp.com/intelli-snake-2/" | |
| let loaded_infos = [] | |
| interval_var_fast = 0 | |
| let start_auto = 1 | |
| let mult = 1 | |
| // WRITING IN A FILE | |
| let file_writing = 0 | |
| let content = '' | |
| let data_line | |
| class Game { | |
| constructor () { | |
| // initializing constants and variables | |
| this.game_items = document.getElementsByClassName("game-item") | |
| this.info = { | |
| "map_type": "none", | |
| "map": 0, | |
| "parts": 2, | |
| "evade_bite": 0, | |
| "allowcollisions": 0, | |
| "score": 0, | |
| "fouls": 0, | |
| "interval_var": 0, | |
| "cache_dir": null, | |
| "prev_dir": null, | |
| "second_pref_count": 0, | |
| "mode": "paused", | |
| "steps": 0, | |
| "steps_limit": 60, | |
| "slow_time": 600, | |
| "fast_time": 200, | |
| "time": 200, | |
| "automated_infos_count": 50, | |
| "automated_time_update_freq": 1, | |
| "overflow_infos": 0, | |
| } | |
| // intializing the game | |
| this.get_map("fixed") | |
| btn_pause_auto.innerText = "Automate" | |
| } | |
| set_game_interval(func) { | |
| clearInterval(this.info.interval_var) | |
| this.info.interval_var = setInterval(func, this.info.time) | |
| } | |
| auto_key_move() { | |
| if (this.info.cache_dir != null) { | |
| if(game.move(this.info.cache_dir)) {this.info.prev_dir = this.info.cache_dir} | |
| else {game.move(this.info.prev_dir)} | |
| } | |
| } | |
| move(dir) { | |
| if (file_writing) {data_line = "\n" + JSON.stringify(this.info.map)} | |
| let h = this.info.map.indexOf(3) | |
| let n = 31*28 | |
| if (dir == 0) { n = h - cols } | |
| else if (dir == 1) { n = h - 1 } | |
| else if (dir == 2) { n = h + cols } | |
| else if (dir == 3) { n = h + 1 } | |
| // IF FOOD IS EATEN | |
| if (this.info.map[n] == 2) { | |
| this.info.score++ | |
| this.info.parts++ | |
| this.info.steps = 0 | |
| if (this.info.map_type == "random" && file_writing) { | |
| // LOADING NEW RANDOM MAP AFTER EATEN | |
| this.pause_game() | |
| this.get_map("random") | |
| return true | |
| } | |
| this.info.map[n] = this.info.parts+3 | |
| let r = Math.floor(Math.random() * (31*28)) | |
| while (this.info.map[r] != 0) { r = Math.floor(Math.random() * (31*28)) } | |
| this.info.map[r] = 2 | |
| this.pause_game() | |
| } | |
| // CHECKING FOR FOUL WHEN HIT THE WALL | |
| if (this.info.map[n] == 1 && this.info.allowcollisions) { this.info.fouls++ } | |
| // IF SNAKE HITS THE BODY | |
| if (this.info.map[n] > 4 && this.info.map[n] != this.info.parts+3 && !this.info.evade_bite) { | |
| let parts_to_remove = (this.info.parts+3) - this.info.map[n] | |
| for (let i=0; i<parts_to_remove; i++) { this.info.map[this.info.map.indexOf(this.info.parts-i+3)] = 0 } | |
| this.info.parts -= parts_to_remove | |
| this.info.fouls++ | |
| } | |
| // MOVING THE BODY | |
| if (this.can_move(n, dir)) { | |
| let cache_n; | |
| for (let part=0; part<=this.info.parts; part++) { | |
| cache_n = this.info.map.indexOf(3+part) | |
| this.info.map[this.info.map.indexOf(3+part)] = 0 | |
| this.info.map[n] = 3+part | |
| n = cache_n | |
| } | |
| this.update_map() | |
| this.info.steps++ | |
| if (this.info.steps > this.info.steps_limit) { btn_replace.click();this.info.steps=0;this.info.fouls++ } | |
| if (file_writing) { | |
| data_line += "," + String(dir) | |
| content += data_line | |
| } | |
| return true | |
| } else {return false} | |
| } | |
| can_move(next_step, dir) { | |
| let next_item = this.info.map[next_step] | |
| // IF SNAKE GOES OUT OF BOUNDARIES | |
| if (next_step < 0 || next_step > 31*28-1) {return false} | |
| if (dir == 1 && next_step % 28 == 27) {return false} | |
| if (dir == 3 && next_step % 28 == 0) {return false} | |
| // ILLEGAL STEP INSIDE THE BOUNDARIES | |
| switch (next_item) { | |
| case 0: return true | |
| case 1: if (this.info.allowcollisions) {return true} return false | |
| case 2: return true | |
| case 3: return false | |
| case 4: return false | |
| default: return true; | |
| } | |
| } | |
| automate_faster(time) { | |
| clearInterval(interval_var_fast) | |
| interval_var_fast = setInterval(() => { | |
| if (loaded_infos.length > 1) { | |
| this.info = loaded_infos[0] | |
| this.update_map() | |
| loaded_infos.shift() | |
| } else { console.log('\n ==== OUT OF INFOS ==== \n') } | |
| }, time); | |
| } | |
| load_automated_infos() { | |
| let time_i = Date.now() | |
| fetch(API_URL + `automate_faster-${JSON.stringify(loaded_infos[loaded_infos.length-1])}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| let returned_infos = JSON.parse(data) | |
| if (btn_fast_automation.innerText == "Fast Automation") {if(btn_guide.innerText == "Guide"){btn_fast_automation.disabled = false};return} | |
| loading.style.setProperty("visibility", "hidden") | |
| // adding more infos | |
| if (loaded_infos.length < 200 || this.info['overflow_infos']) {loaded_infos = loaded_infos.concat(returned_infos)} | |
| console.log("ADDED NEW INFOS") | |
| console.table(`infos count: ${loaded_infos.length}`) | |
| // Finding optimal time for interval | |
| let time_f = Date.now() | |
| let fast_time = (time_f - time_i)/(this.info.automated_infos_count*mult) | |
| if (this.info.automated_time_update_freq) { game.automate_faster(fast_time) } | |
| else {if (start_auto == 1) {game.automate_faster(fast_time); start_auto=0;}} | |
| console.log(`FAST TIME: ${fast_time}`) | |
| console.log("\n") | |
| this.load_automated_infos() | |
| }); | |
| } | |
| automate() { | |
| fetch(API_URL + `automate-${JSON.stringify(this.info)}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| let pred_dirs = JSON.parse(data) // predicted directions sorted by preference | |
| for (let i=0; i<4; i++) { if (this.move(pred_dirs[i])) { this.info.second_pref_count += i; break } } | |
| }); | |
| } | |
| get_map(map_type) { | |
| // getting the maps | |
| loading.style.setProperty("visibility", "visible") | |
| this.info.map_type = map_type | |
| this.info.steps = 0 | |
| fetch(API_URL + `map-${JSON.stringify(this.info)}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| this.info = JSON.parse(data) | |
| loading.style.setProperty("visibility", "hidden") | |
| this.update_map() | |
| }); | |
| } | |
| update_map() { | |
| // APPLYING LIST TO VISUAL GRID | |
| for (let i=0; i<rows*cols; i++) { | |
| this.game_items[i].classList.remove('wall') | |
| this.game_items[i].classList.remove('empty') | |
| this.game_items[i].classList.remove('food') | |
| this.game_items[i].classList.remove('head') | |
| this.game_items[i].classList.remove('body') | |
| switch (this.info.map[i]) { | |
| case 0: this.game_items[i].classList.add("empty"); break | |
| case 1: this.game_items[i].classList.add("wall"); break | |
| case 2: this.game_items[i].classList.add("food"); break | |
| case 3: this.game_items[i].classList.add("head"); break | |
| default: this.game_items[i].classList.add("body"); break | |
| } | |
| } | |
| // UPDATING THE BOARD | |
| score_span.innerText = this.info.score | |
| fouls_span.innerText = this.info.fouls | |
| steps_span.innerText = this.info.steps | |
| } | |
| pause_game() { | |
| clearInterval(this.info.interval_var) | |
| clearInterval(interval_var_fast) | |
| btn_fast_automation.innerText = "Fast Automation" | |
| btn_pause_auto.innerText = "Automate" | |
| this.info.mode = "paused" | |
| loaded_infos = [] | |
| start_auto = 1 | |
| this.info.cache_dir = null | |
| btn_next_map.disabled = false | |
| btn_speeder.disabled = false | |
| if (this.info.map_type == "fixed") {btn_collide.disabled = false} | |
| btn_replace.disabled = false | |
| // btn_fast_automation.disabled = false | |
| btn_pause_auto.disabled = false | |
| loading.style.setProperty("visibility", "hidden") | |
| } | |
| } | |
| let game = new Game() | |
| // KEYBOARD EVENTS | |
| document.onkeydown = (event)=> { | |
| // writing in a file | |
| if (event.key == 'Backspace' && file_writing) { | |
| content = '' | |
| } | |
| if (event.key == 'Enter' && file_writing) { | |
| fetch(API_URL + `write-${content}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| content = '' | |
| return | |
| }); | |
| } | |
| // controls | |
| if (event.key == 'ArrowRight') { game.info.cache_dir = 3 } | |
| if (event.key == 'ArrowLeft') { game.info.cache_dir = 1 } | |
| if (event.key == 'ArrowUp') { game.info.cache_dir = 0 } | |
| if (event.key == 'ArrowDown') { game.info.cache_dir = 2 } | |
| if (event.key == ' ') { game.pause_game(); return } | |
| if (game.info.mode == "paused") { | |
| // PLAY THE GAME WITH KEYS | |
| game.set_game_interval(()=>{ game.auto_key_move() }) | |
| game.info.mode = "key" | |
| } | |
| } | |
| // SWIPE EVENTS | |
| document.addEventListener('swiped-up', function(e) { document.onkeydown({key: 'ArrowUp'})} ); | |
| document.addEventListener('swiped-left', function(e) { document.onkeydown({key: 'ArrowLeft'})} ); | |
| document.addEventListener('swiped-down', function(e) { document.onkeydown({key: 'ArrowDown'})} ); | |
| document.addEventListener('swiped-right', function(e) { document.onkeydown({key: 'ArrowRight'})} ); | |
| // BUTTONS | |
| btn_fast_automation.onclick = ()=>{ | |
| if (btn_fast_automation.innerText == "Fast Automation") { | |
| game.pause_game() | |
| btn_fast_automation.innerText = "Pause" | |
| // FAST AUTOMATE | |
| loading.style.setProperty("visibility", "visible") | |
| loaded_infos = loaded_infos.concat(game.info) | |
| game.load_automated_infos(); | |
| btn_next_map.disabled = true | |
| btn_speeder.disabled = true | |
| btn_collide.disabled = true | |
| btn_replace.disabled = true | |
| } else { | |
| game.pause_game(); | |
| btn_fast_automation.disabled = true | |
| } | |
| } | |
| btn_pause_auto.onclick = () => { | |
| if (btn_pause_auto.innerText == "Automate") { | |
| if (btn_fast_automation.innerText == "Pause") {btn_fast_automation.disabled = true} | |
| game.pause_game() | |
| // AUTOMATE THE GAME | |
| btn_pause_auto.innerText = "Pause" | |
| game.set_game_interval(()=>{ game.automate() }) | |
| game.info.mode = "automated" | |
| btn_speeder.disabled = true | |
| } else {game.pause_game()} | |
| } | |
| btn_next_map.onclick = ()=>{ | |
| game.info.steps = 0 | |
| game.info.score = 0 | |
| game.info.fouls = 0 | |
| if (btn_next_map.innerText == "Random Map") { | |
| // GETTING RANDOM MAP | |
| game.get_map("random") | |
| btn_next_map.innerText = 'Fixed Map' | |
| btn_collide.innerText = 'Disable Collision' | |
| btn_collide.click() | |
| btn_collide.disabled = true | |
| } else { | |
| // GETTING FIXED MAP | |
| game.get_map("fixed") | |
| btn_next_map.innerText = 'Random Map' | |
| btn_collide.disabled = false | |
| } | |
| game.pause_game() | |
| } | |
| btn_speeder.onclick = () => { | |
| if (btn_speeder.innerText == 'Slower') { | |
| // SLOW IT | |
| game.info.time = game.info.slow_time | |
| btn_speeder.innerText = 'Faster' | |
| } else { | |
| // FAST IT | |
| game.info.time = game.info.fast_time | |
| btn_speeder.innerText = 'Slower' | |
| } | |
| if (game.info.mode == "automated") { | |
| game.pause_game() | |
| btn_pause_auto.click() | |
| } else if (game.info.mode == "key") { | |
| game.pause_game() | |
| } | |
| } | |
| btn_collide.onclick = () => { | |
| if (btn_collide.innerText == 'Enable Collision') { | |
| // Enable Collision | |
| game.info.allowcollisions = 1 | |
| btn_collide.innerText = 'Disable Collision' | |
| } else { | |
| // Disable Collision | |
| game.info.allowcollisions = 0 | |
| btn_collide.innerText = 'Enable Collision' | |
| } | |
| } | |
| btn_replace.onclick = () => { | |
| game.info.map[game.info.map.indexOf(2)] = 0 | |
| let r = Math.floor(Math.random() * (31*28)) | |
| while (game.info.map[r] != 0) { r = Math.floor(Math.random() * (31*28)) } | |
| game.info.map[r] = 2 | |
| game.update_map() | |
| } | |
| btn_guide.onclick = ()=>{ | |
| game.pause_game() | |
| if (btn_guide.innerText == "Guide") { | |
| // SHOWING GUIDE | |
| ins.style.setProperty('display', 'block') | |
| btn_guide.innerText = "Close" | |
| btn_fast_automation.disabled = true | |
| btn_pause_auto.disabled = true | |
| btn_next_map.disabled = true | |
| btn_speeder.disabled = true | |
| btn_collide.disabled = true | |
| btn_replace.disabled = true | |
| } else { | |
| // CLOSING GUIDE | |
| ins.style.setProperty('display', 'none') | |
| btn_guide.innerText = "Guide" | |
| btn_fast_automation.disabled = false | |
| } | |
| } | |
| document.querySelector("body").style.setProperty("height", `${window.innerHeight}px`) | |
| document.querySelector(":root").style.setProperty( | |
| "--win_size", | |
| `${(win_size/100) * ((window.innerHeight < window.innerWidth)? window.innerHeight: window.innerWidth)}px` | |
| ) | |
| window.addEventListener("resize", () => { | |
| document.querySelector("body").style.setProperty("height", `${window.innerHeight}px`) | |
| document.querySelector(":root").style.setProperty( | |
| "--win_size", | |
| `${(win_size/100) * ((window.innerHeight < window.innerWidth)? window.innerHeight: window.innerWidth)}px` | |
| ) | |
| }); | |