intelli-snake / web /script.js
geetu040's picture
uploading api
b697ed4
// 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`
)
});