Add alt moves for Castle and Knight; change Lance promotion moves to two tiles on sides.

This commit is contained in:
yukirij 2024-09-03 17:21:56 -07:00
parent efe46428f7
commit 24e5e9d609
2 changed files with 310 additions and 183 deletions

View File

@ -151,10 +151,11 @@ GAME.MovementTile = class {
}; };
GAME.Play = class { GAME.Play = class {
constructor(source, from, to) { constructor(source, from, to, alt=false) {
this.source = source; this.source = source;
this.from = from; this.from = from;
this.to = to; this.to = to;
this.alt = alt;
} }
}; };
@ -170,6 +171,7 @@ GAME.PieceMovement = class {
constructor() { constructor() {
this.direction = 0; this.direction = 0;
this.stride = 0; this.stride = 0;
this.alt = false;
} }
add(direction) { add(direction) {
@ -177,9 +179,14 @@ GAME.PieceMovement = class {
return this; return this;
} }
add_stride(direction) { add_stride(direction, mode=3) {
this.direction |= 1 << direction; this.direction |= 1 << direction;
this.stride |= 1 << direction; this.stride |= mode << (direction * 2);
return this;
}
add_alt() {
this.alt = true;
return this; return this;
} }
@ -187,6 +194,7 @@ GAME.PieceMovement = class {
let copy = new GAME.PieceMovement(); let copy = new GAME.PieceMovement();
copy.direction = BITWISE.rotate_blocks(this.direction); copy.direction = BITWISE.rotate_blocks(this.direction);
copy.stride = BITWISE.rotate_blocks(this.stride); copy.stride = BITWISE.rotate_blocks(this.stride);
copy.alt = this.alt;
return copy; return copy;
} }
}; };
@ -314,6 +322,10 @@ GAME.Game = class {
for(let move of this.movement_tiles(piece, piece.tile)) { for(let move of this.movement_tiles(piece, piece.tile)) {
if(move.valid) { moves += 1; } if(move.valid) { moves += 1; }
} }
for(let move of this.movement_tiles_alt(piece, piece.tile)) {
if(move.valid) { moves += 1; }
}
} }
} }
@ -329,17 +341,6 @@ GAME.Game = class {
} }
process(play) { process(play) {
// Check if swapped piece.
// Check if piece should be promoted.
// Check if swapped piece should be promoted.
// Add piece to pool if taken.
// Move pieces.
// TODO
// - Validate move.
// - Improve data safety validation.
//
if(this.state.code != 0) { return false; } if(this.state.code != 0) { return false; }
let player = this.turn & 1; let player = this.turn & 1;
@ -384,6 +385,16 @@ GAME.Game = class {
if(!piece.promoted && piece.has_promotion() && !HEX.is_valid_board(hex)) { if(!piece.promoted && piece.has_promotion() && !HEX.is_valid_board(hex)) {
piece.promoted = true; piece.promoted = true;
} }
// Handle alt moves.
if(play.alt) {
switch(piece.piece) {
case GAME.Const.PieceId.Knight: {
piece.promoted = false;
} break;
}
}
this.turn++; this.turn++;
} break; } break;
@ -408,7 +419,7 @@ GAME.Game = class {
this.update_board(); this.update_board();
} }
movement_tiles(piece, tile, check_drop=false) { movement_tiles(piece, tile) {
let tiles = [ ]; let tiles = [ ];
let moves = piece.moves(); let moves = piece.moves();
let hex = this.board.tiles[tile].hex; let hex = this.board.tiles[tile].hex;
@ -420,7 +431,10 @@ GAME.Game = class {
for(let mask = BITWISE.lsb(directions); directions > 0; mask = BITWISE.lsb(directions)) { for(let mask = BITWISE.lsb(directions); directions > 0; mask = BITWISE.lsb(directions)) {
let direction_id = BITWISE.ffs(mask); let direction_id = BITWISE.ffs(mask);
let direction = GAME.Const.get_direction(direction_id); let direction = GAME.Const.get_direction(direction_id);
let stride = (moves.stride & mask) != 0; let stride = 0;
if(direction_id < 12) {
stride = (moves.stride & (3 << (direction_id * 2))) >> (direction_id * 2);
}
let dir_mask = mask; let dir_mask = mask;
if((dir_mask & 0xFFF) == 0) { dir_mask >>= 12; } if((dir_mask & 0xFFF) == 0) { dir_mask >>= 12; }
@ -432,7 +446,11 @@ GAME.Game = class {
let move_hex = hex.copy(); let move_hex = hex.copy();
// Check tiles in direction up to movement limit. // Check tiles in direction up to movement limit.
let max_dist = (stride)? 8 : 1; let max_dist = 1;
switch(stride) {
case 1: max_dist = 2; break;
case 3: max_dist = 9; break;
}
for(let dist = 1; dist <= max_dist; ++dist) { for(let dist = 1; dist <= max_dist; ++dist) {
move_hex.add(direction); move_hex.add(direction);
@ -539,73 +557,6 @@ GAME.Game = class {
directions &= ~mask; directions &= ~mask;
} }
// Handle drop rules for promoted castle
if(!check_drop && piece.piece == GAME.Const.PieceId.Castle && piece.promoted) {
let move_hex = hex.copy();
let mask_back = 1 << 3;
if(piece.player == GAME.Const.Player.Dusk) {
mask_back = BITWISE.rotate_blocks(mask_back);
}
let mask_column = mask_back | BITWISE.rotate_blocks(mask_back);
let direction = GAME.Const.get_direction(BITWISE.ffs(mask_back));
move_hex.add(direction);
let status = (block_directions == 0 || (mask_back & block_directions) != 0);
// Check if backward tile meets placement rules.
for(let i = 0; i < 9; ++i) {
move_hex.add(direction);
if(HEX.is_valid_board(move_hex)) {
let valid = status;
let tile_id = HEX.hex_to_tile(move_hex);
let tile_data = this.board.tiles[tile_id];
let target_id = tile_data.piece;
// Check tile is empty.
if(target_id !== null) {
valid = false;
// Prevent change in blocking status
if((mask_column & block_directions) != 0) {
status = false;
}
}
// Prevent placement that does not uncheck King.
let check_direct = (this.state.check & GAME.Const.Check.Direct) != 0;
let check_count = this.state.check & 0x3F;
if(piece.player == (this.turn & 1) && this.state.check != 0) {
if(check_direct == 0 && check_count == 1) {
valid = valid && tile.checking != 0;
} else {
valid = false;
}
}
// Check off-sides.
if(piece.player == 0) {
valid = valid && (move_hex.y <= this.board.columns[move_hex.x].extent[+(!piece.player)]);
} else {
valid = valid && (move_hex.y >= this.board.columns[move_hex.x].extent[+(!piece.player)]);
}
// Check if position puts king in check.
let movements = this.movement_tiles(piece, tile_id, true);
for(let movement of movements) {
if(movement.check) {
valid = false;
break;
}
}
tiles.push(new GAME.MovementTile(tile_id, valid, false, 0, 0));
} else { break; }
}
}
return tiles; return tiles;
} }
@ -626,64 +577,162 @@ GAME.Game = class {
return ((moves.direction & mask) != 0 && (range == 1 || (moves.stride & mask) != 0)); return ((moves.direction & mask) != 0 && (range == 1 || (moves.stride & mask) != 0));
} }
movement_tiles_alt(piece) {
let tiles = [ ];
if(piece.promoted) {
let hex = this.board.tiles[piece.tile].hex;
let block_directions = piece.blocking | BITWISE.rotate_blocks(piece.blocking);
switch(piece.piece) {
case GAME.Const.PieceId.Knight: {
// Check all tiles if not blocking.
if(block_directions == 0) {
for(let i = 0; i < GAME_DATA.board.tiles.length; ++i) {
if(this.placable_tile(piece, i)) {
tiles.push(new GAME.MovementTile(i, true, false, 0, 0));
}
}
}
// Check tiles in blocking directions if blocking.
else {
let directions = block_directions;
for(let mask = BITWISE.lsb(directions); directions > 0; mask = BITWISE.lsb(directions)) {
let direction_id = BITWISE.ffs(mask);
let direction = GAME.Const.get_direction(direction_id);
let move_hex = hex.copy();
for(let dist = 1; dist <= 9; ++dist) {
move_hex.add(direction);
if(HEX.is_valid_board(move_hex)) {
let tile_id = HEX.hex_to_tile(move_hex);
let tile_data = this.board.tiles[tile_id];
let target_id = tile_data.piece;
if(target_id !== null) { break; }
if(this.placable_tile(piece, tile_id)) {
tiles.push(new GAME.MovementTile(tile_id, true, false, 0, 0));
}
} else { break; }
}
directions &= ~mask;
}
}
} break;
case GAME.Const.PieceId.Castle: {
let mask_back = 1 << 3;
if(piece.player == GAME.Const.Player.Dusk) {
mask_back = BITWISE.rotate_blocks(mask_back);
}
let mask_column = mask_back | BITWISE.rotate_blocks(mask_back);
let direction = GAME.Const.get_direction(BITWISE.ffs(mask_back));
let move_hex = hex.copy();
move_hex.add(direction);
let status = (block_directions == 0 || (mask_back & block_directions) != 0);
// Check if backward tile meets placement rules.
for(let i = 0; i < 9; ++i) {
move_hex.add(direction);
if(HEX.is_valid_board(move_hex)) {
let tile_id = HEX.hex_to_tile(move_hex);
let tile_data = this.board.tiles[tile_id];
let target_id = tile_data.piece;
let valid = status && this.placable_tile(piece, tile_id);
if(target_id !== null) {
if((mask_column & block_directions) != 0) {
status = false;
}
}
if(valid) {
tiles.push(new GAME.MovementTile(tile_id, true, false, 0, 0));
}
} else { break; }
}
} break;
}
}
return tiles;
}
placement_tiles(piece_id, player) { placement_tiles(piece_id, player) {
let tiles = [ ]; let tiles = [ ];
let piece = new GAME.Piece(piece_id, player); let piece = new GAME.Piece(piece_id, player);
// Get tiles onto which piece may be placed. // Get tiles onto which piece may be placed.
for(let i = 0; i < this.board.tiles.length; ++i) { for(let i = 0; i < this.board.tiles.length; ++i) {
let hex = HEX.tile_to_hex(i); if(this.placable_tile(piece, i)) {
let tile = this.board.tiles[i]; tiles.push(new GAME.MovementTile(i, true, false, false));
let valid = false;
// Check if tile is occupied.
if(tile.piece === null) {
let position_valid = true;
// Prevent placement that does not uncheck King.
let check_direct = (this.state.check & GAME.Const.Check.Direct) != 0;
let check_count = this.state.check & 0x3F;
if(player == (this.turn & 1) && this.state.check != 0) {
if(check_direct == 0 && check_count == 1) {
position_valid = tile.checking != 0;
} else {
position_valid = false;
}
}
// Check off-sides.
if(piece.player == 0) {
position_valid = position_valid && (hex.y <= this.board.columns[hex.x].extent[+(!player)]);
} else {
position_valid = position_valid && (hex.y >= this.board.columns[hex.x].extent[+(!player)]);
}
// Check militia stacking.
if(piece_id == GAME.Const.PieceId.Militia && this.board.columns[hex.x].militia[player]) {
position_valid = false;
}
// Check if position puts king in check.
let checking = false;
let movements = this.movement_tiles(piece, i, true);
for(let movement of movements) {
if(movement.check) {
checking = true;
break;
}
}
// Piece must have movements and not put king in check.
if(position_valid && movements.length > 0 && !checking) {
valid = true;
}
} }
tiles.push(new GAME.MovementTile(i, valid, false, false));
} }
return tiles; return tiles;
} }
placable_tile(piece, tile_id) {
let valid = false;
let hex = HEX.tile_to_hex(tile_id);
let tile = this.board.tiles[tile_id];
// Check if tile is occupied.
if(tile.piece === null) {
let position_valid = true;
// Prevent placement that does not uncheck King.
let check_direct = (this.state.check & GAME.Const.Check.Direct) != 0;
let check_count = this.state.check & 0x3F;
if(piece.player == (this.turn & 1) && this.state.check != 0) {
if(check_direct == 0 && check_count == 1) {
position_valid = tile.checking != 0;
} else {
position_valid = false;
}
}
// Check off-sides.
if(piece.player == 0) {
position_valid = position_valid && (hex.y <= this.board.columns[hex.x].extent[+(!piece.player)]);
} else {
position_valid = position_valid && (hex.y >= this.board.columns[hex.x].extent[+(!piece.player)]);
}
// Check militia stacking.
if(piece.piece == GAME.Const.PieceId.Militia && this.board.columns[hex.x].militia[piece.player]) {
position_valid = false;
}
// Check if position puts king in check.
let checking = false;
let movements = this.movement_tiles(piece, tile_id, true);
for(let movement of movements) {
if(movement.check) {
checking = true;
break;
}
}
// Piece must have movements and not put king in check.
if(position_valid && movements.length > 0 && !checking) {
valid = true;
}
}
return valid;
}
}; };
GAME.Const = { GAME.Const = {
@ -763,11 +812,11 @@ GAME.Const = {
.add(5), .add(5),
new GAME.PieceMovement() new GAME.PieceMovement()
.add(0) .add(0)
.add(1) .add_stride(1, 1)
.add(2) .add_stride(2, 1)
.add(3) .add(3)
.add(4) .add_stride(4, 1)
.add(5), .add_stride(5, 1),
), ),
new GAME.GamePiece( new GAME.GamePiece(
"Knight", "Knight",
@ -781,8 +830,6 @@ GAME.Const = {
.add(16) .add(16)
.add(17), .add(17),
new GAME.PieceMovement() new GAME.PieceMovement()
.add(0)
.add(3)
.add(6) .add(6)
.add(8) .add(8)
.add(9) .add(9)
@ -790,7 +837,8 @@ GAME.Const = {
.add(13) .add(13)
.add(14) .add(14)
.add(16) .add(16)
.add(17), .add(17)
.add_alt(),
), ),
new GAME.GamePiece( new GAME.GamePiece(
"Tower", "Tower",
@ -831,7 +879,8 @@ GAME.Const = {
.add(4) .add(4)
.add(5) .add(5)
.add(7) .add(7)
.add(10), .add(10)
.add_alt(),
), ),
new GAME.GamePiece( new GAME.GamePiece(
"Dragon", "Dragon",

View File

@ -76,13 +76,23 @@ const INTERFACE = {
if(piece_id !== null) { if(piece_id !== null) {
let piece = GAME_DATA.board.pieces[piece_id]; let piece = GAME_DATA.board.pieces[piece_id];
player = piece.player; player = piece.player;
movements = GAME_DATA.movement_tiles(piece, selection.tile); if(piece.moves().alt && INTERFACE_DATA.alt_mode) {
movements = GAME_DATA.movement_tiles_alt(piece);
} else {
movements = GAME_DATA.movement_tiles(piece, selection.tile);
}
} }
} else { } else {
player = Math.floor(selection.tile / 7); player = Math.floor(selection.tile / 7);
player ^= INTERFACE_DATA.player & 1; player ^= INTERFACE_DATA.player & 1;
if(INTERFACE_DATA.player == 2) { player ^= INTERFACE_DATA.rotate; } if(INTERFACE_DATA.player == 2) { player ^= INTERFACE_DATA.rotate; }
movements = GAME_DATA.placement_tiles(selection.tile % 7, player);
let select_alt = INTERFACE.selection_has_alt(INTERFACE_DATA.select);
if(select_alt !== null) {
movements = GAME_DATA.movement_tiles_alt(select_alt);
} else {
movements = GAME_DATA.placement_tiles(selection.tile % 7, player);
}
} }
if(movements !== null) { if(movements !== null) {
@ -90,7 +100,7 @@ const INTERFACE = {
for(let movement of movements) { for(let movement of movements) {
if(movement.valid) { if(movement.valid) {
// Show valid/threat hints if piece belongs to player and is player turn. // Show valid/threat hints if piece belongs to player and is player turn.
if(INTERFACE_DATA.player == 2 || player == INTERFACE_DATA.player) { // && (GAME_DATA.turn & 1) == player if(INTERFACE_DATA.player == 2 || player == INTERFACE_DATA.player) {
if(GAME_DATA.board.tiles[movement.tile].threaten[+(!player)] > 0) { if(GAME_DATA.board.tiles[movement.tile].threaten[+(!player)] > 0) {
INTERFACE_DATA.board_state[movement.tile][zone] = INTERFACE.TileStatus.Threat; INTERFACE_DATA.board_state[movement.tile][zone] = INTERFACE.TileStatus.Threat;
} else { } else {
@ -195,50 +205,77 @@ const INTERFACE = {
}, },
click() { click() {
let initial_select = INTERFACE_DATA.select;
if(INTERFACE_DATA.hover !== null) { if(INTERFACE_DATA.hover !== null) {
if(INTERFACE.Ui.match_select(INTERFACE_DATA.hover, INTERFACE_DATA.select)) { if(INTERFACE.Ui.match_select(INTERFACE_DATA.hover, INTERFACE_DATA.select)) {
INTERFACE_DATA.select = null; INTERFACE_DATA.select = null;
INTERFACE_DATA.alt_mode = false;
} else { } else {
// Check if operation can be performed on new tile. // Check if operation can be performed on new tile.
// Otherwise, switch selection. // Otherwise, switch selection.
let is_valid = false; let result = 0;
if(INTERFACE_DATA.select !== null && INTERFACE_DATA.hover.source == 0 && INTERFACE_DATA.player == (GAME_DATA.turn & 1)) { if(INTERFACE_DATA.select !== null) {
let tile_state = INTERFACE_DATA.board_state[INTERFACE_DATA.hover.tile][1];
is_valid = (tile_state == INTERFACE.TileStatus.Valid || tile_state == INTERFACE.TileStatus.Threat); // Play selection.
if(INTERFACE_DATA.hover.source == 0 && INTERFACE_DATA.player == (GAME_DATA.turn & 1)) {
let tile_state = INTERFACE_DATA.board_state[INTERFACE_DATA.hover.tile][1];
result = +(tile_state == INTERFACE.TileStatus.Valid || tile_state == INTERFACE.TileStatus.Threat);
}
// Alt move selection.
else if(INTERFACE_DATA.select.source == 0 && INTERFACE_DATA.hover.source == 1) {
let alt_piece = INTERFACE.selection_has_alt(INTERFACE_DATA.select);
if(alt_piece !== null) {
let pool_player = Math.floor(INTERFACE_DATA.hover.tile / 7);
pool_player ^= INTERFACE_DATA.player & 1;
if(INTERFACE_DATA.player == 2) { pool_player ^= INTERFACE_DATA.rotate; }
if((INTERFACE_DATA.hover.tile % 7) == alt_piece.piece && alt_piece.player == pool_player) {
INTERFACE_DATA.alt_mode = !INTERFACE_DATA.alt_mode;
result = 2;
}
}
}
} }
// Handle player action. // Handle player action.
if(is_valid) { switch(result) {
let play = new GAME.Play(INTERFACE_DATA.select.source, INTERFACE_DATA.select.tile, INTERFACE_DATA.hover.tile); case 1: {
INTERFACE.process(play); let play = new GAME.Play(
INTERFACE_DATA.select = null; INTERFACE_DATA.select.source,
} INTERFACE_DATA.select.tile,
INTERFACE_DATA.hover.tile,
INTERFACE_DATA.alt_mode
);
INTERFACE.process(play);
INTERFACE_DATA.select = null;
INTERFACE_DATA.alt_mode = false;
} break;
// Handle new selection. case 0: {
else { // Handle new selection.
INTERFACE_DATA.select = null; INTERFACE_DATA.select = null;
INTERFACE_DATA.alt_mode = false;
// Select tile on board. // Select tile on board.
if(INTERFACE_DATA.hover.source == 0) { if(INTERFACE_DATA.hover.source == 0) {
if(GAME_DATA.board.tiles[INTERFACE_DATA.hover.tile].piece !== null) { if(GAME_DATA.board.tiles[INTERFACE_DATA.hover.tile].piece !== null) {
INTERFACE_DATA.select = INTERFACE_DATA.hover; INTERFACE_DATA.select = INTERFACE_DATA.hover;
}
} }
}
// Select tile in pools. // Select tile in pools.
else { else {
let pool_player = Math.floor(INTERFACE_DATA.hover.tile / 7); let pool_player = Math.floor(INTERFACE_DATA.hover.tile / 7);
pool_player ^= INTERFACE_DATA.player & 1; pool_player ^= INTERFACE_DATA.player & 1;
if(INTERFACE_DATA.player == 2) { pool_player ^= INTERFACE_DATA.rotate; } if(INTERFACE_DATA.player == 2) { pool_player ^= INTERFACE_DATA.rotate; }
let pool_piece = INTERFACE_DATA.hover.tile % 7; let pool_piece = INTERFACE_DATA.hover.tile % 7;
if(GAME_DATA.pools[pool_player].pieces[pool_piece] > 0) { if(GAME_DATA.pools[pool_player].pieces[pool_piece] > 0) {
INTERFACE_DATA.select = INTERFACE_DATA.hover; INTERFACE_DATA.select = INTERFACE_DATA.hover;
}
} }
} } break;
} }
} }
} }
@ -248,9 +285,7 @@ const INTERFACE = {
INTERFACE_DATA.select = null; INTERFACE_DATA.select = null;
} }
if(initial_select !== INTERFACE_DATA.select) { INTERFACE.draw();
INTERFACE.draw();
}
}, },
release() { release() {
@ -263,9 +298,15 @@ const INTERFACE = {
// Handle player action. // Handle player action.
if(is_valid) { if(is_valid) {
let play = new GAME.Play(INTERFACE_DATA.select.source, INTERFACE_DATA.select.tile, INTERFACE_DATA.hover.tile); let play = new GAME.Play(
INTERFACE_DATA.select.source,
INTERFACE_DATA.select.tile,
INTERFACE_DATA.hover.tile,
INTERFACE_DATA.alt_mode
);
INTERFACE.process(play); INTERFACE.process(play);
INTERFACE_DATA.select = null; INTERFACE_DATA.select = null;
INTERFACE_DATA.alt_mode = false;
} }
} }
}, },
@ -784,12 +825,11 @@ const INTERFACE = {
pool(x, y, basis, player) { pool(x, y, basis, player) {
let radius = INTERFACE.Radius * this.scale; let radius = INTERFACE.Radius * this.scale;
let icon_radius = 0.69 * radius; let icon_radius = 0.69 * radius;
for(let i = 0; i < 7; ++i) { for(let i = 0; i < 7; ++i) {
let is_hover = INTERFACE.Ui.tile_is_hover(1, i + basis); let tile_id = i + basis;
let is_select = INTERFACE.Ui.tile_is_select(1, i + basis); let is_hover = INTERFACE.Ui.tile_is_hover(1, tile_id);
let is_select = INTERFACE.Ui.tile_is_select(1, tile_id);
let ix = +(i > 1) + (i > 4); let ix = +(i > 1) + (i > 4);
let iy = i - ((i > 1) * 3) - ((i > 4) * 2) + (0.5 * (ix == 1)); let iy = i - ((i > 1) * 3) - ((i > 4) * 2) + (0.5 * (ix == 1));
@ -802,9 +842,32 @@ const INTERFACE = {
this.ctx.save(); this.ctx.save();
this.ctx.translate(gui_x, gui_y); this.ctx.translate(gui_x, gui_y);
// Get background color.
let background_color = null;
let alt_piece = INTERFACE.selection_has_alt(INTERFACE_DATA.hover);
if(alt_piece !== null) {
if(alt_piece.piece == i && alt_piece.player == player) {
background_color = INTERFACE.Color.HintValidDark;
}
}
alt_piece = INTERFACE.selection_has_alt(INTERFACE_DATA.select);
if(is_select) { background_color = INTERFACE.Color.HintSelect; }
else if(alt_piece !== null) {
if(alt_piece.piece == i && alt_piece.player == player) {
if(INTERFACE_DATA.alt_mode) {
background_color = INTERFACE.Color.HintSelect;
} else {
background_color = INTERFACE.Color.HintValid;
}
}
}
// Draw border // Draw border
if(is_select || is_hover || (INTERFACE_DATA.player == player && INTERFACE_DATA.player == (GAME_DATA.turn & 1)) || (INTERFACE_DATA.player == 2 && player == (GAME_DATA.turn & 1))) { let turn_indicator = player == (GAME_DATA.turn & 1) && (INTERFACE_DATA.player == player || INTERFACE_DATA.player == 2);
if(background_color !== null || turn_indicator) {
if(is_hover) { this.ctx.fillStyle = INTERFACE.Color.HintHover; } if(is_hover) { this.ctx.fillStyle = INTERFACE.Color.HintHover; }
else { this.ctx.fillStyle = player_color; } else { this.ctx.fillStyle = player_color; }
this.ctx.beginPath(); this.ctx.beginPath();
@ -812,9 +875,8 @@ const INTERFACE = {
this.ctx.fill(); this.ctx.fill();
} }
// Draw background if indicator is present. if(background_color === null) { background_color = INTERFACE.Color.TileDark; }
if(is_select) { this.ctx.fillStyle = INTERFACE.Color.HintSelect; } this.ctx.fillStyle = background_color;
else { this.ctx.fillStyle = INTERFACE.Color.TileDark; }
this.ctx.beginPath(); this.ctx.beginPath();
this.hex(0.94); this.hex(0.94);
this.ctx.fill(); this.ctx.fill();
@ -886,6 +948,7 @@ const INTERFACE = {
hover: null, hover: null,
select: null, select: null,
alt_mode: false,
handles: [dawn, dusk], handles: [dawn, dusk],
board_state: [ ], board_state: [ ],
@ -1338,6 +1401,21 @@ const INTERFACE = {
INTERFACE.process(result.play); INTERFACE.process(result.play);
} }
}, },
selection_has_alt(selection) {
if(selection !== null) {
if(selection.source == 0) {
let piece_id = GAME_DATA.board.tiles[selection.tile].piece;
if(piece_id !== null) {
let piece = GAME_DATA.board.pieces[piece_id];
if(piece.moves().alt) {
return piece;
}
}
}
}
return null;
},
}; };
INTERFACE.TileScale = 0.9; INTERFACE.TileScale = 0.9;