A Research Engine for a Game in JavaScript

The JavaScript code listed below implements a simple “technology tree” for a computer game (like the ones in, for example, _Civilization_ or _Master of Orion_ (I think)).

To see the code in action, copy it into an .html file and open that file in a web browser that run JavaScript. Select a technology to research, and then click the “Research + 1” button until enough research is accumulated to “discover” the selected technology. Then choose another available technology and repeat.

ResearchEngine


<html>
<body>
<script type='text/javascript'>

// main

function main()
{
	var technologyTree = new TechnologyTree
	(
		"All Technologies",
		// technologies
		[
			new Technology("A", 		5, []),
			new Technology("A.1", 		8, ["A"]),
			new Technology("A.2", 		8, ["A"]),
			new Technology("A.3", 		8, ["A"]),
			new Technology("B", 		5, []),
			new Technology("C", 		5, []),

			new Technology("A+B", 		10, ["A", "B"]),
			new Technology("A+C", 		10, ["A", "C"]),
			new Technology("B+C", 		10, ["B", "C"]),

			new Technology("A+B+C", 	15, ["A", "B", "C"]),

			new Technology("(A+B)+(B+C)", 	20, ["A+B", "B+C"]),
		]
	);

	var researcher = new Researcher
	(
		"Researcher0",
		null, // nameOfTechnologyBeingResearched,
		0, // researchAccumulated
		// namesOfTechnologiesKnown
		[
			"A",
		]
	);

	var researchSession = new ResearchSession
	(
		technologyTree,
		researcher
	);

	Globals.Instance.initialize
	(
		researchSession
	);
}

// classes

function Globals()
{}
{
	// instance

	Globals.Instance = new Globals();

	Globals.prototype.initialize = function(researchSession)
	{
		this.researchSession = researchSession;

		document.body.appendChild
		(
			this.researchSession.domElementBuild()
		);
	}
}

function Researcher
(
	name, 
	nameOfTechnologyBeingResearched,
	researchAccumulated,
	namesOfTechnologiesKnown
)
{
	this.name = name;
	this.nameOfTechnologyBeingResearched = nameOfTechnologyBeingResearched;
	this.researchAccumulated = researchAccumulated;
	this.namesOfTechnologiesKnown = namesOfTechnologiesKnown;
}
{
	// dom

	Researcher.prototype.domElementBuild = function()
	{
		var divResearcher = document.createElement("div");

		var divName = document.createElement("div");
		
		var labelName = document.createElement("label");
		labelName.innerHTML = "Researcher Name:";
		divName.appendChild(labelName);

		var infoName = document.createElement("input");
		infoName.value = this.name;
		infoName.disabled = true;
		divName.appendChild(infoName);

		divResearcher.appendChild(divName);

		var divKnown = document.createElement("div");

		var labelKnown = document.createElement("label");
		labelKnown.innerHTML = "Technologies Known:";
		divKnown.appendChild(labelKnown);

		this.selectKnown = document.createElement("select");
		this.selectKnown.size = 5;
		divKnown.appendChild(this.selectKnown);

		divResearcher.appendChild(divKnown);

		this.domElement = divResearcher;

		return this.domElement;
	}

	Researcher.prototype.domElementUpdate = function()
	{
		this.selectKnown.innerHTML = "";

		for (var i = 0; i < this.namesOfTechnologiesKnown.length; i++)
		{
			var nameOfTechnologyKnown = this.namesOfTechnologiesKnown[i];

			var optionKnown = document.createElement("option");
			optionKnown.innerHTML = nameOfTechnologyKnown;
			this.selectKnown.appendChild(optionKnown);
		}

	}
}

function ResearchSession(technologyTree, researcher)
{
	this.technologyTree = technologyTree;
	this.researcher = researcher;
}
{
	// dom

	ResearchSession.prototype.domElementBuild = function()
	{
		var divResearchSession = document.createElement("div");

		divResearchSession.appendChild
		(
			this.researcher.domElementBuild()
		);

		var divTechnologyBeingResearched = document.createElement("div");

		var labelTechnologyBeingResearched = document.createElement("label");
		labelTechnologyBeingResearched.innerHTML = "Technology Being Researched:";
		divTechnologyBeingResearched.appendChild(labelTechnologyBeingResearched);

		this.selectTechnologyBeingResearched = document.createElement("select");
		this.selectTechnologyBeingResearched.onchange = this.selectTechnologyBeingResearched_Change.bind(this);

		divTechnologyBeingResearched.appendChild(this.selectTechnologyBeingResearched);

		divResearchSession.appendChild(divTechnologyBeingResearched);

		var divResearchAccumulated = document.createElement("div");

		var labelResearchAccumulated = document.createElement("label");
		labelResearchAccumulated.innerHTML = "Research Accumulated:";
		divResearchAccumulated.appendChild(labelResearchAccumulated);

		this.infoResearchAccumulated = document.createElement("input");
		this.infoResearchAccumulated.disabled = true;
		divResearchAccumulated.appendChild(this.infoResearchAccumulated);

		var labelSlash = document.createElement("label");
		labelSlash.innerHTML = "/";
		divResearchAccumulated.appendChild(labelSlash);

		this.infoResearchRequired = document.createElement("input");
		this.infoResearchRequired.disabled = true;
		divResearchAccumulated.appendChild(this.infoResearchRequired);

		divResearchSession.appendChild(divResearchAccumulated);

		this.buttonResearchIncrement = document.createElement("input");
		this.buttonResearchIncrement.type = "button";
		this.buttonResearchIncrement.value = "Research + 1";
		this.buttonResearchIncrement.disabled = true;
		this.buttonResearchIncrement.onclick = this.buttonResearchIncrement_Click.bind(this);

		divResearchSession.appendChild(this.buttonResearchIncrement);
		
		this.domElement = divResearchSession;

		this.domElementUpdate();

		return this.domElement;	
	}

	ResearchSession.prototype.domElementUpdate = function()
	{		
		this.researcher.domElementUpdate();

		var nameOfTechnologyBeingResearched = this.researcher.nameOfTechnologyBeingResearched;
		var technologyBeingResearched = this.technologyTree.technologies[nameOfTechnologyBeingResearched];

		var isTechnologyBeingResearched = (technologyBeingResearched != null);

		this.selectTechnologyBeingResearched.disabled = isTechnologyBeingResearched;
		this.buttonResearchIncrement.disabled = (isTechnologyBeingResearched == false);

		this.infoResearchAccumulated.value = this.researcher.researchAccumulated;

		var researchRequired;

		if (isTechnologyBeingResearched == true)
		{
			researchRequired = technologyBeingResearched.researchRequired;
		}
		else
		{
			researchRequired = 0;
			this.domElementUpdate_RefreshTechnologyBeingResearched();
		}

		this.infoResearchRequired.value = researchRequired;
	}

	ResearchSession.prototype.domElementUpdate_RefreshTechnologyBeingResearched = function()
	{
		this.selectTechnologyBeingResearched.innerHTML = "";

		var optionTechnologyBeingResearchedNone = document.createElement("option");
		optionTechnologyBeingResearchedNone.value = "";
		optionTechnologyBeingResearchedNone.innerHTML = "[None]";
		this.selectTechnologyBeingResearched.appendChild(optionTechnologyBeingResearchedNone);

		var technologies = this.technologyTree.technologies;
		var technologiesKnown = this.researcher.namesOfTechnologiesKnown;

		for (var i = 0; i < technologies.length; i++)
		{
			var technology = technologies[i];
			var technologyName = technology.name;

			var isAlreadyKnown = (technologiesKnown.indexOf(technologyName) >= 0);
		
			if (isAlreadyKnown == false)
			{
				var prerequisites = technology.namesOfPrerequisiteTechnologies;

				var areAllPrerequisitesKnown = true;
	
				for (var p = 0; p < prerequisites.length; p++)
				{
					var prerequisite = prerequisites[p];
					var isPrerequisiteKnown = (technologiesKnown.indexOf(prerequisite) >= 0);

					if (isPrerequisiteKnown == false)
					{
						areAllPrerequisitesKnown = false;
						break;
					}
				}

				if (areAllPrerequisitesKnown == true)
				{
					var optionTechnology = document.createElement("option");
					optionTechnology.value = technologyName;
					optionTechnology.innerHTML = 
						technologyName 
						+ " - (" + technology.researchRequired + ")";

					this.selectTechnologyBeingResearched.appendChild
					(
						optionTechnology
					);
				}
			}
		}
	}

	// events

	ResearchSession.prototype.buttonResearchIncrement_Click = function(event)
	{
		var researcher = this.researcher;

		var nameOfTechnologyBeingResearched = researcher.nameOfTechnologyBeingResearched;
		var technologyBeingResearched = this.technologyTree.technologies[nameOfTechnologyBeingResearched];

		researcher.researchAccumulated++;
		if (researcher.researchAccumulated >= technologyBeingResearched.researchRequired)
		{
			researcher.namesOfTechnologiesKnown.push
			(
				this.researcher.nameOfTechnologyBeingResearched
			);
			researcher.nameOfTechnologyBeingResearched = null;
			researcher.researchAccumulated = 0;
		}

		this.domElementUpdate();
	}

	ResearchSession.prototype.selectTechnologyBeingResearched_Change = function(event)
	{
		var srcElement = event.srcElement;

		this.researcher.nameOfTechnologyBeingResearched = srcElement.value;
		this.domElementUpdate();
	}

}

function Technology(name, researchRequired, namesOfPrerequisiteTechnologies)
{
	this.name = name;
	this.researchRequired = researchRequired;
	this.namesOfPrerequisiteTechnologies = namesOfPrerequisiteTechnologies;
}

function TechnologyTree(name, technologies)
{
	this.name = name;
	this.technologies = technologies;

	for (var i = 0; i < this.technologies.length; i++)
	{
		var technology = this.technologies[i];
		this.technologies[technology.name] = technology;
	}
}

// run 

main();

</script>
</body>
</html>

Advertisements
This entry was posted in Uncategorized and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s