[gnome-games/gnomine-clutter] Initial import of gnomine-clutter from local git repo.



commit 421276df2a6a29f4a209707a94530682fbd9f2e2
Author: Tim Horton <hortont424 gmail com>
Date:   Tue Aug 18 21:29:39 2009 -0400

    Initial import of gnomine-clutter from local git repo.

 configure.in                                       |   11 +-
 gnomine-clutter/Makefile.am                        |   54 ++++
 gnomine-clutter/data/gnomine.ui                    |  108 ++++++++
 gnomine-clutter/data/themes/Makefile.am            |    1 +
 gnomine-clutter/data/themes/tango/Makefile.am      |   14 +
 gnomine-clutter/data/themes/tango/bang.svg         |   99 ++++++++
 .../data/themes/tango/flag-question.svg            |   26 ++
 gnomine-clutter/data/themes/tango/flag.svg         |   25 ++
 gnomine-clutter/data/themes/tango/mine.svg         |   13 +
 gnomine-clutter/data/themes/tango/theme.js         |  138 ++++++++++
 gnomine-clutter/gnomine-clutter.desktop.in.in      |   13 +
 gnomine-clutter/gnomine-clutter.schemas.in         |   18 ++
 gnomine-clutter/src/CLIGame.js                     |   66 +++++
 gnomine-clutter/src/ClutterGame.js                 |   76 ++++++
 gnomine-clutter/src/ClutterUI.js                   |  258 +++++++++++++++++++
 gnomine-clutter/src/Game.js                        |  266 ++++++++++++++++++++
 gnomine-clutter/src/Path.js.in                     |    1 +
 gnomine-clutter/src/Settings.js                    |    6 +
 gnomine-clutter/src/ThemeLoader.js                 |   38 +++
 gnomine-clutter/src/gnomine-clutter.in             |    5 +
 gnomine-clutter/src/main.js                        |    8 +
 21 files changed, 1242 insertions(+), 2 deletions(-)
---
diff --git a/configure.in b/configure.in
index 6d33431..77a9909 100644
--- a/configure.in
+++ b/configure.in
@@ -25,7 +25,7 @@ AM_MAINTAINER_MODE([enable])
 # This is the canonical list of all game subdirectories.
 allgames="aisleriot blackjack gnometris gnect gnomine same-gnome mahjongg gtali gnotravex gnotski glines iagno glchess gnobots2 gnibbles gnome-sudoku"
 AC_SUBST([allgames])
-staginggames="lightsoff same-gnome-clutter"
+staginggames="lightsoff same-gnome-clutter gnomine-clutter"
 AC_SUBST([staginggames])
 
 gamelist=""
@@ -166,7 +166,7 @@ for game in $gamelist; do
     *) ;;
   esac
   case $game in
-    gnometris|lightsoff|same-gnome-clutter) need_clutter=yes ;;
+    gnometris|lightsoff|same-gnome-clutter|gnomine-clutter) need_clutter=yes ;;
     *) ;;
   esac
   case $game in
@@ -212,6 +212,7 @@ AM_CONDITIONAL([BUILD_IAGNO],[test "$build_iagno" = "yes"])
 AM_CONDITIONAL([BUILD_LIGHTSOFF],[test "$build_lightsoff" = "yes"])
 AM_CONDITIONAL([BUILD_MAHJONGG],[test "$build_mahjongg" = "yes"])
 AM_CONDITIONAL([BUILD_SAME_GNOME],[test "$build_same_gnome" = "yes"])
+AM_CONDITIONAL([BUILD_GNOMINE_CLUTTER],[test "$build_gnomine_clutter" = "yes"])
 
 # Locate various programs
 
@@ -1261,6 +1262,12 @@ lightsoff/data/themes/tango/Makefile
 lightsoff/data/themes/up/Makefile
 tests/Makefile
 tests/libgames-support/Makefile
+gnomine-clutter/src/Path.js
+gnomine-clutter/Makefile
+gnomine-clutter/data/themes/Makefile
+gnomine-clutter/data/themes/tango/Makefile
+gnomine-clutter/gnomine-clutter.desktop.in
+gnomine-clutter/src/gnomine-clutter
 ])
 AC_OUTPUT
 
diff --git a/gnomine-clutter/Makefile.am b/gnomine-clutter/Makefile.am
new file mode 100644
index 0000000..e3093f3
--- /dev/null
+++ b/gnomine-clutter/Makefile.am
@@ -0,0 +1,54 @@
+SUBDIRS = data/themes
+
+gnomine_clutterdir = $(pkgdatadir)/gnomine-clutter
+gnomine_clutter_DATA = \
+	src/CLIGame.js \
+	src/ClutterGame.js \
+	src/ClutterUI.js \
+	src/Game.js \
+	src/main.js \
+	src/Path.js \
+	src/Settings.js \
+	src/ThemeLoader.js \
+	data/gnomine.ui
+
+bin_SCRIPTS = \
+	src/gnomine-clutter
+
+schema_in_files = gnomine-clutter.schemas.in
+if HAVE_GNOME
+schemadir = $(GCONF_SCHEMA_FILE_DIR)
+schema_DATA = $(schema_in_files:.schemas.in=.schemas)
+endif
+
+desktop_in_files = gnomine-clutter.desktop.in.in
+desktopdir = $(datadir)/applications
+desktop_DATA = $(desktop_in_files:.desktop.in.in=.desktop)
+ INTLTOOL_DESKTOP_RULE@
+
+CLEANFILES = $(desktop_DATA)
+
+EXTRA_DIST = \
+	src/CLIGame.js \
+	src/ClutterGame.js \
+	src/ClutterUI.js \
+	src/Game.js \
+	src/main.js \
+	src/Path.js.in \
+	src/Settings.js \
+	src/ThemeLoader.js \
+	data/gnomine.ui \
+	$(schema_in_files)
+
+install-schemas-local: $(schema_DATA)
+if GCONF_SCHEMAS_INSTALL
+	if test -z "$(DESTDIR)" ; then \
+		for p in $^ ; do \
+			GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $$p 2>&1 > /dev/null; \
+		done \
+	fi
+endif
+
+install-data-local: install-schemas-local
+
+ INTLTOOL_SCHEMAS_RULE@
diff --git a/gnomine-clutter/data/gnomine.ui b/gnomine-clutter/data/gnomine.ui
new file mode 100644
index 0000000..37e31b8
--- /dev/null
+++ b/gnomine-clutter/data/gnomine.ui
@@ -0,0 +1,108 @@
+<?xml version="1.0"?>
+<interface>
+	<requires lib="gtk+" version="2.14"/>
+	<object class="GtkWindow" id="game_window">
+		<property name="title" translatable="yes">Mines</property>
+		<property name="resizable">False</property>
+		<property name="icon_name">gnome-mines</property>
+		<accel-groups>
+			<group name="accel_group"/>
+		</accel-groups>
+		<child>
+			<object class="GtkVBox" id="game_vbox">
+				<property name="visible">True</property>
+				<property name="orientation">vertical</property>
+				<!--<child>
+					<object class="GtkMenuBar" id="menu_bar">
+						<property name="visible">True</property>
+						<child>
+							<object class="GtkMenuItem" id="game_menu_item">
+								<property name="visible">True</property>
+								<property name="label" translatable="yes">_Game</property>
+								<property name="use_underline">True</property>
+								<child type="submenu">
+									<object class="GtkMenu" id="game_menu">
+										<property name="visible">True</property>
+										<child>
+											<object class="GtkImageMenuItem" id="new_game_item">
+												<signal name="activate" handler="reset_score"/>
+												<property name="label">games-new-game</property>
+												<property name="visible">True</property>
+												<property name="use_underline">True</property>
+												<property name="use_stock">True</property>
+												<property name="accel_group">accel_group</property>
+											</object>
+										</child>
+										<child>
+											<object class="GtkImageMenuItem" id="show_preferences_item">
+												<signal name="activate" handler="show_settings"/>
+												<property name="label">gtk-preferences</property>
+												<property name="visible">True</property>
+												<property name="use_underline">True</property>
+												<property name="use_stock">True</property>
+												<property name="accel_group">accel_group</property>
+											</object>
+										</child>
+										<child>
+											<object class="GtkSeparatorMenuItem" id="separator1" />
+										</child>
+										<child>
+											<object class="GtkImageMenuItem" id="quit_item">
+												<signal name="activate" handler="quit"/>
+												<property name="label">gtk-quit</property>
+												<property name="visible">True</property>
+												<property name="use_underline">True</property>
+												<property name="use_stock">True</property>
+												<property name="accel_group">accel_group</property>
+											</object>
+										</child>
+									</object>
+								</child>
+							</object>
+						</child>
+						<child>
+							<object class="GtkMenuItem" id="help_menu_item">
+								<property name="visible">True</property>
+								<property name="label" translatable="yes">_Help</property>
+								<property name="use_underline">True</property>
+								<child type="submenu">
+									<object class="GtkMenu" id="help_menu">
+										<property name="visible">True</property>
+										<child>
+											<object class="GtkImageMenuItem" id="show_help_item">
+												<signal name="activate" handler="show_help"/>
+												<property name="label">games-contents</property>
+												<property name="visible">True</property>
+												<property name="use_underline">True</property>
+												<property name="use_stock">True</property>
+												<property name="accel_group">accel_group</property>
+											</object>
+										</child>
+										<child>
+											<object class="GtkImageMenuItem" id="show_about_item">
+												<signal name="activate" handler="show_about"/>
+												<property name="label">gtk-about</property>
+												<property name="visible">True</property>
+												<property name="use_underline">True</property>
+												<property name="use_stock">True</property>
+												<property name="accel_group">accel_group</property>
+											</object>
+										</child>
+									</object>
+								</child>
+							</object>
+						</child>
+					</object>
+					<packing>
+						<property name="expand">False</property>
+						<property name="position">0</property>
+					</packing>
+				</child>-->
+				<child>
+					<placeholder/>
+				</child>
+			</object>
+		</child>
+	</object>
+	<object class="GtkAccelGroup" id="accel_group"/>
+</interface>
diff --git a/gnomine-clutter/data/themes/Makefile.am b/gnomine-clutter/data/themes/Makefile.am
new file mode 100644
index 0000000..4ac00c0
--- /dev/null
+++ b/gnomine-clutter/data/themes/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = tango
diff --git a/gnomine-clutter/data/themes/tango/Makefile.am b/gnomine-clutter/data/themes/tango/Makefile.am
new file mode 100644
index 0000000..f1a981c
--- /dev/null
+++ b/gnomine-clutter/data/themes/tango/Makefile.am
@@ -0,0 +1,14 @@
+themedir = $(pkgdatadir)/gnomine-clutter/themes/tango
+theme_DATA = \
+	bang.svg \
+	flag.svg \
+	flag-question.svg \
+	mine.svg \
+	theme.js
+
+EXTRA_DIST = \
+	bang.svg \
+	flag.svg \
+	flag-question.svg \
+	mine.svg \
+	theme.js
diff --git a/gnomine-clutter/data/themes/tango/bang.svg b/gnomine-clutter/data/themes/tango/bang.svg
new file mode 100644
index 0000000..933f23b
--- /dev/null
+++ b/gnomine-clutter/data/themes/tango/bang.svg
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd";>
+<svg
+   version="1.1"
+   width="161"
+   height="161"
+   id="svg1"
+   sodipodi:version="0.32"
+   inkscape:version="0.40"
+   sodipodi:docname="bang.svg"
+   sodipodi:docbase="/home/callum/Desktop/Development/CVS/gnome/gnome-games/gnomine"
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:cc="http://web.resource.org/cc/";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:xlink="http://www.w3.org/1999/xlink";>
+  <defs
+     id="defs24" />
+  <metadata
+     id="metadata23">
+    <rdf:RDF
+       id="RDF25">
+      <cc:Work
+         rdf:about=""
+         id="Work26">
+        <dc:format
+           id="format27">image/svg+xml</dc:format>
+        <dc:type
+           id="type29"
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="4.3245342"
+     inkscape:cx="64.400000"
+     inkscape:cy="59.775224"
+     inkscape:window-width="1252"
+     inkscape:window-height="742"
+     inkscape:window-x="28"
+     inkscape:window-y="28"
+     inkscape:current-layer="svg1" />
+  <linearGradient
+     id="paint"
+     gradientUnits="userSpaceOnUse"
+     x1="14.5"
+     y1="99"
+     x2="119.5"
+     y2="99">
+    <stop
+       offset="0"
+       style="stop-color:#DA1800"
+       id="stop17" />
+    <stop
+       offset="0.33"
+       style="stop-color:#B42D2D"
+       id="stop18" />
+    <stop
+       offset="0.66"
+       style="stop-color:#FA1818"
+       id="stop19" />
+    <stop
+       offset="1"
+       style="stop-color:#B42D2D"
+       id="stop20" />
+  </linearGradient>
+  <path
+     style="fill:#ff3300;fill-opacity:0.99000001;fill-rule:evenodd;stroke:#000000;stroke-width:5.4832249;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+     d="M 152.98197,67.355937 L 122.43458,90.696181 L 132.66697,124.79975 L 102.62044,117.30637 L 99.600286,148.26881 L 73.111197,125.85311 L 45.041354,144.17356 L 46.548598,112.33632 L 17.238289,106.17280 L 36.690855,84.591940 L 10.184713,59.542496 L 42.432172,52.927710 L 33.309280,16.663758 L 65.305881,36.721744 L 80.754307,5.6726395 L 95.240707,39.312080 L 126.11935,21.432991 L 117.30031,57.590259 L 152.98197,67.355937 z "
+     id="path1073"
+     sodipodi:nodetypes="ccccccccccccccccccc" />
+  <path
+     style="fill:#fffd00;fill-opacity:0.99000001;fill-rule:evenodd;stroke:#000000;stroke-width:3.1000125;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;"
+     d="M 135.30184,70.107371 L 111.08415,87.803137 L 121.08416,113.53165 L 96.518719,106.69957 L 92.471569,132.61588 L 72.517746,116.44931 L 52.982898,130.72879 L 55.935373,107.51456 L 31.252724,101.39935 L 46.169715,83.433168 L 25.059616,64.292483 L 50.428434,59.129342 L 44.469717,31.446818 L 69.202418,47.506318 L 79.936934,21.370636 L 91.166424,51.869973 L 114.20876,38.365670 L 106.98914,64.930209 L 135.30184,70.107371 z "
+     id="path1689"
+     sodipodi:nodetypes="ccccccccccccccccccc" />
+  <path
+     style="fill:#232323;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none;"
+     d="M 57.809695,59.543986 C 44.224417,78.043088 48.849192,91.917415 48.849192,91.917415 L 59.543986,102.61221 L 55.497307,82.378815 L 57.809695,59.543986 z "
+     id="path1067" />
+  <path
+     style="fill:#232323;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none;"
+     d="M 70.816876,55.786355 L 82.667864,68.793537 C 82.667864,68.793537 95.964093,69.371634 97.120287,68.504488 C 98.276481,67.637343 92.206463,48.560144 92.206463,48.560144 L 70.816876,55.786355 z "
+     id="path1068" />
+  <path
+     style="fill:#232323;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none;"
+     d="M 77.464991,85.269300 L 78.332136,104.05745 L 91.339318,110.12747 C 91.339318,110.12747 92.423250,111.93402 99.288151,102.75674 C 105.50269,94.735633 104.27423,92.640036 103.76840,92.784560 L 77.464991,85.269300 z "
+     id="path1069"
+     sodipodi:nodetypes="cccccc" />
+</svg>
diff --git a/gnomine-clutter/data/themes/tango/flag-question.svg b/gnomine-clutter/data/themes/tango/flag-question.svg
new file mode 100644
index 0000000..8398d75
--- /dev/null
+++ b/gnomine-clutter/data/themes/tango/flag-question.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";>
+<svg xmlns="http://www.w3.org/2000/svg"; version="1.1" width="161" height="161">
+  <rect x="102.67" y="19" fill="#777777" stroke="#000000" stroke-width="3" width="36.67" height="8"/>
+  <rect x="98.67" y="60" fill="#777777" stroke="#000000" stroke-width="3" width="42.31" height="8"/>
+  <rect x="94.67" y="99" fill="#777777" stroke="#000000" stroke-width="3" width="50.9" height="8"/>
+  <polygon fill="#404040" points="151.64,126.87 144.6,126.87 132.03,27.19 139.07,27.19"/>
+  <polygon fill="#777777" points="148.1,127.17 144.6,126.87 132.03,27.19 135.53,27.48"/>
+  <polygon fill="none" stroke="#000000" stroke-width="3" points="151.64,126.87 144.6,126.87 132.03,27.19 139.07,27.19"/>
+  <polygon fill="#404040" points="90.86,126.87 97.9,126.87 110.47,27.19 103.43,27.19"/>
+  <polygon fill="#777777" points="90.86,126.87 94.9,126.87 107.47,27.19 103.43,27.19"/>
+  <polygon fill="none" stroke="#000000" stroke-width="3" points="90.86,126.87 97.9,126.87 110.47,27.19 103.43,27.19"/>
+  <path fill="#404040" stroke="#404040" d="M154.18,121.94h-5.24c0,0,0.98,24.81-4.89,24.81c-5.87,0-44.99,0-50.86,0c-4.33,0-4.93-13.47-4.95-20.56c-0.02,8.28,0.51,25.81,5.38,25.81c6.38,0,48.87,0,55.24,0C155.25,152,154.18,121.94,154.18,121.94z"/>
+  <path fill="#777777" stroke="#777777" d="M93.2,146.75c5.87,0,44.99,0,50.86,0c5.87,0,4.89-24.81,4.89-24.81H88.32h-0.01c0,0-0.07,1.72-0.06,4.25C88.27,133.27,88.88,146.75,93.2,146.75z"/>
+  <path fill="none" stroke="#000000" stroke-width="3.5" d="M93.63,152c6.38,0,48.87,0,55.24,0c6.37,0,5.31-30.06,5.31-30.06H88.32C88.32,121.94,87.25,152,93.63,152z"/>
+  <rect x="118.5" y="23" fill="#777777" stroke="#000000" stroke-width="2" width="7" height="80"/>
+  <path fill="#FFFFFF" d="M91.57,137.06c-1.31-13.13-1.31-13.43,24.89-11.81C91.57,127.16,93.48,125.55,91.57,137.06z"/>
+  <linearGradient id="paint" gradientUnits="userSpaceOnUse" x1="14.5" y1="99" x2="119.5" y2="99">
+    <stop offset="0" style="stop-color:#185888"/>
+    <stop offset="0.33" style="stop-color:#2D55B4"/>
+    <stop offset="0.66" style="stop-color:#5050FF"/>
+    <stop offset="1" style="stop-color:#105080"/>
+  </linearGradient>
+  <path fill="url(#paint)" stroke="#000000" stroke-width="6" d="M67.35,13.97c-13.99,13.43-51.85,0-51.85,0V60.6v47.93c0,0,37.86,13.43,51.85,0c14-13.43,53.15,0,53.15,0V60.6V13.97C120.5,13.97,81.35,0.54,67.35,13.97z"/>
+  <path fill="#FFFFFF" stroke="#142359" stroke-width="3" d="M92,46.99c0,2.75-0.41,5.12-1.21,7.11c-0.81,1.99-2.23,4.04-4.26,6.13c-0.92,0.95-2.54,2.27-4.89,3.96c-2.35,1.66-3.95,3.05-4.8,4.11c-0.66,0.84-1.22,1.9-1.64,3.17c-0.43,1.27-0.67,1.98-0.73,2.11c-0.51,1.1-1.25,1.94-2.2,2.5c-0.95,0.57-2.09,0.86-3.42,0.86c-2.15,0-3.81-0.55-5-1.62c-1.17-1.06-1.76-2.57-1.76-4.5c0-1.68,0.44-3.4,1.33-5.13c0.88-1.75,2.14-3.35,3.76-4.82c0.77-0.71,1.92-1.66,3.48-2.9c4.58-3.56,6.87-6.97,6.87-10.24c0-2.8-0.83-5.04-2.47-6.71c-1.66-1.66-3.9-2.5-6.72-2.5c-2.09,0-3.89,0.41-5.38,1.2c-1.5,0.78-2.72,1.98-3.67,3.6c-0.26,0.41-0.6,1.04-1.05,1.87c-1.83,3.45-4.24,5.16-7.27,5.16c-1.87,0-3.35-0.55-4.4-1.62C45.51,47.63,45,46.12,45,44.2c0-1.86,0.5-3.77,1.52-5.75c1.02-1.96,2.46-3.78,4.34-5.46c2.26-2.05,4.78-3.55,7.57-4.53C61.22,27.5,64.42,27,68,27c7.34,0,13.17,1.82,17.5,5.42C89.84,36.06,92,40.91,92,46.99z M60.67,89.64c0-2.07,0.76-3.83,2.23-5.29c1.49-1.47,3.29-2.2,5.43-2.2c2.22,0,4.07,0.73,5.56,2.16c1.49,1.47,2.23,3
 .22,2.23,5.32c0,2.05-0.77,3.78-2.29,5.22C72.33,96.28,70.48,97,68.33,97c-2.09,0-3.9-0.73-5.4-2.17C61.42,93.4,60.67,91.66,60.67,89.64z"/>
+</svg>
diff --git a/gnomine-clutter/data/themes/tango/flag.svg b/gnomine-clutter/data/themes/tango/flag.svg
new file mode 100644
index 0000000..5d706a0
--- /dev/null
+++ b/gnomine-clutter/data/themes/tango/flag.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";>
+<svg xmlns="http://www.w3.org/2000/svg"; version="1.1" width="161" height="161">
+  <rect x="102.67" y="19" fill="#777777" stroke="#000000" stroke-width="3" width="36.67" height="8"/>
+  <rect x="98.67" y="60" fill="#777777" stroke="#000000" stroke-width="3" width="42.31" height="8"/>
+  <rect x="94.67" y="99" fill="#777777" stroke="#000000" stroke-width="3" width="50.9" height="8"/>
+  <polygon fill="#404040" points="151.64,126.87 144.6,126.87 132.03,27.19 139.07,27.19"/>
+  <polygon fill="#777777" points="148.1,127.17 144.6,126.87 132.03,27.19 135.53,27.48"/>
+  <polygon fill="none" stroke="#000000" stroke-width="3" points="151.64,126.87 144.6,126.87 132.03,27.19 139.07,27.19"/>
+  <polygon fill="#404040" points="90.86,126.87 97.9,126.87 110.47,27.19 103.43,27.19"/>
+  <polygon fill="#777777" points="90.86,126.87 94.9,126.87 107.47,27.19 103.43,27.19"/>
+  <polygon fill="none" stroke="#000000" stroke-width="3" points="90.86,126.87 97.9,126.87 110.47,27.19 103.43,27.19"/>
+  <path fill="#404040" stroke="#404040" d="M154.18,121.94h-5.24c0,0,0.98,24.81-4.89,24.81c-5.87,0-44.99,0-50.86,0c-4.33,0-4.93-13.47-4.95-20.56c-0.02,8.28,0.51,25.81,5.38,25.81c6.38,0,48.87,0,55.24,0C155.25,152,154.18,121.94,154.18,121.94z"/>
+  <path fill="#777777" stroke="#777777" d="M93.2,146.75c5.87,0,44.99,0,50.86,0c5.87,0,4.89-24.81,4.89-24.81H88.32h-0.01c0,0-0.07,1.72-0.06,4.25C88.27,133.27,88.88,146.75,93.2,146.75z"/>
+  <path fill="none" stroke="#000000" stroke-width="3.5" d="M93.63,152c6.38,0,48.87,0,55.24,0c6.37,0,5.31-30.06,5.31-30.06H88.32C88.32,121.94,87.25,152,93.63,152z"/>
+  <rect x="118.5" y="23" fill="#777777" stroke="#000000" stroke-width="2" width="7" height="80"/>
+  <path fill="#FFFFFF" d="M91.57,137.06c-1.31-13.13-1.31-13.43,24.89-11.81C91.57,127.16,93.48,125.55,91.57,137.06z"/>
+  <linearGradient id="paint" gradientUnits="userSpaceOnUse" x1="14.5" y1="99" x2="119.5" y2="99">
+    <stop offset="0" style="stop-color:#DA1800"/>
+    <stop offset="0.33" style="stop-color:#B42D2D"/>
+    <stop offset="0.66" style="stop-color:#FA1818"/>
+    <stop offset="1" style="stop-color:#B42D2D"/>
+  </linearGradient>
+  <path fill="url(#paint)" stroke="#000000" stroke-width="6" d="M67.35,13.97c-13.99,13.43-51.85,0-51.85,0V60.6v47.93c0,0,37.86,13.43,51.85,0c14-13.43,53.15,0,53.15,0V60.6V13.97C120.5,13.97,81.35,0.54,67.35,13.97z"/>
+</svg>
diff --git a/gnomine-clutter/data/themes/tango/mine.svg b/gnomine-clutter/data/themes/tango/mine.svg
new file mode 100644
index 0000000..b1b0b73
--- /dev/null
+++ b/gnomine-clutter/data/themes/tango/mine.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";>
+<svg xmlns="http://www.w3.org/2000/svg"; version="1.1" width="160" height="160">
+  <radialGradient id="paint" cx="67" cy="67" r="100" gradientUnits="userSpaceOnUse">
+    <stop offset="0" style="stop-color:#808080"/>
+    <stop offset="0.12" style="stop-color:#606060"/>
+    <stop offset="0.45" style="stop-color:#202020"/>
+    <stop offset="1" style="stop-color:#000000"/>
+  </radialGradient>
+  <path fill="url(#paint)" stroke="#000000" stroke-width="5" d="M155,84.839v-9.678h-21.033c-1.003-11.329-5.486-21.655-12.383-29.901l14.87-14.871l-6.842-6.843L114.74,38.417c-8.246-6.897-18.573-11.38-29.901-12.384V5h-9.678v21.033c-11.33,1.003-21.657,5.486-29.903,12.383l-14.87-14.87l-6.843,6.843l14.87,14.87c-6.896,8.247-11.379,18.574-12.383,29.903H5v9.678h21.033c1.003,11.331,5.485,21.658,12.382,29.903l-14.869,14.87l6.843,6.842l14.869-14.868c8.246,6.896,18.573,11.378,29.904,12.381V155h9.678v-21.033c11.329-1.003,21.656-5.485,29.902-12.382l14.871,14.869l6.842-6.842l-14.869-14.871c6.896-8.245,11.379-18.572,12.382-29.902H155V84z"/>
+  <circle fill="none" stroke="#000000" stroke-width="4" cx="80" cy="80" r="6"/>
+  <circle fill="none" stroke="#000000" stroke-width="5" cx="80" cy="80" r="50"/>
+</svg>
diff --git a/gnomine-clutter/data/themes/tango/theme.js b/gnomine-clutter/data/themes/tango/theme.js
new file mode 100644
index 0000000..e87489f
--- /dev/null
+++ b/gnomine-clutter/data/themes/tango/theme.js
@@ -0,0 +1,138 @@
+cairo = imports.cairo;
+Clutter = imports.gi.Clutter;
+ThemeLoader = imports.ThemeLoader;
+Gtk = imports.gi.Gtk;
+
+var name = "Tango";
+var tile_size = 40;
+
+function draw_tile(color)
+{
+	var tile = new Clutter.CairoTexture();
+	tile.set_surface_size(tile_size, tile_size);
+	var context = tile.create();
+	var cr = new cairo.Context.steal(context);
+	
+	var pattern = new cairo.LinearGradient(0,0,0,tile_size);
+	pattern.add_color_stop_rgba(0,
+	                            color.red / 255,
+	                            color.green / 255,
+	                            color.blue / 255,
+	                            color.alpha / 255);
+	pattern.add_color_stop_rgba(1,
+	                            color.red / 255 - 0.07,
+	                            color.green / 255 - 0.07,
+	                            color.blue / 255 - 0.07,
+	                            color.alpha / 255);
+	cr.set_source(pattern);
+	
+	cr.new_path();
+	cr.move_to(0, 0);
+	cr.line_to(0, tile_size);
+	cr.line_to(tile_size, tile_size);
+	cr.line_to(tile_size, 0);
+	cr.close_path();
+	cr.fill();
+	
+	cr.set_source_rgba(0.1,0.1,0.1,0.3);
+	
+	cr.new_path();
+	cr.move_to(1, 1);
+	cr.line_to(1, tile_size - 1);
+	cr.line_to(tile_size - 1, tile_size - 1);
+	cr.line_to(tile_size - 1, 1);
+	cr.close_path();
+	cr.stroke();
+	
+	cr.set_source_rgba(0.3,0.3,0.3,0.2);
+	
+	cr.new_path();
+	cr.move_to(2, 2);
+	cr.line_to(2, tile_size - 2);
+	cr.line_to(tile_size - 2, tile_size - 2);
+	cr.line_to(tile_size - 2, 2);
+	cr.close_path();
+	cr.stroke();
+	
+	cr.set_source_rgba(c.red / 255 + 0.07,
+	                   c.green / 255 + 0.07,
+	                   c.blue / 255 + 0.07,
+	                   c.alpha / 255);
+	
+	cr.new_path();
+	cr.move_to(0, 0);
+	cr.line_to(0, tile_size);
+	cr.line_to(tile_size, tile_size);
+	cr.line_to(tile_size, 0);
+	cr.close_path();
+	cr.stroke();
+	
+	cr.destroy();
+	
+	return tile;
+}
+
+function draw_glow(color)
+{
+	var tile = new Clutter.CairoTexture();
+	tile.set_surface_size(tile_size, tile_size);
+	var context = tile.create();
+	var cr = new cairo.Context.steal(context);
+	
+	var pattern = new cairo.LinearGradient(0,0,0,tile_size);
+	pattern.add_color_stop_rgba(0, 1.0, 1.0, 1.0, 0.3);
+	pattern.add_color_stop_rgba(1, 1.0, 1.0, 1.0, 0.1);
+	cr.set_source(pattern);
+	
+	cr.new_path();
+	cr.move_to(0, 0);
+	cr.line_to(0, tile_size);
+	cr.line_to(tile_size, tile_size);
+	cr.line_to(tile_size, 0);
+	cr.close_path();
+	cr.fill();
+	
+	cr.set_source_rgba(1.0,1.0,1.0,0.4);
+	
+	cr.new_path();
+	cr.move_to(3, 3);
+	cr.line_to(3, tile_size - 3);
+	cr.line_to(tile_size - 3, tile_size - 3);
+	cr.line_to(tile_size - 3, 3);
+	cr.close_path();
+	cr.stroke();
+	
+	cr.destroy();
+	
+	return tile;
+}
+
+var gtk_settings = Gtk.Settings.get_default();
+var gtk_color_scheme = gtk_settings.gtk_color_scheme;
+var c = new Clutter.Color();
+c.from_string(gtk_color_scheme.match(/selected_bg_color: (.*)/)[1]);
+
+var tile = { "flipped": draw_tile({red: 200, green: 200, blue: 200, alpha: 255}),
+             "normal": draw_tile(c),
+             "glow": draw_glow() };
+
+var mine = ThemeLoader.load_svg("tango", "mine.svg");
+var bang = ThemeLoader.load_svg("tango", "bang.svg");
+var flag = ThemeLoader.load_svg("tango", "flag.svg");
+
+var number_colors = [
+	{red: 000, green: 000, blue: 000, alpha: 255},	/* Black, not used */
+	{red: 000, green: 000, blue: 255, alpha: 255},	/* Blue */
+	{red: 000, green: 160, blue: 000, alpha: 255},	/* Green */
+	{red: 255, green: 000, blue: 000, alpha: 255},	/* Red */
+	{red: 000, green: 000, blue: 127, alpha: 255},	/* Dark Blue */
+	{red: 160, green: 000, blue: 000, alpha: 255},	/* Dark Red */
+	{red: 000, green: 255, blue: 255, alpha: 255},	/* Cyan */
+	{red: 160, green: 000, blue: 160, alpha: 255},	/* Dark Violet */
+	{red: 000, green: 000, blue: 000, alpha: 255}	/* Black */
+];
+
+
+var loaded = false;
+var textures = [tile.flipped, tile.normal, tile.glow, mine, bang, flag];
+
diff --git a/gnomine-clutter/gnomine-clutter.desktop.in.in b/gnomine-clutter/gnomine-clutter.desktop.in.in
new file mode 100644
index 0000000..54af3a4
--- /dev/null
+++ b/gnomine-clutter/gnomine-clutter.desktop.in.in
@@ -0,0 +1,13 @@
+[Desktop Entry]
+_Name=Mines (Clutter)
+_Comment=Clear hidden mines from a minefield
+Icon=gnome-mines
+Exec=lightsoff
+Terminal=false
+Type=Application
+Categories=GNOME;GTK;Game;LogicGame;
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=gnome-games
+X-GNOME-Bugzilla-Component=BugBuddyBugs
+X-GNOME-Bugzilla-Version= VERSION@
+StartupNotify=false
diff --git a/gnomine-clutter/gnomine-clutter.schemas.in b/gnomine-clutter/gnomine-clutter.schemas.in
new file mode 100644
index 0000000..6b1a95c
--- /dev/null
+++ b/gnomine-clutter/gnomine-clutter.schemas.in
@@ -0,0 +1,18 @@
+<gconfschemafile>
+    <schemalist>    
+
+      <schema>
+        <key>/schemas/apps/gnomine-clutter/theme</key>
+        <applyto>/apps/gnomine-clutter/theme</applyto>
+        <owner>gnomine-clutter</owner>
+        <type>string</type>
+        <default>Tango</default>
+        <locale name="C">
+          <short>The theme to use</short>
+          <long>The title of the tile theme to use.</long>
+        </locale>
+      </schema>
+
+  </schemalist>
+  
+</gconfschemafile>
diff --git a/gnomine-clutter/src/CLIGame.js b/gnomine-clutter/src/CLIGame.js
new file mode 100644
index 0000000..2eb29d9
--- /dev/null
+++ b/gnomine-clutter/src/CLIGame.js
@@ -0,0 +1,66 @@
+readline = imports.readline;
+
+// Create a subclass of Game.Board that adds the CLI interface
+Board.prototype = new imports.Game.Board();
+Board.prototype.constructor = Board;
+function Board(width, height, mines)
+{
+	imports.Game.Board.call(this, width, height, mines);
+}
+
+Board.prototype.game_lost = function()
+{
+	print("YOU LOSE!!");
+	Seed.quit(0);
+}
+
+Board.prototype.game_won = function()
+{
+	print("YOU WIN!!");
+	Seed.quit(0);
+}
+
+Board.prototype.show = function()
+{
+	var h_header = "";
+
+	for(x in this.board)
+	{
+		h_header += "=" + x.toString() + "=";
+	}
+
+	print("|" + h_header + "|");
+
+	for(var y = 0; y < this.height; y++)
+	{
+		var line = "";
+
+		for(var x = 0; x < this.width; x++)
+			line += this.board[x][y];
+		print(y.toString() + line + y.toString());
+	}
+
+	print("|" + h_header + "|");
+	print("");
+};
+
+function main_loop()
+{
+	board = new Board(9,10,10);
+	
+	while(1)
+	{
+		var line = "";
+		var x, y;
+
+		board.show();
+
+		line = readline.readline("x,y: ");
+
+		x = parseInt(line.split(",")[0], 10);
+		y = parseInt(line.split(",")[1], 10);
+
+		if(x >= 0 && x < board.width && y >= 0 && y < board.height)
+			board.flip_tile(x, y);
+	}
+}
diff --git a/gnomine-clutter/src/ClutterGame.js b/gnomine-clutter/src/ClutterGame.js
new file mode 100644
index 0000000..06be6e6
--- /dev/null
+++ b/gnomine-clutter/src/ClutterGame.js
@@ -0,0 +1,76 @@
+Clutter = imports.gi.Clutter;
+GtkClutter = imports.gi.GtkClutter;
+Gtk = imports.gi.Gtk;
+
+Gtk.init(Seed.argv);
+GtkClutter.init(Seed.argv);
+
+ClutterUI = imports.ClutterUI;
+Settings = imports.Settings;
+ThemeLoader = imports.ThemeLoader;
+
+var game_view;
+
+// Create a subclass of Game.Board that adds the Clutter interface
+Board.prototype = new imports.Game.Board();
+Board.prototype.constructor = Board;
+function Board(width, height, mines)
+{
+	imports.Game.Board.call(this, width, height, mines);
+}
+
+Board.prototype.game_lost = function()
+{
+	print("YOU LOSE!!");
+	game_view.update();
+	
+}
+
+Board.prototype.game_won = function()
+{
+	print("YOU WIN!!");
+	game_view.update();
+}
+
+function main_loop()
+{
+	handlers = {
+		//show_settings: Settings.show_settings,
+		//show_about: About.show_about_dialog,
+		show_help: function(selector, ud)
+		{
+			//GnomeGamesSupport.help_display(window, "lightsoff", null);
+		},
+		reset_score: function(selector, ud)
+		{
+			//game.reset_game();
+		},
+		quit: Gtk.main_quit
+	};
+
+	b = new Gtk.Builder();
+	b.add_from_file(imports.Path.file_prefix + "/gnomine.ui");
+	b.connect_signals(handlers);
+	
+	var window = b.get_object("game_window");
+	var clutter_embed = new GtkClutter.Embed();
+	window.signal.hide.connect(Gtk.main_quit);
+	b.get_object("game_vbox").pack_start(clutter_embed, true, true);
+
+	var stage = clutter_embed.get_stage();
+	stage.color = {alpha:255};
+	stage.set_use_fog(false);
+
+	stage.show_all();
+
+	ThemeLoader.load_theme(stage, Settings.theme);
+
+	game_view = new ClutterUI.GameView();
+	stage.add_actor(game_view);
+	stage.set_size(game_view.width, game_view.height);
+	clutter_embed.set_size_request(stage.width, stage.height);
+
+	window.show_all();
+
+	Gtk.main();
+}
diff --git a/gnomine-clutter/src/ClutterUI.js b/gnomine-clutter/src/ClutterUI.js
new file mode 100644
index 0000000..112f4d7
--- /dev/null
+++ b/gnomine-clutter/src/ClutterUI.js
@@ -0,0 +1,258 @@
+Clutter = imports.gi.Clutter;
+ClutterGame = imports.ClutterGame;
+Settings = imports.Settings;
+
+var tile_cols = 12, tile_rows = 12, mines = 10;
+
+var click_timelines = [];
+
+var TileStateNormal = 0,
+    TileStateFlagged = 1,
+    TileStateFlipped = 2,
+    TileStateMine = 3,
+    TileStateWrongFlagged = 4;
+
+TileView = new GType({
+	parent: Clutter.Group.type,
+	name: "TileView",
+	init: function(self)
+	{
+		// Private
+		var state = TileStateNormal;
+		var tex = new Clutter.Clone({source: Settings.theme.tile.normal});
+		var over_tex;
+		var glow_tex = new Clutter.Clone({source: Settings.theme.tile.glow})
+		var num = null;
+		
+		var glow = function(actor)
+		{
+			glow_tex.animate(Clutter.AnimationMode.EASE_OUT_SINE, 350,
+			{
+				opacity: 255
+			});
+			
+			return false;
+		};
+		
+		var unglow = function(actor)
+		{
+			glow_tex.animate(Clutter.AnimationMode.EASE_OUT_SINE, 550,
+			{
+				opacity: 0
+			});
+			
+			return true;
+		};
+		
+		// Public
+		this.rep_tile = null;
+		this.rep_board = null;
+		
+		// Acceptable transitions:
+		// Normal -> Flipped
+		// Normal -> Mine
+		// Normal -> Bang Mine (Flipped Mine)
+		// Normal -> WrongFlagged
+		// Normal -> Flagged
+		// Flagged -> Normal
+		this.update = function()
+		{
+			// Tile was just flipped
+			if(state == TileStateNormal &&
+			   this.rep_tile.is_flipped &&
+			   !this.rep_tile.is_mine)
+			{
+				state = TileStateFlipped;
+				
+				//this.remove_actor(tex);
+				over_tex = new Clutter.Clone({source: Settings.theme.tile.flipped});
+				
+				over_tex.anchor_gravity = Clutter.Gravity.CENTER;
+				over_tex.width = tex.width;
+				over_tex.height = tex.height;
+				over_tex.x = tex.width / 2;
+				over_tex.y = tex.height / 2;
+				this.add_actor(over_tex);
+				over_tex.raise(tex);
+				over_tex.scale_x = over_tex.scale_y = 0.0;
+				over_tex.show();
+				
+				over_tex.animate(Clutter.AnimationMode.EASE_OUT_BACK, 500,
+				{
+					scale_x: 1.0,
+					scale_y: 1.0
+				});
+				
+				var neighbors = this.rep_tile.neighbor_count;
+				var fs = (2/3*Settings.theme.tile_size);
+				
+				if(!num && neighbors)
+				{
+					num = new Clutter.Text({text: neighbors,
+					                        font_name: "Sans " + fs});
+					num.color = Settings.theme.number_colors[neighbors];
+					num.anchor_gravity = Clutter.Gravity.CENTER;
+					num.x = this.width / 2;
+					num.y = this.height / 2;
+					this.add_actor(num);
+					num.scale_x = num.scale_y = 0.0;
+					num.show();
+					
+					num.animate(Clutter.AnimationMode.EASE_OUT_BACK, 500,
+					{
+						scale_x: 1.0,
+						scale_y: 1.0
+					});
+				}
+			}
+			
+			// Tile was just (un)flagged
+			if((state == TileStateNormal && this.rep_tile.is_flagged) ||
+			   (state == TileStateFlagged && !this.rep_tile.is_flagged))
+			{
+				state = this.rep_tile.is_flagged ?
+				            TileStateFlagged :
+				            TileStateNormal;
+				
+				// TODO: animation!
+				
+				if(over_tex)
+				{
+					this.remove_actor(over_tex);
+					over_tex = null;
+				}
+				
+				if(state == TileStateFlagged)
+				{
+					over_tex = new Clutter.Clone({source: Settings.theme.flag});
+					
+					over_tex.anchor_gravity = Clutter.Gravity.CENTER;
+					over_tex.width = (3/4*tex.width);
+					over_tex.height = (3/4*tex.height);
+					over_tex.x = tex.width / 2;
+					over_tex.y = tex.height / 2;
+					this.add_actor(over_tex);
+					over_tex.show();
+				}
+			}
+			
+			// Tile was just flipped and has a mine underneath
+			if(state == TileStateNormal && (this.rep_tile.is_mine &&
+			                                this.rep_board.lost))
+			{
+				state = TileStateMine;
+				
+				// TODO: animation!
+				
+				if(this.rep_tile.is_flipped)
+					over_tex = new Clutter.Clone({source: Settings.theme.bang});
+				else
+					over_tex = new Clutter.Clone({source: Settings.theme.mine});
+					
+				over_tex.anchor_gravity = Clutter.Gravity.CENTER;
+				over_tex.width = (3/4*tex.width);
+				over_tex.height = (3/4*tex.height);
+				over_tex.x = tex.width / 2;
+				over_tex.y = tex.height / 2;
+				this.add_actor(over_tex);
+				over_tex.show();
+			}
+		};
+		
+		// Implementation
+		this.reactive = true;
+		
+		tex.anchor_gravity = Clutter.Gravity.CENTER;
+		tex.x = tex.width / 2;
+		tex.y = tex.height / 2;
+		this.add_actor(tex);
+		tex.show();
+		
+		glow_tex.anchor_gravity = Clutter.Gravity.CENTER;
+		glow_tex.x = glow_tex.width / 2;
+		glow_tex.y = glow_tex.height / 2;
+		glow_tex.opacity = 0;
+		this.add_actor(glow_tex);
+		glow_tex.show();
+		
+		this.signal.enter_event.connect(glow);
+		this.signal.leave_event.connect(unglow);
+	}
+});
+
+GameView = new GType({
+	parent: Clutter.Group.type,
+	name: "GameView",
+	init: function(self)
+	{
+		// Private
+		var rep_board;
+		var tiles = [];
+		
+		var click_tile = function(tile, event, coords)
+		{
+			if(event.button.button == 1)
+			{
+				var update_list = rep_board.flip_tile(coords.x, coords.y);
+				
+				for(d in update_list)
+				{
+					var t = new Clutter.Timeline({duration: d * 50 + 1});
+					t.signal.completed.connect(function (t,ud)
+					{
+						for(i in ud)
+						{
+							ud[i].tile_view.update();
+						}
+					}, update_list[d]);
+					t.start();
+					click_timelines.push(t);
+				}
+			}
+			else if(event.button.button == 3)
+			{
+				tile.rep_tile.is_flagged = !tile.rep_tile.is_flagged;
+				tile.update();
+			}
+			
+			//self.update();
+			
+			return false;
+		};
+		
+		// Public
+		
+		this.update = function()
+		{
+			for(t in tiles)
+			{
+				tiles[t].update();
+			}
+		};
+		
+		// Implementation
+		rep_board = new ClutterGame.Board(tile_cols, tile_rows, mines);
+		
+		for(var x = 0; x < tile_cols; x++)
+		{
+			for(var y = 0; y < tile_rows; y++)
+			{
+				var tile = new TileView();
+				tile.rep_tile = rep_board.board[x][y];
+				tile.rep_board = rep_board;
+				
+				rep_board.board[x][y].tile_view = tile;
+				
+				tile.x = x * (tile.width);
+				tile.y = y * (tile.height);
+				
+				tile.signal.button_release_event.connect(click_tile, {"x":x, "y":y});
+				
+				this.add_actor(tile);
+				tile.show();
+				
+				tiles.push(tile);
+			}
+		}
+	}
+});
diff --git a/gnomine-clutter/src/Game.js b/gnomine-clutter/src/Game.js
new file mode 100644
index 0000000..88a325f
--- /dev/null
+++ b/gnomine-clutter/src/Game.js
@@ -0,0 +1,266 @@
+GLib = imports.gi.GLib;
+
+// Silly faux-oo functions
+
+function abstractFunction()
+{
+	print("This should be implemented in a subclass...");
+}
+
+// Tile constructor
+function Tile(ax, ay)
+{
+	this.x = ax;
+	this.y = ay;
+	this.won = false;
+	this.lost = false;
+	this.is_mine = false;
+	this.is_flagged = false;
+	this.is_flipped = false;
+	this.neighbor_count = -1;
+}
+
+Tile.prototype.toString = function()
+{
+	var inner = "";
+	
+	if(this.is_flagged)
+		inner = "|";
+	else if(this.is_mine)
+		// for debugging : inner = "*";
+		inner = " ";
+	else
+	{
+		if(this.is_flipped && this.neighbor_count != 0)		
+			inner = "" + this.neighbor_count;
+		else
+			inner = " ";
+	}
+
+	if(this.is_flipped)
+		return " " + inner + " ";
+	else
+		return "[" + inner + "]";
+};
+
+// Board constructor
+function Board(width, height, mines)
+{
+	this.board = this.initialize(width, height);
+	this.width = width;
+	this.height = height;
+	this.mines = mines;
+	this.has_mines = false;
+}
+
+Board.prototype.initialize = function(width, height)
+{
+	var board = [];
+
+	// Generate a width * height 2D array of tiles
+	for(var x = width - 1; x >= 0; x--)
+	{
+		board[x] = [];
+		for(var y = height - 1; y >= 0; y--)
+		{
+			board[x].push(new Tile(x, y));
+		}
+	}	
+
+	return board;
+};
+
+// Fill the board with mines
+Board.prototype.create_mines = function(not_x, not_y)
+{
+	for(var i = 0; i < this.mines; i++)
+	{
+		var mined = false;
+
+		while(mined == false)
+		{
+			var tile_x = 0, tile_y = 0;
+			
+			// Don't place a mine on the first-clicked tile!
+			
+			do
+			{
+				tile_x = GLib.random_int_range(0, this.width);
+				tile_y = GLib.random_int_range(0, this.height);
+			} while(tile_x == not_x && tile_y == not_y);
+			
+			var tile = this.board[tile_x][tile_y];
+
+			if(!tile.is_mine)
+			{
+				tile.is_mine = true;
+				mined = true;
+			}
+		}
+	}
+	
+	this.update_neighbors();
+}
+
+// Calculate number of neighboring mines (including diagonals) for each tile
+Board.prototype.update_neighbors = function()
+{
+	for(var x = this.width - 1; x >= 0; x--)
+	{
+		for(var y = this.height - 1; y >= 0; y--)
+		{
+			var neighbor_count = 0;
+
+			if(x + 1 < this.width)
+			{
+				neighbor_count += this.board[x + 1][y].is_mine;
+
+				if(y + 1 < this.height)
+					neighbor_count += this.board[x + 1][y + 1].is_mine;
+				if(y - 1 >= 0)
+					neighbor_count += this.board[x + 1][y - 1].is_mine;
+			}
+			if(x - 1 >= 0)
+			{
+				neighbor_count += this.board[x - 1][y].is_mine;
+
+				if(y + 1 < this.height)
+					neighbor_count += this.board[x - 1][y + 1].is_mine;
+				if(y - 1 >= 0)
+					neighbor_count += this.board[x - 1][y - 1].is_mine;
+			}
+
+			if(y + 1 < this.height)
+				neighbor_count += this.board[x][y + 1].is_mine;
+			if(y - 1 >= 0)
+				neighbor_count += this.board[x][y - 1].is_mine;
+
+			this.board[x][y].neighbor_count = neighbor_count;
+		}
+	}
+}
+
+var flood_fill_accumulator = [];
+
+Board.prototype.flood_fill = function(x, y)
+{
+	if(x < 0 || x >= this.width || y < 0 || y >= this.height)
+		return;
+
+	function _flood_fill_direction(board, x, y)
+	{
+		if(x < 0 || x >= board.width || y < 0 || y >= board.height)
+			return;
+
+		var tile = board.board[x][y];
+
+		if(tile.is_flipped)
+			return;
+
+		tile.is_flipped = true;
+		flood_fill_accumulator.push(tile);
+
+		if(tile.neighbor_count == 0)
+		{
+			board.flood_fill(x, y);
+		}
+	}
+
+	_flood_fill_direction(this, x, y + 1);
+	_flood_fill_direction(this, x, y - 1);
+
+	_flood_fill_direction(this, x + 1, y + 1);
+	_flood_fill_direction(this, x + 1, y);
+	_flood_fill_direction(this, x + 1, y - 1);
+
+	_flood_fill_direction(this, x - 1, y + 1);
+	_flood_fill_direction(this, x - 1, y);
+	_flood_fill_direction(this, x - 1, y - 1);
+};
+
+Board.prototype.flip_tile = function(x, y)
+{
+	flood_fill_accumulator = [];
+	
+	if(this.lost || this.won)
+	{
+		print("Trying to make a move on a finished game.");
+		return;
+	}
+	
+	if(!this.has_mines)
+	{
+		this.create_mines(x, y);
+		this.has_mines = true;
+	}
+
+	var tile = this.board[x][y];
+	
+	if(tile.is_flagged)
+		return;
+	
+	// If the tile is a mine, you've lost, no two ways about it
+	if(tile.is_mine)
+	{
+		tile.is_flipped = true;
+		this.lost = true;
+		this.game_lost();
+		return;
+	}
+
+	// If the tile has no neighbors, flood fill outwards in
+	// all directions (including diagonals), flipping tiles
+	// which also have no neighbors and flipping the last tile
+	// (which has a neighbor) in each direction.
+	if(tile.neighbor_count == 0)
+	{
+		update_list = this.flood_fill(x, y);
+	}
+
+	tile.is_flipped = true;
+
+	if(this.check_if_won())
+	{
+		this.won = true;
+		this.game_won();
+	}
+	
+	// Return the list of tiles to update, in an object, indexed by distance
+	// from the clicked tile!
+	flood_fill_accumulator.push(tile);
+	
+	var update_tiles = {};
+	
+	for(i in flood_fill_accumulator)
+	{
+		var t = flood_fill_accumulator[i];
+		var dist = Math.floor(Math.sqrt(Math.pow(t.x - tile.x, 2) +
+		                                Math.pow(t.y - tile.y, 2)));
+		
+		if(!update_tiles[dist])
+			update_tiles[dist] = [];
+		
+		update_tiles[dist].push(t);
+	}
+
+	return update_tiles;
+};
+
+Board.prototype.game_lost = function()
+{
+	abstractFunction();
+};
+
+Board.prototype.game_won = function()
+{
+	abstractFunction();
+};
+
+Board.prototype.check_if_won = function()
+{
+	for(x in this.board)
+		for(y in this.board[x])
+			if(!this.board[x][y].is_mine && !this.board[x][y].is_flipped)
+				return false;
+	return true;
+};
diff --git a/gnomine-clutter/src/Path.js.in b/gnomine-clutter/src/Path.js.in
new file mode 100644
index 0000000..5244d50
--- /dev/null
+++ b/gnomine-clutter/src/Path.js.in
@@ -0,0 +1 @@
+file_prefix = '@prefix@' + "/share/gnome-games/gnomine-clutter/";
diff --git a/gnomine-clutter/src/Settings.js b/gnomine-clutter/src/Settings.js
new file mode 100644
index 0000000..469f4ba
--- /dev/null
+++ b/gnomine-clutter/src/Settings.js
@@ -0,0 +1,6 @@
+ThemeLoader = imports.ThemeLoader;
+
+var theme, themes;
+
+themes = ThemeLoader.load_themes();
+theme = themes["Tango"];
diff --git a/gnomine-clutter/src/ThemeLoader.js b/gnomine-clutter/src/ThemeLoader.js
new file mode 100644
index 0000000..2a18964
--- /dev/null
+++ b/gnomine-clutter/src/ThemeLoader.js
@@ -0,0 +1,38 @@
+Clutter = imports.gi.Clutter;
+Gio = imports.gi.Gio;
+
+function load_svg(theme, file)
+{
+	var tx = new Clutter.Texture({filename: imports.Path.file_prefix + "/themes/"
+	                                        + theme + "/" + file});
+	tx.filter_quality = Clutter.TextureQuality.HIGH;
+	tx.hide();
+	return tx;
+}
+
+function load_theme(stage, theme)
+{
+	if(theme.loaded)
+		return;
+	
+	theme.loaded = true;
+
+	for(actor in theme.textures)
+		stage.add_actor(theme.textures[actor]);
+}
+
+function load_themes()
+{
+	themes = {};
+	
+	file = Gio.file_new_for_path(imports.Path.file_prefix + "/themes");
+	enumerator = file.enumerate_children("standard::name");
+	
+	while((child = enumerator.next_file()))
+	{
+		var c_theme = imports.themes[child.get_name()].theme;
+		themes[c_theme.name] = c_theme;
+	}
+	
+	return themes;
+}
diff --git a/gnomine-clutter/src/gnomine-clutter.in b/gnomine-clutter/src/gnomine-clutter.in
new file mode 100644
index 0000000..07912ca
--- /dev/null
+++ b/gnomine-clutter/src/gnomine-clutter.in
@@ -0,0 +1,5 @@
+#!/usr/bin/env sh
+
+export LD_LIBRARY_PATH= prefix@/lib/gnome-games:$LD_LIBRARY_PATH
+/usr/bin/env seed @prefix@/share/gnome-games/gnomine-clutter/main.js
+
diff --git a/gnomine-clutter/src/main.js b/gnomine-clutter/src/main.js
new file mode 100755
index 0000000..929d40a
--- /dev/null
+++ b/gnomine-clutter/src/main.js
@@ -0,0 +1,8 @@
+#!/usr/bin/env seed
+
+if(Seed.argv[2] == "cli")
+	imports.CLIGame.main_loop();
+else
+	imports.ClutterGame.main_loop();
+
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]