Javascript Collision Detection - javascript

I'm trying to make a snake game in javascript, but I am struggling with collision detection. I've tried various methods so far, but in desperation, have settled storing all the positions of the segments each frame then checking whether there are any duplicates before animating the next. This method hasn't proved successful either unfortunately.
Perhaps this is due a misunderstanding of how JS treats arrays. For a while I was using if(x in y) but from what I can tell that returns if the exact same object is in an array.
Here is the live demo: http://jsfiddle.net/AScYw/2/
Here is the code more easily read: http://pastebin.com/ygj73me6
The code in question is in the snake object, as the function collide.
this.collide = function(){
for(var z=0; z<this.positions.length-1; z++){
for(var q=z+1; q<this.positions.length-1; q++){
return this.positions[z][0] == this.positions[q][0] && this.positions[z][1] == this.positions[q][1];
}
}

You function here needs a little work and it may fix your problem.
this.collide = function(){
for(var z=0; z<this.positions.length-1; z++){
for(var q=z+1; q<this.positions.length-1; q++){
return this.positions[z][0] == this.positions[q][0] && this.positions[z][1] == this.positions[q][1];
}
}
}
2 things are wrong.
You are dropping out of the loop the first comparison. You will want to do something like if (something overlaps) return true then outside of both loops return false if you make it through successfully
You will want to make sure that the z segment != q segment or you will always have a collision
Looks cool. Lets see Mario next ;)

Related

Possible optimizations for my alpha-beta pruning algorithm?

I'm a new programmer currently coding a javascript alpha-beta pruning minimax algorithm for my chess engine, using Chess.js and Chessboard.js. I've implemented a basic algorithm with move ordering. Currently, it's evaluating around 14000 nodes for 8 seconds, which is way too slow. Is there something wrong with my algorithm or are there optimizations that I haven't implemented? My algorithm can't process anything deeper than depth 4 within reasonable time constraints. Thank you.
P.S. the "tracking Eval" function just evaluates each specific move as a way to avoid doing a full evaluation of boards at leaf nodes, this optimization sped up my program by around 50%, but it's still slow right now.
function minimax(game, depth, distanceFromRoot, alpha, beta, gameEval) {//returns gameEval
if (depth === 0) {
nodeNum++;
if(game.turn() === 'b'){
return (-gameEval / 8);
}else{
return (gameEval / 8);
}
}
// run eval
var prevEval = gameEval;
var moves = game.moves();
moveOrdering(moves);
var bestMove = null;
var bestEval = null;
for (let i = 0; i < moves.length; i++) {
var gameCopy = new Chess()//dummy board to pass down
gameCopy.load(game.fen())
const moveInfo = gameCopy.move(moves[i])
var curGameCopy = new Chess()//static board to eval, before the move so we know which piece was taken if a capture occurs
curGameCopy.load(game.fen())
var curEval = trackingEval(curGameCopy, prevEval, moveInfo, moves[i]); //returns the OBJECTIVE eval for the current move for current move sequence
var evaluated = -minimax(gameCopy, depth - 1, distanceFromRoot + 1, -beta, -alpha, curEval);//pass down the current eval for that move
if (evaluated >= beta) {
return beta;
}
if (evaluated > alpha){
alpha = evaluated
bestMove = moves[i]
bestEval = evaluated;
if (distanceFromRoot === 0) {
bestEval = evaluated;
}
}
}
if(distanceFromRoot === 0){
setEval(-bestEval)
return bestMove;
}
return alpha;
}
It's hard to say what optimizations you have made and what is reasonable since we only see a small part of your code. Your evaluation can be slow, your move ordering can be slow/incorrect, and to copy the board is also slower than to make and then unmake the move.
You can find lots of advice on how to speed up your algorithm here: https://www.chessprogramming.org/Search. Chessprogramming.org is a very good resource for developing your engine in general too.
I see two quick optimizations, before going further into other classical optimization.
Do not compute the evaluation of the board except when depth = 0. I assume that you compute the whole evaluation at every step, it's very time consuming and totally unnecessary.
Do not copy the board each time. It's also time consuming. Work with one board for the whole search, in which you make and unmake moves when you are doing the search. The pseudo-code for this is:
for move in moves:
board.do(move) #the original (not a copy) board has made the move
#Alpha-beta stuff like you did
board.undo(move) #restore the board

How do I implement minimax with the chess.js node module

I'm currently working on creating a chess engine using chess.js, chessboard.js, and the minimax algorithm. I eventually want to implement alpha-beta, but for right now, I just want to get minimax to work. It seems like the computer is thinking, but it usually just does Nc6. If I move the pawn to d4, it usually takes with the knight, but sometimes it just moves the rook back and forth in the spot that was opened up by the knight. If there is nothing for the knight to take, the computer moves the Rook or some other pointless move. My best guess is that all of the moves are returning the same valuation, and so it just makes the first move in the array of possible moves, hence the top left rook being a prime target. I should note that part of my confusion is around the way a recursive function works, and most of the stuff I've found online about recursive functions leaves me more confused than when I started.
I'm using Express.js with the chessboard.js config in public/javascripts as a boardInit.js that's included in the index.ejs folder, and when the user makes a move, a Post request is sent to /moveVsComp. It sends it to the server, where the app.post function for /moveVsComp tells chess.js to make the move that the player made.
After the player move is recorded, the computer calls the computerMoveBlack function.
Function call in the post request:
let compMove = computerMoveBlack(3);
game.load(currentFen)
game.move(compMove)
res.status(200).send({snapback: false, fen: game.fen()})
computerMoveBlack Function:
function computerMoveBlack(depth) {
let bestMove = ['', 105];
for (let move of game.moves()) {
game.move(move)
let value = minimax(move, depth-1, false)
if (value < bestMove[1]) {
bestMove = [move, value]
}
game.undo()
}
console.log(bestMove[0])
return bestMove[0]
}
This function loops through all of the moves, and I was using this because it seemed like this was the best way to keep the best move instead of just returning a valuation of the current position.
Minimax Function:
function minimax(node, depth, maximizingPlayer) {
let value = maximizingPlayer ? -105 : 105
if (depth === 0 || game.game_over()) return getValuation()
if (maximizingPlayer) {
for (let move of game.moves()) {
game.move(move)
value = Math.max(value, minimax(move, depth-1, false))
game.undo()
}
return value
} else {
for (let move of game.moves()) {
game.move(move)
value = Math.min(value, minimax(move, depth-1, true))
game.undo()
}
return value
}
}
getValuation Function:
function getValuation() {
let evalString = game.fen().split(' ')[0];
let score = 0;
score += (evalString.split('r').length -1) * -5 || 0;
score += (evalString.split('b').length -1) * -3 || 0;
score += (evalString.split('n').length -1) * -3 || 0;
score += (evalString.split('q').length -1) * -9 || 0;
score += (evalString.split('p').length -1) * -1 || 0;
score += (evalString.split('R').length -1) * 5 || 0;
score += (evalString.split('N').length -1) * 3 || 0;
score += (evalString.split('B').length -1) * 3 || 0;
score += (evalString.split('Q').length -1) * 9 || 0;
score += (evalString.split('P').length -1) || 0;
return score;
}
I should note that I understand using a FEN in the valuation is very slow for this use case, but I'm not really sure what a better alternative would be.
Just as kind of a recap of the questions, I'm trying to figure out why it just makes the first move in the array every time, what is wrong with the format of my functions, and what a better way to get the valuation of a position is as opposed to string manipulation of the FEN.
I will point out a few suggestions below to help you on the way if you are just getting started. First I just want to say that you are probably right that all moves get the same score and therefore it picks the first possible move. Try to add some Piece Square Tables (PST) to your Evaluation function and see if it puts pieces on appropriate squares.
I would implement a Negamax function instead of Minimax. It is way easier to debug and you won't have to duplicate a lot of code when you later make more optimizations. Negamax is one of the standard chess algorithms.
It seems like you don't do the legal move generation yourself, do you know how the board is represented in the library that you use? Instead of using the FEN for evaluation you want to use the board (or bitboards) to be able to do more advanced evaluation (more on it further down).
The min/max value of -105/105 is not a good way to go. Use -inf and inf instead to not get into troubles later on.
Regarding the evaluation you normally use the board representation to figure out how pieces are placed and how they are working together. Chessprogramming.org is a great resource to read up on different evaluation concepts.
For your simple starting evaluation you could just start with counting up all the material score at the beginning of the game. Then you subtract corresponding piece value when a piece is captured since that is the only case where the score is changing. Now you are recalculating lots of things over and over which will be very slow.
If you want to add PST to the evaluation then you also want to add the piece value change for the moving piece depending on the old and new square. To try and sum up the evaluation:
Sum up all piece values at start-up of a game (with PST scores if you use them) and save it as e.g. whiteScore and blackScore
In your evaluation you subtract the piece value from the opponent if you capture a piece. Otherwise you keep score as is and return it as usual.
If using PST you change the own score based on the new location for the moved piece.
I hope it makes sense, let me know if you need any further help.

Should this For-Loop, in theory, work?

I have a question over at collision-detection about a similar issue, but it's not exactly the same. I had an issue with a new game project (I'm trying to learn more about HTML5 Canvases and Socket.io) in which my collisions weren't working. I thought that my issue was centered on collisions, but now I'm starting to think something different. The reason I have a different issue posted here at the for-loop area is because I'm not sure if my issue is for-loop related or collision-detection related. Either way, I'd be happy to take one of my questions down.
This code is looping every frame to get the active positions of bullets and ships. If the bullet touches the ship, it'll be removed and some health points will be removed from the ship.
Tutorial I was using: http://jlongster.com/Making-Sprite-based-Games-with-Canvas
That aside, here's my checkCollisions code. It seems that the collision function is working, because when I started to log all the positions every time we had an iteration, it seemed that the position of my object was changing every single time. Is this one of those for-loop issues where I'm going to need a callback?
Thank you so much in advance for all your help. I'll be sure to upvote/select every response that helps out! :)
SOLVED! Turns out one of my arrays wasn't being passed in correctly. I'd like to thank you guys for telling me to always split it into multiple functions, that really helped me figure that one out!
// Let's start out here: I have a players[] array
//that's essentially a list of all players on the server
// and their positions. I omitted server connection functionality since that's not my error
// source.
function checkCollisions() {
for (var i = 0; i < players.length; i++) { // Iterating through all players
var pos = [players[i].posX, players[i].posY];
var size = [SHIP_WIDTH, SHIP_HEIGHT]; // This is the size of each player, it's a ship game. So these are constants.
if (players[i].userId != PLAYER.userId) { // Each player has a userId object, this is just doublechecking if we're not uselessly iterating
for (var j = 0; j < bullets.length; j++) { // We're now looping through bullets, an array of all the bullets being shot by players
var pos2 = bullets[j].pos;
var size2 = BULLET_SIZE;
var sender = bullets[j].sender;
if (boxCollides(pos, size, pos2, size2)) { // Collision code
if (sender != players[i].userId) {
bullets.splice(j, 1);
i--; // Tried here with j--, and by removing the entire line. Unfortunately it doesn't work :(
break;
}
}
}
}
}
}
Have you tried using console.log to see where the program is breaking? This might help you determine if there are multiple bugs or if it's just this one. If there's something wrong in a previous statement, you may not know it if you've fixed the i-- / j-- ...?
Edit: AH I see that you've fixed things, after I'd posted this. Well congrats and good job!

Should I Ever Use Labels In Javascript? (If So, When?)

Backstory: Once again I was reading in my Javascript book and I bumped into something that the book didn't explain very well, and that I wasn't able to find any good examples of online.
Example from Book:
parser:
while(token != null) {
// Code omitted here
}
The only paragraph used to explain this code said that by using a label I could refer to a statement elsewhere in my code and that labels are "commonly" used for loops. I've never seen a label used before let alone "commonly."
My question is: Are labels used and if so what is a good example of a place where I would want to use one?
The only time I've really seen it is in a nested loop or if statement you can use labels to break to a specific one for example:
function foo ()
{
dance:
for(var k = 0; k < 4; k++){
for(var m = 0; m < 4; m++){
if(m == 2){
break dance;
}
}
}
}
the label "dance" lets you break to that point specifically if m == 2.
In my experience I would not say they are very common.
Example taken from here: How to break nested loops in javascript?
Perhaps better example here: Best way to break from nested loops in Javascript? at the second answer.

JavaScript: multiple array conditions in if statement

I'm pretty new here but i'm posting this cause i haven't found a single answer on the internet to this question.
How can I use multiple arrays as conditions to an if statement. the reason i would need this is simply for creating a 2D game. But i'm learning that even a simple 2D game has tons of variables because of all the objects involved. But here is a simple example for what I've started with.
var a = 27;
var test = 0;
if(a in {18:1, 27:1, 36:1}) {
test = 1;
}
This tests an array of variables against one variable. I've found that this returns true but this is only half the battle.
The only place I've found any close reference to this is here.
How to shorten my conditional statements
Now the hard part is getting two arrays as conditions instead of just a variable and an array. So basically i need this idea made shorter.
var a = 27;
var b = 27;
var c = 50;
var test = 0;
if(a in {18:1, 27:1, 36:1} || b in {18:1, 27:1, 36:1} || c in {18:1, 27:1, 36:1}) {
test = 1;
}
even though i'm a noob my bible is the hacker's standard:P. Which basically means i think that when i'm creating something with the process of doing something over and over without very good reason "IT IS THE DEVIL"(kudos to whoever got the references). So let me explain this again but very specific so there's no confusion. Say i create a lot of NPC(non player character) and i want a system that can detect if the individual NPC has been in contact by lets say a projectile. i want that individual to vanish and give a point to a score board. well creating functions for such characters requires a LOT of if statements. So ideally i want an if statement that somehow uses 2 or more arrays for it's conditions but look almost as short as using two variables.
maybe something that looks like this.
var test = 0;
var a = [5,6,8];
var b = [10,30,8];
if(a in b){
test = 1;
}
NOTE: I've actually already tried this but it only took the index of b and not the numbers inside. I believe this topic deserves attention unless there's already someone out there that posted a solution(in which case it NEEDS to be advertised).
EDIT: After a long while i've come to realize that the proper(more efficient and readable) solution is to use both OOP and game engine design. I was just too young to understand how to work with data. So to anyone who see's this wondering the same thing should simply try to more thoroughly study array and class logic. In honesty javascript is NOT the place to learn this. I recommending taking a trip to processing.org. and learning the ways of using classes. if Your having trouble there you can try openFrameworks and learn OOP in c++. But the biggest part is understanding proper array mechanics. The OOP just makes it easier.
var test = false;
var a = [5, 6, 8];
var b = { 10:1, 30:1, 8:1 };
for (var i = 0; i < a.length; i++) {
if (a[i] in b) {
test = true;
break;
}
}
If you're using a library like jQuery or Underscore.js, they have convenience functions like $.any() that can be used to replace the loop. You can also use the built-in Array#some method, but it's not compatible with IE8. Ex:
return a.some(function(x) {
return x in b;
});

Categories