changeset 0:7e3a0ae9c016

Initial commit
author koryspansel <koryspansel@bendbroadband.com>
date Wed, 07 Sep 2011 12:36:37 -0700
parents
children 858e3689073e
files .hgignore Assets/Maps/map00.def Assets/Maps/map01.def Assets/Maps/map02.def Assets/Maps/map03.def Assets/UI/Arrow.PSD Assets/UI/Background.PSD Assets/UI/Block00.PSD Assets/UI/Block01.PSD Assets/UI/Block02.PSD Assets/UI/Dialog1.PSD Assets/UI/Dialog2.PSD Assets/UI/Exit.PSD Assets/UI/Forward.PSD Assets/UI/Function1.PSD Assets/UI/Function2.PSD Assets/UI/Hand.PSD Assets/UI/Jump.PSD Assets/UI/Left.PSD Assets/UI/Light.PSD Assets/UI/Play.PSD Assets/UI/Right.PSD Assets/UI/RotateCCW.PSD Assets/UI/RotateCW.PSD Assets/UI/Slot.PSD Assets/UI/Stop.PSD Data/Maps/map00.map Data/Maps/map01.map Data/Maps/map02.map Data/Maps/map03.map Data/Shaders/Environment.fx Data/Shaders/TexturedQuad.fx Data/Textures/Arrow.tga Data/Textures/Background.tga Data/Textures/Block00.tga Data/Textures/Block01.tga Data/Textures/Block02.tga Data/Textures/Dialog1.tga Data/Textures/Dialog2.tga Data/Textures/Exit.tga Data/Textures/Forward.tga Data/Textures/Function1.tga Data/Textures/Function2.tga Data/Textures/Hand.tga Data/Textures/Jump.tga Data/Textures/Left.tga Data/Textures/Light.tga Data/Textures/Play.tga Data/Textures/Right.tga Data/Textures/RotateCCW.tga Data/Textures/RotateCW.tga Data/Textures/Slot.tga Data/Textures/Stop.tga Docs/LightClone GDD.txt Docs/LightClone TDD.txt LightClone.sln LightClone.smp LightClone/LightClone.vcproj LightClone/Source/Bot.cpp LightClone/Source/Bot.h LightClone/Source/CameraController.cpp LightClone/Source/CameraController.h LightClone/Source/Clock.cpp LightClone/Source/Clock.h LightClone/Source/Code.cpp LightClone/Source/Code.h LightClone/Source/Controller.cpp LightClone/Source/Controller.h LightClone/Source/Core.cpp LightClone/Source/Core.h LightClone/Source/DragController.cpp LightClone/Source/DragController.h LightClone/Source/Environment.cpp LightClone/Source/Environment.h LightClone/Source/InputManager.cpp LightClone/Source/InputManager.h LightClone/Source/Loader.cpp LightClone/Source/Loader.h LightClone/Source/Main.cpp LightClone/Source/Math.cpp LightClone/Source/Mediator.cpp LightClone/Source/Mediator.h LightClone/Source/Model.cpp LightClone/Source/Model.h LightClone/Source/RenderContext.cpp LightClone/Source/RenderContext.h LightClone/Source/Tower.cpp LightClone/Source/Tower.h LightClone/Source/Util.cpp LightClone/Source/Util.h LightClone/Source/VertexTypes.cpp LightClone/Source/VertexTypes.h LightClone/Source/View.cpp LightClone/Source/View.h LightClone/Source/VirtualMachine.cpp LightClone/Source/VirtualMachine.h LightClone/ToDo.txt LightTools/Build.py LightTools/Map.py
diffstat 97 files changed, 6612 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,8 @@
+syntax: glob
+
+*.user
+*.pyc
+
+Assets\UI\*.png
+Assets\UI\*.jpg
+Assets\UI\*.gif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assets/Maps/map00.def	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,66 @@
+#
+# map00
+#
+
+7,7
+3,1
+0
+2
+10
+10
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+1,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assets/Maps/map01.def	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,66 @@
+#
+# map01
+#
+
+7,7
+3,1
+0
+2
+10
+10
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,2
+0,2
+0,2
+0,2
+0,2
+0,2
+0,2
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+1,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assets/Maps/map02.def	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,66 @@
+#
+# map00
+#
+
+7,7
+3,1
+0
+2
+10
+10
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+1,1
+0,1
+1,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assets/Maps/map03.def	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,66 @@
+#
+# map00
+#
+
+7,7
+3,1
+0
+2
+10
+10
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+1,2
+0,1
+0,1
+
+0,1
+0,1
+0,1
+1,2
+0,1
+1,2
+0,1
+
+0,1
+0,1
+0,1
+0,1
+1,2
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
+0,1
Binary file Assets/UI/Arrow.PSD has changed
Binary file Assets/UI/Background.PSD has changed
Binary file Assets/UI/Block00.PSD has changed
Binary file Assets/UI/Block01.PSD has changed
Binary file Assets/UI/Block02.PSD has changed
Binary file Assets/UI/Dialog1.PSD has changed
Binary file Assets/UI/Dialog2.PSD has changed
Binary file Assets/UI/Exit.PSD has changed
Binary file Assets/UI/Forward.PSD has changed
Binary file Assets/UI/Function1.PSD has changed
Binary file Assets/UI/Function2.PSD has changed
Binary file Assets/UI/Hand.PSD has changed
Binary file Assets/UI/Jump.PSD has changed
Binary file Assets/UI/Left.PSD has changed
Binary file Assets/UI/Light.PSD has changed
Binary file Assets/UI/Play.PSD has changed
Binary file Assets/UI/Right.PSD has changed
Binary file Assets/UI/RotateCCW.PSD has changed
Binary file Assets/UI/RotateCW.PSD has changed
Binary file Assets/UI/Slot.PSD has changed
Binary file Assets/UI/Stop.PSD has changed
Binary file Data/Maps/map00.map has changed
Binary file Data/Maps/map01.map has changed
Binary file Data/Maps/map02.map has changed
Binary file Data/Maps/map03.map has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Data/Shaders/Environment.fx	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,71 @@
+extern uniform float4x4	kWorld;
+extern uniform float4x4	kView;
+extern uniform float4x4	kProjection;
+extern uniform float4	kColor;
+extern uniform texture	kTexture;
+
+sampler TextureSampler = sampler_state
+{
+	Texture		= <kTexture>;
+	MinFilter	= LINEAR;
+	MagFilter	= LINEAR;
+	AddressU	= WRAP;
+	AddressV	= WRAP;
+};
+
+struct VertexOutput
+{
+	/*
+	 * kPosition
+	 */
+	float4 kPosition : POSITION0;
+	
+	/*
+	 * kTextureCoords
+	 */
+	float2 kTextureCoords : TEXCOORD0;
+};
+
+VertexOutput EnvironmentVS(float3 kVertexPosition : POSITION0, float3 kVertexNormal : NORMAL, float2 kTextureCoords : TEXCOORD0)
+{
+	float4x4 kWorldViewProjection = mul(mul(kWorld, kView), kProjection);
+	
+	VertexOutput kOutput;
+	kOutput.kPosition		= mul(float4(kVertexPosition, 1.0f), kWorldViewProjection);
+	kOutput.kTextureCoords	= kTextureCoords;
+
+	return kOutput;
+}
+
+float4 EnvironmentPS(float2 kTextureCoords : TEXCOORD0) : COLOR0
+{
+	float4 kTexture = tex2D(TextureSampler, kTextureCoords);
+	return  float4(kTexture.rgb * kColor.rgb, kTexture.a);
+}
+
+technique Default
+{
+	pass Pass0
+	{
+		vertexShader	= compile vs_2_0 EnvironmentVS();
+		pixelShader		= compile ps_2_0 EnvironmentPS();
+
+		ZEnable			= true;
+		ZWriteEnable	= true;
+		ZFunc			= LessEqual;
+	}
+}
+
+technique Wire
+{
+	pass Pass0
+	{
+		vertexShader	= compile vs_2_0 EnvironmentVS();
+		pixelShader		= compile ps_2_0 EnvironmentPS();
+
+		ZEnable			= true;
+		ZWriteEnable	= false;
+		ZFunc			= LessEqual;
+		FillMode		= Wireframe;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Data/Shaders/TexturedQuad.fx	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,123 @@
+extern uniform float4x4	kProjection;
+extern uniform float4x4 kWorld;
+extern uniform texture	kTexture;
+extern uniform float4	kColor;
+
+/*
+ * TextureSampler
+ */
+sampler TextureSampler = sampler_state
+{
+	Texture		= <kTexture>;
+	MinFilter	= POINT;
+	MagFilter	= POINT;
+	AddressU	= CLAMP;
+	AddressV	= CLAMP;
+};
+
+/*
+ * VertexInput
+ */
+struct VertexInput
+{
+	/*
+	 * Position
+	 */
+	float3 Position : POSITION0;
+
+	/*
+	 * TextureCoordinate
+	 */
+	float2 TextureCoordinate : TEXCOORD0;
+};
+
+/*
+ * VertexOutput
+ */
+struct VertexOutput
+{
+	/*
+	 * Position
+	 */
+	float4 Position : POSITION0;
+
+	/*
+	 * TextureCoordinate
+	 */
+	float2 TextureCoordinate : TEXCOORD0;
+};
+
+/*
+ * PixelInput
+ */
+struct PixelInput
+{
+	/*
+	 * TextureCoordinate
+	 */
+	float2 TextureCoordinate : TEXCOORD0;
+
+	/*
+	 * Color
+	 */
+	float4 Color : COLOR0;
+};
+
+/*
+ * PixelOutput
+ */
+struct PixelOutput
+{
+	/*
+	 * Color
+	 */
+	float4 Color : COLOR0;
+};
+
+/*
+ * TexturedQuadVS
+ */
+VertexOutput TexturedQuadVS(VertexInput kInput)
+{
+	VertexOutput kOutput;
+
+	kOutput.Position			= mul(float4(kInput.Position, 1.0f), mul(kWorld, kProjection));
+	kOutput.TextureCoordinate	= kInput.TextureCoordinate;
+
+	return kOutput;
+}
+
+/*
+ * TexturedQuadPS
+ */
+PixelOutput TexturedQuadPS(PixelInput kInput)
+{
+	PixelOutput kOutput;
+
+	float4 kTexture = tex2D(TextureSampler, kInput.TextureCoordinate);
+
+	kOutput.Color = float4(kTexture.rgb * kColor.rgb, kTexture.a);
+	//kOutput.Color = kColor;
+
+	return kOutput;
+}
+
+technique Default
+{
+	pass Opaque
+	{
+		vertexShader		= compile vs_2_0 TexturedQuadVS();
+		pixelShader			= compile ps_2_0 TexturedQuadPS();
+
+		/*
+		ZEnable				= true;
+		ZWriteEnable		= true;
+		ZFunc				= LessEqual;
+		*/
+
+		AlphaBlendEnable	= true;
+		AlphaFunc			= LessEqual;
+		SrcBlend			= SrcAlpha;
+		DestBlend			= InvSrcAlpha;
+	}
+}
\ No newline at end of file
Binary file Data/Textures/Arrow.tga has changed
Binary file Data/Textures/Background.tga has changed
Binary file Data/Textures/Block00.tga has changed
Binary file Data/Textures/Block01.tga has changed
Binary file Data/Textures/Block02.tga has changed
Binary file Data/Textures/Dialog1.tga has changed
Binary file Data/Textures/Dialog2.tga has changed
Binary file Data/Textures/Exit.tga has changed
Binary file Data/Textures/Forward.tga has changed
Binary file Data/Textures/Function1.tga has changed
Binary file Data/Textures/Function2.tga has changed
Binary file Data/Textures/Hand.tga has changed
Binary file Data/Textures/Jump.tga has changed
Binary file Data/Textures/Left.tga has changed
Binary file Data/Textures/Light.tga has changed
Binary file Data/Textures/Play.tga has changed
Binary file Data/Textures/Right.tga has changed
Binary file Data/Textures/RotateCCW.tga has changed
Binary file Data/Textures/RotateCW.tga has changed
Binary file Data/Textures/Slot.tga has changed
Binary file Data/Textures/Stop.tga has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone.sln	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LightClone", "LightClone\LightClone.vcproj", "{24506D51-1AB0-434D-AFBB-40314CF4DFD6}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{24506D51-1AB0-434D-AFBB-40314CF4DFD6}.Debug|Win32.ActiveCfg = Debug|Win32
+		{24506D51-1AB0-434D-AFBB-40314CF4DFD6}.Debug|Win32.Build.0 = Debug|Win32
+		{24506D51-1AB0-434D-AFBB-40314CF4DFD6}.Release|Win32.ActiveCfg = Release|Win32
+		{24506D51-1AB0-434D-AFBB-40314CF4DFD6}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Binary file LightClone.smp has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/LightClone.vcproj	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,377 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="LightClone"
+	ProjectGUID="{24506D51-1AB0-434D-AFBB-40314CF4DFD6}"
+	RootNamespace="LightClone"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(ProjectDir)Bin\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)Intermediate\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=""
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_WINDOWS=0x0410;_WIN32_IE=0x0700;WIN32_LEAN_AND_MEAN"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="d3d9.lib d3dx9d.lib dxguid.lib dxerr.lib dinput8.lib"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories=""
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(ProjectDir)Bin\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)Intermediate\$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories=""
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;WINVER=0x0600;_WIN32_WINNT=0x0600;_WIN32_WINDOWS=0x0410;_WIN32_IE=0x0700;WIN32_LEAN_AND_MEAN"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="d3d9.lib d3dx9.lib dxguid.lib dxerr.lib dinput8.lib"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories=""
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\Source\Bot.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\CameraController.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Clock.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Code.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Controller.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Core.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\DragController.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Environment.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\InputManager.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Loader.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Main.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Mediator.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Model.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\RenderContext.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Tower.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Util.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\VertexTypes.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\View.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\VirtualMachine.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\Source\Bot.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\CameraController.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Clock.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Code.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Controller.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Core.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\DragController.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Environment.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\InputManager.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Loader.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Mediator.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Model.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\RenderContext.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Tower.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\Util.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\VertexTypes.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\View.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Source\VirtualMachine.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			>
+			<Filter
+				Name="Shaders"
+				>
+				<File
+					RelativePath="..\Data\Shaders\Environment.fx"
+					>
+				</File>
+				<File
+					RelativePath="..\Data\Shaders\TexturedQuad.fx"
+					>
+				</File>
+			</Filter>
+			<Filter
+				Name="Levels"
+				>
+				<File
+					RelativePath="..\Assets\Maps\map00.def"
+					>
+				</File>
+				<File
+					RelativePath="..\Assets\Maps\map01.def"
+					>
+				</File>
+				<File
+					RelativePath="..\Assets\Maps\map02.def"
+					>
+				</File>
+				<File
+					RelativePath="..\Assets\Maps\map03.def"
+					>
+				</File>
+			</Filter>
+		</Filter>
+		<File
+			RelativePath=".\ToDo.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Bot.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,331 @@
+/*
+ * Bot
+ */
+
+#include "Bot.h"
+#include "Clock.h"
+#include <d3d9.h>
+#include <d3dx9.h>
+
+/*
+ * DirectionAngle
+ */
+const float DirectionAngle[] = {-1.0f * D3DX_PI / 2.0f, -4.0f * D3DX_PI / 2.0f, -3.0f * D3DX_PI / 2.0f, -2.0f * D3DX_PI / 2.0f};
+
+/*
+ * DirectionStepX
+ */
+const int32 DirectionStepX[] = {0, 1, 0, -1};
+
+/*
+ * DirectionStepY
+ */
+const int32 DirectionStepY[] = {1, 0, -1, 0};
+
+/*
+ * Bot
+ */
+Bot::Bot()
+{
+	pEnvironment	= 0;
+	nState			= BotState_Idle;
+	kSize			= D3DXVECTOR3(0.55f, 1.00f, 0.55f);
+}
+
+/*
+ * Initialize
+ */
+void Bot::Initialize(Environment* pInstance)
+{
+	pEnvironment	= pInstance;
+	nState			= BotState_Idle;
+	nColor			= D3DCOLOR_XRGB(0, 255, 0);
+
+	kMachine.RemoveAllFunctions();
+}
+
+/*
+ * Reset
+ */
+void Bot::Reset()
+{
+	nState	= BotState_Idle;
+	nColor	= D3DCOLOR_XRGB(0, 255, 0);
+
+	kMachine.Reset();
+}
+
+/* 
+ * GetWorldPosition
+ */
+const D3DXVECTOR3 Bot::GetWorldPosition() const
+{
+	const D3DXVECTOR3& kScale = pEnvironment->GetScale();
+
+	D3DXVECTOR3 kWorldPosition;
+	kWorldPosition.x = kScale.x * kPosition.X;
+	kWorldPosition.y = kScale.y * pEnvironment->GetAltitude(kPosition.X, kPosition.Y);
+	kWorldPosition.z = kScale.z * kPosition.Y;
+
+	if(nState == BotState_Animate)
+	{
+		if(kSequencer.nSequence == BotSequence_Forward)
+		{
+			kWorldPosition.x = kScale.x * ((int32)kPosition.X + kSequencer.fTimer * ((int32)kSequencer.kPosition.X - (int32)kPosition.X));
+			kWorldPosition.z = kScale.z * ((int32)kPosition.Y + kSequencer.fTimer * ((int32)kSequencer.kPosition.Y - (int32)kPosition.Y));
+		}
+		else
+
+		if(kSequencer.nSequence == BotSequence_Jump)
+		{
+			const uint32 nHeightA = pEnvironment->GetAltitude(kPosition.X, kPosition.Y);
+			const uint32 nHeightB = pEnvironment->GetAltitude(kSequencer.kPosition.X, kSequencer.kPosition.Y);
+
+			const float fDistanceX	= kScale.x;
+			const float fDistanceY	= kScale.y * ((float)nHeightB - (float)nHeightA);
+			const float fHeight		= nHeightB > nHeightA ? 2.0f * kScale.y : kScale.y;
+
+			const float fB = (fHeight - 0.25f * fDistanceY) / (-0.25f * fDistanceX + 0.5f * fDistanceX);
+			const float fA = (fDistanceY - fB * fDistanceX) / (fDistanceX * fDistanceX);
+			const float fX = kSequencer.fTimer * fDistanceX;
+
+			kWorldPosition.x = kScale.x * ((int32)kPosition.X + kSequencer.fTimer * ((int32)kSequencer.kPosition.X - (int32)kPosition.X));
+			kWorldPosition.y = nHeightA * kScale.y + fX * (fA * fX + fB);
+			kWorldPosition.z = kScale.z * ((int32)kPosition.Y + kSequencer.fTimer * ((int32)kSequencer.kPosition.Y - (int32)kPosition.Y));
+		}
+	}
+
+	return kWorldPosition;
+}
+
+/*
+ * GetWorldOrientation
+ */
+const D3DXVECTOR3 Bot::GetWorldOrientation() const
+{
+	D3DXVECTOR3 kWorldOrientation;
+	kWorldOrientation.x = 0.0f;
+	kWorldOrientation.y = DirectionAngle[kDirection];
+	kWorldOrientation.z = 0.0f;
+
+	if(nState == BotState_Animate)
+	{
+		if(kSequencer.nSequence == BotSequence_RotateCW || kSequencer.nSequence == BotSequence_RotateCCW)
+		{
+			kWorldOrientation.y = InterpolateDirection(kDirection, kSequencer.kDirection, kSequencer.fTimer);
+		}
+	}
+
+	return kWorldOrientation;
+}
+
+/*
+ * AddFunction
+ */
+void Bot::AddFunction(uint32 nFunction, uint32 nSize)
+{
+	kMachine.AddFunction((uint8)nFunction, (uint8)nSize * 2);
+}
+
+/*
+ * Upload
+ */
+ErrorCode Bot::Upload(Code* pCode, uint32 nCount)
+{
+	ErrorCode eCode = Error_Success;
+
+	for(uint32 i = 0; i < nCount && eCode == Error_Success; ++i)
+	{
+		uint32 nSize = kMachine.GetFunctionSize(i);
+		uint8* pData = kMachine.GetFunctionMemory(i);
+
+		eCode = Compile(pCode + i, pData, nSize);
+	}
+
+	nState = BotState_Evaluate;
+
+	return eCode;
+}
+
+/*
+ * Compile
+ */
+ErrorCode Bot::Compile(Code* pInstance, uint8* pData, uint32 nSize)
+{
+	const uint32 nLength = pInstance->GetLength();
+
+	for(uint32 i = 0; i < nLength; ++i)
+	{
+		const uint32 nAction = pInstance->GetSlot(i);
+
+		if(Action_Forward <= nAction && nAction <= Action_Light)
+		{
+			if(nSize < 2)
+				return Error_Fail;
+
+			*pData++ = Instruction_Action;
+			*pData++ = nAction;
+
+			nSize -= 2;
+		}
+		else
+
+		if(Action_FunctionA <= nAction && nAction <= Action_FunctionB)
+		{
+			if(nSize < 2)
+				return Error_Fail;
+
+			*pData++ = Instruction_Call;
+			*pData++ = nAction - Action_FunctionA + 1;
+
+			nSize -= 2;
+		}
+	}
+
+	return Error_Success;
+}
+
+/*
+ * Update
+ */
+void Bot::Update(float fElapsed)
+{
+	if(nState == BotState_Evaluate)
+	{
+		bool bHandled = false;
+
+		kClock.Reset();
+
+		while(!bHandled && kClock.GetElapsed(false) < fElapsed)
+		{
+			uint32 nAction = kMachine.Step();
+
+			if(Action_Forward <= nAction && nAction <= Action_Light)
+			{
+				if(nAction == Action_Forward)
+				{
+					if(pEnvironment->IsMovementValid(nAction, kPosition.X, kPosition.Y, kDirection))
+					{
+						kSequencer.kPosition.X	= (int32)kPosition.X + DirectionStepX[kDirection];
+						kSequencer.kPosition.Y	= (int32)kPosition.Y + DirectionStepY[kDirection];
+						kSequencer.nSequence	= BotSequence_Forward;
+						kSequencer.fTimer		= 0.0f;
+						kSequencer.fSpeed		= 1.5f;
+						nState					= BotState_Animate;
+					}
+				}
+				else
+
+				if(nAction == Action_RotateCW)
+				{
+					kSequencer.kDirection		= (kDirection + 1) % Direction_Count;
+					kSequencer.nSequence		= BotSequence_RotateCW;
+					kSequencer.fTimer			= 0.0f;
+					kSequencer.fSpeed			= 1.5f;
+					nState						= BotState_Animate;
+				}
+				else
+
+				if(nAction == Action_RotateCCW)
+				{
+					nState						= BotState_Animate;
+					kSequencer.kDirection		= (kDirection - 1 + Direction_Count) % Direction_Count;
+					kSequencer.nSequence		= BotSequence_RotateCCW;
+					kSequencer.fTimer			= 0.0f;
+					kSequencer.fSpeed			= 1.5f;
+				}
+				else
+
+				if(nAction == Action_Jump)
+				{
+					if(pEnvironment->IsMovementValid(nAction, kPosition.X, kPosition.Y, kDirection))
+					{
+						kSequencer.kPosition.X	= (int32)kPosition.X + DirectionStepX[kDirection];
+						kSequencer.kPosition.Y	= (int32)kPosition.Y + DirectionStepY[kDirection];
+					}
+					else
+					{
+						kSequencer.kPosition.X	= kPosition.X;
+						kSequencer.kPosition.Y	= kPosition.Y;
+					}
+
+					nState					= BotState_Animate;
+					kSequencer.nSequence	= BotSequence_Jump;
+					kSequencer.fTimer		= 0.0f;
+					kSequencer.fSpeed		= 1.5f;
+				}
+				else
+
+				if(nAction == Action_Light)
+				{
+					nState					= BotState_Animate;
+					nColor					= D3DCOLOR_XRGB(0, 0, 255);
+					kSequencer.nSequence	= BotSequence_Light;
+					kSequencer.fTimer		= 0.0f;
+					kSequencer.fSpeed		= 3.0f;
+				}
+
+				bHandled = true;
+			}
+		}
+	}
+	else
+
+	if(nState == BotState_Animate)
+	{
+		kSequencer.fTimer += kSequencer.fSpeed * fElapsed;
+		if(kSequencer.fTimer >= 1.0f)
+		{
+			if(kSequencer.nSequence == BotSequence_Forward)
+			{
+				nState				= BotState_Pause;
+				kPosition			= kSequencer.kPosition;
+				kSequencer.fTimer	= 0.4f;
+			}
+			else
+
+			if(kSequencer.nSequence == BotSequence_RotateCW)
+			{
+				nState				= BotState_Pause;
+				kDirection			= kSequencer.kDirection;
+				kSequencer.fTimer	= 0.4f;
+			}
+			else
+
+			if(kSequencer.nSequence == BotSequence_RotateCCW)
+			{
+				nState				= BotState_Pause;
+				kDirection			= kSequencer.kDirection;
+				kSequencer.fTimer	= 0.4f;
+			}
+			else
+
+			if(kSequencer.nSequence == BotSequence_Jump)
+			{
+				nState				= BotState_Pause;
+				kPosition			= kSequencer.kPosition;
+				kSequencer.fTimer	= 0.4f;
+			}
+			else
+
+			if(kSequencer.nSequence == BotSequence_Light)
+			{
+				pEnvironment->NotifyAction(kPosition.X, kPosition.Y);
+					
+				nState				= BotState_Pause;
+				nColor				= D3DCOLOR_XRGB(0, 255, 0);
+				kSequencer.fTimer	= 0.4f;
+			}
+		}
+	}
+	else
+
+	if(nState == BotState_Pause)
+	{
+		kSequencer.fTimer -= fElapsed;
+		if(kSequencer.fTimer <= 0.0f)
+		{
+			nState = BotState_Evaluate;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Bot.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,178 @@
+/*
+ * Bot
+ */
+
+#ifndef __BOT_H__
+#define __BOT_H__
+
+#include "Core.h"
+#include "VirtualMachine.h"
+#include "Environment.h"
+#include "Code.h"
+#include "Clock.h"
+
+/*
+ * BotState
+ */
+enum
+{
+	BotState_Idle,
+	BotState_Evaluate,
+	BotState_Animate,
+	BotState_Pause,
+};
+
+/*
+ * BotSequence
+ */
+enum
+{
+	BotSequence_Forward,
+	BotSequence_RotateCW,
+	BotSequence_RotateCCW,
+	BotSequence_Jump,
+	BotSequence_Light,
+};
+
+/*
+ * Bot
+ */
+class Bot
+{
+	/*
+	 * BotSequencer
+	 */
+	struct BotSequencer
+	{
+		/*
+		 * nSequence
+		 */
+		uint32 nSequence;
+
+		/*
+		 * fTimer
+		 */
+		float fTimer;
+
+		/*
+		 * fSpeed
+		 */
+		float fSpeed;
+
+		/*
+		 * kPosition
+		 */
+		Position kPosition;
+
+		/*
+		 * kDirection
+		 */
+		uint32 kDirection;
+
+		/*
+		 * nColor
+		 */
+		uint32 nColor;
+	};
+
+private:
+
+	/*
+	 * pEnvironment
+	 */
+	Environment* pEnvironment;
+
+	/*
+	 * kMachine
+	 */
+	VirtualMachine kMachine;
+
+	/*
+	 * kClock
+	 *	The clock used to keep track of VM execution
+	 */
+	Clock kClock;
+
+	/*
+	 * nState
+	 */
+	uint32 nState;
+
+	/*
+	 * kSequencer
+	 */
+	BotSequencer kSequencer;
+
+public:
+
+	/*
+	 * kPosition
+	 */
+	Position kPosition;
+
+	/*
+	 * kDirection
+	 */
+	uint32 kDirection;
+
+	/*
+	 * nColor
+	 */
+	uint32 nColor;
+
+	/*
+	 * kSize
+	 */
+	D3DXVECTOR3 kSize;
+
+public:
+
+	/*
+	 * Bot
+	 */
+	Bot();
+
+	/*
+	 * Reset
+	 */
+	void Initialize(Environment* pInstance);
+
+	/*
+	 * Reset
+	 */
+	void Reset();
+
+	/* 
+	 * GetWorldPosition
+	 */
+	const D3DXVECTOR3 GetWorldPosition() const;
+
+	/*
+	 * GetWorldOrientation
+	 */
+	const D3DXVECTOR3 GetWorldOrientation() const;
+
+	/*
+	 * AddFunction
+	 */
+	void AddFunction(uint32 nFunction, uint32 nSize);
+
+	/*
+	 * Upload
+	 */
+	ErrorCode Upload(Code* pCode, uint32 nCount);
+
+	/*
+	 * Update
+	 */
+	void Update(float fElapsed);
+
+private:
+	
+	/*
+	 * Compile
+	 */
+	ErrorCode Compile(Code* pCode, uint8* pData, uint32 nSize);
+};
+
+#endif //__BOT_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/CameraController.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,58 @@
+/*
+ * CameraController
+ */
+
+#include "CameraController.h"
+
+/*
+ * CameraController
+ */
+CameraController::CameraController(float fInitialDistance, float fInitialYaw, float fInitialPitch)
+{
+	fCameraDistance	= fInitialDistance;
+	fCameraYaw		= fInitialYaw;
+	fCameraPitch	= fInitialPitch;
+}
+
+/*
+ * Render
+ */
+void CameraController::Update(float fElapsed)
+{
+}
+
+/*
+ * Yaw
+ */
+void CameraController::Yaw(float fAmount)
+{
+	fCameraYaw += fAmount;
+}
+
+/*
+ * Pitch
+ */
+void CameraController::Pitch(float fAmount)
+{
+	fCameraPitch += fAmount;
+}
+
+/*
+ * Move
+ */
+void CameraController::Move(float fAmount)
+{
+	fCameraDistance += fAmount;
+}
+
+/*
+ * GetLocation
+ */
+const D3DXVECTOR3 CameraController::GetLocation(const D3DXVECTOR3& kTarget) const
+{
+	const float fOffsetX	= fCameraDistance * sinf(0.5f * D3DX_PI - fCameraPitch) * cosf(fCameraYaw);
+	const float fOffsetY	= fCameraDistance * cosf(0.5f * D3DX_PI - fCameraPitch);
+	const float fOffsetZ	= fCameraDistance * sinf(0.5f * D3DX_PI - fCameraPitch) * sinf(fCameraYaw);
+
+	return D3DXVECTOR3(kTarget.x + fOffsetX, kTarget.y + fOffsetY, kTarget.z + fOffsetZ);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/CameraController.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,66 @@
+/*
+ * CameraController
+ */
+
+#ifndef __CAMERACONTROLLER_H__
+#define __CAMERACONTROLLER_H__
+
+#include "Core.h"
+
+/*
+ * CameraController
+ */
+class CameraController
+{
+public:
+
+	/*
+	 * fCameraDistance
+	 */
+	float fCameraDistance;
+
+	/*
+	 * fCameraYaw
+	 */
+	float fCameraYaw;
+
+	/*
+	 * fCameraPitch
+	 */
+	float fCameraPitch;
+
+public:
+
+	/*
+	 * CameraController
+	 */
+	//CameraController(float fInitialDistance = 16.0f, float fInitialYaw = D3DX_PI / 6.0f, float fInitialPitch = D3DX_PI / 4.0);
+	CameraController(float fInitialDistance = 16.0f, float fInitialYaw = 0.306f, float fInitialPitch = 0.875f);
+
+	/*
+	 * Update
+	 */
+	void Update(float fElapsed);
+
+	/*
+	 * Yaw
+	 */
+	void Yaw(float fAmount);
+
+	/*
+	 * Pitch
+	 */
+	void Pitch(float fAmount);
+
+	/*
+	 * Move
+	 */
+	void Move(float fAmount);
+
+	/*
+	 * GetLocation
+	 */
+	const D3DXVECTOR3 GetLocation(const D3DXVECTOR3& kTarget) const;
+};
+
+#endif //__CAMERACONTROLLER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Clock.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,43 @@
+/*
+ * Clock
+ */
+
+#include "Clock.h"
+#include <windows.h>
+
+#define QueryFrequency(variable)	QueryPerformanceFrequency((LARGE_INTEGER*)variable)
+#define QueryCounter(variable)		QueryPerformanceCounter((LARGE_INTEGER*)variable)
+
+/*
+ * Clock
+ */
+Clock::Clock()
+{
+	QueryFrequency(&nFrequency);
+}
+
+/*
+ * Reset
+ */
+void Clock::Reset()
+{
+	QueryCounter(&nCurrent);
+}
+
+/*
+ * GetElapsed
+ */
+float Clock::GetElapsed(bool bReset)
+{
+	unsigned __int64 nTicks = 0;
+	QueryCounter(&nTicks);
+
+	const float fElapsed = (nTicks - nCurrent) / (float)nFrequency;
+
+	if(bReset)
+	{
+		Reset();
+	}
+
+	return fElapsed;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Clock.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,43 @@
+/*
+ * Clock
+ */
+
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+#include "Core.h"
+
+/*
+ * Clock
+ */
+class Clock
+{
+	/*
+	 * nFrequency
+	 */
+	unsigned __int64 nFrequency;
+
+	/*
+	 * nCurrent
+	 */
+	unsigned __int64 nCurrent;
+
+public:
+
+	/*
+	 * Clock
+	 */
+	Clock();
+
+	/*
+	 * Reset
+	 */
+	void Reset();
+
+	/*
+	 * GetElapsed
+	 */
+	float GetElapsed(bool bReset = true);
+};
+
+#endif //__CLOCK_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Code.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,108 @@
+/*
+ * Code
+ */
+
+#include "Code.h"
+
+/*
+ * Code
+ */
+Code::Code()
+{
+	pSlot	= 0;
+	nSize	= 0;
+	nLength	= 0;
+}
+
+/*
+ * Initialize
+ */
+void Code::Initialize(uint32 nValue)
+{
+	if(pSlot)
+	{
+		delete[] pSlot;
+		pSlot = 0;
+	}
+
+	nLength	= 0;
+	nSize	= nValue;
+	pSlot	= new uint32[nValue];
+
+	Clear();
+}
+
+/*
+ * Clear
+ */
+void Code::Clear()
+{
+	for(uint32 i = 0; i < nSize; ++i)
+	{
+		pSlot[i] = 0;
+	}
+}
+
+/*
+ * SetSlot
+ */
+void Code::SetSlot(uint32 nSlot, uint32 nValue)
+{
+	if(nSlot < nSize)
+	{
+		pSlot[nSlot] = nValue;
+	}
+}
+
+/*
+ * GetSlot
+ */
+uint32 Code::GetSlot(uint32 nSlot)
+{
+	return nSlot < nSize ? pSlot[nSlot] : 0;
+}
+
+/*
+ * ClearSlot
+ */
+void Code::ClearSlot(uint32 nSlot)
+{
+	if(nSlot < nSize)
+	{
+		pSlot[nSlot] = 0;
+	}
+}
+
+/*
+ * IsEmptySlot
+ */
+bool Code::IsEmptySlot(uint32 nSlot) const
+{
+	return nSlot < nSize ? (pSlot[nSlot] < Action_Forward || pSlot[nSlot] > Action_Light) : true;
+}
+
+/*
+ * GetSize
+ */
+uint32 Code::GetSize() const
+{
+	return nSize;
+}
+
+/*
+ * GetLength
+ */
+uint32 Code::GetLength() const
+{
+	uint32 nLength = 0;
+
+	for(uint32 i = 0; i < nSize; ++i)
+	{
+		if(pSlot[nLength] != 0)
+		{
+			++nLength;
+		}
+	}
+
+	return nLength;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Code.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,79 @@
+/*
+ * Code
+ */
+
+#ifndef __CODE_H__
+#define __CODE_H__
+
+#include "Core.h"
+
+/*
+ * Code
+ */
+class Code
+{
+	/*
+	 * pSlot
+	 *	Code blocks are made up of an array of actions
+	 */
+	uint32* pSlot;
+
+	/*
+	 * nSize
+	 */
+	uint32 nSize;
+
+	/*
+	 * nLength
+	 */
+	uint32 nLength;
+
+public:
+
+	/*
+	 * Code
+	 */
+	Code();
+
+	/*
+	 * Initialize
+	 */
+	void Initialize(uint32 nLength);
+
+	/*
+	 * Clear
+	 */
+	void Clear();
+
+	/*
+	 * SetSlot
+	 */
+	void SetSlot(uint32 nSlot, uint32 nValue);
+
+	/*
+	 * GetSlot
+	 */
+	uint32 GetSlot(uint32 nSlot);
+
+	/*
+	 * ClearSlot
+	 */
+	void ClearSlot(uint32 nSlot);
+
+	/*
+	 * IsEmptySlot
+	 */
+	bool IsEmptySlot(uint32 nSlot) const;
+
+	/*
+	 * GetSize
+	 */
+	uint32 GetSize() const;
+
+	/*
+	 * GetLength
+	 */
+	uint32 GetLength() const;
+};
+
+#endif //__CODE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Controller.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,273 @@
+/*
+ * Controller
+ */
+
+#include "Controller.h"
+
+/*
+ * Controller
+ */
+Controller::Controller(Model* pModelInstance, View* pViewInstance) : pModel(pModelInstance), pView(pViewInstance)
+{
+}
+
+/*
+ * Initialize
+ */
+ErrorCode Controller::Initialize()
+{
+	return kInputManager.Initialize(pView->GetWindow());
+}
+
+/*
+ * Terminate
+ */
+void Controller::Terminate()
+{
+	kInputManager.Terminate();
+}
+
+/*
+ * Update
+ */
+void Controller::Update(float fElapsed)
+{
+	ProcessInput(fElapsed);
+
+	if(pModel->nGameState == GameState_LoadMap)
+	{
+		char kBuffer[256];
+		sprintf_s(kBuffer, "Data\\Maps\\Map%02d.map", pModel->nCurrentLevel++);
+
+		pModel->nGameState = pModel->Load(kBuffer) ? GameState_Active : GameState_Over;
+
+		/*
+		bool bLoaded = pModel->Load(kBuffer);
+		if(bLoaded)
+		{
+			pModel->nGameState = GameState_Active;
+		}
+		else
+		{
+			//TODO: Display game over dialog
+			pModel->nGameState = GameState_Over;
+		}
+		*/
+	}
+	else
+
+	if(pModel->nGameState == GameState_Active)
+	{
+		if(pModel->nSimulationState == SimulationState_Active)
+		{
+			pModel->GetBot()->Update(fElapsed);
+
+			//TODO: Only check for requirements after an action has completed
+			Environment* pEnvironment = pModel->GetEnvironment();
+			if(pEnvironment->RequirementsMet())
+			{
+				pModel->nGameState = GameState_Complete;
+			}
+		}
+	}
+	else
+
+	if(pModel->nGameState == GameState_Complete)
+	{
+		//TODO: Level is complete 
+		//TODO: Load next level or end game
+		//pModel->nGameState = GameState_LoadMap;
+	}
+	else
+
+	if(pModel->nGameState == GameState_Over)
+	{
+		//TODO: Game is over
+		//pModel->nGameState = GameState_Exit;
+	}
+	else
+
+	if(pModel->nGameState == GameState_Confirm)
+	{
+	}
+}
+
+/*
+ * Start
+ */
+void Controller::Start()
+{
+	if(pModel->nSimulationState == SimulationState_Idle)
+	{
+		pModel->ResetBot();
+		pModel->GetBot()->Upload(pModel->GetFunction(0), pModel->GetFunctionCount()); 
+
+		pModel->nSimulationState = SimulationState_Active;
+	}
+}
+
+/*
+ * Stop
+ */
+void Controller::Stop()
+{
+	if(pModel->nSimulationState == SimulationState_Active)
+	{
+		pModel->ResetEnvironment();
+		pModel->ResetBot();
+
+		pModel->nSimulationState = SimulationState_Idle;
+	}
+}
+
+/*
+ * ProcessInput
+ */
+void Controller::ProcessInput(float fElapsed)
+{
+	kInputManager.Update(fElapsed);
+
+	#if defined(_DEBUG)
+	if(kInputManager.IsKeyDown(DIK_LEFT))
+	{
+		pView->UpdateCameraYaw(0.01f);
+	}
+	else
+
+	if(kInputManager.IsKeyDown(DIK_RIGHT))
+	{
+		pView->UpdateCameraYaw(-0.01f);
+	}
+
+	if(kInputManager.IsKeyDown(DIK_UP))
+	{
+		pView->UpdateCameraPitch(0.01f);
+	}
+	else
+
+	if(kInputManager.IsKeyDown(DIK_DOWN))
+	{
+		pView->UpdateCameraPitch(-0.01f);
+	}
+
+	if(kInputManager.IsKeyDown(DIK_NEXT))
+	{
+		pView->UpdateCameraDistance(-0.1f);
+	}
+	else
+
+	if(kInputManager.IsKeyDown(DIK_PRIOR))
+	{
+		pView->UpdateCameraDistance(0.1f);
+	}
+	#endif
+
+	const float fSensitivity	= 1.5f;
+	const float fDeltaX			= (float)kInputManager.GetMouseDeltaX();
+	const float fDeltaY			= (float)kInputManager.GetMouseDeltaY();
+
+	const float fMouseX = Max(0.0f, Min(pModel->fMouseX + fSensitivity * fDeltaX, (float)ScreenSizeX));
+	const float fMouseY = Max(0.0f, Min(pModel->fMouseY + fSensitivity * fDeltaY, (float)ScreenSizeY));
+
+	pModel->fMouseX = fMouseX;
+	pModel->fMouseY = fMouseY;
+
+	if(pModel->nGameState == GameState_Active)
+	{
+		if(kInputManager.IsButtonDown(0) && !kInputManager.WasButtonDown(0))
+		{
+			for(uint32 i = 0; i < Action_Count; ++i)
+			{
+				if(pModel->kActionBounds[i].Contains(fMouseX, fMouseY))
+				{
+					pModel->kDragController.Begin(Action_Forward + i);
+				}
+			}
+
+			for(uint32 i = 0; i < sizeof(pModel->kMainBounds) / sizeof(pModel->kMainBounds[0]); ++i)
+			{
+				if(pModel->kMainBounds[i].Contains(fMouseX, fMouseY))
+				{
+					Code* pCode = pModel->GetFunction(0);
+					if(!pCode->IsEmptySlot(i))
+					{
+						pModel->kDragController.Begin(pCode->GetSlot(i));
+						pCode->ClearSlot(i);
+					}
+				}
+			}
+
+			for(uint32 i = 0; i < sizeof(pModel->kFunctionBounds) / sizeof(pModel->kFunctionBounds[0]); ++i)
+			{
+				if(pModel->kFunctionBounds[i].Contains(fMouseX, fMouseY))
+				{
+					Code* pCode = pModel->GetFunction(pModel->nCurrentFunction + 1);
+					if(!pCode->IsEmptySlot(i))
+					{
+						pModel->kDragController.Begin(pCode->GetSlot(i));
+						pCode->ClearSlot(i);
+					}
+				}
+			}
+
+			if(!pModel->kDragController.IsActive())
+			{
+				if(pModel->kControlBounds[0].Contains(fMouseX, fMouseY))
+				{
+					Start();
+				}
+				else
+
+				if(pModel->kControlBounds[1].Contains(fMouseX, fMouseY))
+				{
+					Stop();
+				}
+				else
+
+				if(pModel->kControlBounds[2].Contains(fMouseX, fMouseY))
+				{
+					pModel->nGameState = GameState_Exit;
+				}
+				else
+
+				if(pModel->kArrowBounds[0].Contains(fMouseX, fMouseY))
+				{
+					const uint32 nCount = pModel->GetFunctionCount() - 1;
+					pModel->nCurrentFunction = (pModel->nCurrentFunction - 1 + nCount) % nCount;
+				}
+				else
+
+				if(pModel->kArrowBounds[1].Contains(fMouseX, fMouseY))
+				{
+					const uint32 nCount = pModel->GetFunctionCount() - 1;
+					pModel->nCurrentFunction = (pModel->nCurrentFunction + 1) % nCount;
+				}
+			}
+		}
+		else
+
+		if(!kInputManager.IsButtonDown(0) && kInputManager.WasButtonDown(0))
+		{
+			if(pModel->kDragController.IsActive())
+			{
+				const uint32 nAction = pModel->kDragController.End();
+
+				for(uint32 i = 0; i < sizeof(pModel->kMainBounds) / sizeof(pModel->kMainBounds[0]); ++i)
+				{
+					if(pModel->kMainBounds[i].Contains(fMouseX, fMouseY))
+					{
+						pModel->GetFunction(0)->SetSlot(i, nAction);
+					}
+				}
+
+				for(uint32 i = 0; i < sizeof(pModel->kFunctionBounds) / sizeof(pModel->kFunctionBounds[0]); ++i)
+				{
+					if(pModel->kFunctionBounds[i].Contains(fMouseX, fMouseY))
+					{
+						pModel->GetFunction(pModel->nCurrentFunction + 1)->SetSlot(i, nAction);
+					}
+				}
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Controller.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,72 @@
+/*
+ * Controller
+ */
+
+#ifndef __CONTROLLER_H__
+#define __CONTROLLER_H__
+
+#include "View.h"
+#include "Model.h"
+#include "InputManager.h"
+
+/*
+ * Controller
+ */
+class Controller
+{
+	/*
+	 * pModel
+	 */
+	Model* pModel;
+
+	/*
+	 * pView
+	 */
+	View* pView;
+
+	/*
+	 * kInputManager
+	 */
+	InputManager kInputManager;
+
+public:
+
+	/*
+	 * Controller
+	 */
+	Controller(Model* pModel, View* pView);
+
+	/*
+	 * Initialize
+	 */
+	ErrorCode Initialize();
+
+	/*
+	 * Terminate
+	 */
+	void Terminate();
+
+	/*
+	 * Update
+	 */
+	void Update(float fElapsed);
+
+private:
+
+	/*
+	 * Start
+	 */
+	void Start();
+
+	/*
+	 * Stop
+	 */
+	void Stop();
+
+	/*
+	 * ProcessInput
+	 */
+	void ProcessInput(float fElapsed);
+};
+
+#endif //__CONTROLLER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Core.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,84 @@
+/*
+ * Core
+ */
+
+#include "Core.h"
+
+/*
+ * InterpolateDirection
+ */
+float InterpolateDirection(uint32 nStart, uint32 nEnd, float fParameter)
+{
+	//A+t*(B-A)
+	if(nStart == Direction_North)
+	{
+		if(nEnd == Direction_East)
+		{
+			//-90 -> 0
+			return -(D3DX_PI / 2.0f) * (1.0f - fParameter) + 0.0f * fParameter;
+			//return (-(D3DX_PI / 2.0f)) + fParameter * ((0.0f) - -(D3DX_PI / 2.0f)));
+		}
+		else
+
+		if(nEnd == Direction_West)
+		{
+			//-90 -> -180
+			return -(D3DX_PI / 2.0f) * (1.0f - fParameter) - D3DX_PI * fParameter;
+			//return (A) + fParameter * ((B) - (A));
+			//return (-(D3DX_PI / 2.0f)) + fParameter * ((-D3DX_PI) - (-(D3DX_PI / 2.0f)));
+		}
+	}
+	else
+
+	if(nStart == Direction_East)
+	{
+		if(nEnd == Direction_North)
+		{
+			//0 -> -90
+			return 0.0f * (1.0f - fParameter) - (D3DX_PI / 2.0f) * fParameter;
+		}
+		else
+
+		if(nEnd == Direction_South)
+		{
+			//-360 -> -270
+			return -2.0f * D3DX_PI * (1.0f - fParameter) - (3.0f * D3DX_PI / 2.0f) * fParameter;
+		}
+	}
+	else
+
+	if(nStart == Direction_South)
+	{
+		if(nEnd == Direction_East)
+		{
+			//-270 -> -360
+			return -(3.0f * D3DX_PI / 2.0f) * (1.0f - fParameter) - 2.0f * D3DX_PI * fParameter;
+		}
+		else
+
+		if(nEnd == Direction_West)
+		{
+			//-270 -> -180
+			return -(3.0f * D3DX_PI / 2.0f) * (1.0f - fParameter) - (2.0f * D3DX_PI / 2.0f) * fParameter;
+		}
+	}
+	else
+
+	if(nStart == Direction_West)
+	{
+		if(nEnd == Direction_North)
+		{
+			//-180 -> -90
+			return -(2.0f * D3DX_PI / 2.0f) * (1.0f - fParameter) - (1.0f * D3DX_PI / 2.0f) * fParameter;
+		}
+		else
+
+		if(nEnd == Direction_South)
+		{
+			//-180 -> -270
+			return -(2.0f * D3DX_PI / 2.0f) * (1.0f - fParameter) - (3.0f * D3DX_PI / 2.0f) * fParameter;
+		}
+	}
+
+	return 0.0f;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Core.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,270 @@
+/*
+ * Core
+ */
+
+#ifndef __CORE_H__
+#define __CORE_H__
+
+#include <d3d9.h>
+#include <d3dx9.h>
+
+#ifdef _DEBUG
+#include <stdio.h>
+#define DEBUG_PRINT printf
+#else
+#define DEBUG_PRINT(...)
+#endif
+
+/*
+ * int8
+ */
+typedef signed char int8;
+
+/*
+ * int16
+ */
+typedef signed short int16;
+
+/*
+ * int32
+ */
+typedef signed int int32;
+
+/*
+ * uint8
+ */
+typedef unsigned char uint8;
+
+/*
+ * uint16
+ */
+typedef unsigned short uint16;
+
+/*
+ * uint32
+ */
+typedef unsigned int uint32;
+
+/*
+ * ErrorCode
+ */
+typedef int32 ErrorCode;
+
+/*
+ * Error
+ */
+enum
+{
+	Error_Success	= 0,
+	Error_Fail		= -1,
+};
+
+/*
+ * Action
+ */
+enum
+{
+	Action_Default,
+	Action_Complete,
+	Action_Forward,
+	Action_RotateCW,
+	Action_RotateCCW,
+	Action_Jump,
+	Action_Light,
+	Action_FunctionA,
+	Action_FunctionB,
+	//Action_FunctionC,
+	Action_Count = 7,
+};
+
+/*
+ * Direction
+ */
+enum Direction
+{
+	Direction_North,
+	Direction_East,
+	Direction_South,
+	Direction_West,
+	Direction_Count,
+};
+
+/*
+ * Tower
+ */
+enum
+{
+	Tower_Normal,
+	Tower_Light,
+};
+
+/*
+ * ScreenSizeX
+ */
+const uint32 ScreenSizeX = 1280;
+
+/*
+ * ScreenSizeY
+ */
+const uint32 ScreenSizeY = 720;
+
+/*
+ * FacesPerCube
+ */
+const uint32 FacesPerCube = 6;
+
+/*
+ * TrianglesPerFace
+ */
+const uint32 TrianglesPerFace = 2;
+
+/*
+ * VerticesPerTriangle
+ */
+const uint32 VerticesPerTriangle = 3;
+
+/*
+ * TrianglesPerBlock
+ */
+const uint32 TrianglesPerBlock = FacesPerCube * TrianglesPerFace;
+
+/*
+ * VerticesPerBlock
+ */
+const uint32 VerticesPerBlock = FacesPerCube * TrianglesPerFace * VerticesPerTriangle;
+
+/*
+ * MaximumFunctionLength
+ */
+const uint32 MaximumFunctionLength = 16;
+
+/*
+ * MainFunctionLength
+ */
+const uint32 MainFunctionLength = 14;
+
+/*
+ * Position
+ *	Represents the position of an object on a grid
+ */
+struct Position
+{
+	/*
+	 * X
+	 */
+	uint32 X;
+
+	/*
+	 * Y
+	 */
+	uint32 Y;
+};
+
+/*
+ * Size
+ */
+struct Size
+{
+	/*
+	 * X
+	 */
+	uint32 X;
+
+	/*
+	 * Y
+	 */
+	uint32 Y;
+};
+
+/*
+ * Rectangle2
+ */
+struct Rectangle2
+{
+	/*
+	 * X
+	 */
+	float X;
+
+	/*
+	 * Y
+	 */
+	float Y;
+
+	/*
+	 * Width
+	 */
+	float Width;
+
+	/*
+	 * Height
+	 */
+	float Height;
+
+public:
+
+	/*
+	 * Rectangle2
+	 */
+	Rectangle2() : X(0.0f), Y(0.0f), Width(0.0f), Height(0.0f)
+	{
+	}
+
+	/*
+	 * Rectangle2
+	 */
+	Rectangle2(float fX, float fY, float fWidth, float fHeight) : X(fX), Y(fY), Width(fWidth), Height(fHeight)
+	{
+	}
+
+	/*
+	 * Contains
+	 */
+	bool Contains(float fX, float fY)
+	{
+		return (0.0f <= (fX - X) && (fX - X) < Width) && (0.0f <= (fY - Y) && (fY - Y) < Height);
+	}
+};
+
+/*
+ * Min
+ */
+template<typename Type>
+inline Type Min(Type nValueA, Type nValueB)
+{
+	return nValueB < nValueA ? nValueB : nValueA;
+}
+
+/*
+ * Max
+ */
+template<typename Type>
+inline Type Max(Type nValueA, Type nValueB)
+{
+	return nValueB > nValueA ? nValueB : nValueA;
+}
+
+/*
+ * Clamp
+ */
+template<typename Type>
+inline Type Clamp(Type nValue, Type nMinimum, Type nMaximum)
+{
+	return nValue < nMinimum ? nMinimum : nValue > nMaximum ? nMaximum : nValue;
+}
+
+/*
+ * Abs
+ */
+template<typename Type>
+inline Type Abs(Type nValue)
+{
+	return nValue < 0 ? -nValue : nValue;
+}
+
+/*
+ * InterpolateDirection
+ */
+float InterpolateDirection(uint32 nStart, uint32 nEnd, float fParameter);
+
+#endif //__CORE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/DragController.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,57 @@
+/*
+ * DragController
+ */
+
+#include "DragController.h"
+
+/*
+ * DragController
+ */
+DragController::DragController()
+{
+	bActive		= false;
+	nParameter	= 0;
+}
+
+/*
+ * Begin
+ */
+void DragController::Begin(uint32 nValue)
+{
+	bActive		= true;
+	nParameter	= nValue;
+}
+
+/*
+ * End
+ */
+uint32 DragController::End()
+{
+	bActive = false;
+	return nParameter;
+}
+
+/*
+ * Reset
+ */
+void DragController::Reset()
+{
+	bActive		= false;
+	nParameter	= 0;
+}
+
+/*
+ * IsActive
+ */
+bool DragController::IsActive() const
+{
+	return bActive;
+}
+
+/*
+ * GetParameter
+ */
+uint32 DragController::GetParameter() const
+{
+	return nParameter;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/DragController.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,58 @@
+/*
+ * DragController
+ */
+
+#ifndef __DRAGCONTROLLER_H__
+#define __DRAGCONTROLLER_H__
+
+#include "Core.h"
+
+/*
+ * DragController
+ */
+class DragController
+{
+	/*
+	 * bActive
+	 */
+	bool bActive;
+
+	/*
+	 * nParameter
+	 */
+	uint32 nParameter;
+
+public:
+
+	/*
+	 * DragController
+	 */
+	DragController();
+
+	/*
+	 * Begin
+	 */
+	void Begin(uint32 nValue);
+
+	/*
+	 * End
+	 */
+	uint32 End();
+
+	/*
+	 * Reset
+	 */
+	void Reset();
+
+	/*
+	 * IsActive
+	 */
+	bool IsActive() const;
+
+	/*
+	 * GetParameter
+	 */
+	uint32 GetParameter() const;
+};
+
+#endif //__DRAGCONTROLLER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Environment.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,244 @@
+/*
+ * Environment
+ */
+
+#include "Environment.h"
+#include "Util.h"
+#include <windows.h>
+
+/*
+ * Environment
+ */
+Environment::Environment() : pGrid(0)
+{
+	nWidth		= 0;
+	nHeight		= 0;
+
+	kScale.x	= 1.0f;
+	kScale.y	= 0.4f;
+	kScale.z	= 1.0f;
+}
+
+/*
+ * ~Environment
+ */
+Environment::~Environment()
+{
+	delete[] pGrid;
+}
+
+/*
+ * Initialize
+ */
+ErrorCode Environment::Initialize(uint32 nGridWidth, uint32 nGridHeight)
+{
+	if(pGrid)
+	{
+		delete[] pGrid;
+		pGrid = 0;
+	}
+
+	nWidth	= nGridWidth;
+	nHeight	= nGridHeight;
+	pGrid	= new Tower[nGridWidth * nGridHeight];
+
+	return Error_Success;
+}
+
+/*
+ * Reset
+ */
+void Environment::Reset()
+{
+	for(uint32 i = 0; i < nWidth * nHeight; ++i)
+	{
+		pGrid[i].State = 0;
+	}
+}
+
+/*
+ * GetWidth
+ */
+uint32 Environment::GetWidth() const
+{
+	return nWidth;
+}
+
+/*
+ * GetHeight
+ */
+uint32 Environment::GetHeight() const
+{
+	return nHeight;
+}
+
+/*
+ * GetScale
+ */
+const D3DXVECTOR3& Environment::GetScale() const
+{
+	return kScale;
+}
+
+/*
+ * SetType
+ */
+void Environment::SetType(uint32 nX, uint32 nY, uint32 nType)
+{
+	pGrid[nY * nWidth + nX].Type = nType;
+}
+
+/*
+ * GetType
+ */
+uint32 Environment::GetType(uint32 nX, uint32 nY) const
+{
+	return pGrid[nY * nWidth + nX].Type;
+}
+
+/*
+ * SetAltitude
+ */
+void Environment::SetAltitude(uint32 nX, uint32 nY, uint32 nHeight)
+{
+	pGrid[nY * nWidth + nX].Height = nHeight;
+}
+
+/*
+ * GetAltitude
+ */
+uint32 Environment::GetAltitude(uint32 nX, uint32 nY) const
+{
+	return pGrid[nY * nWidth + nX].Height;
+}
+
+/*
+ * GetState
+ */
+uint32 Environment::GetState(uint32 nX, uint32 nY) const
+{
+	return pGrid[nY * nWidth + nX].State;
+}
+
+/*
+ * IsMovementValid
+ */
+bool Environment::IsMovementValid(uint32 nAction, uint32 nX, uint32 nY, uint32 nDirection)
+{
+	if(nAction == Action_Forward)
+	{
+		const uint32 nGridHeight = pGrid[nY * nWidth + nX].Height;
+
+		if(nDirection == Direction_North)
+		{
+			if(nY + 1 < nHeight)
+			{
+				return nGridHeight == pGrid[(nY + 1) * nWidth + nX].Height;
+			}
+		}
+		else
+
+		if(nDirection == Direction_East)
+		{
+			if(nX + 1 < nWidth)
+			{
+				return nGridHeight == pGrid[nY * nWidth + nX + 1].Height;
+			}
+		}
+		else
+
+		if(nDirection == Direction_South)
+		{
+			if(nY - 1 >= 0)
+			{
+				return nGridHeight == pGrid[(nY - 1) * nWidth + nX].Height;
+			}
+		}
+		else
+
+		if(nDirection == Direction_West)
+		{
+			if(nX - 1 >= 0)
+			{
+				return nGridHeight == pGrid[nY * nWidth + nX - 1].Height;
+			}
+		}
+	}
+	else
+
+	if(nAction == Action_Jump)
+	{
+		const int32 nGridHeight = (int32)pGrid[nY * nWidth + nX].Height;
+
+		if(nDirection == Direction_North)
+		{
+			if(nY + 1 < nHeight)
+			{
+				const int32 nDelta = nGridHeight - (int32)pGrid[(nY + 1) * nWidth + nX].Height;
+				return nDelta == 1 || nDelta < 0;
+			}
+		}
+		else
+
+		if(nDirection == Direction_East)
+		{
+			if(nX + 1 < nWidth)
+			{
+				const int32 nDelta = nGridHeight - (int32)pGrid[nY * nWidth + nX + 1].Height;
+				return nDelta == 1 || nDelta < 0;
+			}
+		}
+		else
+
+		if(nDirection == Direction_South)
+		{
+			if(nY - 1 >= 0)
+			{
+				const int32 nDelta = nGridHeight - (int32)pGrid[(nY - 1) * nWidth + nX].Height;
+				return nDelta == 1 || nDelta < 0;
+			}
+		}
+		else
+
+		if(nDirection == Direction_West)
+		{
+			if(nX - 1 >= 0)
+			{
+				const int32 nDelta = nGridHeight - (int32)pGrid[nY * nWidth + nX - 1].Height;
+				return nDelta == 1 || nDelta < 0;
+			}
+		}
+	}
+
+	return false;
+}
+
+/*
+ * NotifyAction
+ */
+void Environment::NotifyAction(uint32 nX, uint32 nY)
+{
+	if(pGrid[nY * nWidth + nX].Type == Tower_Light)
+	{
+		pGrid[nY * nWidth + nX].State ^= 1;
+	}
+}
+
+/*
+ * RequirementsMet
+ */
+bool Environment::RequirementsMet() const
+{
+	for(uint32 i = 0; i < nWidth * nHeight; ++i)
+	{
+		if(pGrid[i].Type == Tower_Light)
+		{
+			if(!pGrid[i].State)
+			{
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Environment.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,117 @@
+/*
+ * Environment
+ */
+
+#ifndef __ENVIRONMENT_H__
+#define __ENVIRONMENT_H__
+
+#include "Core.h"
+#include "Tower.h"
+
+/*
+ * Environment
+ */
+class Environment
+{
+	/*
+	 * nWidth
+	 */
+	uint32 nWidth;
+
+	/*
+	 * nHeight
+	 */
+	uint32 nHeight;
+
+	/*
+	 * kScale
+	 */
+	D3DXVECTOR3 kScale;
+
+	/*
+	 * pGrid
+	 */
+	Tower* pGrid;
+
+public:
+
+	/*
+	 * Environment
+	 */
+	Environment();
+
+	/*
+	 * ~Environment
+	 */
+	~Environment();
+
+	/*
+	 * Initialize
+	 */
+	ErrorCode Initialize(uint32 nGridWidth, uint32 nGridHeight);
+
+	/*
+	 * Reset
+	 */
+	void Reset();
+
+	/*
+	 * GetWidth
+	 */
+	uint32 GetWidth() const;
+
+	/*
+	 * GetHeight
+	 */
+	uint32 GetHeight() const;
+
+	/*
+	 * GetScale
+	 */
+	const D3DXVECTOR3& GetScale() const;
+
+	/*
+	 * SetType
+	 */
+	void SetType(uint32 nX, uint32 nY, uint32 nType);
+
+	/*
+	 * GetType
+	 */
+	uint32 GetType(uint32 nX, uint32 nY) const;
+
+	/*
+	 * SetAltitude
+	 */
+	void SetAltitude(uint32 nX, uint32 nY, uint32 nHeight);
+
+	/*
+	 * GetAltitude
+	 */
+	uint32 GetAltitude(uint32 nX, uint32 nY) const;
+
+	/*
+	 * GetState
+	 */
+	uint32 GetState(uint32 nX, uint32 nY) const;
+
+	/*
+	 * IsMovementValid
+	 */
+	bool IsMovementValid(uint32 nAction, uint32 nX, uint32 nY, uint32 nDirection);
+
+	/*
+	 * RequirementsMet
+	 *	Used to determine if the requirements for completing a 
+	 *  given map have been satisfied.
+	 */
+	bool RequirementsMet() const;
+
+	/*
+	 * NotifyAction
+	 *	Used by objects to notify the environment of changes
+	 */
+	void NotifyAction(uint32 nX, uint32 nY);
+};
+
+#endif //__ENVIRONMENT_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/InputManager.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,204 @@
+/*
+ * InputManager
+ */
+
+#include "InputManager.h"
+
+/*
+ * InputManager
+ */
+InputManager::InputManager()
+{
+	pDirectInput	= NULL;
+	pKeyboard		= NULL;
+	pMouse			= NULL;
+
+	memset(kCurrentKeyboardState, 0, sizeof(kCurrentKeyboardState));
+	memset(kPreviousKeyboardState, 0, sizeof(kPreviousKeyboardState));
+	memset(&kCurrentMouseState, 0, sizeof(kCurrentMouseState));
+	memset(&kPreviousMouseState, 0, sizeof(kPreviousMouseState));
+}
+
+/*
+ * Initialze
+ */
+ErrorCode InputManager::Initialize(HWND kWindow)
+{
+	HINSTANCE hInstance = GetModuleHandle(NULL);
+
+	HRESULT hResult = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&pDirectInput, NULL);
+	if(FAILED(hResult))
+	{
+		return Error_Fail;
+	}
+
+	hResult = pDirectInput->CreateDevice(GUID_SysKeyboard, &pKeyboard, NULL);
+	if(FAILED(hResult))
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	hResult = pKeyboard->SetDataFormat(&c_dfDIKeyboard);
+	if(FAILED(hResult))
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	hResult = pKeyboard->SetCooperativeLevel(kWindow, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
+	if(FAILED(hResult))
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	hResult = pDirectInput->CreateDevice(GUID_SysMouse, &pMouse, NULL);
+	if(FAILED(hResult))
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	hResult = pMouse->SetDataFormat(&c_dfDIMouse);
+	if(FAILED(hResult))
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	hResult = pMouse->SetCooperativeLevel(kWindow, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
+	if(FAILED(hResult))
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	pMouse->Acquire();
+
+	return Error_Success;
+}
+
+/*
+ * Terminate
+ */
+void InputManager::Terminate()
+{
+	if(pMouse)
+	{
+		pMouse->Release();
+		pMouse = NULL;
+	}
+
+	if(pKeyboard)
+	{
+		pKeyboard->Release();
+		pKeyboard = NULL;
+	}
+
+	if(pDirectInput)
+	{
+		pDirectInput->Release();
+		pDirectInput = NULL;
+	}
+}
+
+/*
+ * Update
+ */
+void InputManager::Update(float fElapsed)
+{
+	if(pKeyboard)
+	{
+		memcpy(kPreviousKeyboardState, kCurrentKeyboardState, sizeof(kCurrentKeyboardState));
+
+		HRESULT hResult = pKeyboard->GetDeviceState(sizeof(kCurrentKeyboardState), kCurrentKeyboardState);
+		if(FAILED(hResult))
+		{
+			hResult = pKeyboard->Acquire();
+			if(SUCCEEDED(hResult))
+			{
+				hResult = pKeyboard->GetDeviceState(sizeof(kCurrentKeyboardState), kCurrentKeyboardState);
+			}
+		}
+	}
+
+	if(pMouse)
+	{
+		memcpy(&kPreviousMouseState, &kCurrentMouseState, sizeof(kCurrentMouseState));
+
+		HRESULT hResult = pMouse->GetDeviceState(sizeof(kCurrentMouseState), &kCurrentMouseState);
+		if(FAILED(hResult))
+		{
+			hResult = pMouse->Acquire();
+			if(SUCCEEDED(hResult))
+			{
+				hResult = pMouse->GetDeviceState(sizeof(kCurrentMouseState), &kCurrentMouseState);
+			}
+		}
+	}
+}
+
+/*
+ * GetKeyboardState
+ */
+const char* InputManager::GetKeyboardState(bool bPrevious) const
+{
+	return bPrevious ? kPreviousKeyboardState : kCurrentKeyboardState;
+}
+
+/*
+ * GetMouseState
+ */
+const DIMOUSESTATE* InputManager::GetMouseState(bool bPrevious) const
+{
+	return bPrevious ? &kPreviousMouseState : &kCurrentMouseState;
+}
+
+/*
+ * IsKeyDown
+ */
+bool InputManager::IsKeyDown(uint32 nKey) const
+{
+	return (kCurrentKeyboardState[nKey] & 0x80) != 0;
+}
+
+/*
+ * WasKeyDown
+ */
+bool InputManager::WasKeyDown(uint32 nKey) const
+{
+	return (kPreviousKeyboardState[nKey] & 0x80) != 0;
+}
+
+/*
+ * IsButtonDown
+ */
+bool InputManager::IsButtonDown(uint32 nButton) const
+{
+	return (kCurrentMouseState.rgbButtons[nButton] & 0x80) != 0;
+}
+
+/*
+ * WasButtonDown
+ */
+bool InputManager::WasButtonDown(uint32 nButton) const
+{
+	return (kPreviousMouseState.rgbButtons[nButton] & 0x80) != 0;
+}
+
+/*
+ * GetMouseDeltaX
+ */
+int32 InputManager::GetMouseDeltaX() const
+{
+	return (int32)kCurrentMouseState.lX;
+}
+
+/*
+ * GetMouseDeltaY
+ */
+int32 InputManager::GetMouseDeltaY() const
+{
+	return (int32)kCurrentMouseState.lY;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/InputManager.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,115 @@
+/*
+ * InputManager
+ */
+
+#ifndef __INPUTMANAGER_H__
+#define __INPUTMANAGER_H__
+
+#define DIRECTINPUT_VERSION 0x0800
+#include <dinput.h>
+#include "Core.h"
+
+/*
+ * InputManager
+ */
+class InputManager
+{
+	/*
+	 * pDirectInput
+	 */
+	IDirectInput8* pDirectInput;
+
+	/*
+	 * pKeyboard
+	 */
+	IDirectInputDevice8* pKeyboard;
+
+	/*
+	 * pMouse
+	 */
+	IDirectInputDevice8* pMouse;
+
+	/*
+	 * kCurrentKeyboardState
+	 */
+	char kCurrentKeyboardState[256];
+
+	/*
+	 * kPreviousKeyboardState
+	 */
+	char kPreviousKeyboardState[256];
+
+	/*
+	 * kCurrentMouseState
+	 */
+	DIMOUSESTATE kCurrentMouseState;
+
+	/*
+	 * kPreviousMouseState
+	 */
+	DIMOUSESTATE kPreviousMouseState;
+
+public:
+
+	/*
+	 * InputManager
+	 */
+	InputManager();
+
+	/*
+	 * Initialze
+	 */
+	ErrorCode Initialize(HWND kWindow);
+
+	/*
+	 * Terminate
+	 */
+	void Terminate();
+
+	/*
+	 * Update
+	 */
+	void Update(float fElapsed);
+
+	/*
+	 * GetKeyboardState
+	 */
+	const char* GetKeyboardState(bool bPrevious = false) const;
+
+	/*
+	 * GetMouseState
+	 */
+	const DIMOUSESTATE* GetMouseState(bool bPrevious = false) const;
+
+	/*
+	 * IsKeyDown
+	 */
+	bool IsKeyDown(uint32 nKey) const;
+
+	/*
+	 * WasKeyDown
+	 */
+	bool WasKeyDown(uint32 nKey) const;
+
+	/*
+	 * IsButtonDown
+	 */
+	bool IsButtonDown(uint32 nButton) const;
+
+	/*
+	 * WasButtonDown
+	 */
+	bool WasButtonDown(uint32 nButton) const;
+
+	/*
+	 * GetMouseDeltaX
+	 */
+	int32 GetMouseDeltaX() const;
+
+	/*
+	 * GetMouseDeltaY
+	 */
+	int32 GetMouseDeltaY() const;
+};
+
+#endif //__INPUTMANAGER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Loader.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,175 @@
+/*
+ * Loader
+ */
+
+#include "Loader.h"
+#include "Util.h"
+
+/*
+ * Loader
+ */
+Loader::Loader()
+{
+	kSize.X			= 0;
+	kSize.Y			= 0;
+	pType			= 0;
+	pHeight			= 0;
+	kPosition.X		= 0;
+	kPosition.Y		= 0;
+	kDirection		= Direction_North;
+	nFunctionCount	= 0;
+	pFunctionLength	= 0;
+}
+
+/*
+ * ~Loader
+ */
+Loader::~Loader()
+{
+	if(pType)
+	{
+		delete[] pType;
+		pType = 0;
+	}
+
+	if(pHeight)
+	{
+		delete[] pHeight;
+		pHeight = 0;
+	}
+
+	if(pFunctionLength)
+	{
+		delete[] pFunctionLength;
+		pFunctionLength = 0;
+	}
+}
+
+/*
+ * Load
+ */
+ErrorCode Loader::Load(const char* pName)
+{
+	if(pType)
+	{
+		delete[] pType;
+		pType = 0;
+	}
+
+	if(pHeight)
+	{
+		delete[] pHeight;
+		pHeight = 0;
+	}
+
+	if(pFunctionLength)
+	{
+		delete[] pFunctionLength;
+		pFunctionLength = 0;
+	}
+
+	Buffer kBuffer = LoadFile(pName);
+
+	if(kBuffer.Read(&kSize.X) != Error_Success)
+		return Error_Fail;
+
+	if(kBuffer.Read(&kSize.Y) != Error_Success)
+		return Error_Fail;
+
+	if(kBuffer.Read(&kPosition.X) != Error_Success)
+		return Error_Fail;
+
+	if(kBuffer.Read(&kPosition.Y) != Error_Success)
+		return Error_Fail;
+
+	if(kBuffer.Read(&kDirection) != Error_Success)
+		return Error_Fail;
+
+	if(kBuffer.Read(&nFunctionCount) != Error_Success)
+		return Error_Fail;
+
+	if(kSize.X == 0 || kSize.Y == 0)
+		return Error_Fail;
+
+	pType			= new uint32[kSize.X * kSize.Y];
+	pHeight			= new uint32[kSize.X * kSize.Y];
+	pFunctionLength	= new uint32[nFunctionCount];
+
+	for(uint32 i = 0; i < nFunctionCount; ++i)
+	{
+		if(kBuffer.Read(pFunctionLength + i) != Error_Success)
+			return Error_Fail;
+	}
+
+	for(uint32 nY = 0; nY < kSize.Y; ++nY)
+	{
+		for(uint32 nX = 0; nX < kSize.X; ++nX)
+		{
+			const uint32 nIndex = nY * kSize.X + nX;
+
+			if(kBuffer.Read(pType + nIndex) != Error_Success)
+				return Error_Fail;
+
+			if(kBuffer.Read(pHeight + nIndex) != Error_Success)
+				return Error_Fail;
+		}
+	}
+
+	return Error_Success;
+}
+
+/*
+ * GetSize
+ */
+const Size& Loader::GetSize() const
+{
+	return kSize;
+}
+
+/*
+ * GetTowerType
+ */
+uint32 Loader::GetTowerType(uint32 nX, uint32 nY)
+{
+	return pType[nY * kSize.X + nX];
+}
+
+/*
+ * GetTowerHeight
+ */
+uint32 Loader::GetTowerHeight(uint32 nX, uint32 nY)
+{
+	return pHeight[nY * kSize.X + nX];
+}
+
+/*
+ * GetInitialPosition
+ */
+const Position& Loader::GetInitialPosition() const
+{
+	return kPosition;
+}
+
+/*
+ * GetInitialDirection
+ */
+const Direction& Loader::GetInitialDirection() const
+{
+	return kDirection;
+}
+
+/*
+ * GetFunctionCount
+ */
+uint32 Loader::GetFunctionCount() const
+{
+	return nFunctionCount;
+}
+
+/*
+ * GetFunctionLength
+ */
+uint32 Loader::GetFunctionLength(uint32 nIndex) const
+{
+	return pFunctionLength[nIndex];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Loader.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,103 @@
+/*
+ * Loader
+ */
+
+#ifndef __LOADER_H__
+#define __LOADER_H__
+
+#include "Core.h"
+
+/*
+ * Loader
+ */
+class Loader
+{
+	/*
+	 * kSize
+	 */
+	Size kSize;
+
+	/*
+	 * pType
+	 */
+	uint32* pType;
+
+	/*
+	 * pHeight
+	 */
+	uint32* pHeight;
+
+	/*
+	 * kPosition
+	 */
+	Position kPosition;
+
+	/*
+	 * kDirection
+	 */
+	Direction kDirection;
+
+	/*
+	 * nFunctionCount
+	 */
+	uint32 nFunctionCount;
+
+	/*
+	 * pFunctionLength
+	 */
+	uint32* pFunctionLength;
+
+public:
+
+	/*
+	 * Loader
+	 */
+	Loader();
+
+	/*
+	 * ~Loader
+	 */
+	~Loader();
+
+	/*
+	 * Load
+	 */
+	ErrorCode Load(const char* pName);
+
+	/*
+	 * GetSize
+	 */
+	const Size& GetSize() const;
+
+	/*
+	 * GetTowerType
+	 */
+	uint32 GetTowerType(uint32 nX, uint32 nY);
+
+	/*
+	 * GetTowerHeight
+	 */
+	uint32 GetTowerHeight(uint32 nX, uint32 nY);
+
+	/*
+	 * GetInitialPosition
+	 */
+	const Position& GetInitialPosition() const;
+
+	/*
+	 * GetInitialDirection
+	 */
+	const Direction& GetInitialDirection() const;
+
+	/*
+	 * GetFunctionCount
+	 */
+	uint32 GetFunctionCount() const;
+
+	/*
+	 * GetFunctionLength
+	 */
+	uint32 GetFunctionLength(uint32 nIndex) const;
+};
+
+#endif //__LOADER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Main.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,12 @@
+/*
+ * Main
+ */
+
+#include <windows.h>
+#include <tchar.h>
+#include "Mediator.h"
+
+int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
+{
+	return Mediator().Run();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Math.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,5 @@
+/*
+ * LightMath
+ */
+
+#include "LightMath.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Mediator.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,141 @@
+/*
+ * Mediator
+ */
+
+#include "Mediator.h"
+#include <windows.h>
+
+/*
+ * fUpdatePeriod
+ */
+static const float fUpdatePeriod = 1.0f / 60.0f;
+
+/*
+ * Mediator
+ */
+Mediator::Mediator()
+{
+}
+
+/*
+ * Run
+ */
+ErrorCode Mediator::Run()
+{
+	ErrorCode eCode = Initialize();
+	if(eCode == Error_Success)
+	{
+		float fAccumulator = 0.0f;
+
+		kClock.Reset();
+
+		while(pModel->nGameState != GameState_Exit)
+		{
+			ProcessMessages();
+
+			float fElapsed = kClock.GetElapsed();
+			if(fElapsed > 2 * fUpdatePeriod)
+			{
+				fElapsed = 2 * fUpdatePeriod;
+			}
+
+			fAccumulator += fElapsed;
+
+			while(fAccumulator >= fUpdatePeriod)
+			{
+				Update(fUpdatePeriod);
+				fAccumulator -= fUpdatePeriod;
+			}
+
+			Render();
+		}
+
+		Terminate();
+	}
+
+	return eCode;
+}
+
+/*
+ * Initialize
+ */
+ErrorCode Mediator::Initialize()
+{
+	pModel		= new Model();
+	pView		= new View(pModel);
+	pController = new Controller(pModel, pView);
+
+	ErrorCode eCode = pView->Initialize();
+	if(eCode == Error_Success)
+	{
+		eCode = pController->Initialize();
+		if(eCode == Error_Success)
+		{
+			pModel->nCurrentLevel	= 0;
+			pModel->nGameState		= GameState_LoadMap;
+		}
+	}
+	
+	return eCode;
+}
+
+/*
+ * Terminate
+ */
+void Mediator::Terminate()
+{
+	if(pController)
+	{
+		pController->Terminate();
+
+		delete pController;
+		pController = 0;
+	}
+
+	if(pView)
+	{
+		pView->Terminate();
+
+		delete pView;
+		pView = 0;
+	}
+
+	delete pModel;
+	pModel = 0;
+}
+
+/*
+ * Update
+ */
+void Mediator::Update(float fElapsed)
+{
+	pController->Update(fElapsed);
+}
+
+/*
+ * Render
+ */
+void Mediator::Render()
+{
+	pView->Render();
+}
+
+/*
+ * ProcessMessages
+ */
+void Mediator::ProcessMessages()
+{
+	MSG kMessage;
+
+	while(PeekMessage(&kMessage, NULL, 0, 0, PM_REMOVE))
+	{
+		if(kMessage.message == WM_QUIT)
+		{
+			pModel->nGameState = GameState_Exit;
+			break;
+		}
+
+		TranslateMessage(&kMessage);
+		DispatchMessage(&kMessage);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Mediator.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,91 @@
+/*
+ * Mediator
+ */
+
+#ifndef __MEDIATOR_H__
+#define __MEDIATOR_H__
+
+#include "Core.h"
+#include "Clock.h"
+#include "Model.h"
+#include "View.h"
+#include "Controller.h"
+
+/*
+ * MediatorState
+ */
+enum
+{
+	MediatorState_Initialize,
+	MediatorState_Splash,
+	MediatorState_Game,
+	MediatorState_Complete,
+	MediatorState_Exit,
+};
+
+/*
+ * Mediator
+ */
+class Mediator
+{
+	/*
+	 * kClock
+	 */
+	Clock kClock;
+
+	/*
+	 * pModel
+	 */
+	Model* pModel;
+
+	/*
+	 * pView
+	 */
+	View* pView;
+
+	/*
+	 * pController
+	 */
+	Controller* pController;
+
+public:
+
+	/*
+	 * Mediator
+	 */
+	Mediator();
+
+	/*
+	 * Run
+	 */
+	ErrorCode Run();
+
+protected:
+
+	/*
+	 * Initialize
+	 */
+	virtual ErrorCode Initialize();
+
+	/*
+	 * Terminate
+	 */
+	virtual void Terminate();
+
+	/*
+	 * Update
+	 */
+	void Update(float fElapsed);
+
+	/*
+	 * Render
+	 */
+	void Render();
+
+	/*
+	 * ProcessMessages
+	 */
+	virtual void ProcessMessages();
+};
+
+#endif //__MEDIATOR_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Model.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,177 @@
+/*
+ * Model
+ */
+
+#include "Model.h"
+
+/*
+ * Model
+ */
+Model::Model()
+{
+	nGameState				= GameState_Active;
+	nSimulationState		= SimulationState_Idle;
+	pFunction				= 0;
+	fMouseX					= 0.5f * ScreenSizeX;
+	fMouseY					= 0.5f * ScreenSizeY;
+	nCurrentFunction		= 0;
+	nCurrentLevel			= 0;
+
+	kActionBounds[0]		= Rectangle2(1023.0f + 0 * 54.0f, 85.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kActionBounds[1]		= Rectangle2(1023.0f + 1 * 54.0f, 85.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kActionBounds[2]		= Rectangle2(1023.0f + 2 * 54.0f, 85.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kActionBounds[3]		= Rectangle2(1023.0f + 3 * 54.0f, 85.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kActionBounds[4]		= Rectangle2(1023.0f + 0 * 54.0f, 85.0f + 1 * 54.0f, 48.0f, 48.0f);
+	kActionBounds[5]		= Rectangle2(1023.0f + 1 * 54.0f, 85.0f + 1 * 54.0f, 48.0f, 48.0f);
+	kActionBounds[6]		= Rectangle2(1023.0f + 2 * 54.0f, 85.0f + 1 * 54.0f, 48.0f, 48.0f);
+	kActionBounds[7]		= Rectangle2(1023.0f + 3 * 54.0f, 85.0f + 1 * 54.0f, 48.0f, 48.0f);
+
+	kMainBounds[0]			= Rectangle2(1023.0f + 0 * 54.0f, 238.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[1]			= Rectangle2(1023.0f + 1 * 54.0f, 238.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[2]			= Rectangle2(1023.0f + 2 * 54.0f, 238.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[3]			= Rectangle2(1023.0f + 3 * 54.0f, 238.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[4]			= Rectangle2(1023.0f + 0 * 54.0f, 238.0f + 1 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[5]			= Rectangle2(1023.0f + 1 * 54.0f, 238.0f + 1 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[6]			= Rectangle2(1023.0f + 2 * 54.0f, 238.0f + 1 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[7]			= Rectangle2(1023.0f + 3 * 54.0f, 238.0f + 1 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[8]			= Rectangle2(1023.0f + 0 * 54.0f, 238.0f + 2 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[9]			= Rectangle2(1023.0f + 1 * 54.0f, 238.0f + 2 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[10]			= Rectangle2(1023.0f + 2 * 54.0f, 238.0f + 2 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[11]			= Rectangle2(1023.0f + 3 * 54.0f, 238.0f + 2 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[12]			= Rectangle2(1023.0f + 0 * 54.0f, 238.0f + 3 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[13]			= Rectangle2(1023.0f + 1 * 54.0f, 238.0f + 3 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[14]			= Rectangle2(1023.0f + 2 * 54.0f, 238.0f + 3 * 54.0f, 48.0f, 48.0f);
+	kMainBounds[15]			= Rectangle2(1023.0f + 3 * 54.0f, 238.0f + 3 * 54.0f, 48.0f, 48.0f);
+
+	kFunctionBounds[0]		= Rectangle2(1023.0f + 0 * 54.0f, 501.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kFunctionBounds[1]		= Rectangle2(1023.0f + 1 * 54.0f, 501.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kFunctionBounds[2]		= Rectangle2(1023.0f + 2 * 54.0f, 501.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kFunctionBounds[3]		= Rectangle2(1023.0f + 3 * 54.0f, 501.0f + 0 * 54.0f, 48.0f, 48.0f);
+	kFunctionBounds[4]		= Rectangle2(1023.0f + 0 * 54.0f, 501.0f + 1 * 54.0f, 48.0f, 48.0f);
+	kFunctionBounds[5]		= Rectangle2(1023.0f + 1 * 54.0f, 501.0f + 1 * 54.0f, 48.0f, 48.0f);
+	kFunctionBounds[6]		= Rectangle2(1023.0f + 2 * 54.0f, 501.0f + 1 * 54.0f, 48.0f, 48.0f);
+	kFunctionBounds[7]		= Rectangle2(1023.0f + 3 * 54.0f, 501.0f + 1 * 54.0f, 48.0f, 48.0f);
+
+	kArrowBounds[0]			= Rectangle2(1206.0f + 0 * 16.0f, 473.0f + 0 * 54.0f, 16.0f, 16.0f);
+	kArrowBounds[1]			= Rectangle2(1206.0f + 2 * 16.0f, 473.0f + 0 * 54.0f, 16.0f, 16.0f);
+
+	kControlBounds[0]		= Rectangle2(1023.0f + 0.5f * 54.0f, 638.0f + 0 * 00.0f, 48.0f, 48.0f);
+	kControlBounds[1]		= Rectangle2(1023.0f + 1.5f * 54.0f, 638.0f + 0 * 00.0f, 48.0f, 48.0f);
+	kControlBounds[2]		= Rectangle2(1023.0f + 2.5f * 54.0f, 638.0f + 0 * 00.0f, 48.0f, 48.0f);
+}
+
+/*
+ * Load
+ */
+bool Model::Load(const char* pName)
+{
+	if(pFunction)
+	{
+		delete[] pFunction;
+		pFunction = NULL;
+	}
+
+	ErrorCode eCode = kLoader.Load(pName);
+	if(eCode == Error_Success)
+	{
+		const Size& kSize = kLoader.GetSize();
+
+		eCode = kEnvironment.Initialize(kSize.X, kSize.Y);
+		if(eCode == Error_Success)
+		{
+			for(uint32 nY = 0; nY < kSize.Y; ++nY)
+			{
+				for(uint32 nX = 0; nX < kSize.X; ++nX)
+				{
+					kEnvironment.SetType(nX, nY, kLoader.GetTowerType(nX, nY));
+					kEnvironment.SetAltitude(nX, nY, kLoader.GetTowerHeight(nX, nY));
+				}
+			}
+
+			kBot.Initialize(&kEnvironment);
+			kBot.kPosition	= kLoader.GetInitialPosition();
+			kBot.kDirection	= kLoader.GetInitialDirection();
+
+			const uint32 nCount = kLoader.GetFunctionCount();
+
+			pFunction = new Code[nCount + 1];
+			pFunction[0].Initialize(MainFunctionLength);
+			pFunction[0].Clear();
+
+			kBot.AddFunction(0, MainFunctionLength);
+
+			for(uint32 i = 0; i < nCount; ++i)
+			{
+				const uint32 nLength = kLoader.GetFunctionLength(i);
+
+				pFunction[i + 1].Initialize(nLength);
+				pFunction[i + 1].Clear();
+
+				kBot.AddFunction(i + 1, nLength);
+			}
+		}
+	}
+
+	return eCode == Error_Success;
+}
+
+/*
+ * GetBot
+ */
+Bot* Model::GetBot()
+{
+	return &kBot;
+}
+
+/*
+ * GetFunction
+ */
+Code* Model::GetFunction(uint32 nIndex)
+{
+	return &pFunction[nIndex];
+}
+
+/*
+ * GetFunctionCount
+ */
+uint32 Model::GetFunctionCount()
+{
+	return kLoader.GetFunctionCount() + 1;
+}
+
+/*
+ * GetEnvironment
+ */
+Environment* Model::GetEnvironment()
+{
+	return &kEnvironment;
+}
+
+/*
+ * ResetEnvironment
+ */
+void Model::ResetEnvironment()
+{
+	kEnvironment.Reset();
+}
+
+/*
+ * ResetBot
+ */
+void Model::ResetBot()
+{
+	kBot.Reset();
+	kBot.kPosition	= kLoader.GetInitialPosition();
+	kBot.kDirection	= kLoader.GetInitialDirection();
+}
+
+/*
+ * ClearCode
+ */
+void Model::ClearCode()
+{
+	for(uint32 i = 0; i < kLoader.GetFunctionCount(); ++i)
+	{
+		pFunction[i].Clear();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Model.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,175 @@
+/*
+ * Model
+ */
+
+#ifndef __MODEL_H__
+#define __MODEL_H__
+
+#include "Core.h"
+#include "Bot.h"
+#include "Environment.h"
+#include "Code.h"
+#include "Loader.h"
+#include "DragController.h"
+
+/*
+ * GameState
+ */
+enum
+{
+	GameState_Idle,
+	GameState_LoadMap,
+	GameState_Active,
+	GameState_Complete,
+	GameState_Over,
+	GameState_Confirm,
+	GameState_Exit,
+};
+
+/*
+ * SimulationState
+ */
+enum
+{
+	SimulationState_Idle,
+	SimulationState_Active,
+};
+
+/*
+ * Model
+ */
+class Model
+{
+	/*
+	 * kLoader
+	 */
+	Loader kLoader;
+
+	/*
+	 * kEnvironment
+	 */
+	Environment kEnvironment;
+
+	/*
+	 * kBot
+	 */
+	Bot kBot;
+
+	/*
+	 * kFunction
+	 */
+	Code* pFunction;
+
+public:
+
+	/*
+	 * nGameState
+	 */
+	uint32 nGameState;
+
+	/*
+	 * nSimulationState
+	 */
+	uint32 nSimulationState;
+
+	/*
+	 * nCurrentLevel
+	 */
+	uint32 nCurrentLevel;
+
+	/*
+	 * nCurrentFunction
+	 */
+	uint32 nCurrentFunction;
+
+public:
+
+	/*
+	 * kActionBounds
+	 */
+	Rectangle2 kActionBounds[8];
+
+	/*
+	 * kMainBounds
+	 */
+	Rectangle2 kMainBounds[16];
+
+	/*
+	 * kFunctionBounds
+	 */
+	Rectangle2 kFunctionBounds[8];
+
+	/*
+	 * kArrowBounds
+	 */
+	Rectangle2 kArrowBounds[2];
+
+	/*
+	 * kControlBounds
+	 */
+	Rectangle2 kControlBounds[3];
+
+	/*
+	 * fMouseX
+	 */
+	float fMouseX;
+
+	/*
+	 * fMouseY
+	 */
+	float fMouseY;
+
+	/*
+	 * kDragController
+	 */
+	DragController kDragController;
+
+public:
+
+	/*
+	 * Model
+	 */
+	Model();
+
+	/*
+	 * Load
+	 */
+	bool Load(const char* pName);
+
+	/*
+	 * GetEnvironment
+	 */
+	Environment* GetEnvironment();
+
+	/*
+	 * GetBot
+	 */
+	Bot* GetBot();
+
+	/*
+	 * GetFunction
+	 */
+	Code* GetFunction(uint32 nIndex);
+
+	/*
+	 * GetFunctionCount
+	 */
+	uint32 GetFunctionCount();
+
+	/*
+	 * ResetEnvironment
+	 */
+	void ResetEnvironment();
+
+	/*
+	 * ResetBot
+	 */
+	void ResetBot();
+
+	/*
+	 * ResetCode
+	 */
+	void ClearCode();
+};
+
+#endif //__MODEL_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/RenderContext.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,227 @@
+/*
+ * RenderContext
+ */
+
+#include "RenderContext.h"
+#include "VertexTypes.h"
+
+/*
+ * RenderContext
+ */
+RenderContext::RenderContext()
+{
+	pDirect3D				= NULL;
+	pDevice					= NULL;
+}
+
+/*
+ * Initialize
+ */
+ErrorCode RenderContext::Initialize(HWND kWindow, uint32 nWidth, uint32 nHeight)
+{
+	pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
+	if(!pDirect3D)
+	{
+		return Error_Fail;
+	}
+
+	uint32 nAdapter = D3DADAPTER_DEFAULT;
+	uint32 nFlags	= D3DCREATE_HARDWARE_VERTEXPROCESSING;
+
+	kParameters.BackBufferCount				= 1;
+	kParameters.BackBufferWidth				= nWidth;
+	kParameters.BackBufferHeight			= nHeight;
+	kParameters.BackBufferFormat			= D3DFMT_UNKNOWN;
+	kParameters.MultiSampleType				= D3DMULTISAMPLE_NONE;
+	kParameters.MultiSampleQuality			= 0;
+	kParameters.SwapEffect					= D3DSWAPEFFECT_DISCARD;
+	kParameters.hDeviceWindow				= kWindow;
+	kParameters.Windowed					= TRUE;
+	kParameters.EnableAutoDepthStencil		= TRUE;
+	kParameters.AutoDepthStencilFormat		= D3DFMT_D24S8;
+	kParameters.Flags						= 0;
+	kParameters.FullScreen_RefreshRateInHz	= 0;
+	kParameters.PresentationInterval		= D3DPRESENT_INTERVAL_DEFAULT;
+
+	HRESULT hResult = pDirect3D->CreateDevice(nAdapter, D3DDEVTYPE_HAL, kWindow, nFlags, &kParameters, &pDevice);
+	if(FAILED(hResult))
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	if(InitializeVertexTypes(pDevice) != Error_Success)
+	{
+		return Error_Fail;
+	}
+
+	return Error_Success;
+}
+
+/* 
+ * Terminate
+ */
+void RenderContext::Terminate()
+{
+	TerminateVertexTypes();
+
+	if(pDevice)
+	{
+		pDevice->Release();
+		pDevice = 0;
+	}
+
+	if(pDirect3D)
+	{
+		pDirect3D->Release();
+		pDirect3D = 0;
+	}
+}
+
+/*
+ * CreateTextureFromFile
+ */
+ErrorCode RenderContext::CreateTextureFromFile(const char* pName, IDirect3DTexture9** pTexture)
+{
+	const uint32 nSizeX		= D3DX_DEFAULT_NONPOW2;
+	const uint32 nSizeY		= D3DX_DEFAULT_NONPOW2;
+	const uint32 nFilter	= D3DX_DEFAULT;
+	const uint32 nFilterMip	= D3DX_DEFAULT;
+
+	HRESULT hResult = D3DXCreateTextureFromFileExA(pDevice, pName, nSizeX, nSizeY, 0, 0, D3DFMT_FROM_FILE, D3DPOOL_MANAGED, nFilter, nFilterMip, 0, NULL, NULL, pTexture);
+	if(FAILED(hResult))
+	{
+		return Error_Fail;
+	}
+
+	return Error_Success;
+}
+
+/*
+ * CreateEffectFromFile
+ */
+ErrorCode RenderContext::CreateEffectFromFile(const char* pName, ID3DXEffect** pEffect)
+{
+	ID3DXBuffer* pBuffer = NULL;
+
+	HRESULT hResult = D3DXCreateEffectFromFileA(pDevice, pName, NULL, NULL, 0, NULL, pEffect, &pBuffer);
+	if(FAILED(hResult))
+	{
+		if(pBuffer)
+		{
+			const char* pError = (const char*)pBuffer->GetBufferPointer();
+		}
+
+		return Error_Fail;
+	}
+
+	return Error_Success;
+}
+
+/*
+ * CreateVertexBuffer
+ */
+ErrorCode RenderContext::CreateVertexBuffer(uint32 nSize, uint32 nUsage, uint32 nPool, IDirect3DVertexBuffer9** pBuffer)
+{
+	HRESULT hResult = pDevice->CreateVertexBuffer(nSize, nUsage, 0, (D3DPOOL)nPool, pBuffer, NULL);
+	if(FAILED(hResult))
+	{
+		return Error_Fail;
+	}
+
+	return Error_Success;
+}
+
+/*
+ * CreateFontFromName
+ */
+ErrorCode RenderContext::CreateFontFromName(const char* pName, uint32 nSize, uint32 nWeight, ID3DXFont** pFont)
+{
+	HRESULT hResult = D3DXCreateFontA(pDevice, nSize, 0, nWeight, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, pName, pFont);
+	if(FAILED(hResult))
+	{
+		return Error_Fail;
+	}
+
+	return Error_Success;
+}
+
+/*
+ * Begin
+ */
+void RenderContext::Begin(uint32 nColor)
+{
+	pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, nColor, 1.0f, 0);
+	pDevice->BeginScene();
+}
+
+/*
+ * End
+ */
+void RenderContext::End()
+{
+	pDevice->EndScene();
+	pDevice->Present(NULL, NULL, NULL, NULL);
+}
+
+/*
+ * SetupCamera3D
+ */
+void RenderContext::SetupCamera3D(ID3DXEffect* pEffect, const D3DXVECTOR3& kLocation, const D3DXVECTOR3& kTarget, float fViewAngle)
+{
+	D3DVIEWPORT9 kViewport;
+	if(SUCCEEDED(pDevice->GetViewport(&kViewport)))
+	{
+		D3DXHANDLE kHandleProj	= pEffect->GetParameterByName(NULL, "kProjection");
+		D3DXHANDLE kHandleView	= pEffect->GetParameterByName(NULL, "kView");
+
+		if(kHandleProj && kHandleView)
+		{
+			D3DXMATRIX kProjection;
+			D3DXMatrixPerspectiveFovLH(&kProjection, fViewAngle, (float)kViewport.Width / (float)kViewport.Height, 1.0f, 1024.0f);
+
+			D3DXMATRIX kView;
+			D3DXMatrixLookAtLH(&kView, &kLocation, &kTarget, &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
+
+			pEffect->SetMatrix(kHandleProj, &kProjection);
+			pEffect->SetMatrix(kHandleView, &kView);
+		}
+	}
+}
+
+/*
+ * SetupCamera2D
+ */
+void RenderContext::SetupCamera2D(ID3DXEffect* pEffect)
+{
+	D3DVIEWPORT9 kViewport;
+	if(SUCCEEDED(pDevice->GetViewport(&kViewport)))
+	{
+		D3DXHANDLE kHandle = pEffect->GetParameterByName(NULL, "kProjection");
+		if(kHandle)
+		{
+			D3DXMATRIX kProjection;
+			D3DXMatrixOrthoLH(&kProjection, (float)kViewport.Width, (float)kViewport.Height, 1.0f, 1024.0f);
+
+			pEffect->SetMatrix(kHandle, &kProjection);
+		}
+	}
+}
+
+/*
+ * DrawTriangles
+ */
+void RenderContext::DrawTriangles(IDirect3DVertexDeclaration9* pDeclaration, IDirect3DVertexBuffer9* pBuffer, uint32 nSize, uint32 nCount)
+{
+	pDevice->SetVertexDeclaration(pDeclaration);
+	pDevice->SetStreamSource(0, pBuffer, 0, nSize);
+	pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, nCount);
+}
+
+/*
+ * GetViewport
+ */
+ErrorCode RenderContext::GetViewport(D3DVIEWPORT9* pViewport)
+{
+	return SUCCEEDED(pDevice->GetViewport(pViewport)) ? Error_Success : Error_Fail;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/RenderContext.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,100 @@
+/*
+ * RenderContext
+ */
+
+#ifndef __RENDERCONTEXT_H__
+#define __RENDERCONTEXT_H__
+
+#include "Core.h"
+#include <d3d9.h>
+#include <d3dx9.h>
+
+/*
+ * RenderContext
+ */
+class RenderContext
+{
+	/*
+	 * pDirect3D
+	 */
+	IDirect3D9* pDirect3D;
+
+	/*
+	 * pDevice
+	 */
+	IDirect3DDevice9* pDevice;
+
+	/*
+	 * kParameters
+	 */
+	D3DPRESENT_PARAMETERS kParameters;
+
+public:
+
+	/*
+	 * RenderContext
+	 */
+	RenderContext();
+
+	/*
+	 * Initialize
+	 */
+	ErrorCode Initialize(HWND kWindow, uint32 nWidth, uint32 nHeight);
+
+	/* 
+	 * Terminate
+	 */
+	void Terminate();
+
+	/*
+	 * CreateTextureFromFile
+	 */
+	ErrorCode CreateTextureFromFile(const char* pName, IDirect3DTexture9** pTexture);
+
+	/*
+	 * CreateEffectFromFile
+	 */
+	ErrorCode CreateEffectFromFile(const char* pName, ID3DXEffect** pEffect);
+
+	/*
+	 * CreateVertexBuffer
+	 */
+	ErrorCode CreateVertexBuffer(uint32 nSize, uint32 nUsage, uint32 nPool, IDirect3DVertexBuffer9** pBuffer);
+
+	/*
+	 * CreateFontFromName
+	 */
+	ErrorCode CreateFontFromName(const char* pName, uint32 nSize, uint32 nWeight, ID3DXFont** pFont);
+
+	/*
+	 * Begin
+	 */
+	void Begin(uint32 nColor = 0);
+
+	/*
+	 * End
+	 */
+	void End();
+
+	/*
+	 * SetupCamera3D
+	 */
+	void SetupCamera3D(ID3DXEffect* pEffect, const D3DXVECTOR3& kLocation, const D3DXVECTOR3& kTarget, float fViewAngle = D3DX_PI / 4.0f);
+
+	/*
+	 * SetupCamera2D
+	 */
+	void SetupCamera2D(ID3DXEffect* pEffect);
+
+	/*
+	 * DrawTriangles
+	 */
+	void DrawTriangles(IDirect3DVertexDeclaration9* pDeclaration, IDirect3DVertexBuffer9* pBuffer, uint32 nSize, uint32 nCount);
+
+	/*
+	 * GetViewport
+	 */
+	ErrorCode GetViewport(D3DVIEWPORT9* pViewport);
+};
+
+#endif //__RENDERCONTEXT_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Tower.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,12 @@
+/*
+ * Tower
+ */
+
+#include "Tower.h"
+
+/*
+ * Tower
+ */
+Tower::Tower() : Type(0), Height(1), State(0), User(0)
+{
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Tower.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,43 @@
+/*
+ * Tower
+ */
+
+#ifndef __TOWER_H__
+#define __TOWER_H__
+
+#include "Core.h"
+
+/*
+ * Tower
+ */
+struct Tower
+{
+	/*
+	 * Type
+	 */
+	uint32 Type;
+
+	/*
+	 * Height
+	 */
+	uint32 Height;
+
+	/*
+	 * State
+	 */
+	uint32 State;
+
+	/*
+	 * User
+	 */
+	uint32 User;
+
+public:
+
+	/*
+	 * Tower
+	 */
+	Tower();
+};
+
+#endif //__TOWER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Util.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,41 @@
+/*
+ * Util
+ */
+
+#include "Util.h"
+#include <stdio.h>
+
+/*
+ * LoadFile
+ */
+Buffer LoadFile(const char* pName)
+{
+	uint8* pData = NULL;
+	uint32 nSize = 0;
+
+	FILE* pFile = NULL;
+	if(fopen_s(&pFile, pName, "rt") == 0)
+	{
+		fseek(pFile, 0, SEEK_END);
+		nSize = (uint32)ftell(pFile);
+		fseek(pFile, 0, SEEK_SET);
+
+		if(nSize > 0)
+		{
+			pData = new uint8[nSize];
+
+			uint32 nCount = (uint32)fread(pData, sizeof(uint8), nSize, pFile);
+			if(nCount != nSize)
+			{
+				delete[] pData;
+
+				pData = NULL;
+				nSize = 0;
+			}
+		}
+
+		fclose(pFile);
+	}
+
+	return Buffer(pData, nSize);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/Util.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,93 @@
+/*
+ * Util
+ */
+
+#ifndef __UTIL_H__
+#define __UTIL_H__
+
+#include "Core.h"
+
+/*
+ * Buffer
+ */
+class Buffer
+{
+	/*
+	 * pData
+	 */
+	uint8* pData;
+
+	/*
+	 * nSize
+	 */
+	uint32 nSize;
+
+	/*
+	 * nOffset
+	 */
+	uint32 nOffset;
+
+public:
+
+	/*
+	 * Buffer
+	 *	Construct a Buffer instance by taking ownership of the data
+	 */
+	Buffer(uint8* pBuffer, uint32 nLength, bool bCopy = true) : pData(pBuffer), nSize(nLength), nOffset(0)
+	{
+		if(bCopy)
+		{
+			pData = new uint8[nLength];
+
+			for(uint32 i = 0; i < nLength; ++i)
+				pData[i] = pBuffer[i];
+		}
+	}
+
+	/*
+	 * ~Buffer
+	 */
+	~Buffer()
+	{
+		delete[] pData;
+	}
+
+	/*
+	 * Read
+	 */
+	template<typename Type>
+	ErrorCode Read(Type* pValue)
+	{
+		if(pData)
+		{
+			const uint32 nLength = sizeof(Type);
+
+			if(nOffset + nLength <= nSize)
+			{
+				if(pValue)
+					*pValue = *(Type*)(pData + nOffset);
+			
+				nOffset += nLength;
+
+				return Error_Success;
+			}
+		}
+
+		return Error_Fail;
+	}
+
+	/*
+	 * IsValid
+	 */
+	bool IsValid() const
+	{
+		return pData && nSize > 0;
+	}
+};
+
+/*
+ * LoadFile
+ */
+Buffer LoadFile(const char* pName);
+
+#endif //__UTIL_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/VertexTypes.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,74 @@
+/*
+ * VertexTypes
+ */
+
+#include "VertexTypes.h"
+
+/*
+ * BlockVertex::Declaration
+ */
+IDirect3DVertexDeclaration9* Vertex::Block::Declaration = NULL;
+
+/*
+ * QuadVertex::Declaration
+ */
+IDirect3DVertexDeclaration9* Vertex::Quad::Declaration = NULL;
+
+/*
+ * InitializeVertexTypes
+ */
+ErrorCode InitializeVertexTypes(IDirect3DDevice9* pDevice)
+{
+	{
+		const D3DVERTEXELEMENT9 kElements[] = 
+		{
+			{0,	0,	D3DDECLTYPE_FLOAT3,		D3DDECLMETHOD_DEFAULT,	D3DDECLUSAGE_POSITION,	0},
+			{0, 12,	D3DDECLTYPE_FLOAT3,		D3DDECLMETHOD_DEFAULT,	D3DDECLUSAGE_NORMAL,	0},
+			{0, 24,	D3DDECLTYPE_FLOAT2,		D3DDECLMETHOD_DEFAULT,	D3DDECLUSAGE_TEXCOORD,	0},
+
+			D3DDECL_END(),
+		};
+
+		HRESULT hResult = pDevice->CreateVertexDeclaration(kElements, &Vertex::Block::Declaration);
+		if(FAILED(hResult))
+		{
+			return Error_Fail;
+		}
+	}
+
+	{
+		const D3DVERTEXELEMENT9 kElements[] = 
+		{
+			{0,	0,	D3DDECLTYPE_FLOAT3,		D3DDECLMETHOD_DEFAULT,	D3DDECLUSAGE_POSITION,	0},
+			{0, 12,	D3DDECLTYPE_FLOAT2,		D3DDECLMETHOD_DEFAULT,	D3DDECLUSAGE_TEXCOORD,	0},
+
+			D3DDECL_END(),
+		};
+
+		HRESULT hResult = pDevice->CreateVertexDeclaration(kElements, &Vertex::Quad::Declaration);
+		if(FAILED(hResult))
+		{
+			return Error_Fail;
+		}
+	}
+
+	return Error_Success;
+}
+
+/*
+ * TerminateVertexTypes
+ */
+void TerminateVertexTypes()
+{
+	if(Vertex::Quad::Declaration)
+	{
+		Vertex::Quad::Declaration->Release();
+		Vertex::Quad::Declaration = NULL;
+	}
+
+	if(Vertex::Block::Declaration)
+	{
+		Vertex::Block::Declaration->Release();
+		Vertex::Block::Declaration = NULL;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/VertexTypes.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,106 @@
+/*
+ * VertexTypes
+ */
+
+#ifndef __VERTEXTYPES_H__
+#define __VERTEXTYPES_H__
+
+#include "Core.h"
+#include <d3d9.h>
+#include <d3dx9.h>
+
+/*
+ * Vertex
+ */
+namespace Vertex
+{
+	/*
+	 * Block
+	 */
+	struct Block
+	{
+		/*
+		 * Position
+		 */
+		D3DXVECTOR3 Position;
+
+		/*
+		 * Normal
+		 */
+		D3DXVECTOR3 Normal;
+
+		/*
+		 * TextureCoordinates
+		 */
+		D3DXVECTOR2 TextureCoordinates;
+
+		/*
+		 * Declaration
+		 */
+		static IDirect3DVertexDeclaration9* Declaration;
+
+	public:
+
+		/*
+		 * Block
+		 */
+		Block(float fX, float fY, float fZ, float fNormalX, float fNormalY, float fNormalZ, float fU, float fV)
+		{
+			Position.x				= fX;
+			Position.y				= fY;
+			Position.z				= fZ;
+			Normal.x				= fNormalX;
+			Normal.y				= fNormalY;
+			Normal.z				= fNormalZ;
+			TextureCoordinates.x	= fU;
+			TextureCoordinates.y	= fV;
+		}
+	};
+
+	/*
+	 * Quad
+	 */
+	struct Quad
+	{
+		/*
+		 * Position
+		 */
+		D3DXVECTOR3 Position;
+
+		/*
+		 * TextureCoordinates
+		 */
+		D3DXVECTOR2 TextureCoordinates;
+
+		/*
+		 * Declaration
+		 */
+		static IDirect3DVertexDeclaration9* Declaration;
+
+	public:
+
+		/*
+		 * Quad
+		 */
+		Quad(float fX, float fY, float fZ, float fU, float fV)
+		{
+			Position.x				= fX;
+			Position.y				= fY;
+			Position.z				= fZ;
+			TextureCoordinates.x	= fU;
+			TextureCoordinates.y	= fV;
+		}
+	};
+}
+
+/*
+ * InitializeVertexTypes
+ */
+ErrorCode InitializeVertexTypes(IDirect3DDevice9* pDevice);
+
+/*
+ * TerminateVertexTypes
+ */
+void TerminateVertexTypes();
+
+#endif //__VERTEXTYPES_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/View.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,1033 @@
+/*
+ * View
+ */
+
+#include "View.h"
+#include "VertexTypes.h"
+
+/*
+ * kClassName
+ */
+static const TCHAR* kClassName = L"LightCloneClass";
+
+/*
+ * kCaption
+ */
+static const TCHAR* kCaption = L"LightClone";
+
+/*
+ * pActionTextureName
+ */
+static const char* pActionTextureName[] = 
+{
+	"Data\\Textures\\Forward.tga",
+	"Data\\Textures\\RotateCW.tga",
+	"Data\\Textures\\RotateCCW.tga",
+	"Data\\Textures\\Jump.tga",
+	"Data\\Textures\\Light.tga",
+	"Data\\Textures\\Function1.tga",
+	"Data\\Textures\\Function2.tga",
+};
+
+/*
+ * pControlTextureName
+ */
+const char* pControlTextureName[] =
+{
+	"Data\\Textures\\Play.tga",
+	"Data\\Textures\\Stop.tga",
+	"Data\\Textures\\Exit.tga",
+};
+
+/*
+ * pArrowTextureName
+ */
+const char* pArrowTextureName[] =
+{
+	"Data\\Textures\\Left.tga",
+	"Data\\Textures\\Right.tga",
+};
+
+/*
+ * pView
+ */
+View* View::pView = NULL;
+
+/*
+ * View
+ */
+View::View(Model* pInstance) : pModel(pInstance)
+{
+	pView					= this;
+
+	kWindow					= NULL;
+	pBlockEffect			= NULL;
+	pInterfaceEffect		= NULL;
+	pInterfaceFont			= NULL;
+	pBlockVertexBuffer		= NULL;
+	pInterfaceVertexBuffer	= NULL;
+	pBlockTexture			= NULL;
+	pBackgroundTexture		= NULL;
+	pCursorTexture			= NULL;
+
+	memset(pActionTextures, 0, sizeof(pActionTextures));
+	memset(pControlTextures, 0, sizeof(pControlTextures));
+	memset(pArrowTextures, 0, sizeof(pArrowTextures));
+}
+
+/*
+ * Initialize
+ */
+ErrorCode View::Initialize()
+{
+	HINSTANCE hInstance = GetModuleHandle(NULL);
+
+	WNDCLASSEX kClass;
+	kClass.cbSize			= sizeof(WNDCLASSEX);
+	kClass.cbClsExtra		= 0;
+	kClass.cbWndExtra		= 0;
+	kClass.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
+	kClass.hCursor			= LoadCursor(NULL, IDC_ARROW);
+	kClass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
+	kClass.hIconSm			= LoadIcon(NULL, IDI_APPLICATION);
+	kClass.hInstance		= hInstance;
+	kClass.lpfnWndProc		= &MessageRouter;
+	kClass.lpszClassName	= kClassName;
+	kClass.lpszMenuName		= NULL;
+	kClass.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+
+	ATOM kAtom = RegisterClassEx(&kClass);
+	if(kAtom == 0)
+	{
+		return Error_Fail;
+	}
+
+	const uint32 nStyleEx	= WS_EX_OVERLAPPEDWINDOW;
+	const uint32 nStyle		= WS_OVERLAPPEDWINDOW;
+
+	RECT kDesktopRectangle;
+	GetClientRect(GetDesktopWindow(), &kDesktopRectangle);
+
+	RECT kRectangle;
+	kRectangle.left		= 0;
+	kRectangle.top		= 0;
+	kRectangle.right	= ScreenSizeX;
+	kRectangle.bottom	= ScreenSizeY;
+
+	AdjustWindowRectEx(&kRectangle, nStyle, FALSE, nStyleEx);
+
+	uint32 nW			= kRectangle.right - kRectangle.left;
+	uint32 nH			= kRectangle.bottom - kRectangle.top;
+	uint32 nX			= ((kDesktopRectangle.right - kDesktopRectangle.left) - nW) / 2;
+	uint32 nY			= ((kDesktopRectangle.bottom - kDesktopRectangle.top) - nH) / 2;
+
+	kWindow = CreateWindowEx(nStyleEx, kClassName, kCaption, nStyle, nX, nY, nW, nH, NULL, NULL, hInstance, NULL);
+	if(!kWindow)
+	{
+		return Error_Fail;
+	}
+
+	UpdateWindow(kWindow);
+	ShowWindow(kWindow, SW_SHOW);
+
+	ErrorCode eCode = kContext.Initialize(kWindow, ScreenSizeX, ScreenSizeY);
+	if(eCode != Error_Success)
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	eCode = kContext.CreateEffectFromFile("Data\\Shaders\\Environment.fx", &pBlockEffect);
+	if(eCode != Error_Success)
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	eCode = kContext.CreateEffectFromFile("Data\\Shaders\\TexturedQuad.fx", &pInterfaceEffect);
+	if(eCode != Error_Success)
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	eCode = kContext.CreateFontFromName("Courier New", 18, FW_BOLD, &pInterfaceFont);
+	if(eCode != Error_Success)
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	eCode = kContext.CreateTextureFromFile("Data\\Textures\\Block01.tga", &pBlockTexture);
+	if(eCode != Error_Success)
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	eCode = kContext.CreateTextureFromFile("Data\\Textures\\Background.tga", &pBackgroundTexture);
+	if(eCode != Error_Success)
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	for(uint32 i = 0; i < Action_Count; ++i)
+	{
+		eCode = kContext.CreateTextureFromFile(pActionTextureName[i], pActionTextures + i);
+		if(eCode != Error_Success)
+		{
+			Terminate();
+			return Error_Fail;
+		}
+	}
+
+	for(uint32 i = 0; i < sizeof(pControlTextureName) / sizeof(pControlTextureName[0]); ++i)
+	{
+		eCode = kContext.CreateTextureFromFile(pControlTextureName[i], pControlTextures + i);
+		if(eCode != Error_Success)
+		{
+			Terminate();
+			return Error_Fail;
+		}
+	}
+
+	for(uint32 i = 0; i < sizeof(pArrowTextureName) / sizeof(pArrowTextureName[0]); ++i)
+	{
+		eCode = kContext.CreateTextureFromFile(pArrowTextureName[i], pArrowTextures + i);
+		if(eCode != Error_Success)
+		{
+			Terminate();
+			return Error_Fail;
+		}
+	}
+
+	eCode = kContext.CreateTextureFromFile("Data\\Textures\\Dialog1.tga", &pDialog1Texture);
+	if(eCode != Error_Success)
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	eCode = kContext.CreateTextureFromFile("Data\\Textures\\Dialog2.tga", &pDialog2Texture);
+	if(eCode != Error_Success)
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	eCode = kContext.CreateTextureFromFile("Data\\Textures\\Arrow.tga", &pCursorTexture);
+	if(eCode != Error_Success)
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	eCode = kContext.CreateVertexBuffer(VerticesPerBlock * sizeof(Vertex::Block), D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED, &pBlockVertexBuffer);
+	if(eCode != Error_Success)
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	eCode = kContext.CreateVertexBuffer(TrianglesPerFace * VerticesPerTriangle * sizeof(Vertex::Quad), D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED, &pInterfaceVertexBuffer);
+	if(eCode != Error_Success)
+	{
+		Terminate();
+		return Error_Fail;
+	}
+
+	return SetupVertexBuffers();
+}
+
+/* 
+ * Terminate
+ */
+void View::Terminate()
+{
+	if(pCursorTexture)
+	{
+		pCursorTexture->Release();
+		pCursorTexture = NULL;
+	}
+
+	if(pDialog1Texture)
+	{
+		pDialog1Texture->Release();
+		pDialog1Texture = NULL;
+	}
+
+	if(pDialog2Texture)
+	{
+		pDialog2Texture->Release();
+		pDialog2Texture = NULL;
+	}
+
+	for(uint32 i = 0; i < sizeof(pArrowTextures) / sizeof(pArrowTextures[0]); ++i)
+	{
+		if(pArrowTextures[i])
+		{
+			pArrowTextures[i]->Release();
+			pArrowTextures[i] = NULL;
+		}
+	}
+
+	for(uint32 i = 0; i < sizeof(pControlTextures) / sizeof(pControlTextures[0]); ++i)
+	{
+		if(pControlTextures[i])
+		{
+			pControlTextures[i]->Release();
+			pControlTextures[i] = NULL;
+		}
+	}
+
+	for(uint32 i = 0; i < Action_Count; ++i)
+	{
+		if(pActionTextures[i])
+		{
+			pActionTextures[i]->Release();
+			pActionTextures[i] = NULL;
+		}
+	}
+
+	if(pBackgroundTexture)
+	{
+		pBackgroundTexture->Release();
+		pBackgroundTexture = NULL;
+	}
+
+	if(pBlockTexture)
+	{
+		pBlockTexture->Release();
+		pBlockTexture = NULL;
+	}
+
+	if(pInterfaceVertexBuffer)
+	{
+		pInterfaceVertexBuffer->Release();
+		pInterfaceVertexBuffer = NULL;
+	}
+
+	if(pBlockVertexBuffer)
+	{
+		pBlockVertexBuffer->Release();
+		pBlockVertexBuffer = NULL;
+	}
+
+	if(pInterfaceFont)
+	{
+		pInterfaceFont->Release();
+		pInterfaceFont = NULL;
+	}
+
+	if(pInterfaceEffect)
+	{
+		pInterfaceEffect->Release();
+		pInterfaceEffect = NULL;
+	}
+
+	if(pBlockEffect)
+	{
+		pBlockEffect->Release();
+		pBlockEffect = 0;
+	}
+
+	kContext.Terminate();
+}
+
+/*
+ * Render
+ */
+void View::Render()
+{
+	const uint32 nColor = D3DCOLOR_XRGB(32, 32, 32);
+
+	kContext.Begin(nColor);
+
+	if(pModel)
+	{
+		if(pModel->nGameState >= GameState_Active)
+		{
+			Render3D();
+			Render2D();
+		}
+	}
+
+	kContext.End();
+}
+
+/*
+ * GetWindow
+ */
+HWND View::GetWindow() const
+{
+	return kWindow;
+}
+
+/*
+ * UpdateCameraYaw
+ */
+void View::UpdateCameraYaw(float fDelta)
+{
+	kCameraController.Yaw(fDelta);
+}
+
+/*
+ * UpdateCameraPitch
+ */
+void View::UpdateCameraPitch(float fDelta)
+{
+	kCameraController.Pitch(fDelta);
+}
+
+/*
+ * UpdateCameraDistance
+ */
+void View::UpdateCameraDistance(float fDelta)
+{
+	kCameraController.Move(fDelta);
+}
+
+/*
+ * SetupVertexBuffers
+ */
+ErrorCode View::SetupVertexBuffers()
+{
+	{
+		Vertex::Block* pVertices = NULL;
+		
+		HRESULT hResult = pBlockVertexBuffer->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
+		if(FAILED(hResult))
+		{
+			return Error_Fail;
+		}
+
+		const float fU1	= 0.66f;
+		const float fV1 = 0.66f;
+
+		// front
+		pVertices[0]	= Vertex::Block(-0.5f, 0.0f, -0.5f, 0.0f, 0.0f, -1.0f, 0.00f, 1.00f);
+		pVertices[1]	= Vertex::Block(-0.5f, 1.0f, -0.5f, 0.0f, 0.0f, -1.0f, 0.00f, 0.66f);
+		pVertices[2]	= Vertex::Block(+0.5f, 1.0f, -0.5f, 0.0f, 0.0f, -1.0f, 1.00f, 0.66f);
+		pVertices[3]	= Vertex::Block(-0.5f, 0.0f, -0.5f, 0.0f, 0.0f, -1.0f, 0.00f, 1.00f);
+		pVertices[4]	= Vertex::Block(+0.5f, 1.0f, -0.5f, 0.0f, 0.0f, -1.0f, 1.00f, 0.66f);
+		pVertices[5]	= Vertex::Block(+0.5f, 0.0f, -0.5f, 0.0f, 0.0f, -1.0f, 1.00f, 1.00f);
+		// back
+		pVertices[6]	= Vertex::Block(+0.5f, 0.0f, +0.5f, 0.0f, 0.0f, +1.0f, 0.00f, 1.00f);
+		pVertices[7]	= Vertex::Block(+0.5f, 1.0f, +0.5f, 0.0f, 0.0f, +1.0f, 0.00f, 0.66f);
+		pVertices[8]	= Vertex::Block(-0.5f, 1.0f, +0.5f, 0.0f, 0.0f, +1.0f, 1.00f, 0.66f);
+		pVertices[9]	= Vertex::Block(+0.5f, 0.0f, +0.5f, 0.0f, 0.0f, +1.0f, 0.00f, 1.00f);
+		pVertices[10]	= Vertex::Block(-0.5f, 1.0f, +0.5f, 0.0f, 0.0f, +1.0f, 1.00f, 0.66f);
+		pVertices[11]	= Vertex::Block(-0.5f, 0.0f, +0.5f, 0.0f, 0.0f, +1.0f, 1.00f, 1.00f);
+		// left
+		pVertices[12]	= Vertex::Block(-0.5f, 0.0f, +0.5f, -1.0f, 0.0f, 0.0f, 0.00f, 1.00f);
+		pVertices[13]	= Vertex::Block(-0.5f, 1.0f, +0.5f, -1.0f, 0.0f, 0.0f, 0.00f, 0.66f);
+		pVertices[14]	= Vertex::Block(-0.5f, 1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 1.00f, 0.66f);
+		pVertices[15]	= Vertex::Block(-0.5f, 0.0f, +0.5f, -1.0f, 0.0f, 0.0f, 0.00f, 1.00f);
+		pVertices[16]	= Vertex::Block(-0.5f, 1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 1.00f, 0.66f);
+		pVertices[17]	= Vertex::Block(-0.5f, 0.0f, -0.5f, -1.0f, 0.0f, 0.0f, 1.00f, 1.00f);
+		// right
+		pVertices[18]	= Vertex::Block(+0.5f, 0.0f, -0.5f, +1.0f, 0.0f, 0.0f, 0.00f, 1.00f);
+		pVertices[19]	= Vertex::Block(+0.5f, 1.0f, -0.5f, +1.0f, 0.0f, 0.0f, 0.00f, 0.66f);
+		pVertices[20]	= Vertex::Block(+0.5f, 1.0f, +0.5f, +1.0f, 0.0f, 0.0f, 1.00f, 0.66f);
+		pVertices[21]	= Vertex::Block(+0.5f, 0.0f, -0.5f, +1.0f, 0.0f, 0.0f, 0.00f, 1.00f);
+		pVertices[22]	= Vertex::Block(+0.5f, 1.0f, +0.5f, +1.0f, 0.0f, 0.0f, 1.00f, 0.66f);
+		pVertices[23]	= Vertex::Block(+0.5f, 0.0f, +0.5f, +1.0f, 0.0f, 0.0f, 1.00f, 1.00f);
+		// top
+		pVertices[24]	= Vertex::Block(-0.5f, 1.0f, -0.5f, 0.0f, +1.0f, 0.0f, 0.00f, 0.66f);
+		pVertices[25]	= Vertex::Block(-0.5f, 1.0f, +0.5f, 0.0f, +1.0f, 0.0f, 0.00f, 0.00f);
+		pVertices[26]	= Vertex::Block(+0.5f, 1.0f, +0.5f, 0.0f, +1.0f, 0.0f, 1.00f, 0.00f);
+		pVertices[27]	= Vertex::Block(-0.5f, 1.0f, -0.5f, 0.0f, +1.0f, 0.0f, 0.00f, 0.66f);
+		pVertices[28]	= Vertex::Block(+0.5f, 1.0f, +0.5f, 0.0f, +1.0f, 0.0f, 1.00f, 0.00f);
+		pVertices[29]	= Vertex::Block(+0.5f, 1.0f, -0.5f, 0.0f, +1.0f, 0.0f, 1.00f, 0.66f);
+		// bottom
+		pVertices[30]	= Vertex::Block(-0.5f, 0.0f, +0.5f, 0.0f, -1.0f, 0.0f, 0.00f, 0.66f);
+		pVertices[31]	= Vertex::Block(-0.5f, 0.0f, -0.5f, 0.0f, -1.0f, 0.0f, 0.00f, 0.00f);
+		pVertices[32]	= Vertex::Block(+0.5f, 0.0f, -0.5f, 0.0f, -1.0f, 0.0f, 1.00f, 0.00f);
+		pVertices[33]	= Vertex::Block(-0.5f, 0.0f, +0.5f, 0.0f, -1.0f, 0.0f, 0.00f, 0.66f);
+		pVertices[34]	= Vertex::Block(+0.5f, 0.0f, -0.5f, 0.0f, -1.0f, 0.0f, 1.00f, 0.00f);
+		pVertices[35]	= Vertex::Block(+0.5f, 0.0f, +0.5f, 0.0f, -1.0f, 0.0f, 1.00f, 0.66f);
+
+		pBlockVertexBuffer->Unlock();
+	}
+
+	{
+		Vertex::Quad* pVertices = NULL;
+
+		HRESULT hResult = pInterfaceVertexBuffer->Lock(0, 0, (void**)&pVertices, D3DLOCK_DISCARD);
+		if(FAILED(hResult))
+		{
+			return Error_Fail;
+		}
+
+		pVertices[0]	= Vertex::Quad(+0.0f, -1.0f, 1.0f, 0.0f, 1.0f);
+		pVertices[1]	= Vertex::Quad(+0.0f, +0.0f, 1.0f, 0.0f, 0.0f);
+		pVertices[2]	= Vertex::Quad(+1.0f, +0.0f, 1.0f, 1.0f, 0.0f);
+		pVertices[3]	= Vertex::Quad(+0.0f, -1.0f, 1.0f, 0.0f, 1.0f);
+		pVertices[4]	= Vertex::Quad(+1.0f, +0.0f, 1.0f, 1.0f, 0.0f);
+		pVertices[5]	= Vertex::Quad(+1.0f, -1.0f, 1.0f, 1.0f, 1.0f);
+
+		pInterfaceVertexBuffer->Unlock();
+	}
+
+	return Error_Success;
+}
+
+/*
+ * Render3D
+ */
+void View::Render3D()
+{
+	Environment* pEnvironment = pModel->GetEnvironment();
+	if(pEnvironment)
+	{
+		Bot* pBot = pModel->GetBot();
+		if(pBot)
+		{
+			const D3DXVECTOR3& kScale	= pEnvironment->GetScale();
+			const uint32 nSizeX			= pEnvironment->GetWidth();
+			const uint32 nSizeY			= pEnvironment->GetHeight();
+
+			const D3DXVECTOR3 kTarget(0.5f * (nSizeX - 1) * kScale.x, 0.0f, 0.5f * (nSizeY - 1) * kScale.z);
+
+			kContext.SetupCamera3D(pBlockEffect, kCameraController.GetLocation(kTarget), kTarget);
+
+			RenderEnvironment(pEnvironment);
+			RenderBot(pEnvironment, pBot);
+		}
+	}
+}
+
+/* 
+ * Render2D
+ */
+void View::Render2D()
+{
+	Environment* pEnvironment = pModel->GetEnvironment();
+	if(pEnvironment)
+	{
+		Bot* pBot = pModel->GetBot();
+		if(pBot)
+		{
+			kContext.SetupCamera2D(pInterfaceEffect);
+
+			uint32 nPasses = 0;
+
+			pInterfaceEffect->SetTechnique(pInterfaceEffect->GetTechnique(0));
+			pInterfaceEffect->Begin(&nPasses, 0);
+			pInterfaceEffect->BeginPass(0);
+
+			//RenderControlPanel();
+			RenderBackground();
+			RenderToolbar();
+			RenderMain();
+			RenderFunction();
+			RenderControls();
+
+			if(pModel->nGameState == GameState_Complete)
+			{
+				RenderLevelDialog();
+			}
+			else
+
+			if(pModel->nGameState == GameState_Over)
+			{
+				RenderGameOverDialog();
+			}
+
+			RenderCursor();
+
+			pInterfaceEffect->EndPass();
+			pInterfaceEffect->End();
+		}
+	}
+}
+
+/*
+ * 	RenderEnvironment
+ */
+void View::RenderEnvironment(Environment* pEnvironment)
+{
+	const D3DXVECTOR3& kScale = pEnvironment->GetScale();
+
+	uint32 nPasses = 0;
+
+	pBlockEffect->SetTechnique(pBlockEffect->GetTechnique(0));
+	pBlockEffect->Begin(&nPasses, 0);
+	pBlockEffect->BeginPass(0);
+
+	D3DXMATRIX kScaleMatrix;
+	D3DXMatrixScaling(&kScaleMatrix, kScale.x, kScale.y, kScale.z);
+
+	const uint32 nSizeX			= pEnvironment->GetWidth();
+	const uint32 nSizeY			= pEnvironment->GetHeight();
+
+	D3DXVECTOR3 kCenterWorld(-0.0f, 0.0f, -0.0f);
+	//D3DXVec3Unproject(&kCenterWorld, &kCenterScreen, &kViewport, &kProjectionMatrix, &kViewMatrix, &kWorldMatrix);
+
+	for(uint32 nZ = 0; nZ < nSizeY; ++nZ)
+	{
+		for(uint32 nX = 0; nX < nSizeX; ++nX)
+		{
+			uint32 nType	= pEnvironment->GetType(nX, nZ);
+			uint32 nHeight	= pEnvironment->GetAltitude(nX, nZ);
+			uint32 nState	= pEnvironment->GetState(nX, nZ);
+			uint32 nColor	= D3DCOLOR_XRGB(0x80, 0x80, 0x80);
+
+			if(nType == 1)
+			{
+				nColor = nState ? D3DCOLOR_XRGB(0, 0, 255) : D3DCOLOR_XRGB(255, 0, 0);
+			}
+
+			for(uint32 i = 0; i < pEnvironment->GetAltitude(nX, nZ); ++i)
+			{
+				D3DXMATRIX kTranslateMatrix;
+				D3DXMatrixTranslation(&kTranslateMatrix, kCenterWorld.x + nX * kScale.x, i * kScale.y, kCenterWorld.z + nZ * kScale.z);
+
+				D3DXMATRIX kWorldMatrix;
+				D3DXMatrixMultiply(&kWorldMatrix, &kScaleMatrix, &kTranslateMatrix);
+
+				RenderBlock(kWorldMatrix, nColor);
+			}
+		}
+	}
+
+	pBlockEffect->EndPass();
+	pBlockEffect->End();
+
+	if(false) // wireframe
+	{
+		pBlockEffect->SetTechnique(pBlockEffect->GetTechniqueByName("Wire"));
+		pBlockEffect->Begin(&nPasses, 0);
+		pBlockEffect->BeginPass(0);
+
+		for(uint32 nZ = 0; nZ < nSizeY; ++nZ)
+		{
+			for(uint32 nX = 0; nX < nSizeX; ++nX)
+			{
+				for(uint32 i = 0; i < pEnvironment->GetAltitude(nX, nZ); ++i)
+				{
+					D3DXMATRIX kTranslateMatrix;
+					D3DXMatrixTranslation(&kTranslateMatrix, nX * kScale.x, i * kScale.y, nZ * kScale.z);
+
+					D3DXMATRIX kWorldMatrix;
+					D3DXMatrixMultiply(&kWorldMatrix, &kScaleMatrix, &kTranslateMatrix);
+
+					RenderBlock(kWorldMatrix, D3DCOLOR_XRGB(0x00, 0x00, 0x00));
+				}
+			}
+		}
+
+		pBlockEffect->EndPass();
+		pBlockEffect->End();
+	}
+}
+
+/*
+ * RenderBot
+ */
+void View::RenderBot(Environment* pEnvironment, Bot* pBot)
+{
+	const D3DXVECTOR3& kPosition	= pBot->GetWorldPosition();
+	const D3DXVECTOR3& kOrientation	= pBot->GetWorldOrientation();
+
+	uint32 nPasses = 0;
+
+	pBlockEffect->SetTechnique(pBlockEffect->GetTechnique(0));
+	pBlockEffect->Begin(&nPasses, 0);
+	pBlockEffect->BeginPass(0);
+
+	D3DXMATRIX kScale;
+	D3DXMatrixScaling(&kScale, pBot->kSize.x, pBot->kSize.y, pBot->kSize.z);
+
+	D3DXMATRIX kTranslate;
+	D3DXMatrixTranslation(&kTranslate, kPosition.x, kPosition.y, kPosition.z);
+
+	D3DXMATRIX kRotate;
+	D3DXMatrixRotationY(&kRotate, kOrientation.y);
+
+	D3DXMATRIX kTempMatrix;
+	D3DXMATRIX kWorldMatrix;
+	D3DXMatrixMultiply(&kWorldMatrix, D3DXMatrixMultiply(&kTempMatrix, &kScale, &kRotate), &kTranslate);
+
+	const float fAlpha	= ((pBot->nColor >> 24) & 0xFF) / 255.0f;
+	const float fRed	= ((pBot->nColor >> 16) & 0xFF) / 255.0f;
+	const float fGreen	= ((pBot->nColor >> 8 ) & 0xFF) / 255.0f;
+	const float fBlue	= ((pBot->nColor >> 0 ) & 0xFF) / 255.0f;
+
+	const D3DXVECTOR4 kColorVector(fRed, fGreen, fBlue, fAlpha);
+
+	pBlockEffect->SetMatrix(pBlockEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
+	pBlockEffect->SetVector(pBlockEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
+	pBlockEffect->SetTexture(pBlockEffect->GetParameterByName(NULL, "kTexture"), NULL);
+	pBlockEffect->CommitChanges();
+
+	kContext.DrawTriangles(Vertex::Block::Declaration, pBlockVertexBuffer, sizeof(Vertex::Block), FacesPerCube * TrianglesPerFace);
+
+	pBlockEffect->EndPass();
+	pBlockEffect->End();
+}
+
+/*
+ * RenderBlock
+ */
+void View::RenderBlock(const D3DXMATRIX& kWorldMatrix, D3DCOLOR kColor)
+{
+	const float fAlpha	= ((kColor >> 24) & 0xFF) / 255.0f;
+	const float fRed	= ((kColor >> 16) & 0xFF) / 255.0f;
+	const float fGreen	= ((kColor >> 8 ) & 0xFF) / 255.0f;
+	const float fBlue	= ((kColor >> 0 ) & 0xFF) / 255.0f;
+
+	const D3DXVECTOR4 kColorVector(fRed, fGreen, fBlue, fAlpha);
+
+	pBlockEffect->SetMatrix(pBlockEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
+	pBlockEffect->SetVector(pBlockEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
+	pBlockEffect->SetTexture(pBlockEffect->GetParameterByName(NULL, "kTexture"), pBlockTexture);
+	pBlockEffect->CommitChanges();
+
+	kContext.DrawTriangles(Vertex::Block::Declaration, pBlockVertexBuffer, sizeof(Vertex::Block), FacesPerCube * TrianglesPerFace);
+}
+
+/*
+ * RenderBackground
+ */
+void View::RenderBackground()
+{
+	const D3DXVECTOR4 kColorVector(1.0f, 1.0f, 1.0f, 1.0f);
+
+	const float fWidth	= 304.0f;//10.0f * ScreenSizeX / 26.0f;
+	const float fHeight	= ScreenSizeY;
+	const float fX		= ScreenSizeX - fWidth;
+	const float fY		= 0.0f;
+
+	D3DXMATRIX kScale;
+	D3DXMatrixScaling(&kScale, fWidth, fHeight, 1.0f);
+
+	D3DXMATRIX kTranslate;
+	D3DXMatrixTranslation(&kTranslate, -0.5f * ScreenSizeX + fX + 0.5f, 0.5f * ScreenSizeY - fY + 0.5f, 0.0f);
+
+	D3DXMATRIX kWorldMatrix;
+	D3DXMatrixMultiply(&kWorldMatrix, &kScale, &kTranslate);
+
+	pInterfaceEffect->SetMatrix(pInterfaceEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
+	pInterfaceEffect->SetVector(pInterfaceEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
+	pInterfaceEffect->SetTexture(pInterfaceEffect->GetParameterByName(NULL, "kTexture"), pBackgroundTexture);
+	pInterfaceEffect->CommitChanges();
+
+	kContext.DrawTriangles(Vertex::Quad::Declaration, pInterfaceVertexBuffer, sizeof(Vertex::Quad), TrianglesPerFace);
+}
+
+/*
+ * RenderToolbar
+ */
+void View::RenderToolbar()
+{
+	const D3DXVECTOR4 kColorVector(1.0f, 1.0f, 1.0f, 1.0f);
+
+	for(uint32 i = 0; i < Action_Count; ++i)
+	{
+		D3DXMATRIX kScale;
+		D3DXMatrixScaling(&kScale, pModel->kActionBounds[i].Width, pModel->kActionBounds[i].Height, 1.0f);
+
+		D3DXMATRIX kTranslate;
+		D3DXMatrixTranslation(&kTranslate, -0.5f * ScreenSizeX + pModel->kActionBounds[i].X, 0.5f * ScreenSizeY - pModel->kActionBounds[i].Y, 0.0f);
+
+		D3DXMATRIX kWorldMatrix;
+		D3DXMatrixMultiply(&kWorldMatrix, &kScale, &kTranslate);
+
+		pInterfaceEffect->SetMatrix(pInterfaceEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
+		pInterfaceEffect->SetVector(pInterfaceEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
+		pInterfaceEffect->SetTexture(pInterfaceEffect->GetParameterByName(NULL, "kTexture"), pActionTextures[i]);
+		pInterfaceEffect->CommitChanges();
+
+		kContext.DrawTriangles(Vertex::Quad::Declaration, pInterfaceVertexBuffer, sizeof(Vertex::Quad), TrianglesPerFace);
+	}
+}
+
+/*
+ * RenderMain
+ */
+void View::RenderMain()
+{
+	Code* pCode = pModel->GetFunction(0);
+	if(pCode)
+	{
+		const D3DXVECTOR4 kColorVector(1.0f, 1.0f, 1.0f, 1.0f);
+
+		for(uint32 i = 0; i < Max(pCode->GetSize(), 16U); ++i)
+		{
+			const uint32 nAction = pCode->GetSlot(i);
+
+			if(Action_Forward <= nAction && nAction <= Action_FunctionB)
+			{
+				D3DXMATRIX kScale;
+				D3DXMatrixScaling(&kScale, pModel->kMainBounds[i].Width, pModel->kMainBounds[i].Height, 1.0f);
+
+				D3DXMATRIX kTranslate;
+				D3DXMatrixTranslation(&kTranslate, -0.5f * ScreenSizeX + pModel->kMainBounds[i].X, 0.5f * ScreenSizeY - pModel->kMainBounds[i].Y, 0.0f);
+
+				D3DXMATRIX kWorldMatrix;
+				D3DXMatrixMultiply(&kWorldMatrix, &kScale, &kTranslate);
+
+				pInterfaceEffect->SetMatrix(pInterfaceEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
+				pInterfaceEffect->SetVector(pInterfaceEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
+				pInterfaceEffect->SetTexture(pInterfaceEffect->GetParameterByName(NULL, "kTexture"), pActionTextures[nAction - Action_Forward]);
+				pInterfaceEffect->CommitChanges();
+
+				kContext.DrawTriangles(Vertex::Quad::Declaration, pInterfaceVertexBuffer, sizeof(Vertex::Quad), TrianglesPerFace);
+			}
+		}
+	}
+}
+
+/*
+ * RenderFunction();
+ */
+void View::RenderFunction()
+{
+	Code* pCode = pModel->GetFunction(pModel->nCurrentFunction + 1);
+	if(pCode)
+	{
+		const D3DXVECTOR4 kColorVector(1.0f, 1.0f, 1.0f, 1.0f);
+
+		for(uint32 i = 0; i < Max(pCode->GetSize(), 8U); ++i)
+		{
+			const uint32 nAction = pCode->GetSlot(i);
+
+			if(Action_Forward <= nAction && nAction <= Action_FunctionB)
+			{
+				D3DXMATRIX kScale;
+				D3DXMatrixScaling(&kScale, pModel->kFunctionBounds[i].Width, pModel->kFunctionBounds[i].Height, 1.0f);
+
+				D3DXMATRIX kTranslate;
+				D3DXMatrixTranslation(&kTranslate, -0.5f * ScreenSizeX + pModel->kFunctionBounds[i].X, 0.5f * ScreenSizeY - pModel->kFunctionBounds[i].Y, 0.0f);
+
+				D3DXMATRIX kWorldMatrix;
+				D3DXMatrixMultiply(&kWorldMatrix, &kScale, &kTranslate);
+
+				pInterfaceEffect->SetMatrix(pInterfaceEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
+				pInterfaceEffect->SetVector(pInterfaceEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
+				pInterfaceEffect->SetTexture(pInterfaceEffect->GetParameterByName(NULL, "kTexture"), pActionTextures[nAction - Action_Forward]);
+				pInterfaceEffect->CommitChanges();
+
+				kContext.DrawTriangles(Vertex::Quad::Declaration, pInterfaceVertexBuffer, sizeof(Vertex::Quad), TrianglesPerFace);
+			}
+		}
+	}
+}
+
+/*
+ * RenderControls
+ */
+void View::RenderControls()
+{
+	const D3DXVECTOR4 kColorVector(1.0f, 1.0f, 1.0f, 1.0f);
+
+	for(uint32 i = 0; i < sizeof(pModel->kControlBounds) / sizeof(pModel->kControlBounds[0]); ++i)
+	{
+		D3DXMATRIX kScale;
+		D3DXMatrixScaling(&kScale, pModel->kControlBounds[i].Width, pModel->kControlBounds[i].Height, 1.0f);
+
+		D3DXMATRIX kTranslate;
+		D3DXMatrixTranslation(&kTranslate, -0.5f * ScreenSizeX + pModel->kControlBounds[i].X, 0.5f * ScreenSizeY - pModel->kControlBounds[i].Y, 0.0f);
+
+		D3DXMATRIX kWorldMatrix;
+		D3DXMatrixMultiply(&kWorldMatrix, &kScale, &kTranslate);
+
+		pInterfaceEffect->SetMatrix(pInterfaceEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
+		pInterfaceEffect->SetVector(pInterfaceEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
+		pInterfaceEffect->SetTexture(pInterfaceEffect->GetParameterByName(NULL, "kTexture"), pControlTextures[i]);
+		pInterfaceEffect->CommitChanges();
+
+		kContext.DrawTriangles(Vertex::Quad::Declaration, pInterfaceVertexBuffer, sizeof(Vertex::Quad), TrianglesPerFace);
+	}
+
+	for(uint32 i = 0; i < sizeof(pModel->kArrowBounds) / sizeof(pModel->kArrowBounds[0]); ++i)
+	{
+		D3DXMATRIX kScale;
+		D3DXMatrixScaling(&kScale, pModel->kArrowBounds[i].Width, pModel->kArrowBounds[i].Height, 1.0f);
+
+		D3DXMATRIX kTranslate;
+		D3DXMatrixTranslation(&kTranslate, -0.5f * ScreenSizeX + pModel->kArrowBounds[i].X, 0.5f * ScreenSizeY - pModel->kArrowBounds[i].Y, 0.0f);
+
+		D3DXMATRIX kWorldMatrix;
+		D3DXMatrixMultiply(&kWorldMatrix, &kScale, &kTranslate);
+
+		pInterfaceEffect->SetMatrix(pInterfaceEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
+		pInterfaceEffect->SetVector(pInterfaceEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
+		pInterfaceEffect->SetTexture(pInterfaceEffect->GetParameterByName(NULL, "kTexture"), pArrowTextures[i]);
+		pInterfaceEffect->CommitChanges();
+
+		kContext.DrawTriangles(Vertex::Quad::Declaration, pInterfaceVertexBuffer, sizeof(Vertex::Quad), TrianglesPerFace);
+	}
+
+	const uint32 nColor = D3DCOLOR_XRGB(0, 0, 0);
+
+	RECT kRectangle;
+
+	kRectangle.left		= 1008;
+	kRectangle.top		= 199;
+	kRectangle.right	= kRectangle.left + 200;
+	kRectangle.bottom	= kRectangle.top + 200; 
+
+	pInterfaceFont->DrawTextA(NULL, "Main", -1, &kRectangle, 0, nColor);
+
+	kRectangle.left		= 1008;
+	kRectangle.top		= 472;
+	kRectangle.right	= kRectangle.left + 200;
+	kRectangle.bottom	= kRectangle.top + 200; 
+
+	pInterfaceFont->DrawTextA(NULL, "Function", -1, &kRectangle, 0, nColor);
+
+	char kBuffer[16];
+	sprintf_s(kBuffer, "%d", pModel->nCurrentFunction + 1);
+
+	kRectangle.left		= 1225;
+	kRectangle.top		= 473;
+	kRectangle.right	= kRectangle.left + 200;
+	kRectangle.bottom	= kRectangle.top + 200; 
+
+	pInterfaceFont->DrawTextA(NULL, kBuffer, -1, &kRectangle, 0, nColor);
+}
+
+/*
+ * RenderLevelDialog
+ */
+void View::RenderLevelDialog()
+{
+	const D3DXVECTOR4 kColorVector(1.0f, 1.0f, 1.0f, 1.0f);
+
+	D3DSURFACE_DESC kDescriptor;
+	pDialog1Texture->GetLevelDesc(0, &kDescriptor);
+
+	const float fSizeX	= (float)kDescriptor.Width;
+	const float fSizeY	= (float)kDescriptor.Height;
+
+	D3DXMATRIX kScale;
+	D3DXMatrixScaling(&kScale, fSizeX, fSizeY, 1.0f);
+
+	D3DXMATRIX kTranslate;
+	//D3DXMatrixTranslation(&kTranslate, -0.5f * ScreenSizeX + pModel->kControlBounds[i].X, 0.5f * ScreenSizeY - pModel->kControlBounds[i].Y, 0.0f);
+	D3DXMatrixTranslation(&kTranslate, -0.5f * fSizeX, 0.5f * fSizeY, 0.0f);
+
+	D3DXMATRIX kWorldMatrix;
+	D3DXMatrixMultiply(&kWorldMatrix, &kScale, &kTranslate);
+
+	pInterfaceEffect->SetMatrix(pInterfaceEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
+	pInterfaceEffect->SetVector(pInterfaceEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
+	pInterfaceEffect->SetTexture(pInterfaceEffect->GetParameterByName(NULL, "kTexture"), pDialog1Texture);
+	pInterfaceEffect->CommitChanges();
+
+	kContext.DrawTriangles(Vertex::Quad::Declaration, pInterfaceVertexBuffer, sizeof(Vertex::Quad), TrianglesPerFace);
+
+	RECT kRectangle;
+
+	kRectangle.left		= ScreenSizeX / 2;
+	kRectangle.top		= ScreenSizeY / 2 - 24;
+	kRectangle.right	= ScreenSizeX / 2;
+	kRectangle.bottom	= ScreenSizeY / 2 - 24;
+
+	char kMessage[256];
+	sprintf_s(kMessage, "Congratulations!\nYou have completed level %d", pModel->nCurrentLevel);
+
+	pInterfaceFont->DrawTextA(NULL, kMessage, -1, &kRectangle, DT_CENTER | DT_VCENTER | DT_CALCRECT, D3DCOLOR_XRGB(0, 0, 0));
+	pInterfaceFont->DrawTextA(NULL, kMessage, -1, &kRectangle, DT_CENTER | DT_VCENTER, D3DCOLOR_XRGB(0, 0, 0));
+}
+
+/*
+ * RenderGameOverDialog
+ */
+void View::RenderGameOverDialog()
+{
+}
+
+/*
+ * RenderCursor
+ */
+void View::RenderCursor()
+{
+	const D3DXVECTOR4 kColorVector(1.0f, 1.0f, 1.0f, 1.0f);
+
+	if(pCursorTexture)
+	{
+		if(pModel->kDragController.IsActive())
+		{
+			const uint32 nAction = pModel->kDragController.GetParameter() - Action_Forward;
+
+			D3DSURFACE_DESC kDescriptor;
+			pActionTextures[nAction]->GetLevelDesc(0, &kDescriptor);
+
+			const float fSizeX = (float)kDescriptor.Width;
+			const float fSizeY = (float)kDescriptor.Height;
+
+			D3DXMATRIX kScale;
+			D3DXMatrixScaling(&kScale, fSizeX, fSizeY, 1.0f);
+
+			D3DXMATRIX kTranslate;
+			D3DXMatrixTranslation(&kTranslate, -0.5f * ScreenSizeX + (pModel->fMouseX - 0.5f * fSizeX) + 0.5f, 0.5f * ScreenSizeY - (pModel->fMouseY - 0.5f * fSizeY) + 0.5f, 0.0f);
+
+			D3DXMATRIX kWorldMatrix;
+			D3DXMatrixMultiply(&kWorldMatrix, &kScale, &kTranslate);
+
+			pInterfaceEffect->SetMatrix(pInterfaceEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
+			pInterfaceEffect->SetVector(pInterfaceEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
+			pInterfaceEffect->SetTexture(pInterfaceEffect->GetParameterByName(NULL, "kTexture"), pActionTextures[nAction]);
+			pInterfaceEffect->CommitChanges();
+
+			kContext.DrawTriangles(Vertex::Quad::Declaration, pInterfaceVertexBuffer, sizeof(Vertex::Quad), TrianglesPerFace);
+		}
+
+		D3DSURFACE_DESC kDescriptor;
+		pCursorTexture->GetLevelDesc(0, &kDescriptor);
+
+		D3DXMATRIX kScale;
+		D3DXMatrixScaling(&kScale, (float)kDescriptor.Width, (float)kDescriptor.Height, 1.0f);
+
+		D3DXMATRIX kTranslate;
+		D3DXMatrixTranslation(&kTranslate, -0.5f * ScreenSizeX + pModel->fMouseX + 0.5f, 0.5f * ScreenSizeY - pModel->fMouseY + 0.5f, 0.0f);
+
+		D3DXMATRIX kWorldMatrix;
+		D3DXMatrixMultiply(&kWorldMatrix, &kScale, &kTranslate);
+
+		pInterfaceEffect->SetMatrix(pInterfaceEffect->GetParameterByName(NULL, "kWorld"), &kWorldMatrix);
+		pInterfaceEffect->SetVector(pInterfaceEffect->GetParameterByName(NULL, "kColor"), &kColorVector);
+		pInterfaceEffect->SetTexture(pInterfaceEffect->GetParameterByName(NULL, "kTexture"), pCursorTexture);
+		pInterfaceEffect->CommitChanges();
+
+		kContext.DrawTriangles(Vertex::Quad::Declaration, pInterfaceVertexBuffer, sizeof(Vertex::Quad), TrianglesPerFace);
+	}
+}
+
+/*
+ * OnMessage
+ */
+LRESULT View::OnMessage(UINT nMessage, WPARAM wParam, LPARAM lParam)
+{
+	if(nMessage == WM_CLOSE)
+	{
+		DestroyWindow(kWindow);
+		return 0;
+	}
+	else
+	
+	if(nMessage == WM_DESTROY)
+	{
+		PostQuitMessage(0);
+		return 0;
+	}
+
+	return DefWindowProc(kWindow, nMessage, wParam, lParam);
+}
+
+/*
+ * MessageRouter
+ */
+LRESULT CALLBACK View::MessageRouter(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
+{
+	if(pView && pView->kWindow)
+	{
+		return pView->OnMessage(nMessage, wParam, lParam);
+	}
+
+	return DefWindowProc(hWnd, nMessage, wParam, lParam);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/View.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,236 @@
+/*
+ * View
+ */
+
+#ifndef __VIEW_H__
+#define __VIEW_H__
+
+//#include <windows.h>
+//#include <d3d9.h>
+//#include <d3dx9.h>
+#include "Core.h"
+#include "Model.h"
+#include "RenderContext.h"
+#include "CameraController.h"
+
+/*
+ * View
+ */
+class View
+{
+	/*
+	 * pView
+	 */
+	static View* pView;
+
+	/*
+	 * pModel
+	 */
+	Model* pModel;
+
+	/*
+	 * kWindow
+	 */
+	HWND kWindow;
+
+	/*
+	 * kContext
+	 */
+	RenderContext kContext;
+
+	/*
+	 * kCameraController
+	 */
+	CameraController kCameraController;
+
+	/*
+	 * pBlockEffect
+	 */
+	ID3DXEffect* pBlockEffect;
+
+	/*
+	 * pInterfaceEffect
+	 */
+	ID3DXEffect* pInterfaceEffect;
+
+	/*
+	 * pInterfaceFont
+	 */
+	ID3DXFont* pInterfaceFont;
+
+	/*
+	 * pBlockVertexBuffer
+	 */
+	IDirect3DVertexBuffer9* pBlockVertexBuffer;
+
+	/*
+	 * pInterfaceVertexBuffer
+	 */
+	IDirect3DVertexBuffer9* pInterfaceVertexBuffer;
+
+	/*
+	 * pBlockTexture
+	 */
+	IDirect3DTexture9* pBlockTexture;
+
+	/*
+	 * pBackgroundTexture
+	 */
+	IDirect3DTexture9* pBackgroundTexture;
+
+	/*
+	 * pActionTextures
+	 */
+	IDirect3DTexture9* pActionTextures[Action_Count];
+
+	/*
+	 * pControlTextures
+	 */
+	IDirect3DTexture9* pControlTextures[3];
+
+	/*
+	 * pArrowTextures
+	 */
+	IDirect3DTexture9* pArrowTextures[2];
+
+	/*
+	 * pDialog1Texture
+	 */
+	IDirect3DTexture9* pDialog1Texture;
+
+	/*
+	 * pDialog2Texture
+	 */
+	IDirect3DTexture9* pDialog2Texture;
+
+	/*
+	 * pCursorTexture
+	 */
+	IDirect3DTexture9* pCursorTexture;
+
+public:
+
+	/*
+	 * View
+	 */
+	View(Model* pModel);
+
+	/*
+	 * Initialize
+	 */
+	ErrorCode Initialize();
+
+	/* 
+	 * Terminate
+	 */
+	void Terminate();
+
+	/*
+	 * Render
+	 */
+	void Render();
+
+	/*
+	 * GetWindow
+	 */
+	HWND GetWindow() const;
+
+	/*
+	 * UpdateCameraYaw
+	 */
+	void UpdateCameraYaw(float fDelta);
+
+	/*
+	 * UpdateCameraPitch
+	 */
+	void UpdateCameraPitch(float fDelta);
+
+	/*
+	 * UpdateCameraDistance
+	 */
+	void UpdateCameraDistance(float fDelta);
+
+private:
+
+	/*
+	 * SetupVertexBuffers
+	 */
+	ErrorCode SetupVertexBuffers();
+
+	/*
+	 * Render3D
+	 */
+	void Render3D();
+
+	/* 
+	 * Render2D
+	 */
+	void Render2D();
+
+	/*
+	 * 	RenderEnvironment
+	 */
+	void RenderEnvironment(Environment* pEnvironment);
+
+	/*
+	 * RenderBot
+	 */
+	void RenderBot(Environment* pEnvironment, Bot* pBot);
+
+	/*
+	 * RenderBlock
+	 */
+	void RenderBlock(const D3DXMATRIX& kWorldMatrix, D3DCOLOR kColor);
+
+	/*
+	 * RenderBackground
+	 */
+	void RenderBackground();
+
+	/*
+	 * RenderToolbar
+	 */
+	void RenderToolbar();
+
+	/*
+	 * RenderMain
+	 */
+	void RenderMain();
+
+	/*
+	 * RenderFunction();
+	 */
+	void RenderFunction();
+
+	/*
+	 * RenderControls
+	 */
+	void RenderControls();
+
+	/*
+	 * RenderLevelDialog
+	 */
+	void RenderLevelDialog();
+
+	/*
+	 * RenderGameOverDialog
+	 */
+	void RenderGameOverDialog();
+
+	/*
+	 * RenderCursor
+	 */
+	void RenderCursor();
+
+	/*
+	 * OnMessage
+	 */
+	LRESULT OnMessage(UINT nMessage, WPARAM wParam, LPARAM lParam);
+
+	/*
+	 * MessageRouter
+	 */
+	static LRESULT CALLBACK MessageRouter(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam);
+};
+
+#endif //__VIEW_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/VirtualMachine.cpp	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,187 @@
+/*
+ * VirtualMachine.cpp
+ */
+
+#include "VirtualMachine.h"
+
+/*
+ * VirtualMachine
+ */
+VirtualMachine::VirtualMachine() : nInstructionPointer(0), nFunctionCount(0)
+{
+	ClearMemory();
+}
+
+/*
+ * Step
+ */
+uint32 VirtualMachine::Step()
+{
+	// decode and validate instruction pointer function and offset
+	const uint8 nSourceFunction	= DecodeAddressFunction(nInstructionPointer);
+	const uint8 nSourceOffset	= DecodeAddressOffset(nInstructionPointer);
+
+	if(nSourceFunction < nFunctionCount && nSourceOffset <= kFunction[nSourceFunction].nSize)
+	{
+		DEBUG_PRINT("Reading address %d\n", nInstructionPointer);
+
+		// read the next instruction
+		const uint8 nInstruction	= Read();
+		const uint8 nParameter		= Read();
+
+		DEBUG_PRINT("Decoded I:%d P:%d\n", nInstruction, nParameter);
+
+		if(nInstruction == Instruction_None)
+		{
+			return Action_Default;
+		}
+		else
+
+		if(nInstruction == Instruction_Action)
+		{
+			// action instruction, the parameter is the action
+			DEBUG_PRINT("  -- Action Decoded: %d\n", nParameter);
+			return nParameter;
+		}
+		else
+	
+		if(nInstruction == Instruction_Call)
+		{
+			DEBUG_PRINT("  -- Call Decoded: %d\n", nParameter);
+
+			// set instruction pointer to destination
+			if(nParameter < nFunctionCount)
+			{
+				const uint8 nDestinationSize = kFunction[nParameter].nSize;
+
+				// insert continuation jump into destination function
+				nMemory[nParameter * FunctionStride + nDestinationSize + 0] = Instruction_Jump;
+				nMemory[nParameter * FunctionStride + nDestinationSize + 1] = nInstructionPointer;
+
+				DEBUG_PRINT("       - Inserting continuation\n");
+				DEBUG_PRINT("         Instruction: %d\n", Instruction_Jump);
+				DEBUG_PRINT("         Destination: %d\n", nInstructionPointer);
+
+				// update instruction pointer to destination address
+				nInstructionPointer = nParameter * FunctionStride;
+
+				// signal that we're not yet done
+				return Action_Default;
+			}
+		}
+		else
+
+		if(nInstruction == Instruction_Jump)
+		{
+			DEBUG_PRINT("  -- Jump Decoded: %d\n", nParameter);
+
+			// decode and validate destination function and offset
+			const uint8 nDestinationFunction	= DecodeAddressFunction(nParameter);
+			const uint8 nDestinationOffset		= DecodeAddressOffset(nParameter);
+
+			DEBUG_PRINT("       - Function: %d\n", nDestinationFunction);
+			DEBUG_PRINT("       - Offset  : %d\n", nDestinationOffset);
+
+			// set instruction pointer to destination
+			if(nDestinationFunction < nFunctionCount && nDestinationOffset <= kFunction[nDestinationFunction].nSize)
+			{
+				// update instruction pointer to destination address
+				nInstructionPointer = nParameter;
+
+				// signal that we're not yet done
+				return Action_Default;
+			}
+		}
+	}
+
+	return Action_Complete;
+}
+
+/*
+ * Reset
+ */
+void VirtualMachine::Reset()
+{
+	nInstructionPointer = 0;
+}
+
+/*
+ * SetMemory
+ */
+bool VirtualMachine::SetMemory(uint8 nFunction, const uint8* pData, uint8 nSize)
+{
+	if(nFunction < nFunctionCount)
+	{
+		const uint8 nFunctionAddress	= kFunction[nFunction].nAddress;
+		const uint8 nFunctionSize		= kFunction[nFunction].nSize;
+
+		for(uint8 nOffset = 0; nOffset < Min(nFunctionSize, nSize); ++nOffset)
+		{
+			nMemory[nFunctionAddress + nOffset] = pData[nOffset];
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * ClearMemory
+ */
+void VirtualMachine::ClearMemory()
+{
+	for(uint8 nFunction = 0; nFunction < MaximumFunctionCount; ++nFunction)
+	{
+		for(uint8 nLocation = 0; nLocation < MaximumInstructionCount; ++nLocation)
+		{
+			nMemory[nFunction * FunctionStride + nLocation] = Instruction_None;
+		}
+
+		nMemory[nFunction * FunctionStride + FunctionStride - ContinuationInstructionSize + 0] = Instruction_Jump;
+		nMemory[nFunction * FunctionStride + FunctionStride - ContinuationInstructionSize + 1] = 0;
+
+	}
+}
+
+/*
+ * AddFunction
+ */
+bool VirtualMachine::AddFunction(uint8 nFunction, uint8 nSize)
+{
+	if(nFunctionCount + 1 < MaximumFunctionCount)
+	{
+		kFunction[nFunctionCount].nAddress	= nFunctionCount * FunctionStride;
+		kFunction[nFunctionCount].nSize		= nSize;
+
+		++nFunctionCount;
+
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * RemoveAllFunctions
+ */
+void VirtualMachine::RemoveAllFunctions()
+{
+	nFunctionCount = 0;
+}
+
+/*
+ * GetFunctionSize
+ */
+uint32 VirtualMachine::GetFunctionSize(uint32 nIndex) const
+{
+	return nIndex < nFunctionCount ? kFunction[nIndex].nSize : 0;
+}
+
+/*
+ * GetFunctionMemory
+ */
+uint8* VirtualMachine::GetFunctionMemory(uint32 nIndex)
+{
+	return nIndex < nFunctionCount ? &nMemory[kFunction[nIndex].nAddress] : 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/Source/VirtualMachine.h	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,198 @@
+/*
+ * VirtualMachine.h
+ */
+
+#ifndef __VIRTUALMACHINE_H__
+#define __VIRTUALMACHINE_H__
+
+#include "Core.h"
+
+/*
+ * Instruction
+ */
+enum
+{
+	Instruction_None	= 0,
+	Instruction_Action	= 1,
+	Instruction_Jump	= 2,
+	Instruction_Call	= 3,
+	Instruction_End		= 4,
+};
+
+/*
+ * VirtualMachine
+ */
+class VirtualMachine
+{
+	/*
+	 * FunctionDefinition
+	 */
+	struct FunctionDefinition
+	{
+		/*
+		 * nId
+		 */
+		uint8 nAddress;
+
+		/*
+		 * nSize
+		 */
+		uint8 nSize;
+	};
+
+	/*
+	 * WordBits
+	 */
+	static const uint8 WordBits = sizeof(uint8) << 3;
+
+	/*
+	 * FunctionBits
+	 */
+	static const uint8 FunctionBits = 3;
+
+	/*
+	 * FunctionShift
+	 */
+	static const uint8 FunctionShift = WordBits - FunctionBits;
+
+	/*
+	 * FunctionMask
+	 */
+	static const uint8 FunctionMask = ((1 << FunctionBits) - 1) << FunctionShift;
+
+	/*
+	 * InstructionBits
+	 */
+	static const uint8 InstructionBits = WordBits - FunctionBits;
+
+	/*
+	 * InstructionShift
+	 */
+	static const uint8 InstructionShift = 0;
+
+	/*
+	 * InstructionMask
+	 */
+	static const uint8 InstructionMask = ((1 << InstructionBits) - 1) << InstructionShift;
+
+	/*
+	 * MaximumFunctionCount
+	 */
+	static const uint8 MaximumFunctionCount = 1 << FunctionBits;
+
+	/*
+	 * ContinuationInstructionSize
+	 *	Continuations use two instruction slots, one for the jump and one for the address
+	 */
+	static const uint8 ContinuationInstructionSize = 2;
+
+	/*
+	 * MaximumInstructionCount
+	 */
+	static const uint8 MaximumInstructionCount = (1 << InstructionBits) - ContinuationInstructionSize;
+
+	/*
+	 * FunctionStride
+	 */
+	static const uint8 FunctionStride = 1 << InstructionBits;
+
+	/*
+	 * nMemory
+	 *	Define the memory layout for each possible function.  The 
+	 *	additional instruction is used to implement function 
+	 *	continuations.
+	 */
+	uint8 nMemory[MaximumFunctionCount * FunctionStride];
+
+	/*
+	 * nInstructionPointer
+	 *	Points to the instruction currently being executed.  The value
+	 *	can be decoded into a function index and instruction offset
+	 */
+	uint8 nInstructionPointer;
+
+	/*
+	 * kFunction
+	 */
+	FunctionDefinition kFunction[MaximumFunctionCount];
+
+	/*
+	 * nFunctionCount
+	 */
+	uint8 nFunctionCount;
+
+public:
+
+	/*
+	 * VirtualMachine
+	 */
+	VirtualMachine();
+
+	/*
+	 * Step
+	 */
+	uint32 Step();
+
+	/*
+	 * Reset
+	 */
+	void Reset();
+
+	/*
+	 * SetMemory
+	 */
+	bool SetMemory(uint8 nFunction, const uint8* pData, uint8 nSize);
+
+	/*
+	 * ClearMemory
+	 */
+	void ClearMemory();
+
+	/*
+	 * AddFunction
+	 */
+	bool AddFunction(uint8 nFunction, uint8 nSize);
+
+	/*
+	 * RemoveAllFunctions
+	 */
+	void RemoveAllFunctions();
+
+	/*
+	 * GetFunctionSize
+	 */
+	uint32 GetFunctionSize(uint32 nFunction) const;
+
+	/*
+	 * GetFunctionMemory
+	 */
+	uint8* GetFunctionMemory(uint32 nFunction);
+
+private:
+
+	/*
+	 * Read
+	 */
+	uint8 Read()
+	{
+		return nMemory[nInstructionPointer++];
+	}
+
+	/*
+	 * DecodeAddressFunction
+	 */
+	uint8 DecodeAddressFunction(uint8 nAddress) const
+	{
+		return (nAddress & FunctionMask) >> FunctionShift;
+	}
+
+	/*
+	 * DecodeAddressOffset
+	 */
+	uint8 DecodeAddressOffset(uint8 nAddress) const
+	{
+		return (nAddress & InstructionMask) >> InstructionShift;
+	}
+};
+
+#endif //__VIRTUALMACHINE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightClone/ToDo.txt	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,6 @@
+1. Check for ending conditions
+2. Only draw slots that are being used
+3. Center grid in viewport
+4. Button tool tips
+5. Main menu
+6. Robot model & texture
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightTools/Build.py	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,30 @@
+#
+# Build
+#
+
+import Map
+import os
+import sys
+
+if __name__ == '__main__':
+    path_root   = os.path.dirname(sys.argv[0])
+    path_assets = os.path.abspath(os.path.join(path_root, '..', 'Assets', 'Maps'))
+    path_build  = os.path.abspath(os.path.join(path_root, '..', 'Data', 'Maps'))
+
+    if os.path.isdir(path_assets):
+        for filename in os.listdir(path_assets):
+            if not filename.endswith('.def'):
+                continue
+
+            definition = Map.ReadDefinition(os.path.join(path_assets, filename))
+            if not definition:
+                continue
+
+            output = os.path.join(path_build, os.path.splitext(filename)[0] + '.map')
+            folder = os.path.dirname(output)
+
+            if not os.path.isdir(folder):
+                os.makedirs(folder)
+
+            print 'Building %s from %s' % (os.path.basename(output), os.path.basename(filename))
+            definition.Write(output)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LightTools/Map.py	Wed Sep 07 12:36:37 2011 -0700
@@ -0,0 +1,84 @@
+#
+# Map
+#
+
+import sys
+import string
+import struct
+import os
+import functools
+
+class MapDefinition:
+    Parse = functools.partial(string.split, sep=',')
+
+    def __init__(self, size, position, direction, fcount, functions, grid):
+        self.Size = self._ParseVector(size)
+        self.Position = self._ParseVector(position)
+        self.Direction = self._ParseVector(direction)
+        self.Count = self._ParseVector(fcount)
+        self.Functions = self._ParseList(functions)
+        self.Grid = self._ParseList(grid)
+
+    def Write(self, filename):
+        with open(filename, 'wb') as handle:
+            handle.write(struct.pack('i' * len(self.Size),      *self.Size))            # 8
+            handle.write(struct.pack('i' * len(self.Position),  *self.Position))        # 8
+            handle.write(struct.pack('i' * len(self.Direction), *self.Direction))       # 4
+            handle.write(struct.pack('i' * len(self.Count),     *self.Count))           # 4
+
+            for function in self.Functions:
+                handle.write(struct.pack('i' * len(function), *function))               # 4 * Count
+
+            for tower in self.Grid:
+                handle.write(struct.pack('i' * len(tower), *tower))                     # 8 * Size.X * Size.Y
+
+    def _ParseVector(self, line):
+        return map(int, self.Parse(line))
+
+    def _ParseList(self, lines):
+        return [self._ParseVector(line) for line in lines]
+
+def ReadDefinition(filename):
+    def FilterLines(lines):
+        for line in map(string.strip, lines):
+            if line and not line.startswith('#'):
+                yield line.split('#')[0]
+
+    with open(filename, 'rt') as handle:
+        lines = handle.readlines()
+
+    definition = tuple(FilterLines(lines))
+
+    offset = 0
+    size = definition[offset]
+    offset += 1
+    position = definition[offset]
+    offset += 1
+    direction = definition[offset]
+    offset += 1
+    fcount = definition[offset]
+    offset += 1
+    length = int(fcount)
+    functions = definition[offset:offset+length]
+    offset += length
+    grid = definition[offset:]
+
+    return MapDefinition(size, position, direction, fcount, functions, grid)
+
+if __name__ == '__main__':
+    if len(sys.argv) < 2:
+        print 'Usage: Map <map> [output]'
+        sys.exit()
+
+    path_input  = os.path.abspath(sys.argv[1])
+    path_output = os.path.splitext(path_input)[0] + '.map'
+
+    if len(sys.argv) > 2:
+        path_output = os.path.abspath(sys.argv[2])
+        if os.path.isdir(path_output):
+            path_output += os.path.splitext(os.path.basename(path_input))[0] + '.map'
+
+    definition = ReadDefinition(path_input)
+    if definition:
+        print 'Building %s from %s' % (os.path.basename(path_output), os.path.basename(path_input))
+        definition.Write(path_output)
\ No newline at end of file