TLF RCI Redesign Tester

This is a mini-game to try out various RCI models for TLF.

HTML

<body>
<div style="border: 2px solid black;border-radius: 5px;background-color: #d0e0f0;box-shadow: 4px 4px 5px #b0b0b0">
	Date: <span id="date"></span><br>
	Current RCI Value:<span id="curRCI"></span><br>
</div><br>
<div style="border: 2px solid black;border-radius: 5px;background-color: #d0e0f0;box-shadow: 4px 4px 5px #b0b0b0">
List of Effects<br>
<div id="effectList">
</div>
</div><br>
<div style="border: 2px solid black;border-radius: 5px;background-color: #d0e0f0;box-shadow: 4px 4px 5px #b0b0b0">
Last Message: <span id="message"></span><br>
Current Action: <span id="action"></span><br>
Time left: <span id="timeleft"></span><br>
</div><br>

<div style="border: 2px solid black;border-radius: 5px;background-color: #d0e0f0;box-shadow: 4px 4px 5px #b0b0b0">
	<input type="button" value="Dispatch (+10/yr)" onclick="setAction(0)">
	<input type="button" value="Dispatch (-10/yr)" onclick="setAction(1)">
	<input type="button" value="Construct Building (2yr)" onclick="setAction(2)">
	<input type="button" value="Cause Disaster (2yr)" onclick="setAction(3)">
	<input type="button" value="Do Nothing" onclick="setAction(4)">
</div><br>

<div style="border: 2px solid black;border-radius: 5px;background-color: #d0e0f0;box-shadow: 4px 4px 5px #b0b0b0">
	a: <input type="number" value="0.75" onchange="setAlpha(this.value)"><br>
	Randomness: <input type="number" value="0.6" onchange="setRandom(this.value)"><br>
	<input type="button" value="Reset" onclick="reset()">
</div><br>
</body>

JavaScript

var lastEvent = 0;
var curDate = 0;
var curAction = 0;
var actionTimer = 0;
var RCIValue = 0;
var alpha=0.75;
var randomness=0.6;
var lastMessage="";
var lastts = 0, lasttime = 0;
var actionNames = [ "Dispatch +", "Dispatch -", "Construct Building", "Cause Disaster", "Doing Nothing" ];
var actionTiming = [ 0.07, 0.07, 1.95, 1.95, 0.07 ];
var effectList = [];

function reset()
{
	lastEvent = 0;
	curDate = 0;
	curAction = 0;
	actionTimer = 0;
	RCIValue = 0;
}

function setAlpha(a)
{
	alpha=a;
}

function setRandom(r)
{
	randomness=r;
}

function adjustRCI(delta)
{
	if (delta>0)
	{
		RCIValue = RCIValue + 2*delta*Math.exp(alpha*RCIValue/100)*(100-RCIValue)/200;
		if (RCIValue>100) RCIValue=100;
	}
	else
	{
		RCIValue = RCIValue + 2*delta*Math.exp(-alpha*RCIValue/100)*(100+RCIValue)/200;
		if (RCIValue<-100) RCIValue=-100;
	}
}

function updateRCI(delta)
{
	var dir=1;
	if (delta<0) { dir=-1; delta=-delta; }
	
	var intervals = Math.floor(delta/0.1);
	
	for (var i=0;i<intervals;i++)
		adjustRCI(dir*0.1);
	adjustRCI(dir*(delta-0.1*intervals));
}

function addEffect(name, duration, effectFunction)
{
	effectList.push({name: name, duration: duration, effectFunction: effectFunction});
}

function doAction(act)
{
	switch (act)
	{
		case 0:
			updateRCI(1.0);
			break;
		case 1:
			updateRCI(-1.0);
			break;
		case 2:
			addEffect("Building", -1, function() { updateRCI(0.1); });
			lastMessage="You constructed a building! RCI will improve at 0.1/month";
			break;
		case 3:
			addEffect("Disaster", 5, function() { updateRCI(-2); });
			lastMessage="You started a disaster! RCI will suffer -2/month.";
			break;
	}
}

function updateTime()
{
	var dtime = 0.1;
	
	curDate += dtime;
	actionTimer -= dtime;
	
	if (actionTimer<0)
	{
		doAction(curAction);
		actionTimer = actionTiming[curAction];
	}
	
	for (var i=0;i<effectList.length;i++)
	{
		effectList[i].effectFunction();
		
		if (effectList[i].duration>-0.9)
			effectList[i].duration -= dtime;
		
		if...