class Move { constructor(player, abalone) { this.id = -1; this.player = player; this.abalone = abalone; this.type = -1; // 1 marble / 2 column / 3 line this.done = false; this.repr = "" this.pieces = [] this.direction = "" } add_piece(piece) { if (piece.player !== this.player) { // Piece is not owned by current player return false; } else if (this.pieces.length >= 3) { // Maximum pieces by move reached return false; } else if (this.pieces.indexOf(piece) != -1) { // Piece is already selected return false; } else if (this.pieces.length == 0) { // Move set is empty this.pieces.push(piece); return true; } else if ( Slot.are_aligned(this.pieces.concat([piece]))) { this.pieces.push(piece); return true; } return false; } del_piece(piece) { let i = this.pieces.indexOf(piece); if (i == -1) { return false; } this.pieces.splice(i, 1); return true; } set_direction(dir) { if (['nw','ne','e','se','sw','w'].indexOf(dir) == -1) { return false; } this.direction = dir; return true; } set_type() { this.sort_pieces(); if (this.pieces.length < 1) { this.type = -1; return; } else if (this.pieces.length == 1) { this.type = 1; return; } let coord = this.pieces[1].get_direction_coord(this.direction); if (coord == false) { this.type = -1; return; } else if (coord.x == this.pieces[0].coord.x && coord.y == this.pieces[0].coord.y) { this.type = 2; return; } else { this.type = 3; return; } } is_possible() { this.set_type(); if (this.type == -1) { alert('Select at least one piece'); return false; } else if (this.pieces.length > 3) { alert('Too much marbles are selected'); } for (let piece of this.pieces) { let coord = piece.get_direction_coord(this.direction); if (typeof(coord) == 'undefined') { return false; } let next_slot = this.abalone.board.get_coord(coord); if (typeof(next_slot) != 'undefined' && next_slot.length > 1) { // A piece is located in the next slot if (this.pieces.indexOf(next_slot[1])) { // The next slot is already in the move continue; } else if (next_slot[1].player == this.player && piece == this.pieces[0]) { // There is another piece of the current player // It means that we can't move return false; } else { // This is a sumito case if (this.sumito()) { this.sort_pieces(); return this.move_pieces(); } } } else { // The slot is free, so we move all the pieces in this direction return this.move_pieces(); } } } move_pieces() { for (let piece of this.pieces) { this.abalone.board.pop_coord(piece.coord); let slot = this.abalone.board.get_slot(piece.coord); let new_coord = piece.get_direction_coord(this.direction); if (this.abalone.board.get_slot(new_coord) != false) { piece.new_coord = new_coord; } else { piece.new_coord = false; piece.out = true; } } for (let piece of this.pieces) { if (piece.out == true || piece.new_coord == false) { this.abalone.add_point(piece); piece.set_out(); continue; } let next_slot = this.abalone.board.get_slot(piece.new_coord); if (next_slot == false || typeof(next_slot) == 'undefined') { break; } this.abalone.board.push_coord(piece.new_coord, piece); piece.coord = piece.new_coord; piece.move(next_slot.element.position(), next_slot.element.rotation(), next_slot.element.offsetX()); if (piece.selected) { piece.set_selected(); } } this.abalone.layers.pieces.draw(); return true; } sumito() { if (this.type != 2) { return false; } let new_coord = this.pieces[0].get_direction_coord(this.direction); let next_slot = this.abalone.board.get_coord(new_coord); if (next_slot.length <= 1) { // Free slot! - should not happen in this function return true; } let enemy_piece = next_slot[1]; new_coord = enemy_piece.get_direction_coord(this.direction); next_slot = this.abalone.board.get_coord(new_coord); if (next_slot == false || next_slot.length <= 1) { // It's outside! || it's free this.pieces.unshift(enemy_piece); return true; } else if (this.pieces.length <= 2) { // We don't have enough pieces to face 2 enemy marbles return false; } else { this.pieces.unshift(enemy_piece); } enemy_piece = next_slot[1]; new_coord = enemy_piece.get_direction_coord(this.direction); next_slot = this.abalone.board.get_coord(new_coord); if (next_slot == false || next_slot.length <= 1) { this.pieces.unshift(enemy_piece); return true; } return false; } sort_pieces() { let sort_function = false; switch (this.direction[0]) { case 'e': sort_function = function (a, b) { return parseInt(b.coord.y) - parseInt(a.coord.y); } break; case 'w': sort_function = function (a, b) { return parseInt(a.coord.y) - parseInt(b.coord.y); } break; case 'n': sort_function = function (a, b) { return a.coord.x.charCodeAt() - b.coord.x.charCodeAt(); } break; case 's': sort_function = function (a, b) { return b.coord.x.charCodeAt() - a.coord.x.charCodeAt(); } break; } this.pieces.sort(sort_function); } }