Two player number battling simulator favours second player - javascript

I am writing a fairly basic (for now) number crunching battle simulator in javascript. Its purpose is to test formula for a forthcoming game, so we can balance players stats.
Currently, the sim reduces a players health based on the following formula
player1.hp -= (Math.floor(Math.random() * 5) + 1) * player2[Math.floor(Math.random() * player2.length)].str;
HP starts on 100, and str is 2.
player2[Math.floor(Math.random() * player2.length)].str
The above code picks 1 of 3 "parts" of the player (head, body, legs) as each piece has its own stats.
So for any particular turn, starting with player 1, their head's HP is reduced by an amount based on the first formula (random part of player 2 picked, it's str stat is multiplied by a random number between 1 and 5)
Then player 2's parts are attacked, with a random part of player 1 being picked for the str stat.
(Yes, player 2 attacks first always currently, then player 1 - this may be the issue?)
When I run a single "battle", the results are fairly mixed. But when I run 100 or 1000 battles, player 2 typically comes out on top, with an average 60% win rate.
JS file here (download and run via Node)

Player who starts always has advantage because he is 1st to be able to do the finishing blow if you think of a situation where each player has 100 hp and 1 hit = 10 damage then player who started will do the 10th hit and finish the battle while player 2 will have done only 9 hits. Randomizing damage still gives advantage as 1st player has 1 hit advantage

This is a well-known problem in military combat simulation models which are turn-based. There are a couple of solutions that are commonly used. One is to randomize who gets to go first. The second is to calculate the deltas for both players before applying those deltas. The second approach has the interesting (and realistic) result that in some cases both players can be killed.

Related

How to use loop in JavaScript using while?

please excuse my ignorance; I am learning JavaScript from scratch with no background in coding.
Here is the question:
Define three variables for the LaunchCode shuttle---one for the starting fuel level, another for the number of astronauts aboard, and the third for the altitude the shuttle reaches.
Construct while loops to do the following:
Prompt the user to enter the starting fuel level. The loop should continue until the user enters a positive value greater than 5000 but less than 30000. I am very confused by the question, can you please explain it to me?
Use a second loop to query the user for the number of astronauts (up to a maximum of 7). Validate the entry by having the loop continue until the user enters an integer from 1 - 7.
Use a final loop to monitor the fuel status and the altitude of the shuttle. Each iteration, decrease the fuel level by 100 units for each astronaut aboard. Also, increase the altitude by 50 kilometers. (Hint: The loop should end when there is not enough fuel to boost the crew another 50 km, so the fuel level might not reach 0).
After the loops complete, output the result with the phrase, The shuttle gained an altitude of ___ km.
If the altitude is 2000 km or higher, add "Orbit achieved!"
Otherwise add, "Failed to reach orbit."
And here is my code for the question to answer first part:
const input = require("readline-sync")
let startingFuelLevel=0;
let numberAstronautsAboard =0;
let altitudeshuttleReaches =0;
//a:
while (startingFuelLevel <= 5000 || startingFuelLevel >30000){
startingFuelLevel = input.question("Enter the starting fuel level: ")
};
//b:
while(numberAstronautsAboard < 1 || numberAstronautsAboard > 7){
numberAstronautsAboard = input.question("Enter the number of astronauts: ")
}
JSFiddle (pure js):
https://jsfiddle.net/DariusM/14parbue/18/
Apart from the messages, a condition and a check for isNaN, it seems that you got the first two parts somewhat right - the user input.
As for the third loop, you can use setInterval() to run a function repeatedly, each time doing the following:
decrease fuel level
increase altitude
check if there is enough fuel for another iteration.
Depending on the check at (3) above, you can then show a certain message to the user depending on the current altitude.
Then, after the fuel is finished and the final message is displayed to the user, the interval needs to be cleared using clearInterval()
Good luck with your endeavor and happy coding!

How to make optimal decision in poker like single player card game?

I need some help to finish my app that helps to make optimal decision in card game.
Short game description:
Single player game - 1 player one deck only for himself
24 card deck, card values from 1 to 8, 3 colors of each (Red,Yellow, Blue).
At start of the game deck gets randomly shuffled then player pulls 5 cards (19 left in deck) to his hand and from this point he's allowed to:
Put away one card (this card is not in game anylonger) and take one card from top of shuffled deck for its place.
or
Can put away 3 cards that form a one of possible point granting combinations, then takes 3 cards to his hand.
Game ends when cards in deck ends and player have no more possible scoring combinations.
Goal of the game is to obtain as much points as possible.
List of variants: (called later combinations)
Three of a kind (8 possible in total):
111 - 20 points
222 - 30 points
333 - 40 points
444 - 50 points
555 - 60 points
666 - 70 points
777 - 80 points
888 - 90 points
Straight (card can have any color, 144 possible in total):
123 - 10 points
234 - 20 points
345 - 30 points
456 - 40 points
567 - 50 points
678 - 60 points
Straight flush (cards have to be in the same color, RRR/YYY/BBB, 18 possible in total):
123 - 50 points
234 - 60 points
345 - 70 points
456 - 80 points
567 - 90 points
678 - 100 points
I created the whole game logic in JS but suffer to make algoritm that will help me:
which card to put away from hand? - to get highest chance for combination
or:
which card to put away from hand?- to lose least amount of possible combinations
I don't really know which approach i should take. Or should i combine them somehow and let the formula decide? Currently I'm reading about risk reward ratio maybe thats the way to go?
I have to remember that with each card less i have less and less possible combinations (starting with 170), but sometimes its worth in later stage of the game to sacrifice cheaper combination for higher point score.
My past ways of thinking:
Calculate the probability of each possible remaining combination when putting away each card from hand.(i.e. 5 times) and decide which one is the worst.
Calculate the probability of each possible remaining combination for every 2 card subset of 5 card set in hand (so 10 times looking for 1 card to fill the combination) and decide which card from hand is the worst.
Calculate the probability of each possible remaining combination left in deck (not counting cards in hand there). 3+ moves in advance
And somehow add those three together to get optimal/close to optimal solution?
Should i add potential loss to my calculations and how to form them? If i take weak combination and later in the game i can not obtain higher ones since they are mutually exclusive.

When does Math.random() start repeating?

I have this simple test in nodejs, I left it running overnight and could not get Math.random() to repeat. I realize that sooner or later the values (or even the whole sequence) will repeat, but is there any reasonable expectancy as to when it is going to happen?
let v = {};
for (let i = 0;; i++) {
let r = Math.random();
if (r in v) break;
v[r] = r;
}
console.log(i);
It is browser specific:
https://www.ecma-international.org/ecma-262/6.0/#sec-math.random
20.2.2.27
Math.random ( ) Returns a Number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly or pseudo
randomly with approximately uniform distribution over that range,
using an implementation-dependent algorithm or strategy. This function
takes no arguments.
Each Math.random function created for distinct code Realms must
produce a distinct sequence of values from successive calls.
The requirement here is just pseudo-random with uniform distribution.
Here's a blog post from V8 (Chrome and NodeJs's Javascript Engine).
https://v8.dev/blog/math-random
Where they say they are using xorshift128+, which has a maximal period of 2^128 -1.
Related (on another site): Acceptable to rely on random ints being unique?
Also extremely related: How many double numbers are there between 0.0 and 1.0?
Mathematically, there are an infinite number of real numbers between 0 and 1. However, there are only a finite number of possible values that Math.Random could generate (because computers only have a finite number of bits to represent numbers). Let's say that there are N possible values that it could generate. Then, by the Pigeonhole Principle, there is a 100% chance of getting at least one duplicate value once you generate exactly N + 1 values.
At this point, the Birthday Paradox demonstrates that you should start seeing duplicates surprisingly quickly. According to this "paradox" (which isn't a true paradox, just counterintuitive), given a room with only 23 people, there's a greater than 50% chance of two of them having the same birthday.
Returning to our example, the rule of thumb for calculating this (see the linked Wikipedia article) suggests that Math.Random reaches a 50% probability of duplicates once you generate approximately sqrt(N) numbers.
From the linked Stack Overflow question, if we assume that there are 7,036,874,417,766 numbers between 0 and 1 like the accepted answer says (and please read the linked question for a more detailed explanation of how many there actually are), then sqrt(7036874417766) is just over 2.652 million, which isn't actually all that many. If you are generating 10,000 random numbers per second, you'd reach 50% probability in approximately 737 hours, which is just under 31 days. Less fortunately, even at 10,000 per second, it would take approximately 195,468 hours (which is approximately 22.3 years) to reach 100% probability.
Some of the other answers give much higher figures for how many numbers there are, so take your pick.

How to find the amount of each review based on the average and total number of reviews

So I have this problem that I need to work out for work, but I can't figure out a good algorithm. I am given the average for the reviews and the number of total reviews. From those two pieces of information, I need to randomly generate how many 5 star, 4 star, 3 star, 2 star, and 1 star reviews were made. Here are two formulas that might better explain what exactly the problem is.
Given Review Average (x)
Given Total Number of Reviews (y)
Find:
a = # of 5 star reviews
b = # of 4 star reviews
c = # of 3 star reviews
d = # of 2 star reviews
e = # of 1 star reviews
a + b + c + d + e = total # of reviews (KNOWN: y)
(5*a + 4*b + 3*c + 2*d + 1*e) = total number of stars = average(x) * total reviews(y)
This is more of a type of math problem than programming, but I need to be able to write some type of algorithm to get a,b,c,d, and e programatically in JavaScript. Does anyone know of any good algorithms for something like this? Thanks!
You can get the maximum possible points total by making everything a 5-star review. You can reduce this total by one by making one of the 5-star reviews a 4-star review. You could continue reducing this by one until everything is a 4-star review. Again, reduce by one by making a 4-star review a 3-star review...
So there is a way to get every possible points total from all 5-stars to all 1-stars, and you can get some sort of answer for every possible total.
Of course, you don't need to compute this point by point. You can start your search by comparing the points total with all 5-stars, all 4-stars.. all 1-stars and find the smallest total bigger than your target. Then change just enough of whatever star you have settled on to the next smallest value to reach your exact target.
(Of course this will look a bit artificial but you couldn't be creating fake review numbers to push products on a sight because this would be false advertising and sooner or later you would get caught).

Rounding glitch in javascript, returning 4000%

I am trying to measure the percentage of the amount of enemies in a javascript game I am developing.
Math.round(10000000 / V.S * 100) / 100
This code works fine when V.S is over 1 million, however returns observed values such as 3400% when V.S is around the thousands, but this should be about 0.01%.
V.S is the amount of enemies
10 million is the amount of enemies needed to make you lose the game
I want to show the percentage between the amount currently and the amount needed to lose the game.
How can I make it show that?
V.S is the amount of enemies
10 million is the amount of enemies needed to make you lose the game
Your current code yields how many times V.S goes into 10 million
I want to show the percentage between the amount currently and the
amount needed to lose the game.
If you want to know what percentage of the 10 million has shown up:
var pctShown = V.S/100000; //or Math.round(V.S/100000) if you want only whole pcts
(note: reduction of dividing by 10,000,000 then * 100 to get a pct representation)
If you want the percent remaining, simply find the inverse:
var pctRemaining = 100 - V.S/100000; //or again Math.round(100 - V.S/100000)

Categories

Resources