Help. Javascript Code Is Breaking Sometimes When Ran...

Started by
7 comments, last by Durakken 7 years, 8 months ago

So i'm having a problem here. The code will go into an infinite loop or seems to break and the population seems to stop growing at a low number.

But this only happens sometimes.

At the end of every 12 months it's supposed to show the year and population and it's working, but only some of the time.

I suppose the inconsistency of the population numbers could just be coincidence, but it doesn't seem like it to me and the infiniteloop or whatever is happening that makes it take a longer time to process than i'm willing to wait points to there being a problem, but I can't see it.


//y = year
//py = previous year
// Age is based on months, not years
py = 0;

var Women = new Array();
var Men = new Array();
var Woman = {ID: 0, Age: 240, SinceLastBirth: 0, Pregnant: "no", MonthsPregnant: 0, Dead: "no"};
var Man = {ID: 0, Age: 240, Soldier: "no", Dead: "no"};
Women.push(Woman);
Men.push(Man);
	
for(i = 0; i < 18001; i++) {

	for(x = 0; x < Women.length; x++) {
		Women[x].Age++;
	}
	
	for(x = 0; x < Women.length; x++) {
		if(Women[x].Age <= 168 && Women[x].Dead == "no") {
			DeathCheck = Math.random();
			if(DeathCheck <= 0.00166) {
				Women[x].Dead = "yes";
			}
		}
	}
	
	for(x = 0; x < Women.length; x++) {
		if(Women[x].Pregnant == "yes" && Women[x].Dead == "no") {
			MiscarryCheck = Math.random()
			if(MiscarryCheck <= 0.036){
				Women[x].Pregnant = "no"
				Women[x].MonthsPregnant = 0;
			} else {
				Women[x].MonthsPregnant++;
			}
		}
		if(Women[x].MonthsPregnant >= 9 && Women[x].Dead == "no") {
			Sex = Math.floor((Math.random() *2) +1);
			if(Sex == 2) {
				Man = {ID: 0, Age: 0, Soldier: "no", Dead: "no"};
				Men.push(Man);
			} else {
				Woman = {ID: 0, Age: 0, SinceLastBirth: 0, Pregnant: "no", MonthsPregnant: 0, Dead: "no"};
				Women.push(Woman);
			}
			BirthDeathCheck = Math.random();
			if(BirthDeathCheck < 0.01) {
				Women[x].Dead = "yes";
			} else {
				Women[x].MonthsPregnant = 0;
				Women[x].SinceLastBirth = 48;
			}
		}
	}

	for(x = 0; x < Women.length; x++) {
		if(Women[x].Age >= 168 && Women[x].Age <= 1860 && Women[x].SinceLastBirth <= 0 && Women[x].Dead == "no") {
			PregnantCheck = Math.random();
			if(PregnantCheck <= 0.05 && Women[x].Pregnant == "no") {
				Women[x].Pregnant = "yes";
			}
		}
		if(Women.SinceLastBirth > 0  && Women[x].Dead == "no") {
			Women.SinceLastBirth--;
		}
	}
	
	m = 0;
	y = 0;
	for(x = 0; x <= i; x++) {
		if(m == 12) {
			y++;
			m = 0;
		}
		m++
	}
	
	if(y > py) {
		Population = 0;
		for(x = 0; x < Men.length; x++) {
			if(Men[x].Dead == "no") {
				Population++
			}
		}
		for(x = 0; x < Women.length; x++) {
			if(Women[x].Dead == "no") {
				Population++
			} 
		}
		document.write(y + " : " + Population + "<br />");
		py = y;
	}
}
Advertisement

Figured it out... still some annoyances I haven't worked out but this particular problem was fixed. Thanks anyways

Figured it out... still some annoyances I haven't worked out but this particular problem was fixed. Thanks anyways

It's generally very good form to explain what you have figured out/fixed so that other people finding this question via Google with a similar problem get the benefit of your experience.

I can't put into words how frustrating it is to have a problem and being able to find evidence that someone else had that same problem and that they fixed it but didn't bother to share what the fix was. :)

Sean Middleditch – Game Systems Engineer – Join my team!

I can't put into words how frustrating it is to have a problem and being able to find evidence that someone else had that same problem and that they fixed it but didn't bother to share what the fix was.

As always, xkcd has a relevant comic:

https://xkcd.com/979/

Hello to all my stalkers.

As always, xkcd has a relevant comic:

I personally am so much happier seeing no answer than I am when I see "nevermind, fixed." In the first case, maybe I'm the first one who will ever actually figure this out; in the second case, I'm just a chump trying to keep up with those who've gone before.

I like being a trail blazer way more than I like being a chump. :p

Sean Middleditch – Game Systems Engineer – Join my team!

Well the vast amount of prints/alerts made it hard to pin down till figured out how to handle that. Once I did it was just stupid minor errors probably because I was up late where I missed the array reference and some stupid stuff like that...

I still need to add in soldiering deaths to what I have but other than that it's finished more or less for the base level of what I want. If anyone can help make it run faster I'd apreciate it, because it struggles on my PC to run through it with fairly low numbers. I would like to be able to get the numbers to higher population numbers, but meh. And i might add in a family tree output, but not till later most likely ^.^.The biggest problem is getting the population statistics right. If I set them just a little higher (and more accurately) the population quickly dies off and then there is the fact that I can't find how exactly to model the death rate per month of a persons life... Oh well... Here's the updated code...

Oh also can't figure out how to make the do while loop to end on a year rather than a month which makes the last "year" lower than the 1000 members in a population number and why I just put a population write after that final loop. There should be a away to fix it but meh.

Also ID is currently useless right now, but if I ever wanted to print out the list of relations it would be used to ID mother/father.


// Age is based on months, not years
py = 0;
Population = 0;
PregPop = 0;

var Women = new Array();
var Men = new Array();
var Woman = {ID: 0, Age: 240, SinceLastBirth: 0, Pregnant: "no", MonthsPregnant: 0, Dead: "no"};
var Man = {ID: 0, Age: 240, Soldier: "no", Dead: "no"};
Women.push(Woman);
Men.push(Man);
Population = Population + 2;
	
	i = 0;
do {
//for(i = 0; i < 3601; i++) {
	
	for(x = 0; x < Women.length; x++) {
		
		if(Women[x].Dead == "no") {
			Women[x].Age++;
		
			if(Women[x].Age <= 168) {
				DeathCheck = Math.random();
				if(DeathCheck <= 0.00083) {
					Women[x].Dead = "yes";
					Population--;
					//document.write("Dead before 14 <br />");
				}
			}
	
			DeathProb = 0;
			if(Women[x].Age > 168) {
				DeathCheck = Math.random();
				if(Women[x].Age >= 3024) {
					DeathProb = 0.02;
				} else {
					y = 0;
					while(y < Women[x].Age) {
						DeathProb = DeathProb + 0.000000661;
						y++;
					}
				}
				if(DeathCheck <= DeathProb) {
					Women[x].Dead = "yes";
					Population--;
					//document.write("Woman Dead <br />");
				}
			}
	
			if(Women[x].Pregnant == "yes") {
				MiscarryCheck = Math.random()
				if(MiscarryCheck <= 0.036){
					Women[x].Pregnant = "no";
					Women[x].MonthsPregnant = 0;
					PregPop--;
					//document.write("Miscarry <br />");
				} else {
					Women[x].MonthsPregnant++;
					//document.write("Pregnancy month added <br />");
				}
			}
			if(Women[x].MonthsPregnant >= 9) {
				Sex = Math.floor((Math.random() *2) +1);
				if(Sex == 2) {
					Man = {ID: Men.Length + 1, Age: 0, Soldier: "no", Dead: "no"};
					Men.push(Man);
					//document.write("Baby Boy Born<br />");
				} else {
					Woman = {ID: Women.length + 1, Age: 0, SinceLastBirth: 0, Pregnant: "no", MonthsPregnant: 0, Dead: "no"};
					Women.push(Woman);
					//document.write("Baby Girl Born<br />");
				}
				Population++;
				BirthDeathCheck = Math.random();
				if(BirthDeathCheck < 0.01) {
					Women[x].Dead = "yes";
					Population--;
					//document.write("Mother died in birth<br />");
				} else {
					//document.write("Mother didn't die in birth <br />");
					Women[x].MonthsPregnant = 0;
					Women[x].SinceLastBirth = 48;
				}
				Women[x].Pregnant = "no";
				PregPop--;
			}

			if(Women[x].Age >= 168 && Women[x].Age <= 1860 && Women[x].SinceLastBirth <= 0) {
				PregnantCheck = Math.random();
				if(PregnantCheck <= 0.013 && Women[x].Pregnant == "no") {
					Women[x].Pregnant = "yes";
					PregPop++;
					//document.write("Woman got pregnant <br />");
				}
			}
			if(Women[x].SinceLastBirth > 0 ) {
				Women[x].SinceLastBirth--;
				//document.write("Since Last Birth working<br />");
			}

		}
	}
		
	for(x = 0; x < Men.length; x++) {
		
		if(Men[x].Dead == "no") {
			Men[x].Age++;
		
			if(Men[x].Age <= 168) {
				DeathCheck = Math.random();
				if(DeathCheck <= 0.00083) {
					Men[x].Dead = "yes";
					Population--;
					//document.write("Dead before 14 <br />");
				}
			}
	
			DeathProb = 0;
			if(Men[x].Age > 168) {
				DeathCheck = Math.random();
				if(Men[x].Age >= 3024) {
					DeathProb = 0.02;
				} else {
					y = 0;
					while(y < Men[x].Age) {
						DeathProb = DeathProb + 0.000000661;
						y++;
					}
				}
				if(DeathCheck <= DeathProb) {
					Men[x].Dead = "yes";
					Population--;
					//document.write("Man Dead <br />");
				}
			}
		}
	}
	
	m = 0;
	y = 0;
	for(x = 0; x <= i; x++) {
		if(m == 12) {
			y++;
			m = 0;
		}
		m++
	}
	
	if(y > py) {
		WPop = 0;
		for(x = 0; x < Women.length; x++) {
			if(Women[x].Dead == "no") {
				WPop++;
			} 
		}
		PercWomenPreg = ((PregPop / WPop) * 100).toFixed(2);

		document.write(y + " : " + Population + " | " +PercWomenPreg+ "%<br />");
		py = y;
	}
	i++
} while(Population < 1001 || Population <= 0);
		Dead = 0;
		for(x = 0; x < Women.length; x++) {
			if(Women[x].Dead == "yes") {
				Dead++;
			}
		}
		for(x = 0; x < Men.length; x++) {
			if(Men[x].Dead == "yes") {
				Dead++;
			}
		}
		document.write("Dead: " +Dead + " | Pop: " +Population);

At least your year and month calculations can be simplified.

Instead of a loop, you can just do integer division and modulo.

y = months / 12

m = months % 12

Apart from that, maybe delete (or move, if you need to keep history of them) the people marked as dead?

By not having them in your lists, you might be able to skip some iteration time.

Alternatively, at the beginning of your loops, continue (I think that's also a valid javascript keyword?) if == dead.

Related, might it be better to have a boolean instead of a string for the "yes"/"no" checks?

I would imagine a string comparison being a lot more expensive than a boolean check.

Hello to all my stalkers.

At least your year and month calculations can be simplified.

Instead of a loop, you can just do integer division and modulo.

y = months / 12

m = months % 12

Apart from that, maybe delete (or move, if you need to keep history of them) the people marked as dead?

By not having them in your lists, you might be able to skip some iteration time.

Alternatively, at the beginning of your loops, continue (I think that's also a valid javascript keyword?) if == dead.

Related, might it be better to have a boolean instead of a string for the "yes"/"no" checks?

I would imagine a string comparison being a lot more expensive than a boolean check.

I'll look at the year month thing in a bit, but I tried using

} while((Population < 1001 && i % 12 == 0 )|| Population <= 0);

which didn't work, can that not be done?

The moving people from the population arrays to a dead population array thing... I don't know how to do that. But it doesn't seem like it would save time as the average number when aiming for 1000 pop is around 300.

I don't think continue is a valid js keyword, but I've already got the equive as the second if.

boolean is quicker I think... I guess i'll change that soon.

also... The speed of the script right now seems to be about the same speed as executing this...


var scalingExp = .75;

for (pop = 0; pop <300001; pop++) {
HomeRange = Math.pow(pop, scalingExp).toFixed(1);
document.write("Pop: " +pop+ " | Home range size: " +HomeRange+ " square km <br />");
}

So 1500-ish running is running about the same speed as 300,000 of these power equations.

Made several changes and so far it looks like it completes almost instantly when set to 1000 pop

EDITED because I changed the DeathProb thing from a loop to a straight calculation and that pretty much eliminated the delay.


// Age is based on months, not years
Population = 0;
PregPop = 0;
Months = 0;
Years = 0;

var Women = new Array();
var Men = new Array();
var DeadWomen = new Array();
var DeadMen = new Array();
var Woman = {ID: 0, Age: 240, SinceLastBirth: 0, Pregnant: false, MonthsPregnant: 0, Dead: false};
var Man = {ID: 0, Age: 240, Soldier: false, Dead: false};
Women.push(Woman);
Men.push(Man);

do {

for(x = 0; x < Women.length; x++) {

Women[x].Age++;

if(Women[x].Age <= 168) {
DeathCheck = Math.random();
if(DeathCheck <= 0.00083) {
Women[x].Dead = true;
//document.write("Dead before 14 <br />");
}
}

DeathProb = 0;
if(Women[x].Age > 168) {
DeathCheck = Math.random();
if(Women[x].Age >= 3024) {
DeathProb = 0.02;
} else {
DeathProb = Women[x].Age * 0.000000661;
}
if(DeathCheck <= DeathProb) {
Women[x].Dead = true;
//document.write("Woman Dead <br />");
}
}

if(!Women[x].Dead) {
if(Women[x].Pregnant) {
MiscarryCheck = Math.random()
if(MiscarryCheck <= 0.036){
Women[x].Pregnant = false;
Women[x].MonthsPregnant = 0;
PregPop--;
//document.write("Miscarry <br />");
} else {
Women[x].MonthsPregnant++;
//document.write("Pregnancy month added <br />");
}
}
if(Women[x].MonthsPregnant >= 9) {
Sex = Math.floor((Math.random() *2) +1);
if(Sex == 2) {
Man = {ID: Men.Length + 1, Age: 0, Soldier: false, Dead: false};
Men.push(Man);
//document.write("Baby Boy Born<br />");
} else {
Woman = {ID: Women.length + 1, Age: 0, SinceLastBirth: 0, Pregnant: false, MonthsPregnant: 0, Dead: false};
Women.push(Woman);
//document.write("Baby Girl Born<br />");
}
BirthDeathCheck = Math.random();
if(BirthDeathCheck < 0.01) {
Women[x].Dead = true;
//document.write("Mother died in birth<br />");
} else {
//document.write("Mother didn't die in birth <br />");
Women[x].MonthsPregnant = 0;
Women[x].SinceLastBirth = 48;
}
Women[x].Pregnant = false;
PregPop--;
}

if(Women[x].Age >= 168 && Women[x].Age <= 1860 && Women[x].SinceLastBirth <= 0) {
PregnantCheck = Math.random();
if(PregnantCheck <= 0.013 && Women[x].Pregnant == false) {
Women[x].Pregnant = true;
PregPop++;
//document.write("Woman got pregnant <br />");
}
}
if(Women[x].SinceLastBirth > 0 ) {
Women[x].SinceLastBirth--;
//document.write("Since Last Birth working<br />");
}

} else {
DeadWomen.push(Women[x]);
Women.splice(x,1);
}
}

for(x = 0; x < Men.length; x++) {

Men[x].Age++;

if(Men[x].Age <= 168) {
DeathCheck = Math.random();
if(DeathCheck <= 0.00083) {
Men[x].Dead = true;
//document.write("Dead before 14 <br />");
}
}

DeathProb = 0;
if(Men[x].Age > 168) {
DeathCheck = Math.random();
if(Men[x].Age >= 3024) {
DeathProb = 0.02;
} else {
DeathProb = Men[x].Age * 0.000000661;
}
if(DeathCheck <= DeathProb) {
Men[x].Dead = true;
//document.write("Man Dead <br />");
}
}
if(!Men[x].Dead) {

} else {
DeadMen.push(Women[x]);
Men.splice(x,1);
}
}

m = Months % 12
if(m == 0 && Months != 0) {
Years++;
Population = Women.length + Men.length;
PercWomenPreg = ((PregPop / Women.length) * 100).toFixed(2);
document.write(Years + " : " + Population + " | " +PercWomenPreg+ "%<br />");
}

Months++;

} while(Population < 1001 || Population <= 0);
Dead = DeadWomen.length + DeadMen.length;
document.write("Dead: " +Dead + " | Pop: " +Population);

This topic is closed to new replies.

Advertisement