first commit, working abalone
This commit is contained in:
commit
690ccce89b
|
@ -0,0 +1,310 @@
|
|||
class Abalone {
|
||||
constructor(layers) {
|
||||
this.id = 0;
|
||||
this.secret = "lol";
|
||||
this.players = [];
|
||||
this.turn = 0;
|
||||
|
||||
// State : -1 => Not Started, 0 => Ended, 1 => Running
|
||||
this.state = -1;
|
||||
this.moves = [];
|
||||
this.board = false;
|
||||
this.layers = layers;
|
||||
this.colors = settings.colors.background;
|
||||
this.pieces = [];
|
||||
this.texts = {};
|
||||
|
||||
this.draw();
|
||||
|
||||
this.board = new Board(this.layers.board, this.layers.pieces);
|
||||
}
|
||||
|
||||
start() {
|
||||
var p0_name = prompt('1st player name?');
|
||||
if (p0_name.length <= 0) {
|
||||
p0_name = 'Player 0';
|
||||
}
|
||||
var p1_name = prompt('2nd player name?');
|
||||
if (p1_name.length <= 0) {
|
||||
p1_name = 'Player 1';
|
||||
}
|
||||
var slot = false;
|
||||
|
||||
this.add_player(new Player(0, p0_name));
|
||||
this.add_player(new Player(1, p1_name));
|
||||
|
||||
var starting_position = this.starting_position(
|
||||
document.getElementById('startpos').value);
|
||||
for (let player_id in starting_position) {
|
||||
for (let coord_id in starting_position[player_id]) {
|
||||
let coord = starting_position[player_id][coord_id];
|
||||
slot = this.board.get_slot(coord);
|
||||
let piece = new Piece(
|
||||
this.pieces.length,
|
||||
this.players[player_id],
|
||||
slot.x, slot.y, slot.r - 2, slot.rot, slot.o,
|
||||
coord,
|
||||
this
|
||||
);
|
||||
this.pieces.push(piece);
|
||||
}
|
||||
}
|
||||
|
||||
this.board.draw_pieces(this.pieces);
|
||||
|
||||
this.state = 1;
|
||||
this.play();
|
||||
}
|
||||
|
||||
next_turn() {
|
||||
this.turn++;
|
||||
this.texts.turn.text(this.turn);
|
||||
this.layers.background.draw();
|
||||
this.texts.turn.draw();
|
||||
this.play();
|
||||
}
|
||||
|
||||
play() {
|
||||
if (this.moves.length > 0) {
|
||||
console.log(this.moves[this.moves.length - 1]);
|
||||
}
|
||||
if (this.turn % 2 == 0) {
|
||||
this.moves.push( new Move(this.players[0], this));
|
||||
alert('Player 1, it is your turn');
|
||||
}
|
||||
else {
|
||||
this.moves.push( new Move(this.players[1], this));
|
||||
alert('Player 2, it is your turn');
|
||||
}
|
||||
}
|
||||
|
||||
draw() {
|
||||
var rect = new Kinetic.Rect({
|
||||
x : 0,
|
||||
y : 0,
|
||||
width : 800,
|
||||
height : 500,
|
||||
stroke : this.colors.stroke,
|
||||
fill : this.colors.bg
|
||||
});
|
||||
|
||||
var text_cont = new Kinetic.Group({
|
||||
x : 800-160,
|
||||
y : 10,
|
||||
width : 150,
|
||||
height : 200,
|
||||
});
|
||||
|
||||
|
||||
var text_rect = new Kinetic.Rect({
|
||||
x : 0,
|
||||
y : 0,
|
||||
width : 150,
|
||||
height : 200,
|
||||
stroke : '#010101',
|
||||
fill : '#F0F0F0'
|
||||
});
|
||||
|
||||
text_cont.add(text_rect);
|
||||
|
||||
var title_text = new Kinetic.Text({
|
||||
x : 5,
|
||||
y : 5,
|
||||
width : 150,
|
||||
height : 30,
|
||||
text : 'Abalone',
|
||||
fill : 'red',
|
||||
fontSize : 25
|
||||
});
|
||||
var turn_text = new Kinetic.Text({
|
||||
x : 5,
|
||||
y : 35,
|
||||
width : 150,
|
||||
height : 30,
|
||||
text : 'Turn : ',
|
||||
fill : 'red',
|
||||
fontSize : 25
|
||||
});
|
||||
var turn_value = new Kinetic.Text({
|
||||
x : 95,
|
||||
y : 35,
|
||||
width : 50,
|
||||
height : 30,
|
||||
text : this.turn,
|
||||
fill : 'red',
|
||||
fontSize : 25,
|
||||
align : 'right'
|
||||
});
|
||||
this.texts.turn = turn_value;
|
||||
|
||||
var p0_text = new Kinetic.Text({
|
||||
x : 5,
|
||||
y : 65,
|
||||
width : 150,
|
||||
height : 30,
|
||||
text : '',
|
||||
fill : 'white',
|
||||
stroke : 'black',
|
||||
fontSize : 25
|
||||
});
|
||||
this.texts.p0_name = p0_text;
|
||||
var p0_value = new Kinetic.Text({
|
||||
x : 95,
|
||||
y : 65,
|
||||
width : 50,
|
||||
height : 30,
|
||||
text : '0',
|
||||
fill : 'white',
|
||||
stroke : '#101010',
|
||||
fontSize : 25,
|
||||
align : 'right'
|
||||
});
|
||||
this.texts.p0_score = p0_value;
|
||||
|
||||
var p1_text = new Kinetic.Text({
|
||||
x : 5,
|
||||
y : 95,
|
||||
width : 150,
|
||||
height : 30,
|
||||
text : '',
|
||||
fill : 'black',
|
||||
stroke : '#101010',
|
||||
fontSize : 25
|
||||
});
|
||||
this.texts.p1_name = p1_text;
|
||||
var p1_value = new Kinetic.Text({
|
||||
x : 95,
|
||||
y : 95,
|
||||
width : 50,
|
||||
height : 30,
|
||||
text : '0',
|
||||
fill : 'black',
|
||||
stroke : 'black',
|
||||
fontSize : 25,
|
||||
align : 'right'
|
||||
});
|
||||
this.texts.p1_score = p1_value;
|
||||
|
||||
text_cont.add(title_text);
|
||||
text_cont.add(turn_text);
|
||||
text_cont.add(turn_value);
|
||||
text_cont.add(p0_text, p0_value, p1_text, p1_value);
|
||||
|
||||
|
||||
this.layers.background.add(rect)
|
||||
this.layers.background.add(text_cont)
|
||||
return rect
|
||||
}
|
||||
|
||||
get_positions() {
|
||||
console.log(this.players[0]);
|
||||
return [
|
||||
this.players[0].get_positions(),
|
||||
this.players[1].get_positions()
|
||||
]
|
||||
}
|
||||
|
||||
starting_position(name=false) {
|
||||
switch (name) {
|
||||
case 'margbelg':
|
||||
return [ [
|
||||
{'x': 'A', 'y': '1'},
|
||||
{'x': 'A', 'y': '2'},
|
||||
{'x': 'B', 'y': '1'},
|
||||
{'x': 'B', 'y': '2'},
|
||||
{'x': 'B', 'y': '3'},
|
||||
{'x': 'C', 'y': '2'},
|
||||
{'x': 'C', 'y': '3'},
|
||||
{'x': 'G', 'y': '7'},
|
||||
{'x': 'G', 'y': '8'},
|
||||
{'x': 'H', 'y': '7'},
|
||||
{'x': 'H', 'y': '8'},
|
||||
{'x': 'H', 'y': '9'},
|
||||
{'x': 'I', 'y': '8'},
|
||||
{'x': 'I', 'y': '9'},
|
||||
], [
|
||||
{'x': 'A', 'y': '4'},
|
||||
{'x': 'A', 'y': '5'},
|
||||
{'x': 'B', 'y': '4'},
|
||||
{'x': 'B', 'y': '5'},
|
||||
{'x': 'B', 'y': '6'},
|
||||
{'x': 'C', 'y': '5'},
|
||||
{'x': 'C', 'y': '6'},
|
||||
{'x': 'G', 'y': '4'},
|
||||
{'x': 'G', 'y': '5'},
|
||||
{'x': 'H', 'y': '4'},
|
||||
{'x': 'H', 'y': '5'},
|
||||
{'x': 'H', 'y': '6'},
|
||||
{'x': 'I', 'y': '5'},
|
||||
{'x': 'I', 'y': '6'},
|
||||
] ];
|
||||
}
|
||||
return [ [
|
||||
{'x': 'A', 'y': '1'},
|
||||
{'x': 'A', 'y': '2'},
|
||||
{'x': 'A', 'y': '3'},
|
||||
{'x': 'A', 'y': '4'},
|
||||
{'x': 'A', 'y': '5'},
|
||||
{'x': 'B', 'y': '1'},
|
||||
{'x': 'B', 'y': '2'},
|
||||
{'x': 'B', 'y': '3'},
|
||||
{'x': 'B', 'y': '4'},
|
||||
{'x': 'B', 'y': '5'},
|
||||
{'x': 'B', 'y': '6'},
|
||||
{'x': 'C', 'y': '2'},
|
||||
{'x': 'C', 'y': '3'},
|
||||
{'x': 'C', 'y': '4'},
|
||||
{'x': 'C', 'y': '5'},
|
||||
{'x': 'C', 'y': '6'},
|
||||
], [
|
||||
{'x': 'I', 'y': '5'},
|
||||
{'x': 'I', 'y': '6'},
|
||||
{'x': 'I', 'y': '7'},
|
||||
{'x': 'I', 'y': '8'},
|
||||
{'x': 'I', 'y': '9'},
|
||||
{'x': 'H', 'y': '4'},
|
||||
{'x': 'H', 'y': '5'},
|
||||
{'x': 'H', 'y': '6'},
|
||||
{'x': 'H', 'y': '7'},
|
||||
{'x': 'H', 'y': '8'},
|
||||
{'x': 'H', 'y': '9'},
|
||||
{'x': 'G', 'y': '4'},
|
||||
{'x': 'G', 'y': '5'},
|
||||
{'x': 'G', 'y': '6'},
|
||||
{'x': 'G', 'y': '7'},
|
||||
{'x': 'G', 'y': '8'},
|
||||
] ];
|
||||
}
|
||||
|
||||
cur_move() {
|
||||
return this.moves[this.moves.length-1];
|
||||
}
|
||||
|
||||
isplayerturn(player_id) {
|
||||
return player_id == (this.turn % 2);
|
||||
}
|
||||
|
||||
add_player(player) {
|
||||
this.players.push(player);
|
||||
this.texts['p' + player.id +'_name'].text(player.name);
|
||||
this.layers.background.draw();
|
||||
}
|
||||
|
||||
add_point(piece) {
|
||||
if (piece.player.id < 1) {
|
||||
this.players[1].score++;
|
||||
this.texts.p1_score.text(this.players[1].score);
|
||||
if (this.players[1].score === 6) {
|
||||
alert(this.players[1].name + ' WINS!');
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.players[0].score++;
|
||||
this.texts.p0_score.text(this.players[0].score);
|
||||
if (this.players[0].score === 6) {
|
||||
alert(this.players[0].name + ' WINS!');
|
||||
}
|
||||
}
|
||||
this.layers.background.draw();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
class Board {
|
||||
constructor(layer, layer_pieces) {
|
||||
this.grid = {
|
||||
A:{1:[],2:[],3:[],4:[],5:[]}, //Plateau de jeu
|
||||
B:{1:[],2:[],3:[],4:[],5:[],6:[]},
|
||||
C:{1:[],2:[],3:[],4:[],5:[],6:[],7:[]},
|
||||
D:{1:[],2:[],3:[],4:[],5:[],6:[],7:[],8:[]},
|
||||
E:{1:[],2:[],3:[],4:[],5:[],6:[],7:[],8:[],9:[]},
|
||||
F:{2:[],3:[],4:[],5:[],6:[],7:[],8:[],9:[]},
|
||||
G:{3:[],4:[],5:[],6:[],7:[],8:[],9:[]},
|
||||
H:{4:[],5:[],6:[],7:[],8:[],9:[]},
|
||||
I:{5:[],6:[],7:[],8:[],9:[]}
|
||||
};
|
||||
|
||||
this.colors = settings.colors.board;
|
||||
this.colors_hole = settings.colors.hole;
|
||||
this.colors_p0 = settings.colors.piece_0;
|
||||
this.colors_p1 = settings.colors.piece_1;
|
||||
|
||||
this.layer = layer;
|
||||
this.layer_pieces = layer_pieces;
|
||||
|
||||
this.draw();
|
||||
this.draw_slots();
|
||||
}
|
||||
|
||||
draw() {
|
||||
console.log('Board draw');
|
||||
var hexagon = new Kinetic.RegularPolygon({
|
||||
sides : 6,
|
||||
radius : settings.radius,
|
||||
stroke : this.colors.stroke,
|
||||
strokeWidth : 5,
|
||||
fill : this.colors.bg,
|
||||
x : settings.x,
|
||||
y : settings.y,
|
||||
})
|
||||
hexagon.rotate(Math.PI/6)
|
||||
|
||||
this.layer.add(hexagon)
|
||||
return hexagon
|
||||
}
|
||||
|
||||
draw_slots() {
|
||||
var grid = this.grid;
|
||||
var colors = this.colors_hole
|
||||
var x = settings.x;
|
||||
var y = settings.y;
|
||||
var radius = settings.radius;
|
||||
var r = settings.r;
|
||||
var hor = ["A","B","C","D","E","F","G","H","I"];
|
||||
var dia = ["1","2","3","4","5","6","7","8","9"];
|
||||
var h = 4;
|
||||
var d = 4;
|
||||
var rad = -1;
|
||||
var off = -1;
|
||||
var offx = -1;
|
||||
var radx = -1;
|
||||
var slot = false;
|
||||
|
||||
// center circle
|
||||
slot = new Slot(x, y, r, 0, 0,
|
||||
{ x: hor[h], y: dia[d] });
|
||||
|
||||
grid[hor[h]][dia[d]].push(slot);
|
||||
// we turn around the center, each "i"
|
||||
// is a sixth of PI/2
|
||||
for (var i = 0; i < 6; i++) {
|
||||
rad = i * Math.PI / 3;
|
||||
|
||||
// center coordinates
|
||||
h = 4
|
||||
d = 4
|
||||
|
||||
for (var j = 0; j < 4; j++) {
|
||||
off = (j + 1) * (2 * r + (radius / 20));
|
||||
switch (i) {
|
||||
case 1: case 2:
|
||||
h--;
|
||||
break;
|
||||
case 4: case 5:
|
||||
h++;
|
||||
break;
|
||||
}
|
||||
switch (i) {
|
||||
case 0: case 1:
|
||||
d--;
|
||||
break;
|
||||
case 3: case 4:
|
||||
d++;
|
||||
break;
|
||||
}
|
||||
|
||||
slot = new Slot(x, y, r, rad, off,
|
||||
{ x: hor[h], y: dia[d] });
|
||||
|
||||
grid[hor[h]][dia[d]].push(slot);
|
||||
|
||||
var h_ = h
|
||||
var d_ = d
|
||||
for (var k = 0; k < j; k++) {
|
||||
|
||||
offx = Math.sqrt(Math.pow(j, 2) + j + 1);
|
||||
radx = Math.atan(Math.sqrt(3) / (j * 2 + 1));
|
||||
if (k >= (j / 2)) {
|
||||
radx = Math.PI/3 - radx;
|
||||
}
|
||||
else if (k == 1 && j == 3) {
|
||||
offx = 2 * Math.sqrt(3);
|
||||
radx = Math.atan(Math.sqrt(3) / 3);
|
||||
}
|
||||
|
||||
radx += (i * Math.PI / 3);
|
||||
|
||||
switch (i) {
|
||||
case 2:
|
||||
case 3:
|
||||
h_++;
|
||||
break;
|
||||
case 0:
|
||||
case 5:
|
||||
h_--;
|
||||
break;
|
||||
}
|
||||
switch (i) {
|
||||
case 1: case 2:
|
||||
d_++;
|
||||
break;
|
||||
case 4: case 5:
|
||||
d_--;
|
||||
break;
|
||||
}
|
||||
|
||||
slot = new Slot(x, y, r, radx,
|
||||
offx * off / (j + 1),
|
||||
{ x: hor[h_], y: dia[d_] });
|
||||
|
||||
grid[hor[h_]][dia[d_]].push(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let g in grid) {
|
||||
for (let row in grid[g]) {
|
||||
this.layer.add(grid[g][row][0].draw());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_pieces(pieces) {
|
||||
let grid = this.grid;
|
||||
let coord = false;
|
||||
let slot = false;
|
||||
for (let i in pieces) {
|
||||
coord = pieces[i].coord;
|
||||
grid[coord.x][coord.y][0].element.setZIndex(1);
|
||||
grid[coord.x][coord.y][0].element.draw();
|
||||
grid[coord.x][coord.y].push(pieces[i]);
|
||||
grid[coord.x][coord.y][1].draw();
|
||||
this.layer_pieces.add(grid[coord.x][coord.y][1].element);
|
||||
grid[coord.x][coord.y][1].element.setZIndex(10);
|
||||
grid[coord.x][coord.y][1].element.draw();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
get_coord(coord) {
|
||||
if (this.grid.hasOwnProperty(coord.x) ==
|
||||
false) {
|
||||
console.log('Undefined line :' + coord.x);
|
||||
return false;
|
||||
}
|
||||
if (this.grid[coord.x].hasOwnProperty(coord.y) ==
|
||||
false) {
|
||||
console.log('Undefined column of line ' + coord.x + ' :' + coord.y);
|
||||
return false;
|
||||
}
|
||||
if (!(this.grid[coord.x][coord.y] instanceof Array)) {
|
||||
console.log(this.grid[coord.x][coord.y]);
|
||||
console.log('is not array');
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.grid[coord.x][coord.y];
|
||||
}
|
||||
pop_coord(coord) {
|
||||
if (this.get_coord(coord) !== false) {
|
||||
return this.get_coord(coord).pop();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
push_coord(coord, slot) {
|
||||
if (this.get_coord(coord) !== false) {
|
||||
return this.get_coord(coord).push(slot);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
get_slot(coord) {
|
||||
if (this.get_coord(coord) !== false) {
|
||||
return this.get_coord(coord)[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
class Piece extends Slot {
|
||||
constructor(id, player, x, y, r, rot, o, coord, abalone) {
|
||||
super(x, y, r, rot, o, coord)
|
||||
this.id = id;
|
||||
this.player = player;
|
||||
this.player.pieces.push(this);
|
||||
this.abalone = abalone;
|
||||
this.zIndex = 10;
|
||||
this.out = false;
|
||||
this.colors = settings.colors['piece_'+player.id];
|
||||
this.strokeWidth = 5;
|
||||
this.selected = false;
|
||||
this.hovered = false;
|
||||
this.new_coord = false;
|
||||
|
||||
}
|
||||
|
||||
click() {
|
||||
super.click();
|
||||
|
||||
if (typeof(this.abalone) == 'undefined' ||
|
||||
this.abalone.state !== 1) {
|
||||
alert('The game is not running!');
|
||||
}
|
||||
if (this.selected) {
|
||||
// unselect
|
||||
if (this.abalone.cur_move().del_piece(this)) {
|
||||
this.set_selected();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (this.abalone.cur_move().add_piece(this)) {
|
||||
console.log(this.abalone.cur_move());
|
||||
this.set_selected();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
mouseenter() {
|
||||
if (typeof(this.abalone) == 'undefined' ||
|
||||
this.abalone.state !== 1) {
|
||||
alert('The game is not running!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.abalone.isplayerturn(this.player.id)) {
|
||||
return;
|
||||
}
|
||||
this.hovered = true;
|
||||
this.element.stroke(this.colors.selected);
|
||||
this.element.draw();
|
||||
}
|
||||
|
||||
mouseleave(element) {
|
||||
if (typeof(this.abalone) == 'undefined' ||
|
||||
this.abalone.state !== 1) {
|
||||
alert('The game is not running!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.selected || !this.hovered) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.hovered = false;
|
||||
element.stroke(this.colors.stroke);
|
||||
element.draw();
|
||||
}
|
||||
|
||||
set_coord(coord) {
|
||||
this.coord = coord;
|
||||
}
|
||||
|
||||
set_selected() {
|
||||
if (this.selected != false) {
|
||||
this.selected = false;
|
||||
this.element.stroke(this.colors.stroke);
|
||||
this.element.draw();
|
||||
return;
|
||||
}
|
||||
|
||||
this.selected = true;
|
||||
this.element.stroke(this.colors.selected);
|
||||
this.element.draw();
|
||||
}
|
||||
|
||||
set_out() {
|
||||
this.element.hide();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
class Player {
|
||||
constructor(id, name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.pieces = [];
|
||||
this.colors = settings.colors['piece_' + id];
|
||||
this.score = 0;
|
||||
}
|
||||
|
||||
get_positions() {
|
||||
return this.pieces.map(function (piece) {
|
||||
return piece.coord;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
class Slot {
|
||||
constructor(x, y, r, rot, o, coord) {
|
||||
this.colors = settings.colors.slot;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.r = r;
|
||||
this.rot = rot;
|
||||
this.o = o;
|
||||
this.coord = coord;
|
||||
this.zIndex = 1;
|
||||
this.player = false;
|
||||
this.element = false;
|
||||
this.piece = false;
|
||||
}
|
||||
|
||||
draw() {
|
||||
let _this = this;
|
||||
let circle = new Kinetic.Circle({
|
||||
layer : true,
|
||||
stroke : this.colors.stroke,
|
||||
strokeWidth : this.strokeWidth,
|
||||
fill : this.colors.bg,
|
||||
x : this.x,
|
||||
y : this.y,
|
||||
radius : this.r,
|
||||
rotation : this.rot,
|
||||
offset :{
|
||||
x : this.o,
|
||||
y : 0
|
||||
}
|
||||
}).on('click', function (e) {
|
||||
_this.click();
|
||||
}).on('mouseenter', function (e) {
|
||||
_this.mouseenter();
|
||||
}).on('mouseleave', function (e) {
|
||||
_this.mouseleave(this);
|
||||
}).on('mouseover', function (e) {
|
||||
_this.over();
|
||||
}, function(e) {
|
||||
});
|
||||
this.element = circle;
|
||||
return this.element;
|
||||
}
|
||||
|
||||
click() {
|
||||
}
|
||||
mouseenter() {
|
||||
}
|
||||
mouseleave() {
|
||||
}
|
||||
over() {
|
||||
//console.log('Slot coord : ' + JSON.stringify(this.coord));
|
||||
}
|
||||
|
||||
move(pos, rotation, offx) {
|
||||
this.element.position(pos);
|
||||
this.element.rotation(rotation);
|
||||
this.element.offsetX(offx);
|
||||
this.element.draw();
|
||||
}
|
||||
|
||||
is_sibling(slot) {
|
||||
let x0_val = this.coord.x.charCodeAt();
|
||||
let x1_val = slot.coord.x.charCodeAt();
|
||||
let y0_val = parseInt(this.coord.y);
|
||||
let y1_val = parseInt(slot.coord.y);
|
||||
|
||||
let e_val = 'E'.charCodeAt();
|
||||
|
||||
console.log(x0_val + ':' + y0_val);
|
||||
console.log(x1_val + ':' + y1_val);
|
||||
if (x0_val === x1_val) {
|
||||
return Math.abs(y0_val - y1_val) === 1;
|
||||
}
|
||||
else if (Math.abs(x0_val - x1_val) === 1) {
|
||||
return (y0_val - y1_val) <= 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
count_siblings(slots) {
|
||||
let res = 0;
|
||||
for (let slot of slots) {
|
||||
if (this.is_sibling(slot)) {
|
||||
res++;
|
||||
}
|
||||
}
|
||||
console.log(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
get_direction_coord(direction) {
|
||||
let res = {'x': this.coord.x, 'y': this.coord.y};
|
||||
let e_val = 'E'.charCodeAt();
|
||||
let x_val = res.x.charCodeAt();
|
||||
if (direction == 'e') {
|
||||
res.y = (parseInt(res.y) + 1).toString();
|
||||
}
|
||||
else if (direction == 'w') {
|
||||
res.y = (parseInt(res.y) - 1).toString();
|
||||
}
|
||||
else if (direction.charAt(0) == 'n') {
|
||||
res.x = String.fromCharCode(x_val - 1);
|
||||
if (direction.charAt(1) == 'w') {
|
||||
res.y = (parseInt(res.y) - 1).toString();
|
||||
}
|
||||
}
|
||||
else if (direction.charAt(0) == 's') {
|
||||
res.x = String.fromCharCode(x_val + 1);
|
||||
if (direction.charAt(1) == 'e') {
|
||||
res.y = (parseInt(res.y) + 1).toString();
|
||||
}
|
||||
}
|
||||
else {
|
||||
res = false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static are_aligned(slots, dir = false) {
|
||||
if (slots.length == 1) {
|
||||
return true;
|
||||
}
|
||||
let slot = slots.pop();
|
||||
let x0 = slot.coord.x.charCodeAt();
|
||||
let y0 = parseInt(slot.coord.y);
|
||||
let next_slot = false;
|
||||
if (dir === false) {
|
||||
for (dir of ['ne', 'nw', 'w', 'sw', 'se', 'e']) {
|
||||
console.log('trying dir : ' + dir);
|
||||
next_slot = this.find_by_coord(slots,
|
||||
slot.get_direction_coord(dir));
|
||||
if (next_slot !== false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
next_slot = this.find_by_coord(slots,
|
||||
slot.get_direction_coord(dir));
|
||||
}
|
||||
|
||||
if (next_slot) {
|
||||
slots.slice(slots.indexOf(next_slot), 1);
|
||||
return this.are_aligned(slots, dir);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static find_by_coord(slots, coord) {
|
||||
let x0 = coord.x.charCodeAt();
|
||||
let y0 = parseInt(coord.y);
|
||||
for (let slot of slots) {
|
||||
if (slot.coord.x.charCodeAt() == x0
|
||||
&& parseInt(slot.coord.y) == y0) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.direction {
|
||||
display : inline-block;
|
||||
width : 150px;
|
||||
}
|
||||
</style>
|
||||
<script src="./kinetic.js"></script>
|
||||
<script src="./settings.js"></script>
|
||||
<script src="./Abalone.class.js"></script>
|
||||
<script src="./Player.class.js"></script>
|
||||
<script src="./Board.class.js"></script>
|
||||
<script src="./Slot.class.js"></script>
|
||||
<script src="./Piece.class.js"></script>
|
||||
<script src="./Move.class.js"></script>
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
|
||||
console.log('Hello world!');
|
||||
if (typeof(Kinetic) == 'undefined' &&
|
||||
typeof(Kinetic.Stage) == 'undefined') {
|
||||
document.getElementById('container').innerHTML = 'Missing concrete library'
|
||||
return;
|
||||
}
|
||||
|
||||
Kinetic.angleDeg = false
|
||||
|
||||
var cont = document.getElementById('container')
|
||||
var stage= new Kinetic.Stage({
|
||||
width : 800,
|
||||
height : 800,
|
||||
container : cont
|
||||
})
|
||||
|
||||
var layers = {
|
||||
background : new Kinetic.Layer(),
|
||||
board : new Kinetic.Layer(),
|
||||
pieces : new Kinetic.Layer()
|
||||
}
|
||||
|
||||
var abalone = false;
|
||||
function init() {
|
||||
abalone = new Abalone(layers);
|
||||
for (var l in layers) {
|
||||
stage.add(layers[l])
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
document.getElementById('start').addEventListener('click', function (e) {
|
||||
abalone.start();
|
||||
});
|
||||
|
||||
var directions = document.getElementsByClassName('direction');
|
||||
Array.prototype.forEach.call(directions, function (element) {
|
||||
element.addEventListener('click', function (e) {
|
||||
let move = abalone.cur_move();
|
||||
if (move) {
|
||||
if (move.set_direction(element.id)) {
|
||||
if (move.is_possible()) {
|
||||
return abalone.next_turn();
|
||||
}
|
||||
else {
|
||||
alert('Move not possible, try another one');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Debug
|
||||
/*
|
||||
document.getElementById('reset').addEventListener('click', function (e) {
|
||||
delete abalone;
|
||||
init();
|
||||
});
|
||||
*/
|
||||
|
||||
document.getElementById('dump_grid').addEventListener('click', function (e) {
|
||||
console.log(JSON.stringify(abalone.get_positions()));
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
</div>
|
||||
<div id="buttons"
|
||||
style="position: fixed;
|
||||
bottom: 0;
|
||||
width:'150px';
|
||||
height:'150px'">
|
||||
<button id="start">
|
||||
START GAME
|
||||
</button>
|
||||
<button id="player1">
|
||||
PLAYER1
|
||||
</button>
|
||||
<button id="player2">
|
||||
PLAYER2
|
||||
</button>
|
||||
<select id="startpos" name="startpos">
|
||||
<option value="">---</option>
|
||||
<option value="standard">Standard</option>
|
||||
<option value="margbelg">Marguerite Belge</option>
|
||||
</select>
|
||||
<br />
|
||||
<br />
|
||||
Direction :
|
||||
<br />
|
||||
<button class="direction" id="nw">North-West</button>
|
||||
<button class="direction" id="ne">North-East</button>
|
||||
<br />
|
||||
<button class="direction" id="w">West</button>
|
||||
<button class="direction" id="e">East</button>
|
||||
<br />
|
||||
<button class="direction" id="sw">South-West</button>
|
||||
<button class="direction" id="se">South-East</button>
|
||||
</div>
|
||||
<div id="debug"
|
||||
style="position: fixed;
|
||||
top: 0;
|
||||
right:150px;
|
||||
width:150px;
|
||||
height:150px">
|
||||
Debug :
|
||||
<!--
|
||||
<button id="reset">Reset</button>
|
||||
<br />
|
||||
-->
|
||||
<button id="dump_grid">Dump Grid</button>
|
||||
<br />
|
||||
<button id=""></button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,33 @@
|
|||
var radius = 250;
|
||||
var r = radius / 10 - radius / 50;
|
||||
var settings = {
|
||||
size : [800, 800],
|
||||
x : 400,
|
||||
y : 250,
|
||||
radius : radius,
|
||||
r : r,
|
||||
colors : {
|
||||
background: {
|
||||
stroke: '#000000',
|
||||
bg: '#BFFCBF'
|
||||
},
|
||||
board: {
|
||||
stroke: '#0f0f0f',
|
||||
bg: '#1f1f1f',
|
||||
},
|
||||
slot: {
|
||||
stroke: '#101010',
|
||||
bg: '#6F6FE0',
|
||||
},
|
||||
piece_0: {
|
||||
stroke: '#101010',
|
||||
bg: '#FFFFFF',
|
||||
selected: '#ffa500'
|
||||
},
|
||||
piece_1: {
|
||||
stroke: '#101010',
|
||||
bg: '#000000',
|
||||
selected: '#3dff0c'
|
||||
}
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue