JS game Crowns and Anchors: error in outcome - javascript

I'm having trouble understanding the outcome of a game I have developed with the help of the book 'Learning JavaScript' by Ethan Brown.
Here is the code:
//helper functions for randomizing
function rand(x,y){
return x + Math.floor((y-x+1)*Math.random());
}
function getFace(){ return ['crown','heart','spade','club','diamond','anchor'][rand(0,5)]; }
//the game
function crownsAndAnchors(){
console.log('Let\'s play Crowns and Anchors!');
let rounds = 0;
let funds = 50;
while( funds > 1 && funds < 100 ){
rounds ++;
console.log(`Round: ${rounds}`);
let totalBet = 7;
let bets = { crown: 0, heart: 0, spade:0, club:0, diamond:0, anchor:0 };
if (totalBet == 7){
totalBet = funds;
console.log('You pulled out 7p, your lucky number! Bet all on heart');
bets.heart = totalBet;
}else{
//distribute totalBet randomly
}
funds = funds - totalBet;
console.log('\tBets: ' + Object.keys(bets).map(face => `${face} ${bets[face]}p`).join(' || ') + ` (total: ${totalBet} pence)`);
const hand = [];
// roll the dice
console.log("_______________rolling the dice ____________")
for (let i = 0; i < 3; i++) {
hand.push(getFace());
}
console.log(`\tHand: ${hand.join(', ')}`);
//check for winnings
let wins = 0;
for (let i = 0; i < hand.length; i++) {
let face = hand[i];
if (bets[face] > 0) wins = wins + bets[face];
}
funds = funds + wins;
console.log(`\tWinnings: ${wins}`);
}
console.log(`\nEnding Funds: ${funds}`);
}
crownsAndAnchors();
I have hard-coded variable totalBet to be 7 to easily monitor final outcome. For example, if two out of three die outcomes are heart than the Ending Funds should be 150, correct?
However, when I run the code (Node v7.6.0) this is what I am returned:
Let's play Crowns and Anchors!
Round: 1
You pulled out 7p, your lucky number! Bet all on heart
Bets: crown: 0p || heart: 50p || spade: 0p || club: 0p || diamond: 0p || anchor: 0p (total: 50 pence)
_______________rolling the dice ____________
Hand: heart, heart, club
Winnings: 100
Ending funds: 100
I know I'm somehow updating funds incorrectly I just cannot figure out why.
Thank you so much in advance!!!

The line
funds = funds - totalBet;
is setting funds to 0, then later you get two wins of 50 added to it to give you 100.
If you eliminate that line where funds = funds - totalBet, then you get the 150 you are expecting.
Or move that line to after the dice roll and only execute it if you did not win anything.

Related

Flappy bird game with AI - Genetics algorithm doesn't work properly

I have a flappy bird game built with p5.js, every bird in my game is a neural network with 4 inputs, 4 hidden nodes, and 1 output.
if the output is bigger than 0.5, the bird should jump.
I use the genetics algorithm to improve the neural network, and I mostly select the neural networks(birds) with the best weights and biases, which are determined by the fitness score, crossover the parents, mutate by a low rate, and pass the offspring on to the next generation.
So for total of 10 birds, in the next generation, there should be 10 offspring that are somewhat better than the last 10 birds' generation.
After printing the fitness scores of my birds, seems like even after 300 generations, there is no improvement in the fitness score of each individual bird.
The way I calculate fitness is by the score itself, the score is incrementing every frame for each bird, and the longer the bird stays alive, the higher the score is.
My first approach was to look for anything that could overwrite the next generation with a brand new array of birds, but I couldn't spot anything that does it.
nextGeneration():
const nextGeneration = () => {
calculateFitness();
for (let i = 0; i < TOTAL; i++) {
// Select the most fit bird
let bird1 = rouletteWheelSelection();
print("Bird 1: " + bird1.fitness)
// Select another most fit bird
let bird2 = rouletteWheelSelection();
print("Bird 2: " + bird2.fitness)
// Use the crossover function to create an offspring from bird1 and bird2
let offspringBrain = crossOver(bird1, bird2);
// Mutate the offspring's brain with a small probability
offspringBrain.mutate(0.1);
// Add the offspring to the new population of birds
birds[i] = new Bird(offspringBrain);
}
// Clear the saved birds for the next generation
savedBirds = [];
}
rouletteWheelSelection():
const rouletteWheelSelection = () => {
//Sum of total fitness
let totalFitness = 0
savedBirds.forEach( element => {
totalFitness += element.fitness
});
// Generate a random number between 0 and the total fitness
const rand = Math.random() * totalFitness;
// Select the chromosome with the corresponding fitness
let fitnessSum = 0;
for (let i = 0; i < savedBirds.length; i++) {
fitnessSum += savedBirds[i].fitness;
if (fitnessSum >= rand) return savedBirds[i];
}
}
crossOver():
const crossOver = (bird1, bird2) => {
// Create a new NeuralNetwork by cloning bird1's brain
let offspring = bird1.brain.copy()
// Select a random point to split the weights and biases
let splitPoint = Math.floor(Math.random() * offspring.weights_ih.data.length);
// Cross over the weights and biases of bird1 and bird2 at the split point
for (let i = splitPoint; i < offspring.weights_ih.data.length; i++) {
offspring.weights_ih.data[i] = bird2.brain.weights_ih.data[i];
offspring.weights_ho.data[i] = bird2.brain.weights_ho.data[i];
offspring.bias_h.data[i] = bird2.brain.bias_h.data[i];
offspring.bias_o.data[i] = bird2.brain.bias_o.data[i];
}
return offspring;
}
draw() in the main sketch.js file:
function draw() {
if (counter % 150 == 0) {
pipes.push(new Pipe());
}
counter++;
for (var i = pipes.length - 1; i >= 0; i--) {
pipes[i].update();
for (let j = birds.length - 1; j >= 0; j--) {
if (pipes[i].hits(birds[j])) {
savedBirds.push(birds.splice(j, 1)[0]);
}
if (pipes[i].offscreen()) {
pipes.splice(i, 1);
}
}
}
for (let bird of birds) {
bird.think(pipes);
bird.update();
}
if (birds.length == 0 ) {
counter = 0;
nextGeneration();
pipes = [];
}
background(bgImg);
for (let bird of birds) {
bird.show();
}
for (let pipe of pipes) {
pipe.show();
}
}
Another approach I had in mind, was to look at the game side itself, and see if there's any issue in the way that the birds try to predict the output, but it does seem like the input nodes are correct.
think() in Bird.js:
think(pipes) {
//Find closest pipe
let closest = null;
let closestD = Infinity;
for (let i = 0; i < pipes.length; i++) {
let d = pipes[i].x - this.x;
if (d < closestD && d > 0) {
closest = pipes[i];
closestD = d;
}
}
let inputs = [];
inputs[0] = this.y / height; // bird's y
inputs[1] = closest.top / height; // top pipe's y
inputs[2] = closest.bottom / height; // bottom pipe's y
inputs[3] = closest.x / width; // pipes' x
let output = this.brain.predict(inputs); // predict if bird should jump
if (output[0] > 0.5) {
this.up()
}
}
What am I missing?

JavaScript function won't run twice with different inputs

I'm trying to make this function run twice with two different inputs, but it only runs once.
the code:
const data1dolphins = 44 + 23 + 71;
const data1Koalas = 65 + 54 + 49;
const data2dolphins = 85 + 54 + 41;
const data2Koalas = 23 + 34 + 27;
function calcAverage(data, dataValue) {
const scoreAverage = data * dataValue
return scoreAverage;
}
const data1DolphinsAverage = calcAverage(data1dolphins, 3)
const data1KoalasAverage = calcAverage(data1Koalas, 3)
const data2DolphinsAverage = calcAverage(data2dolphins, 3)
const data2KoalasAverage = calcAverage(data2Koalas, 3)
function checkWinner(avgTeamOne, avgTeamTwo) {
if (avgTeamOne >= (avgTeamTwo * 2)) {
console.log(`team one won with average score of : ${avgTeamOne}, while team two lost with average score of : ${avgTeamTwo}`)
} else if (avgTeamTwo >= (avgTeamOne * 2)) {
console.log(`team two won with average score of : ${avgTeamTwo}, while team one lost with average score of : ${avgTeamOne}`)
}
// console.log('testing round')
}
console.log('before')
checkWinner(data1DolphinsAverage, data1KoalasAverage)
console.log('middle')
checkWinner(data2DolphinsAverage, data2KoalasAverage)
console.log('after')
the output:
before
team one won with average score of : 540, while team two lost with average score of : 252
middle
after
Have you tried an else statement?
function checkWinner (avgTeamOne,avgTeamTwo){
if(avgTeamOne >= (avgTeamTwo*2)) {
console.log(`team one won with average score of : ${avgTeamOne}, while team two lost with average score of : ${avgTeamTwo}`);
} else if (avgTeamTwo >= (avgTeamOne*2)){
console.log(`team two won with average score of : ${avgTeamTwo}, while team one lost with average score of : ${avgTeamOne}`);
} else { <<
console.log("neither of these things happened."); <<
} <<
}
I find it a bit hard to see your purpose, as you didn't provide values for data1dolphins, data1Koalas, data2dolphins, or data2Koalas, but I'm guessing that this is the fix that you need.
the function ran fine after adding an else statment:
const data1dolphins = 44+23+71;
const data1Koalas = 65+54+49;
const data2dolphins = 85+54+41;
const data2Koalas = 23+34+27;
function calcAverage (data,dataValue){
const scoreAverage = data * dataValue
return scoreAverage;
}
const data1DolphinsAverage = calcAverage(data1dolphins,3)
const data1KoalasAverage = calcAverage(data1Koalas,3)
const data2DolphinsAverage = calcAverage(data2dolphins,3)
const data2KoalasAverage = calcAverage(data2Koalas,3)
function checkWinner (avgTeamOne,avgTeamTwo){
if(avgTeamOne >= (2*avgTeamTwo)) {
console.log(`team one won with average score of : ${avgTeamOne}, while team two lost with average score of : ${avgTeamTwo}`)
} else if (avgTeamTwo >= (2*avgTeamOne)){
console.log(`team two won with average score of : ${avgTeamTwo}, while team one lost with average score of : ${avgTeamOne}`)
}else {
console.log('none of the above')
}
}
console.log('before')
checkWinner(data1DolphinsAverage, data1KoalasAverage)
console.log('middle')
checkWinner(data2DolphinsAverage, data2KoalasAverage)
console.log('after')

How to make a AJAX driven board in a Snake and ladder turn based game which updates with players playing in different browsers?

I am working on developing a Multiplayer turn based Snake & Ladder game using HTML/JS(Front-end), PHP/MySQL back ended.
It is a AJAX driven game.
I have successfully done the following:
Created a login/Register page storing values in the database.
Upon Login -> Clicking on a button called 'multiplayer game': the user will be directed to a Chat-room where he can select a player with whom he needs to play.
Have implemented the AJAX driven chat system so real time chatting is achieved.
Once a user selects a player, both there pages get updated with against whom they are playing but not the board(since board is not written to implement ajax as of now)
Have been utilizing resources in the web and developing this game. But now the issue I am having is:
I have designed the board game logic in Javascript and upon rolling of dice the two players move along the board. THIS BOARD IS FOR NOW NOT AJAX DRIVEN i.e, if Player1 makes a move, the move has to be updated in the Player 2 board as well.
ABOVE SCREENSHOT: When two players I registered and logged in 'Chris' & 'Paul' for instance are in there respective boards and you can see there chats too work. But When I click on the 'Roll Dice' button, the players indicated by white and yellow move just in one board, which is logical since I have just created two players in Javascript and wrote the logic(They are not yet related to Crane and Chris).
BOARD.JS file below:
var player1 = $("#UserName").val();
var player2 = $("#Opponent").val();
var gameId = $("#GameId").val();
console.log("name of first player: ",player1);
console.log("name of second player: ",player2);
console.log("Game ID is: ",gameId);//getting above values through session variables
window.rollDice = ()=>{
const max = 6;
const roll = Math.ceil(Math.random() * max);
$('.rolledValue').html("Rolled Dice Value is: " + roll);
console.log("You rolled", roll);
let currentPlayer = players[currentPlayerTurn];
currentPlayer.position += roll;
ladders.forEach(ladder=>{
if (ladder.start === currentPlayer.position) {
console.log("You stepped on a ladder!");
currentPlayer.position = ladder.end;
}
});
if (currentPlayer.position === position) {
console.log("Player has won!");
hasWon = true;
}
if (currentPlayer.position === position) {
const diff = currentPlayer.position - position;
currentPlayerPosition = position - diff;
}
currentPlayerTurn ++;
if (currentPlayerTurn >= players.length) {
currentPlayerTurn = 0;
}
renderBoard();
}
const players = [{
name: player1,
position: 0,
color: "gold"
},{
name:player2,
position: 0,
color: "white"
}];
let currentPlayerTurn = 0;
const width = 9;
const height = 9;
const board = [];
let position = 0;
let blackSquare = false;
const ladders = [{
start: 2,
end: 22
},{
start: 50,
end: 34
},{
start: 10,
end: 44
},{
start: 61,
end: 19
},{
start: 70,
end: 83
},{
start:78,
end: 4
}];
for (var y = height; y >= 0; y--) {
let row = [];
board.push(row);
for (var x = 0; x < width; x++) {
row.push({x,y,occupied:null,position,color: blackSquare ? "steelblue" : "silver"});
blackSquare = !blackSquare;
position ++;
}
}
const boardSizeConst = 50;
const renderBoard = ()=>{
let boardHTML = ``;
board.forEach(row=>{
row.forEach(square=>{
boardHTML += `<div class=square style="top:${square.y * boardSizeConst}px; left:${square.x * boardSizeConst}px; background-color:${square.color}"></div>`
});
});
players.forEach(player=>{
let square = null;
board.forEach(row=>{
row.forEach(square=>{
if (square.position === player.position) {
boardHTML += `<div class=player style="top:${square.y * boardSizeConst + 5}px; left:${square.x * boardSizeConst + 5}px;background-color:${player.color}"></div>`;
}
});
});
});
ladders.forEach(ladder=>{
//let start = 0;
let startPos = {x:0,y:0};
let endPos = {x:0,y:0};
board.forEach(row=>{
row.forEach(square=>{
if (square.position === ladder.start) {
startPos.x = square.x * boardSizeConst;
startPos.y = square.y * boardSizeConst;
}
if (square.position === ladder.end) {
endPos.x = square.x * boardSizeConst;
endPos.y = square.y * boardSizeConst;
}
});
});
const isLadder = ladder.end > ladder.start;
drawLine({color : isLadder ? "green" : "red",startPos,endPos});
});
document.getElementById("board").innerHTML = boardHTML;
}
However, for now circles are not related to them. But I want to create a mechanism 'When Chris rolls dice in his board, it has to get updated in Crane board & vice-versa.
Need help. I am newbie to php but kind of have come till this point.

NodeJS - Sorting Like Rock Paper Scissors - Dynamic Number Of Players

I'm working on a game that has a sort of rock paper scissors system, only more complicated, using "values" such as 3 rock beats 2 rock, where one player can choose the amount of rocks he wants to use in one turn. This game can/has to handle more than 2 players, but 2 players is also possible. I was only able to do that with values, using this code:
array.push({ "player": player, "score": parseInt(cardInformation.value), "Seat": i, element: cardInformation.element});
array.sort(function (a, b) {
return b.score - a.score;
});
var rank = 1;
var lastWinner = -1;
for (var i = 0; i < array.length; i++) {
if (i > 0 && array[i].score < array[i - 1].score) {
rank++;
}
array[i].rank = rank;
array[i].winStatus = loss;
if(rank == 1) {
if(lastWinner != -1) {
array[lastWinner].winStatus = tie;
array[i].winStatus = tie;
} else
array[i].winStatus = win;
lastWinner = i;
}
}
I've looked all over for a system like rock paper scissors but all I could find was for 2 players and I'm unsure how to make it more. Please help me if you have the time.
Hope this helps :
const TURN_INTERVAL = 10//seconds
const GAME_STATE = {
status:1, // 1:player action is allowed / 0:player action is frozen
turnData:{ // temp storage for playerIDs grouped by value chosen
1:[], //paper
2:[], //scissors
3:[] //rock
},
versus:{ //what kills what
1:3,
2:1,
3:2
}
}
function GlobalTurn(){
console.log('[Round]','started')
GAME_STATE.status = 0; // players must wait for turn end response
for(var i=1; i<4;i++){ // notify each group of how many they killed
var thisGroupKills = GAME_STATE.versus[i]; //which is the weak group against this one
var totalKilled = GAME_STATE.turnData[thisGroupKills].length //how much this group has killed
console.log('group',i,'killed a total of',totalKilled) //send to clients instead
/* Here you can iterate over each playerID if you need to :
for(var j=0; j<GAME_STATE.turnData[i].length){
console.log('player',GAME_STATE.turnData[i],'killed a total of',totalKilled)
}
*/
}
EndTurn()
}
function EndTurn(){
console.log('Next round will start in',TURN_INTERVAL,'seconds')
GAME_STATE.turnData = {1:[],2:[],3:[]} //reset for next round
GAME_STATE.status = 1; // players can send actions (their pick)
setTimeout(GlobalTurn,TURN_INTERVAL*1000); //prepare next round calculator
}

Select random winner with percentages

I would want to select a random winner from about 2 - 10 players.
Every player have precent chance to win. Someone have 50% and someone 10%.
Let's say we have 2 players. One player have 20% and other have 80%. How do I select winner between these two?.
Players are in array
var players = {
player1: {
chance: 20 //%
}
player2: {
chance: 80 //%
}
}
//Select winner from json
(Assuming the percentages all add up to 100)
You would first have to order the players. Then take a random number from 1 to 100, and find out which player that random number falls under.
For example:
// Modified json to array so we can easily loop through them
// If you would like help turning the json to an array, I can provide code for that upon request
var players = [
{
chance: 20
},
{
chance: 40
},
{
chance: 40
}
];
// Generate random number
var perc = Math.random() * 100; // between 0 and 99.999~
// Save where we are in the percentage
var currentPerc = 0;
// Loop through the players and check who the random number chose
for ( var pID = 0; pID < players.length; pID++ ) {
// Check if the current player we are looking at has won
if (perc < (players[pID].chance + currentPerc)) {
alert("PLAYER " + (pID + 1) + " HAS WON.");
// Do player winning code here
break; // break out of the loop, we're done
} else {
currentPerc += players[pID].chance;
}
}
In the above example, imagine that the random number chose 45 (0.45 * 100 since math.random gives us 0.0 to 0.99~).
This would mean that player 2 won
0 to 20 = Player 1 wins
21 to 60 = Player 2 wins
61 to 100 = Player 3 wins
Using 45 as the random number chosen The first iteration, we check if player 1 has won. He has not, so we add player 1's percentage to the "current percentage".
Then in the second iteration we check player 2. Since 45 < (20 + 40), player 2 has won chosen. We alert that he has won and will do some code for that.
var players = [20,5,15,40,20];
var getWinner = function(players){
var random = Math.random();
var sum = 0;
for(var i = 0; i < players.length; i++){
sum+= players[i]/100;
if(random<= sum) return i;
}
}
Returns the number of the player(index 0) who wins

Categories

Resources