Check for Checkmate in Chessboard.js - javascript

I making a chess game with chessboardjs and I want to check for checkmate.
How can I do this ?
I'm using that code but it isn't working.
if (game.game_over() == true) {
alert("Game Over");
}
The whole function is:
var onDragStart = function (source, piece, position, orientation) {
if (game.game_over() == true) {
alert("Game Over");
}
if (turn == 1) {
if (piece.search(/^b/) === -1) {
return false;
}
} else {
if (piece.search(/^w/) === -1) {
return false;
}
}
if (turn == 1) {
turn = 0;
} else {
turn = 1;
}
};

To check the state of a chess position, you'll need more than the chessboard representation but also a chess engine (the program which understands/enforces chess rules). A favorite for javascript is: chess.js (chessboard.js is only a graphical representation of the board and doesn't include any of the logic required to check for possible moves etc)
Like in this question How can I integrate chess.js and chessboard.js?
These libraries are often used together: https://github.com/jhlywa/chess.js/
and from there you have access to the rules of chess: https://github.com/jhlywa/chess.js/#game_over

To determine a game has ended, you have to calculate the possible legal moves for the side to move.
No legal moves for the side to move implies the game has ended.
If there are no legal moves and the king of the side to move is in check => checkmate.
Otherwise it is stalemate.

Related

matter.js: collisionStart triggered many times for one collision

I am working on a game app using React native and Matter.js.
I am trying to implement a system that adds points every time a bullet hits a target.
In order to do this, I am trying to use collisionStart to detect the collision.
However, even though the bullet and target collide only once, the event seems to be triggered 41 times.
This is the code:
Matter.Events.on(engine, 'collisionStart', (event) => {
let pairs = event.pairs
for (const pair of pairs) {
if (pair.bodyA.label === 'bullet' && pair.bodyB.label === 'Worm') {
console.log("target hit");
}
}
})
In the end, I'm planning to replace console.log with something that adds points. At the current moment, one collision seems like it would trigger the add points 41 times, which is obviously not ideal.
Any ideas what is happening here and how I can get this to trigger only once for one collision?
Try next example. I take it from my own project [you need little adaptd from ts to js]:
Matter.Events.on(this.starter.getEngine(), "collisionStart", function (event) {
root.collisionCheck(event, true);
});
public collisionCheck(event, ground: boolean) {
const myInstance = this;
const pairs = event.pairs;
for (let i = 0, j = pairs.length; i !== j; ++i) {
const pair = pairs[i];
if (pair.activeContacts) {
if (pair.bodyA.label === "bullet" && pair.bodyB.label === "Worm") {
const collectitem = pair.bodyA;
this.playerDie(collectitem);
} else if (pair.bodyB.label === "bullet" && pair.bodyA.label === "Worm") {
const collectitem = pair.bodyB;
this.playerDie(collectitem);
}
// ....
}
}
}
public destroyBody = (destroyBody) => {
try {
Matter.Composite.remove(this.getWorld(), destroyBody);
} catch(err) {
console.log(err)
}
}
If you still have same problem , we can adapt also with flag PREVENT_DOUBLE_BY_1_SECOUND for example.

How to put an Application's value as a variable in javascript?

I have a counter that updates itself everytime the page loads. I want to use that counter's value as a variable in javascript so that I could use it. How do I do this?
if (Application["counter"] == null)
{
Application["counter"] = 0;
}
if (Application["counter"] != null)
{
if (Request.Form["sub1"]==null)
{
Response.Write("<script>alert('You must Enter Number')</script>");
}
if (Request.Form["sub1"] != null)
{
Application["counter"] =(int)Application["counter"]+ 1;
Response.Write(Application["counter"]);
}
}
this is the code for the counter in the cs page.
Whenever I go to write Javascript and try to save it as a variable it gives me an error: Error 16 Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement.
var y=<%Application["counter"];>%;
For the server side code, you can use it like below. Just a recommendation. And for front end side, you have typos.
// Server side code - Correct usage
if (Application["counter"] == null) {
Application["counter"] = 0;
}
// there's no need to check Application["counter"] after the code above
if (Request.Form["sub1"] == null)
{
Response.Write("<script>alert('You must Enter Number')</script>");
}
// also, you can use else in here instead of another if, because there isn't any other condition.
else {
Application["counter"] = (int)Application["counter"] + 1;
Response.Write(Application["counter"]);
}
// JS Code
var y = <%= Application["counter"] %>;

Is there a more elegant way of writing a function that returns the name of an image based on the argument of the function?

I have an object which has a property called tier which has 9 possible values - IRON, BRONZE, SILVER, GOLD, PLATINUM, DIAMOND, MASTER, GRANDMASTER and CHALLENGER.
Based on that property, I want to display the emblem corresponding to the tier, however, whilst the tier might be called IRON, the image file with the emblem would be called Emblem_Iron.
This is why I've created a function which takes a tier as an argument and then returns the file name of the emblem image corresponding to the tier so that I could do this:
<img class='ranked-emblem' :src="'../emblems/' + rankedEmblem(league.tier) + '.png'" alt="">
And my function is:
rankedEmblem(tier){
if (tier === 'IRON') {
return 'Emblem_Iron'
} else if (tier === 'BRONZE') {
return 'Emblem_Bronze'
} else if (tier === 'SILVER') {
return 'Emblem_Silver'
} else if (tier === 'GOLD') {
return 'Emblem_Gold'
} else if (tier === 'PLATINUM') {
return 'Emblem_Platinum'
} else if (tier === 'DIAMOND') {
return 'Emblem_Diamond'
} else if (tier === 'MASTER') {
return 'Emblem_Master'
} else if (tier === 'GRANDMASTER') {
return 'Emblem_Grandmaster'
} else if (tier === 'CHALLENGER') {
return 'Emblem_Challenger'
}
}
While this works completely fine, I was wondering if there's a more elegant way of doing this that would shorten the function and maybe remove a couple of if els.
You can use a plain Object as a map.
var emblems = {
IRON: "Emblem_Iron",
BRONZE: "Emblem_Bronze",
SILVER: "Emblem_Silver",
GOLD: "Emblem_Gold",
PLATINUM: "Emblem_Platinum",
DIAMOND: "Emblem_Diamond",
MASTER: "Emblem_Master",
GRANDMASTER: "Emblem_Grandmaster",
CHALLENGER: "Emblem_Challenger"
};
function rankedEmblem(tier) {
// Could also help user by doing: emblems[tier.toUpperCase()]
return emblems[tier] || "No_Emblem";
}
console.log(rankedEmblem("GOLD"));
console.log(rankedEmblem("PLATINUM"));
You can use String concatination and functions like so:
function rankedEmblem(tier){
return "Emblem_" + tier.charAt(0).toUpperCase() + tier.slice(1).toLowerCase();
}
console.log(rankedEmblem("CHALLENGER"));
rankedEmblem(tier){
let myEmblems = {IRON: 'Emblem_Iron', BRONZE: 'Emblem_Bronze' };
//You can put whatever emblem you want as key:value pair
return myEmblems[tier];
}
rankedEmblem(tier) {
return 'Emblem_' + tier.substr(0, 1) + tier.substr(2).toLowerCase();
}
You're in Javascript: use an object. There is no reason for if or which when you know what the mapping is:
// this mapping will probably live in its own file
const mapping = {
IRON: `emblem-Iron.png`,
GOLD: `emblem-Gold.png`,
...
}
// this function will probably _also_ live in its own file,
// and import that mapping (either with import or require).
function getImageForTier(tier) {
let tierImage = mapping[tier];
if (!tierImage) {
// ... somehow, your code allowed for an unknown tier to make it this far.
console.error(`unknown tier ${tier}!`);
return UNKNOWN_TIER_IMAGE;
}
return tierImage;
}
You could use a function to just blindly generate the image filename based on the tier string, but then you run into the problem of "what about if the tier is actually wrong/unknown?".
If you already validate the tier somewhere earlier, then you don't even need a function, a template string will let you do this. But then at least make sure all your image filenames are in lowercase, because you should be able to rely on assets existing, and having to worry about "are there supposed to be capital letters in this file?" makes a dev life unnecessarily difficult:
image.src = `${baselocation}/ember-${tier.toLowerCase()}.png`

Creating multiples of the same DOM Element Image

I am a new Developer and am working on a Tic Tac Toe SPA. I have a working game, but I want to customize the game tokens. I have tried creating a DOM element a few different ways, which were all successful. Here is the problem:
Every time I go to make a second move for a player, the DOM image disappears and reappears in the new square selected. Obviously this is not the desired action. Is there something I don't know about creating a DOM element. I have googled this and read countless articles and watched countless videos.
const stark = document.createElement('img')
stark.src = 'https://i.imgur.com/d70XlET.png'
stark.height = 80
stark.width = 80
const lanister = document.createElement('img')
lanister.src = 'https://i.imgur.com/d70XlET.png'
lanister.height = 80
lanister.width = 80
const play = (event) => {
if (gameOver === false) {
if (event.target.innerHTML === '') {
$('#' + event.target.id).append(turn)
}
}
}
'turn' is a variable that works with a toggle function to switch between players and stores whichever players turn it is(i.e. 'stark')
I would be really grateful if someone could point me in the direction of a resource where I could learn more about this.
const player1 = stark
const player2 = lanister
let turn = player1
let prevTurn = player2
const togglePrevTurn = () => {
if (!gameOver) {
if (prevTurn === player1) {
prevTurn = player2
} else {
prevTurn = player1
}
}
}
const toggleTurn = () => {
if (!gameOver) {
if (turn === player1) {
turn = player2
} else {
turn = player1
}
$('#message').text(turn + " 's turn")
}
}
Whenever you use Javascript's appendChild or jQuery's append, when you pass it an element, that element gets removed from its previous location in the DOM (if it's in the DOM), and then gets inserted at the new position. It sounds like what you need to do is explicitly create a new element each time, which you might do with cloneNode().
Also, probably best to name your variables precisely - if turn is an image, name it to make it clear that it's an image, perhaps currentPlayerImage.
In addition, because you already have a reference to the event.target, there's no need to reselect it with $('#' + event.target.id) - just select event.target:
const play = (event) => {
if (gameOver === false) {
if (event.target.innerHTML === '') {
$(event.target).append(currentPlayerImage.cloneNode());
}
}
}

Getting touchInput from a touch that starts outside of the Unity player

I have a Unity WebGL player that is embedded in a React application. The React application has drag and drop tiles that can be drug and dropped onto the WebGL player. When the tiles begin to be drug unity starts raycasting so that you can tell what object in the screen you are going to drop onto. All of this works perfectly when using a mouse, but I've noticed Input.touchCount always returns 0 unless the touch originates inside the WebGL player. Does anyone know a fix to this? Been head bashing this one for a moment now...
Here is the raycasting code. Like I said, it works perfectly for a mouse... but I cannot get a touch.position returned.
public void LateUpdate()
{
if (SHOULD_CAST_RAY)
{
// always returning 0
Debug.Log(Input.touchCount);
RaycastHit hit;
Vector3 position = Input.touchSupported
&& Input.touchCount == 1
? new Vector3(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y, 0)
: Input.mousePosition;
if (Physics.Raycast(RigsCamera.ScreenPointToRay(position), out hit, CameraRigControllerScript.CameraDistanceMax * 1.5f, 1 << 10))
{
if (CURRENT_SELECTION == null)
{
CURRENT_SELECTION = UnsafeGetModelInstantiationFromRaycast(hit);
ApplySelectionIndication();
}
else if (!IsAlreadySelected(hit))
{
RemoveSelectionIndication();
CURRENT_SELECTION = UnsafeGetModelInstantiationFromRaycast(hit);
ApplySelectionIndication();
}
return;
}
if (CURRENT_SELECTION != null)
{
RemoveSelectionIndication();
CURRENT_SELECTION = null;
}
}
}
Also, if I touch the screen on the Unity WebGL player and then start dragging one of my React components which sends a message to Unity to start raycasting; I get atouch.position that is at the point I touched and does not move with the finger... The hell?
If you have Unity 5+ version you can use mousePosition for everything, since the Input class handles the Touch (0) and Mouse (0) exactly the same, have you tried that?
Vector3 position = Input.touchSupported && Input.touchCount == 1
? new Vector3(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y, 0)
: Input.mousePosition;
Try changing this to only
Vector3 position = Input.mousePosition;
I posted a solution on the Unity forums in-case there is any update to this thread in the future.
In WebGL, the Unity Input class does not register touch events that originate begin outside of the WebGL player. To solve this problem I used a couple boolean values that are toggled by my React components through the GameInstance.SendMessage method; as well as a Vector3 to store a value sent from React, also through SendMessage. Here are the important c# bits. If anyone has any questions, please ask and I'll walk you through the rest!
bool SHOULD_CAST_RAY;
bool USE_EXTERNAL_ORIGINATING_TOUCH_POS;
Vector3 EXTERNAL_ORIGINATING_TOUCH_POS;
public void LateUpdate()
{
if (SHOULD_CAST_RAY)
{
if (USE_EXTERNAL_ORIGINATING_TOUCH_POS && EXTERNAL_ORIGINATING_TOUCH_POS.z < 0) { return; }
RaycastHit hit;
Vector3 screenPoint = Input.mousePresent ? Input.mousePosition : Vector3.zero;
Vector3 viewportPoint = USE_EXTERNAL_ORIGINATING_TOUCH_POS ? RigsCamera.ScreenToViewportPoint(EXTERNAL_ORIGINATING_TOUCH_POS) : Vector3.zero;
if (Physics.Raycast(
USE_EXTERNAL_ORIGINATING_TOUCH_POS
? RigsCamera.ViewportPointToRay(new Vector3(viewportPoint.x, 1 - viewportPoint.y, 0))
: RigsCamera.ScreenPointToRay(screenPoint),
out hit,
CameraRigControllerScript.CameraDistanceMax * 1.5f,
1 << 10
)) {
if (CURRENT_SELECTION == null)
{
CURRENT_SELECTION = UnsafeGetModelInstantiationFromRaycast(hit);
ApplySelectionIndication();
}
else if (!IsAlreadySelected(hit))
{
RemoveSelectionIndication();
CURRENT_SELECTION = UnsafeGetModelInstantiationFromRaycast(hit);
ApplySelectionIndication();
}
return;
}
if (CURRENT_SELECTION != null)
{
RemoveSelectionIndication();
CURRENT_SELECTION = null;
}
}
}
// The below methods are used to control the raycasting from React through sendMessage
public void ClearExternalOriginatingTouchPosition()
{
EXTERNAL_ORIGINATING_TOUCH_POS = new Vector3(0, 0, -1f);
USE_EXTERNAL_ORIGINATING_TOUCH_POS = false;
}
public void DisableRaycasting()
{
SHOULD_CAST_RAY = false;
RemoveSelectionIndication();
CURRENT_SELECTION = null;
}
public void EnableRaycasting()
{
SHOULD_CAST_RAY = true;
}
public void SetExternalOriginatingTouchPosition(string csv)
{
string[] pos = csv.Split(',');
EXTERNAL_ORIGINATING_TOUCH_POS = new Vector3(float.Parse(pos[0]), float.Parse(pos[1]), 0);
USE_EXTERNAL_ORIGINATING_TOUCH_POS = true;
}

Categories

Resources