contrib: delete the friendz game
authorAlexis Laferrière <alexis.laf@xymus.net>
Sun, 7 Jan 2018 14:41:31 +0000 (09:41 -0500)
committerAlexis Laferrière <alexis.laf@xymus.net>
Wed, 24 Jan 2018 18:04:24 +0000 (13:04 -0500)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

25 files changed:
contrib/friendz/.gitignore [deleted file]
contrib/friendz/Makefile [deleted file]
contrib/friendz/README.md [deleted file]
contrib/friendz/android/res/raw/music.ogg [deleted file]
contrib/friendz/art/icon.svg [deleted file]
contrib/friendz/assets/background.png [deleted file]
contrib/friendz/assets/bing.wav [deleted file]
contrib/friendz/assets/click.wav [deleted file]
contrib/friendz/assets/deltaforce_font.png [deleted file]
contrib/friendz/assets/duh.wav [deleted file]
contrib/friendz/assets/hitbox.png [deleted file]
contrib/friendz/assets/level.wav [deleted file]
contrib/friendz/assets/logo.png [deleted file]
contrib/friendz/assets/music.ogg [deleted file]
contrib/friendz/assets/tiles2.png [deleted file]
contrib/friendz/assets/whip.wav [deleted file]
contrib/friendz/org.nitlanguage.friendz_android.txt [deleted file]
contrib/friendz/package.ini [deleted file]
contrib/friendz/src/friendz.nit [deleted file]
contrib/friendz/src/friendz_android.nit [deleted file]
contrib/friendz/src/friendz_linux.nit [deleted file]
contrib/friendz/src/grid.nit [deleted file]
contrib/friendz/src/level.nit [deleted file]
contrib/friendz/src/solver.nit [deleted file]
contrib/friendz/src/solver_cmd.nit [deleted file]

diff --git a/contrib/friendz/.gitignore b/contrib/friendz/.gitignore
deleted file mode 100644 (file)
index 1e1503b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-android/
diff --git a/contrib/friendz/Makefile b/contrib/friendz/Makefile
deleted file mode 100644 (file)
index 7b7d953..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-default: linux
-
-linux:
-       mkdir -p bin
-       nitc -o bin/friendz src/friendz_linux.nit
-
-android: android/res/drawable-hdpi/icon.png
-       mkdir -p bin
-       nitc -o bin/friendz.apk src/friendz_android.nit
-
-android-release: android/res/drawable-hdpi/icon.png
-       mkdir -p bin
-       nitc -o bin/friendz.apk src/friendz_android.nit --release
-
-android/res/drawable-hdpi/icon.png: art/icon.svg
-       mkdir -p android/res
-       ../inkscape_tools/bin/svg_to_icons art/icon.svg --android --out android/res/
-
-doc:
-       mkdir -p doc
-       nitdoc -d doc/ src/friendz.nit src/friendz_linux.nit
-
-clean:
-       rm -rf bin/ doc/ android/
diff --git a/contrib/friendz/README.md b/contrib/friendz/README.md
deleted file mode 100644 (file)
index b30803b..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-Chainz of Friendz, a multi-platform puzzle game
-
-# Objectives
-
-Place monsters to create big chains of friends. You cannot add or
-remove monsters on a metal block. Monsters cannot have more that two
-direct friends. You must build one chain for each type of monster.
-
-# Controls
-
-Select a monster in the right pane and click on the board to add or
-remove the monster. Keep the mouse button down on the map to place
-multiple monsters. Click on a monster on a metal block to automatically
-select the monster.
-
-Keyboard shortcuts:
-
-* 1 to 9 : select a monster
-* 0 : eraser
-* q : metal block (editor only)
-
-# Editor
-
-Once the editor is unlocked you can create your own levels.
-
-# Challenge levels
-
-In challenge level you have to place as much as monster as possible.
-
-# Misc
-
-This game was originally developed for the [Casual Gameplay Design Competition
-\#9](http://jayisgames.com/cgdc9).
-
-# Artwork
-
-The artwork was created by Sam Hocevar <sam@zoy.org> for the Monsterz arcade
-puzzle game http://sam.zoy.org/monsterz/
diff --git a/contrib/friendz/android/res/raw/music.ogg b/contrib/friendz/android/res/raw/music.ogg
deleted file mode 100644 (file)
index 8dcfa3b..0000000
Binary files a/contrib/friendz/android/res/raw/music.ogg and /dev/null differ
diff --git a/contrib/friendz/art/icon.svg b/contrib/friendz/art/icon.svg
deleted file mode 100644 (file)
index 3584b06..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="256"
-   height="256"
-   id="svg4386"
-   version="1.1"
-   inkscape:version="0.48.5 r10040"
-   sodipodi:docname="icon.svg">
-  <defs
-     id="defs4388">
-    <radialGradient
-       r="7.7875042"
-       fy="141.32838"
-       fx="106.50102"
-       cy="141.3284"
-       cx="106.50099"
-       gradientTransform="scale(1.02976,0.9711)"
-       gradientUnits="userSpaceOnUse"
-       id="radialGradient8339"
-       xlink:href="#linearGradient5606"
-       inkscape:collect="always" />
-    <linearGradient
-       id="linearGradient5606">
-      <stop
-         id="stop5608"
-         offset="0.0000000"
-         style="stop-color:#000000;stop-opacity:1.0000000;" />
-      <stop
-         id="stop5614"
-         offset="0.20000000"
-         style="stop-color:#000000;stop-opacity:1.0000000;" />
-      <stop
-         id="stop5616"
-         offset="0.30000001"
-         style="stop-color:#ffffff;stop-opacity:1.0000000;" />
-      <stop
-         id="stop5610"
-         offset="1.0000000"
-         style="stop-color:#ffffff;stop-opacity:1.0000000;" />
-    </linearGradient>
-    <filter
-       inkscape:label="Desaturate"
-       x="0"
-       y="0"
-       width="1"
-       height="1"
-       inkscape:menu="Color"
-       inkscape:menu-tooltip="Render in shades of gray by reducing saturation to zero"
-       color-interpolation-filters="sRGB"
-       id="filter3078">
-      <feColorMatrix
-         type="saturate"
-         values="0"
-         id="feColorMatrix3080" />
-    </filter>
-    <filter
-       inkscape:label="Desaturate"
-       x="0"
-       y="0"
-       width="1"
-       height="1"
-       inkscape:menu="Color"
-       inkscape:menu-tooltip="Render in shades of gray by reducing saturation to zero"
-       color-interpolation-filters="sRGB"
-       id="filter3082">
-      <feColorMatrix
-         type="saturate"
-         values="0"
-         id="feColorMatrix3084" />
-    </filter>
-    <filter
-       inkscape:label="Desaturate"
-       x="0"
-       y="0"
-       width="1"
-       height="1"
-       inkscape:menu="Color"
-       inkscape:menu-tooltip="Render in shades of gray by reducing saturation to zero"
-       color-interpolation-filters="sRGB"
-       id="filter3086">
-      <feColorMatrix
-         type="saturate"
-         values="0"
-         id="feColorMatrix3088" />
-    </filter>
-    <filter
-       inkscape:label="Desaturate"
-       x="0"
-       y="0"
-       width="1"
-       height="1"
-       inkscape:menu="Color"
-       inkscape:menu-tooltip="Render in shades of gray by reducing saturation to zero"
-       color-interpolation-filters="sRGB"
-       id="filter3090">
-      <feColorMatrix
-         type="saturate"
-         values="0.71980676328502413"
-         id="feColorMatrix3092" />
-    </filter>
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.98994949"
-     inkscape:cx="76.110583"
-     inkscape:cy="101.8389"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="false"
-     inkscape:window-width="1279"
-     inkscape:window-height="1377"
-     inkscape:window-x="1279"
-     inkscape:window-y="29"
-     inkscape:window-maximized="0" />
-  <metadata
-     id="metadata4391">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(0,-796.36218)">
-    <g
-       inkscape:export-ydpi="72.000000"
-       inkscape:export-xdpi="72.000000"
-       inkscape:export-filename="/home/sam/monsterz/monsterz/tiles.png"
-       transform="matrix(4.2708842,0,0,4.1991018,0.37397342,-2109.743)"
-       id="g8300"
-       style="filter:url(#filter3090)">
-      <g
-         style="stroke:none"
-         inkscape:export-ydpi="72.000000"
-         inkscape:export-xdpi="72.000000"
-         inkscape:export-filename="/home/sam/monsterz/monsterz/test.png"
-         transform="matrix(0.823543,0,0,0.832736,-337.8784,464.3823)"
-         id="g8288">
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="cc"
-           id="path8290"
-           d="M 427.22149,306.26985 C 400,308.61218 417.5,276.66759 427.5,286.11218"
-           style="fill:#01ff03;fill-opacity:1;fill-rule:evenodd" />
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="cc"
-           id="path8292"
-           d="m 467.5,283.61218 c 18.75,-6.25 17.5,28.75 -2.5,18.75"
-           style="fill:#01ff03;fill-opacity:1;fill-rule:evenodd" />
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="ccc"
-           id="path8294"
-           d="M 428.58387,304.20437 C 406.97719,274.86218 485,259.86218 465,302.36218 c 53.75,37.5 -81.25,70 -36.41613,1.84219 z"
-           style="fill:#01ff03;fill-opacity:1;fill-rule:evenodd" />
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="cc"
-           id="path8296"
-           d="m 420,292.36218 c -1.95031,4.4858 0,6.25 1.25,7.5"
-           style="fill:none" />
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="cc"
-           id="path8298"
-           d="m 473.75,289.34798 c 0.60933,3.0142 1.25,4.2642 -1.25,7.44624"
-           style="fill:none" />
-      </g>
-      <path
-         inkscape:connector-curvature="0"
-         sodipodi:nodetypes="ccc"
-         id="path8275"
-         d="m 20,747.36218 c 23.207741,2.5 36.25,-13.75 31.25,-20 -1.25,10 -18.03209,20.56008 -31.25,20 z"
-         style="fill:#000000;fill-opacity:0.1372549;fill-rule:evenodd;stroke:none" />
-      <g
-         id="g8283">
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="ccc"
-           id="path8277"
-           d="M 14.300999,703.00709 C 5.5600809,697.36218 -4.2738645,716.11218 7.5,718.61218 c -5,-5.67209 -2.5,-13.75 6.800999,-15.60509 z"
-           style="fill:#ffffff;fill-opacity:0.41176471;fill-rule:evenodd;stroke:none" />
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="ccc"
-           id="path8279"
-           d="m 45,698.61218 c -13.75,-11.25 -42.5,-0.73064 -28.75,20 -3.75,-12.5 11.25,-25 28.75,-20 z"
-           style="fill:#ffffff;fill-opacity:0.41176471;fill-rule:evenodd;stroke:none" />
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="ccc"
-           id="path8281"
-           d="m 57.5,708.61218 c 1.25,-9.4761 -12.5,-11.25 -10,-4.41905 5.560081,-1.83095 7.321465,0.72043 10,4.41905 z"
-           style="fill:#ffffff;fill-opacity:0.41176471;fill-rule:evenodd;stroke:none" />
-      </g>
-      <g
-         style="fill:none"
-         inkscape:export-ydpi="72.000000"
-         inkscape:export-xdpi="72.000000"
-         inkscape:export-filename="/home/sam/monsterz/monsterz/test.png"
-         transform="matrix(0.823543,0,0,0.832736,-337.8784,464.3823)"
-         id="g7882">
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="cc"
-           id="path7659"
-           d="M 427.22149,306.26985 C 400,308.61218 417.5,276.66759 427.5,286.11218"
-           style="stroke:#000000;stroke-width:3.11108565;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="cc"
-           id="path7661"
-           d="m 467.5,283.61218 c 18.75,-6.25 17.5,28.75 -2.5,18.75"
-           style="stroke:#000000;stroke-width:3.11108565;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="ccc"
-           id="path7657"
-           d="M 428.58387,304.20437 C 406.97719,274.86218 485,259.86218 465,302.36218 c 53.75,37.5 -81.25,70 -36.41613,1.84219 z"
-           style="stroke:#000000;stroke-width:3.11108565;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="cc"
-           id="path7663"
-           d="m 420,292.36218 c -1.95031,4.4858 0,6.25 1.25,7.5"
-           style="stroke:#000000;stroke-width:3.11108565;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
-        <path
-           inkscape:connector-curvature="0"
-           sodipodi:nodetypes="cc"
-           id="path7665"
-           d="m 473.75,289.34798 c 0.60933,3.0142 1.25,4.2642 -1.25,7.44624"
-           style="stroke:#000000;stroke-width:3.11108565;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
-      </g>
-    </g>
-    <g
-       inkscape:export-ydpi="72.000000"
-       inkscape:export-xdpi="72.000000"
-       inkscape:export-filename="/home/sam/monsterz/monsterz/tiles.png"
-       transform="matrix(4.3642738,0,0,-0.17844664,-531.2477,940.61654)"
-       id="g8323"
-       style="filter:url(#filter3090)">
-      <path
-         inkscape:connector-curvature="0"
-         sodipodi:nodetypes="cc"
-         id="path8325"
-         d="M 150.47232,132.96909 150,134.86218"
-         style="fill:none;stroke:#000000;stroke-width:12.36332512;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
-      <path
-         inkscape:connector-curvature="0"
-         sodipodi:nodetypes="cc"
-         id="path8327"
-         d="m 153.75,132.96909 0.47232,1.89309"
-         style="fill:none;stroke:#000000;stroke-width:12.36332512;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
-    </g>
-    <g
-       inkscape:export-ydpi="72.000000"
-       inkscape:export-xdpi="72.000000"
-       inkscape:export-filename="/home/sam/monsterz/monsterz/tiles.png"
-       transform="matrix(4.3642695,0,0,4.3642084,-733.54667,664.62487)"
-       id="g8329"
-       style="filter:url(#filter3090)">
-      <path
-         inkscape:connector-curvature="0"
-         inkscape:export-ydpi="72.000000"
-         inkscape:export-xdpi="72.000000"
-         inkscape:export-filename="/home/sam/monsterz/monsterz/test.png"
-         sodipodi:nodetypes="cc"
-         id="path8331"
-         d="m 191.8115,62.362183 c 2.83835,1.82034 7.56893,1.99609 11.3534,0"
-         style="fill:none;stroke:#ffffff;stroke-width:2.49998164;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.41176471" />
-      <path
-         inkscape:connector-curvature="0"
-         inkscape:export-ydpi="72.000000"
-         inkscape:export-xdpi="72.000000"
-         inkscape:export-filename="/home/sam/monsterz/monsterz/test.png"
-         sodipodi:nodetypes="cc"
-         id="path8333"
-         d="m 193.0615,64.152194 c 2.83835,1.82034 7.56893,1.99609 11.3534,0"
-         style="fill:none;stroke:#000000;stroke-width:2.49998164;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.1372549" />
-      <path
-         inkscape:connector-curvature="0"
-         inkscape:export-ydpi="72.000000"
-         inkscape:export-xdpi="72.000000"
-         inkscape:export-filename="/home/sam/monsterz/monsterz/test.png"
-         sodipodi:nodetypes="cc"
-         id="path8335"
-         d="m 192.5,63.430263 c 2.83835,1.82034 7.56893,1.99609 11.3534,0"
-         style="fill:none;stroke:#000000;stroke-width:2.49998164;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
-    </g>
-    <path
-       inkscape:export-ydpi="72.000000"
-       inkscape:export-xdpi="72.000000"
-       inkscape:export-filename="/home/sam/monsterz/monsterz/tiles.png"
-       transform="matrix(4.2024883,1.3865396,-2.0345896,3.8609453,-52.336063,179.80496)"
-       d="m 115.86819,137.36218 a 6.1977272,6.1227274 0 1 1 -12.39545,0 6.1977272,6.1227274 0 1 1 12.39545,0 z"
-       sodipodi:ry="6.1227274"
-       sodipodi:rx="6.1977272"
-       sodipodi:cy="137.36218"
-       sodipodi:cx="109.67046"
-       id="path8337"
-       style="fill:url(#radialGradient8339);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.49998115999999992;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;filter:url(#filter3090)"
-       sodipodi:type="arc" />
-  </g>
-</svg>
diff --git a/contrib/friendz/assets/background.png b/contrib/friendz/assets/background.png
deleted file mode 100644 (file)
index a21aab4..0000000
Binary files a/contrib/friendz/assets/background.png and /dev/null differ
diff --git a/contrib/friendz/assets/bing.wav b/contrib/friendz/assets/bing.wav
deleted file mode 100644 (file)
index c7cae5b..0000000
Binary files a/contrib/friendz/assets/bing.wav and /dev/null differ
diff --git a/contrib/friendz/assets/click.wav b/contrib/friendz/assets/click.wav
deleted file mode 100644 (file)
index 3d07b83..0000000
Binary files a/contrib/friendz/assets/click.wav and /dev/null differ
diff --git a/contrib/friendz/assets/deltaforce_font.png b/contrib/friendz/assets/deltaforce_font.png
deleted file mode 100644 (file)
index fb6cc4b..0000000
Binary files a/contrib/friendz/assets/deltaforce_font.png and /dev/null differ
diff --git a/contrib/friendz/assets/duh.wav b/contrib/friendz/assets/duh.wav
deleted file mode 100644 (file)
index 054e1fe..0000000
Binary files a/contrib/friendz/assets/duh.wav and /dev/null differ
diff --git a/contrib/friendz/assets/hitbox.png b/contrib/friendz/assets/hitbox.png
deleted file mode 100644 (file)
index bb48006..0000000
Binary files a/contrib/friendz/assets/hitbox.png and /dev/null differ
diff --git a/contrib/friendz/assets/level.wav b/contrib/friendz/assets/level.wav
deleted file mode 100644 (file)
index 2d30b6e..0000000
Binary files a/contrib/friendz/assets/level.wav and /dev/null differ
diff --git a/contrib/friendz/assets/logo.png b/contrib/friendz/assets/logo.png
deleted file mode 100644 (file)
index 6370e2a..0000000
Binary files a/contrib/friendz/assets/logo.png and /dev/null differ
diff --git a/contrib/friendz/assets/music.ogg b/contrib/friendz/assets/music.ogg
deleted file mode 100644 (file)
index 8dcfa3b..0000000
Binary files a/contrib/friendz/assets/music.ogg and /dev/null differ
diff --git a/contrib/friendz/assets/tiles2.png b/contrib/friendz/assets/tiles2.png
deleted file mode 100644 (file)
index 24038a9..0000000
Binary files a/contrib/friendz/assets/tiles2.png and /dev/null differ
diff --git a/contrib/friendz/assets/whip.wav b/contrib/friendz/assets/whip.wav
deleted file mode 100644 (file)
index b907832..0000000
Binary files a/contrib/friendz/assets/whip.wav and /dev/null differ
diff --git a/contrib/friendz/org.nitlanguage.friendz_android.txt b/contrib/friendz/org.nitlanguage.friendz_android.txt
deleted file mode 100644 (file)
index 904dcc5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-Categories:Nit,Games
-License:WTFPL
-Web Site:http://nitlanguage.org
-Source Code:http://nitlanguage.org/nit.git/tree/HEAD:/contrib/friendz
-Issue Tracker:https://github.com/nitlang/nit/issues
-
-Summary:Puzzle game
-Description:
-Connect colored monsters to from bit continuous chains of friends.
-.
diff --git a/contrib/friendz/package.ini b/contrib/friendz/package.ini
deleted file mode 100644 (file)
index 7ef0618..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name=friendz
-tags=game
-maintainer=Jean Privat <jean@pryen.org>
-license=Apache-2.0
-[upstream]
-browse=https://github.com/nitlang/nit/tree/master/contrib/friendz/
-git=https://github.com/nitlang/nit.git
-git.directory=contrib/friendz/
-homepage=http://nitlanguage.org
-issues=https://github.com/nitlang/nit/issues
-apk=http://nitlanguage.org/fdroid/apk/friendz_android.apk
diff --git a/contrib/friendz/src/friendz.nit b/contrib/friendz/src/friendz.nit
deleted file mode 100644 (file)
index 762eb1d..0000000
+++ /dev/null
@@ -1,1669 +0,0 @@
-# Monsterz - Chains of Friends
-#
-# 2010-2014 (c) Jean Privat <jean@pryen.org>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the Do What The Fuck You Want To
-# Public License, Version 2, as published by Sam Hocevar. See
-# http://sam.zoy.org/projects/COPYING.WTFPL for more details.
-
-# Full UI for the game
-module friendz is
-       app_name("ChainZ of FriendZ")
-       app_version(0, 1, git_revision)
-end
-
-import app::audio
-import mnit
-import realtime
-import solver
-import mnit::tileset
-import app::data_store
-
-intrude import grid
-intrude import level
-
-redef class Grid
-       # Zoom level in %
-       # higher means more dense grid
-       var ratio = 100
-
-       # Various grid sizes from large to small (16x16, 12x12, 8x8, 6x6)
-       var ratios: Array[Int] = [200, 150, 100, 75]
-
-       redef fun resize(w,h)
-       do
-               super
-               for r in ratios do
-                       if w*100/r <= 8 and h*100/r <= 8 then self.ratio = r
-               end
-       end
-end
-
-#   * ENTITIES ****************************************************************
-
-# A game entity is something that is displayed and may interact with the player.
-abstract class Entity
-       # The associated game
-       var game: Game
-
-       # X left coordinate (in pixel).
-       var x: Int
-
-       # Y top coordinate (in pixel).
-       var y: Int
-
-       # X right coordinate (in pixel).
-       fun x2: Int do return x + width
-
-       # Y bottom coordinate (in pixel).
-       fun y2: Int do return y + height
-
-       # Width
-       var width: Int
-
-       # Height
-       var height: Int
-
-       # Tool tip text (if any)
-       var over: nullable String = null
-
-       # can the entity intercepts drag ang drop events?
-       var draggable = false
-
-       # Draw function. To implement
-       fun draw(ctx: Display) do end
-
-       # Update function. Called each loop. To implement
-       fun update do end
-
-       # Enter function. Called when the cursor enter in the element. To implement
-       fun enter(ev: Event) do end
-
-       # Click function. Called when the player click in the element.
-       # (or activate it with a shortcut).
-       fun click(ev: Event) do end
-
-       # keyboard shortcut do activate the entity, if any
-       var shortcut: nullable String = null
-
-       # Are events received?
-       var enabled = true
-
-       fun bw: Int do return game.bw
-       fun bh: Int do return game.bh
-
-       # Should the entity be redrawn
-       var dirty = true
-end
-
-# TEXT BUTTONS ***********************************************************/
-
-# Button entity displayed as a simple text.
-# if `over1` is null, then the button is a simple pasive label
-# if `over1` is set but `over2` is null, then the button is a normal button
-# if both `over1` and `over2` arew set, then the button is a toggleable button with two states
-class TextButton
-       super Entity
-       var str: String
-       init(game: Game, str: String, x,y: Int, color: nullable String, over, over2: nullable String)
-       do
-               var w = 10 # TODO
-               super(game, x,y,w,24)
-               self.str = str
-               self.color = color or else "purple"
-               self.over = over
-               self.over1 = over
-               self.over2 = over2
-               self.textx = x
-               if self.toggleable then
-                       self.x -= bw/2 + 4
-               end
-       end
-
-       var color: String
-
-       # The description of the button action
-       var over1: nullable String
-       # The description of the state2 button action
-       var over2: nullable String
-
-       # is the button a two-state button
-       fun toggleable: Bool do return over2 != null
-
-       # is the toggleable button in its second state?
-       var toggled = false
-
-       # ttl for highlighting
-       var ttl = 0
-
-       # position of the start of the text
-       # in a toggleable button, there is space for the mark between `x` and `textx`
-       var textx: Int
-
-       redef fun draw(ctx) do
-               if self.toggleable then
-                       var w
-                       if self.toggled or not self.enabled then w = 6 else w = 7
-                       ctx.blit(game.img2[w,0], self.x, self.y)
-               end
-               var c
-               if self.enabled then c = self.color else c = "gray"
-               var c2= null
-               if self.ttl > 0 then c2 = "rgba(255,255,255,{self.ttl/10})"
-               ctx.textx(self.str, self.textx, self.y, self.height, c, c2)
-               self.width = ctx.measureText(self.str, self.height)
-               if self.toggleable then self.width += bw/2 + 4
-       end
-
-       redef fun update
-       do
-               if game.statusbar.over_what != self and self.ttl > 0 then
-                       self.ttl-=1
-                       self.dirty = true
-               end
-       end
-
-       redef fun enter(ev)
-       do
-               if over1 == null then return
-               if not self.enabled then return
-               game.snd_click.play
-               self.ttl = 10
-               self.dirty = true
-               self.enter2
-       end
-
-       # Called by `enter` do perform additionnal work if the button is active
-       # Specific button should implement this instead of `enter`
-       fun enter2 do end
-
-       redef fun click(ev)
-       do
-               if not self.enabled then
-                       game.snd_bing.play
-               else
-                       if self.toggleable then
-                               self.toggled = not self.toggled
-                               if self.toggled then self.over = self.over2 else self.over = self.over1
-                               game.statusbar.over_txt = self.over
-                       end
-                       game.snd_whip.play
-               end
-               self.click2(ev)
-       end
-
-       # Called by `click` do perform additionnal work if the button is active
-       # Specific button should implement this instead of `click`
-       fun click2(ev: Event) do end
-
-end
-
-# LEVEL BUTTONS ***********************************************************/
-
-# button to play a level in the menu screen
-class LevelButton
-       super Entity
-
-       # The associated level to play
-       var level: Level
-
-       init(l: Level)
-       do
-               self.level = l
-               var i = l.number
-               super(l.game, (i%5)*56 + 54, (i/5)*56 + 55, l.game.bw, l.game.bh)
-
-               self.over = self.level.fullname
-               if self.level.get_state >= l.l_won then
-                       if game.levels[9].get_state >= l.l_won then self.over += " --- {self.level.score}/{self.level.gold}"
-               else if self.level.get_state >= l.l_open then
-                       if game.levels[9].get_state >= l.l_open then self.over +=  " --- ?/{self.level.gold}"
-               end
-               self.enabled = l.get_state >= l.l_open or game.cheated
-       end
-
-       redef fun draw(ctx)
-       do
-               var l = level
-               var s = self.level.get_state
-               var ix = 5 + l.number % 2
-               var iy = 0
-               if s == l.l_disabled then
-                       ix = 3
-                       iy = 3
-               else if s == l.l_open then
-                       ix = 1
-                       iy = 1
-                       ctx.blit(game.img[ix,iy], self.x, self.y)
-                       ix = 0
-                       iy = 0
-               end
-               ctx.blit(game.img[ix,iy], self.x, self.y)
-
-               if s == l.l_gold then
-                       ctx.blit(game.img2[7,0], self.x + bw*5/8, self.y-bh*1/8)
-               end
-               ctx.textx(self.level.name, self.x+5, self.y+5, 24, null, null)
-       end
-
-       redef fun click(ev)
-       do
-               if self.enabled then
-                       game.snd_whip.play
-                       game.play(self.level)
-               else
-                       game.snd_bing.play
-                       game.statusbar.set_tmp("Locked level", "red")
-               end
-       end
-
-end
-
-# ACHIEVEMENTS ************************************************************/
-
-# Achievement (monster-like) button in the menu screen
-class Achievement
-       super Button
-
-       # The number of the achievement (0 is first)
-       var number: Int
-
-       # The name of the achievement
-       var name: String
-
-       init(game: Game, i: Int, name: String)
-       do
-               super(game, 5*56 + 54, i*56 + 55, game.bw, game.bh)
-               self.over = name
-               self.number = i
-               self.name = name
-               var l =  game.levels[number*5+4]
-               enabled = l.get_state >= l.l_won
-               if self.enabled then self.over = name + " (unlocked)" else self.over = name + " (locked)"
-       end
-
-       redef fun draw(ctx)
-       do
-               var w
-               if self.enabled then w = 5 else w = 3
-               ctx.blit(game.img[w,self.number+5], self.x, self.y)
-       end
-
-       redef fun click(ev)
-       do
-               if not self.enabled then
-                       game.snd_bing.play
-                       game.statusbar.set_tmp("Locked achievement!", "red")
-               else
-                       game.snd_whip.play
-                       self.click2(ev)
-               end
-       end
-
-       fun click2(ev: Event) do
-               # TODO
-       end
-end
-
-
-# BOARD (THE GRID) *******************************************************/
-
-# The board game element.
-class Board
-       super Entity
-       init(game: Game)
-       do
-               super(game, game.xpad, game.ypad, 8*game.bw, 8*game.bh)
-               draggable = true
-       end
-
-       redef fun draw(ctx)
-       do
-               var grid = game.grid
-               var bwr = bw*100/grid.ratio
-               var bhr = bh*100/grid.ratio
-               var w = grid.width
-               var h = grid.height
-               if game.selected_button == game.button_size then
-                       bwr = bw/2
-                       bhr = bh/2
-                       w = game.gw
-                       h = game.gh
-               end
-               self.x = game.xpad+(48*8/2)-w*bwr/2
-               self.y = game.ypad+(48*8/2)-h*bhr/2
-               self.width = w*bwr
-               self.height = h*bhr
-               for i in [0..w[ do
-                       for j in [0..h[ do
-                               var t = grid.grid[i][j]
-                               var dx = i * bwr + self.x
-                               var dy = j * bhr + self.y
-                               if (i+j)%2 == 0 then
-                                       ctx.blit_scaled(game.img[5,0], dx, dy, bwr, bhr)
-                               else
-                                       ctx.blit_scaled(game.img[6,0], dx, dy, bwr, bhr)
-                               end
-                               if t.fixed then
-                                       if t.shape != null and not game.editing then
-                                               #ctx.drawImage(game.img, t.shape.x*bw, (2+t.shape.y)*bh, bw, bh, i * bwr + self.x, j * bhr + self.y, bwr, bhr)
-                                               ctx.blit_scaled(game.img[3,3], dx, dy, bwr, bhr)
-                                       else
-                                               ctx.blit_scaled(game.img[3,3], dx, dy, bwr, bhr)
-                                       end
-                               end
-                               if t.kind>0 then
-                                       var m = grid.monsters[t.kind]
-                                       var s = 0
-                                       if t.blink > 0 then s = 1
-                                       if t.nexts > 2 then s = 3
-                                       if t.nexts == 0 then s = 6
-                                       if m.chain then s = 5
-                                       if t.shocked>0 then s = 2
-                                       ctx.blit_scaled(game.img[s,(4+t.kind)], dx, dy, bwr, bhr)
-                               end
-                               #ctx.textx(t.chain_mark.to_s, dx, dy, 20, "", null)
-                       end
-               end
-               if game.selected_button == game.button_size then
-                       var x0 = self.x
-                       var x1 = (grid.width) * bwr - bwr/2 + self.x
-                       var y0 = self.y
-                       var y1 = (grid.height) * bhr - bhr/2 + self.y
-                       ctx.blit_scaled(game.img2[0,0], x0, y0, bwr/2, bhr/2)
-                       ctx.blit_scaled(game.img2[1,0], x1, y0, bwr/2, bhr/2)
-                       ctx.blit_scaled(game.img2[1,1], x1, y1, bwr/2, bhr/2)
-                       ctx.blit_scaled(game.img2[0,1], x0, y1, bwr/2, bhr/2)
-                       ctx.textx("{grid.width}x{grid.height}",self.x + grid.width*bwr/2,self.y+grid.height*bhr/2,20,"orange",null)
-               end
-       end
-
-       redef fun update
-       do
-               var grid = game.grid
-               for i in [0..grid.width[ do
-                       for j in [0..grid.height[ do
-                               var t = grid.grid[i][j]
-                               if t.kind == 0 then continue
-                               if t.blink > 0 then
-                                       t.blink-=1
-                                       self.dirty=true
-                               end
-                               if t.shocked > 0 then
-                                       t.shocked-=1
-                                       self.dirty=true
-                               else if 100.rand == 0 then
-                                       t.blink = 5
-                                       self.dirty=true
-                               end
-                       end
-               end
-       end
-
-       # Last clicked tile
-       # Uded to filter drag events
-       private var last: nullable Tile = null
-
-       redef fun click(ev)
-       do
-               var grid = game.grid
-               var r = grid.ratio
-               if game.selected_button == game.button_size then r = 200
-               var x = ev.game_x * r / bw / 100
-               var y = ev.game_y * r / bh / 100
-               var t = grid.grid[x][y]
-
-               if ev.drag and last == t then return
-               last = t
-
-               if game.selected_button != game.button_size and (x>=grid.width or y>=grid.height) then return
-
-               # print "{ev.game_x},{ev.game_y},{ev.drag} -> {x},{y}:{t}"
-
-               if game.selected_button != null then
-                       game.selected_button.click_board(ev, t)
-               end
-       end
-end
-
-# BUTTONS *****************************************************************/
-
-# A in-game selectable button for monsters or tools
-class Button
-       super Entity
-
-       # The x tile
-       var imgx: Int = 0
-
-       # The y tile
-       var imgy: Int = 0
-
-       # The associated monster tile
-       # >0 for monsters, <=0 for tools
-       var kind = 0
-
-       redef fun draw(ctx)
-       do
-               ctx.blit(game.img[self.imgx, self.imgy], self.x, self.y)
-               if game.selected_button == self then ctx.blit(game.img[0, 0], self.x, self.y)
-       end
-
-       redef fun click(ev)
-       do
-               var sel = game.selected_button
-               if game.selected_button == game.button_size then game.board.dirty=true
-               if sel != null then sel.dirty=true
-               game.selected_button = self
-               game.snd_click.play
-       end
-
-       # Current inputed chain
-       # Used for drag
-       private var chain = new Array[Tile]
-
-       # Board click. Called when the player click on the board with the button selected.
-       fun click_board(ev: Event, t: Tile)
-       do
-               game.score.dirty = true
-               if ev.drag and self.kind>0 and not chain.is_empty then
-                       if self.chain.length >= 2 and self.chain[1] == t then
-                               var t2 = self.chain.shift
-                               game.snd_click.play
-                               if t2.fixed and not game.editing then return
-                               t2.update(0)
-                               return
-                       end
-                       if t.fixed and t.kind == self.kind then
-                               self.chain.unshift(t)
-                               game.snd_click.play
-                               return
-                       end
-                       if (self.chain[0].x - t.x).abs + (self.chain[0].y - t.y).abs != 1 then return
-                       if t.fixed and not game.editing then
-                               game.snd_bing.play
-                               return
-                       end
-                       if t.kind != 0 and t.kind != self.kind then
-                               t.shocked = 5
-                               game.snd_duh.play
-                               return
-                       end
-                       self.chain.unshift(t)
-                       if t.kind == self.kind then return
-                       game.snd_click.play
-                       t.update(self.kind)
-                       return
-               end
-
-               if t.fixed and not game.editing then
-                       if t.kind == 0 then
-                               game.snd_bing.play
-                               return
-                       end
-                       if t.kind != self.kind and not ev.drag then
-                               game.buttons[t.kind].click(ev)
-                               game.buttons[t.kind].chain = [t]
-                       else
-                               self.chain = [t]
-                               game.snd_bing.play
-                       end
-                       return
-               end
-               if t.fixed and game.editing and self == game.button_erase and t.kind == 0 then
-                       t.fixed = false
-                       game.snd_click.play
-                       return
-               end
-
-               var nkind = 0 # the new kind
-               if ev.drag then
-                       # Here we clean
-                       if t.kind == 0 then return
-                       if self.kind != 0 and t.kind != self.kind then
-                               t.shocked = 5
-                               game.snd_duh.play
-                               return
-                       end
-                       nkind = 0
-               else if t.kind != self.kind then
-                       nkind = self.kind
-                       self.chain = [t]
-               else if t.kind != 0 then
-                       nkind = 0
-                       self.chain.clear
-               end
-               if nkind == t.kind then return
-               game.snd_click.play
-               t.update(nkind)
-       end
-end
-
-# A monster button
-class MonsterButton
-       super Button
-
-       # TTL for the monster being angry
-       var angries = 0
-       # TTL for the monster being happy
-       var happy = 0
-       # TTL for the monster being shocked
-       var shocked = 0
-       # TTL for the monster blinking
-       var blink = 0
-
-       init(game: Game, i: Int)
-       do
-               self.game = game
-               var x = 440 + 58 * ((i-1).abs%3)
-               var y = 150 + (bh+5) * ((i-1)/3)
-               super(game, x, y, game.bw, game.bh)
-               if i == 0 then return
-               kind = i
-               imgx = 0
-               imgy = (4+i)
-               over = game.colors[i] + " monster ({i})"
-               shortcut = i.to_s # code for 1 trough 9
-       end
-
-       redef fun click(ev)
-       do
-               super
-               self.shocked = 5
-       end
-
-       redef fun update
-       do
-               if self.happy > 0 then
-                       self.happy-=1
-                       self.dirty=true
-               end
-               if self.shocked > 0 then
-                       self.shocked-=1
-                       self.dirty=true
-               end
-               if self.blink > 0 then
-                       self.blink-=1
-                       self.dirty=true
-               else if 100.rand == 0 then
-                       self.blink = 5
-                       self.dirty=true
-               end
-       end
-
-       redef fun draw(ctx)
-       do
-               var s = self.imgx
-               if self.angries>0 then
-                       s += 3
-               else if self.happy > 5 then
-                       s += 5
-               else if self.shocked > 0 then
-                       s += 5
-               else if self.blink > 0 then
-                       s += 1
-               end
-               ctx.blit(game.img[s, self.imgy], self.x, self.y)
-               if game.selected_button == self then ctx.blit(game.img[0, 0], self.x, self.y)
-       end
-end
-
-# Erase button.
-class EraseButton
-       super Button
-       init(game: Game) do
-               super(game, 440, 92, game.bh, 22+game.bh)
-               imgx = 4
-               imgy = 13
-               kind = 0
-               over = "Eraser (0)"
-               shortcut = "0"
-       end
-end
-
-# Metal (fixed) button.
-class MetalButton
-       super Button
-       init(game: Game)
-       do
-               super(game, 498, 92, game.bh, 20+game.bh)
-               imgx = 3
-               imgy = 3
-               kind = -1
-               over = "Metal block (q)"
-               shortcut = "q"
-       end
-
-       private var fixed = false
-
-       redef fun click_board(ev,t)
-       do
-               if not ev.drag then self.fixed = not t.fixed
-               if t.fixed == self.fixed then return
-               t.fixed = self.fixed
-               game.snd_click.play
-       end
-end
-
-# Resize button.
-class ResizeButton
-       super Button
-
-       init(game: Game)
-       do
-               super(game,556, 92, game.bh, 20+game.bh)
-               kind = -2
-               over = "Resize the grid"
-       end
-
-       redef fun draw(ctx)
-       do
-               for i in [0..3[ do
-                       for j in [0..3[ do
-                               var x = self.x + i*bw/3
-                               var y = self.y + j*bh/3
-                               ctx.blit_scaled(game.img[5+(i+j)%2,0], x, y, bw/3, bh/3)
-                       end
-               end
-               if game.selected_button == self then ctx.blit(game.img[0, 0], self.x, self.y)
-       end
-
-       redef fun click(ev)
-       do
-               if game.selected_button != game.button_size then
-                       super
-               else
-                       game.selected_button = null
-                       game.board.dirty=true
-               end
-       end
-
-       redef fun click_board(evt, t)
-       do
-               var grid = t.grid
-               var w = t.x+1
-               var h = t.y+1
-               if w < 3 or h < 3 then
-                       game.snd_bing.play
-                       game.statusbar.set_tmp("Too small!", "red")
-                       return
-               end
-               var aborts = false
-               for i in [0..grid.width[ do
-                       for j in [0..grid.height[ do
-                               if i>=w or j>=h then
-                                       var t2 = grid.grid[i][j]
-                                       if t2.kind > 0 then
-                                               aborts = true
-                                               t2.shocked = 5
-                                       end
-                               end
-                       end
-               end
-               if aborts then
-                       game.snd_duh.play
-                       game.statusbar.set_tmp("Monsters on the way!", "red")
-                       return
-               end
-               game.snd_click.play
-               grid.resize(w,h)
-       end
-end
-
-# Inactive area used to display the score
-class Score
-       super Entity
-       init(game: Game)
-       do
-               super(game,440,310,199,62)
-       end
-       redef fun draw(ctx)
-       do
-               ctx.textx("MONSTERS: {game.grid.number}",self.x,self.y+1,21,"cyan",null)
-               var level = game.level
-               if level == null then return
-               if level.get_state >= level.l_won then
-                       ctx.textx("BEST: {level.score}",self.x,self.y+22,21,"pink", null)
-               else
-                       ctx.textx("BEST: -",self.x,self.y+22,21,"pink", null)
-               end
-               if game.levels[9].get_state >= level.l_won then
-                       if level.is_challenge then
-                               ctx.textx("GOAL: {level.gold}",self.x,self.y+44,21,"yellow",null)
-                       else
-                               ctx.textx("GOLD: {level.gold}",self.x,self.y+44,21,"yellow",null)
-                       end
-               end
-       end
-end
-
-# Status bar element.
-class StatusBar
-       super Entity
-       init(game: Game)
-       do
-               super(game,24, 440, 418-24, 30)
-       end
-
-       # Permanant text, if any
-       var main_txt: nullable String = null
-
-       # Text to display when the cursor if over an entity (`over_what`), if any
-       var over_txt: nullable String = null
-
-       # What is the entity for `over_txt`
-       var over_what: nullable Entity
-
-       # Text to temporally display, for some game event, if any
-       var tmp_txt: nullable String = null
-
-       # time-to-live for the `tmp_txt`
-       var tmp_txt_ttl = 0
-
-       # Color used to display `tmp_txt`
-       var tmp_txt_color: nullable String = null
-
-       # reset the status
-       fun clear do
-               self.main_txt = null
-               self.over_txt = null
-               self.tmp_txt = null
-               self.over = null
-       end
-
-       # set a temporary text
-       fun set_tmp(txt, color: String)
-       do
-               print "***STATUS** {txt}"
-               self.tmp_txt = txt
-               self.tmp_txt_ttl = 60
-               self.tmp_txt_color = color
-       end
-
-       redef fun draw(ctx)
-       do
-               var tmp_txt = self.tmp_txt
-               var over_txt = self.over_txt
-               var main_txt = self.main_txt
-               if tmp_txt != null and self.tmp_txt_ttl>0 then
-                       ctx.textx(tmp_txt,24,442,24,self.tmp_txt_color,null)
-               else if over_txt != null then
-                       ctx.textx(over_txt,24,442,24,"yellow",null)
-               else if main_txt != null then
-                       ctx.textx(main_txt,24,442,24,"white",null)
-               end
-       end
-
-       redef fun update
-       do
-               if self.tmp_txt_ttl>0 then
-                       self.tmp_txt_ttl-=1
-                       self.dirty=true
-               end
-       end
-end
-
-# ************************************************************************/
-
-redef class Display
-       # Display a text
-       fun textx(str: String, x, y, height: Int, color, color2: nullable String)
-       do
-               #var w = measureText(str, height)
-               #rect(x,y,w,height)
-               text(str.to_upper, app.game.font, x, y)
-       end
-
-       # give the width for a giver text
-       fun measureText(str: String, height: Int): Int
-       do
-               var font = app.game.font
-               return str.length * (font.width + font.hspace.to_i)
-       end
-
-       # displays a debug rectangle
-       fun rect(x,y,w,h:Int)
-       do
-               var image = once app.load_image("hitbox.png")
-               blit_scaled(image, x, y, w, h)
-       end
-end
-
-# Simple basic class for event
-class Event
-       # Is a drag event?
-       var drag = false
-       # screen x
-       var offset_x: Int
-       # screen y
-       var offset_y: Int
-       # entity x
-       var game_x = 0
-       # entity y
-       var game_y = 0
-       # key pressed
-       var char_code: String
-end
-
-redef class Game
-       # width of a tile, used for most width reference in the game
-       var bw = 48
-       # height a tile, used for most width reference in the game
-       var bh = 48
-       # x-coordinate of the board (padding)
-       var xpad = 24
-       # y-coordinate of the board (padding)
-       var ypad = 24
-
-       # Load tiles
-
-       # Basic tileset
-       var img = new TileSet(app.load_image("tiles2.png"),48,48)
-
-       # Sub tileset (for marks or other)
-       var img2 = new TileSet(app.load_image("tiles2.png"),24,24)
-
-       # background image
-       var back: Image = app.load_image("background.png")
-
-       # Logo image
-       var logo: Image = app.load_image("logo.png")
-
-       # Font
-       var font = new TileSetFont(app.load_image("deltaforce_font.png"), 16, 17, "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789.:;!?\"'() -,/")
-
-       # DISPLAY *****************************************************************
-
-       # Is the game in editing mode
-       var editing = false
-
-       # The selected button, if any
-       var selected_button: nullable Button = null
-
-       # SOUND
-
-       # Is the music muted?
-       var music_muted: Bool = app.data_store["music_muted"] == true
-
-       # Is the sound effects muted?
-       var sfx_muted: Bool = app.data_store["sfx_muted"] == true
-
-       # The background music resource. */
-       var music = new Music("music.ogg")
-
-       # Click sound
-       var snd_click = new Sound("click.wav")
-
-       # Wining soulf
-       var snd_win = new Sound("level.wav")
-
-       # Shocked sound
-       var snd_duh = new Sound("duh.wav")
-
-       # metal sound
-       var snd_bing = new Sound("bing.wav")
-
-       # transition sound
-       var snd_whip = new Sound("whip.wav")
-
-
-       # INPUT ******************************************************************
-
-       # Current grid edited (if any).
-       var grid_edit: nullable Grid = null
-
-       # Sequence of current entities
-       var entities = new Array[Entity]
-
-       # The current statusbar
-       var statusbar = new StatusBar(self)
-
-       # The grid board
-       var board = new Board(self)
-
-       # The current score board
-       var score = new Score(self)
-
-       # Monster button game elements.
-       var buttons = new Array[MonsterButton]
-
-       # MetalButton
-       var button_wall = new MetalButton(self)
-
-       # EraseButton
-       var button_erase = new EraseButton(self)
-
-       # ResizeButton
-       var button_size = new ResizeButton(self)
-
-       # Cheat mode enabled?
-       var cheated = false
-
-       init
-       do
-               init_buttons
-               entities.clear
-               title
-
-               if not music_muted then music.play
-       end
-
-       # fill `buttons`
-       fun init_buttons
-       do
-               for i in [0..9] do
-                       buttons[i] = new MonsterButton(self, i)
-               end
-       end
-
-       # Play a level in player mode.
-       fun play(l: Level)
-       do
-               save # save the previous level grid
-               level = l
-               grid.load(level.saved_str or else level.str)
-               init_play_menu(false)
-               if level.status != "" then
-                       statusbar.main_txt = level.status
-               else
-                       statusbar.main_txt = level.fullname
-               end
-               var t = new NextLevelButton(self)
-               entities.push(t)
-               run
-       end
-
-       # Play the next level.
-       fun play_next
-       do
-               play(levels[level.number+1])
-       end
-
-
-       # Helper function to initialize all states.
-       # Set up buttons for music and SFX.
-       fun init_game
-       do
-               editing = false
-               solver = null
-               entities.clear
-               entities.push(new MusicButton(self))
-               entities.push(new SFXButton(self))
-               entities.push(new MenuButton(self))
-               statusbar.clear
-               entities.push(statusbar)
-       end
-
-       # Helper function to initialize monster menu entries.
-       fun init_play_menu(full: Bool)
-       do
-               init_game
-               entities.push(board)
-               entities.push(new ResetButton(self))
-               entities.push(button_erase)
-               # Push monster buttons and determine the selected one
-               var sel: nullable Button = null
-               for i in [1..monsters] do
-                       if grid.monsters[i].number > 0 or full then
-                               if selected_button == buttons[i] or sel == null then
-                                       sel = buttons[i]
-                               end
-                               entities.push(buttons[i])
-                       end
-               end
-               selected_button = sel
-               entities.push(score)
-       end
-
-       # Play a arbitrary grid in try mode.
-       fun play_grid(g: Grid)
-       do
-               grid = g
-               init_play_menu(false)
-               statusbar.main_txt = "User level"
-               if grid_edit != null then
-                       entities.push(new EditButton(self))
-               end
-               entities.push(new WonButton(self))
-               run
-       end
-
-       # Launch the editor starting with a grid.
-       fun edit_grid(g: Grid)
-       do
-               grid = g
-               init_play_menu(true)
-               editing = true
-               statusbar.main_txt = "Level editor"
-               if level != null then statusbar.main_txt += ": level "+level.name
-               entities.push(button_wall)
-               entities.push(button_size)
-               entities.push(new TestButton(self))
-               entities.push(new SaveButton(self))
-               entities.push(new LoadButton(self))
-               run
-       end
-
-       # Launch the title screen
-       fun title
-       do
-               init_menu
-               entities.push(new Splash(self))
-               run
-       end
-
-       # Helper function to initialize the menu (and tile) screen
-       fun init_menu
-       do
-               save # save the previous level grid
-               init_game
-               level = null
-               var i = levels.first
-               for l in levels do
-                       i = l
-                       if l.get_state == l.l_open then break
-               end
-               entities.push(new StartButton(self, i))
-       end
-
-       # Launch the menu.
-       fun menu
-       do
-               init_menu
-               var t
-               t = new TextButton(self,"LEVEL SELECT", 120, ypad, "white", null, null)
-               entities.push(t)
-               for i in [0..levels.length[ do
-                       var b = new LevelButton(levels[i])
-                       entities.push(b)
-               end
-               t = new Achievement(self, 0, "Training")
-               entities.push(t)
-               t = new Achievement(self, 1, "Gold")
-               entities.push(t)
-               t = new Achievement(self, 2, "Editor")
-               entities.push(t)
-               t = new Achievement(self, 3, "Challenge")
-               entities.push(t)
-               t = new Achievement(self, 4, "Congraturation")
-               entities.push(t)
-               t = new Achievement(self, 5, "Awesome")
-               entities.push(t)
-               run
-       end
-
-       # Last function called when the lauch state is ready
-       fun run do
-               dirty_all = true
-       end
-
-       # Should all entity redrawn?
-       var dirty_all = true
-
-       # Draw all game entities.
-       fun draw(display: Display) do
-               dirty_all = true
-               if dirty_all then display.blit(back, 0, 0)
-               for g in entities do
-                       if g.dirty or dirty_all then
-                               g.dirty = false
-                               #if g.x2-g.x>0 and g.y2-g.y>0 then ctx.drawImage(back, g.x, g.y, g.x2-g.x, g.y2-g.y, g.x, g.y, g.x2-g.x, g.y2-g.y)
-                               g.draw(display)
-                               #ctx.rect(g.x, g.y, g.width, g.height)
-                       end
-               end
-               var ev = lastev
-               if ev isa Event then
-                       # Cursor, kept for debugging
-                       #display.blit(img[4,0],ev.offset_x-42,ev.offset_y-6)
-               end
-               dirty_all = false
-       end
-
-       # Update all game entities.
-       fun step do
-               if solver != null and not solver_pause then
-                       if solver.run_steps(solver_steps) != null then solver_pause = true
-                       print solver.to_s
-                       if not solver.is_running then solver = null
-               end
-               for g in entities do
-                       g.update
-               end
-       end
-
-       # Return the game entity located at a mouse event.
-       fun get_game_element(ev: Event): nullable Entity
-       do
-               var x = ev.offset_x
-               var y = ev.offset_y
-               for g in entities do
-                       if x>=g.x and x<g.x2 and y>g.y and y<g.y2 then
-                               ev.game_x = x-g.x
-                               ev.game_y = y-g.y
-                               #print "get {g}"
-                               return g
-                       end
-               end
-               return null
-       end
-
-       # The game entlty the mouse went down on
-       var drag: nullable Entity = null
-
-       # Last mouse event. Used to dray the cursor
-       var lastev: nullable Event = null
-
-       # Callback when the mouse is pressed
-       fun onMouseDown(ev: Event) do
-               lastev = ev
-               var g = get_game_element(ev)
-               if g != null then
-                       g.click(ev)
-                       g.dirty = true
-               end
-               drag = g
-       end
-
-       # Callback when the mouse is releassed
-       fun onMouseUp(ev: Event) do
-               drag = null
-       end
-
-       # Callback when the mouse if moved while pressed
-       fun onMouseMove(ev: Event) do
-               lastev = ev
-               var g = get_game_element(ev)
-               if g == null then
-                       statusbar.dirty = true
-                       statusbar.over_txt = null
-                       statusbar.over_what = null
-                       return
-               end
-               if statusbar.over_what != g then
-                       statusbar.dirty = true
-                       var go = g.over
-                       statusbar.over_txt = go
-                       statusbar.over_what = g
-                       g.enter(ev)
-                       if go != null then print "***OVER*** {go}"
-               end
-               # We moved abode a element that accepts drag event
-               if drag == g and g.draggable then
-                       # print "DRAG {g}"
-                       ev.drag = true
-                       g.click(ev)
-                       g.dirty = true
-               end
-       end
-
-       # Current solver, if any
-       var solver: nullable BacktrackSolver[Grid, Action] = null
-
-       # Is the solver paused?
-       var solver_pause = false
-
-       # Number of solver steps played in a single game `update`
-       var solver_steps = 20000
-
-       # Callback when a keyboard event is recieved
-       fun onKeyDown(ev: Event) do
-               var kc = ev.char_code
-               if kc == "e" then
-                       set_tmp("RUN EDITOR")
-                       grid_edit = grid.copy(true)
-                       edit_grid(grid)
-               else if kc == "c" then
-                       if cheated then
-                               set_tmp("CHEAT: OFF")
-                               snd_duh.play
-                               cheated = false
-                       else
-                               set_tmp("CHEAT: ON")
-                               snd_win.play
-                               cheated = true
-                       end
-               else if kc == "s" then
-                       if solver == null then
-                               solver = (new FriendzProblem(grid)).solve
-                               solver_pause = false
-                       else
-                               solver_pause = not solver_pause
-                       end
-                       if solver_pause then
-                               set_tmp("SOLVER: PAUSED")
-                       else
-                               set_tmp("SOLVER: ON")
-                       end
-                       #solver.step
-               else if kc == "d" then
-                       if solver == null then
-                               solver = (new FriendzProblem(grid)).solve
-                               solver_pause = true
-                               set_tmp("SOLVER: ON")
-                       else
-                               solver_pause = true
-                               solver.run_steps(1)
-                               set_tmp("SOLVER: ONE STEP")
-                       end
-               else if kc == "+" then
-                       solver_steps += 100
-                       set_tmp("SOLVER: {solver_steps} STEPS")
-               else if kc == "-" then
-                       solver_steps -= 100
-                       set_tmp("SOLVER: {solver_steps} STEPS")
-               else for g in entities do
-                       if kc == g.shortcut then
-                               g.click(ev)
-                               g.dirty = true
-                       end
-               end
-       end
-
-       fun set_tmp(s: String)
-       do
-               statusbar.set_tmp(s, "cyan")
-       end
-
-       redef fun load_levels
-       do
-               super
-
-               for level in levels do
-                       var score = app.data_store["s{level.str}"]
-                       if score isa Int then
-                               level.score = score
-                       end
-                       var saved_str = app.data_store["g{level.str}"]
-                       if saved_str isa String then
-                               print "LOAD {level.name}: {saved_str}"
-                               level.saved_str = saved_str
-                       end
-               end
-       end
-
-       fun save
-       do
-               var l = level
-               if l != null then
-                       l.save
-               end
-       end
-end
-
-# The spash title image
-class Splash
-       super Entity
-       init(game: Game)
-       do
-               super(game,game.xpad,game.ypad,380,350)
-       end
-       redef fun draw(ctx)
-       do
-               ctx.blit(game.logo, game.xpad, game.ypad)
-       end
-       redef fun click(ev)
-       do
-               game.snd_whip.play
-               game.menu
-       end
-end
-
-class NextLevelButton
-       super TextButton
-       init(game: Game)
-       do
-               super(game, "NEXT LEVEL", 440, 24, "cyan", "Play next level", null)
-               enabled = false
-       end
-
-       redef fun update
-       do
-               var w = game.level.check_won(game.grid)
-               if self.enabled != w then
-                       self.dirty = true
-                       self.enabled = w
-                       if w then
-                               game.snd_win.play
-                               game.statusbar.set_tmp("Level solved!", "cyan")
-                       end
-               end
-       end
-
-       redef fun click(ev)
-       do
-               if not self.enabled then
-                       game.snd_duh.play
-                       var grid = game.grid
-                       var monsters = grid.monsters
-                       var angry = new Array[Tile]
-                       var lonely = new Array[Tile]
-                       var edges = new Array[Tile]
-                       for i in [0..grid.width[ do
-                               for j in [0..grid.height[ do
-                                       var t = grid.grid[i][j]
-                                       if t.kind == 0 then continue
-                                       if t.nexts == 0 then lonely.push(t)
-                                       if t.nexts == 1 and not monsters[t.kind].chain then edges.push(t)
-                                       if t.nexts > 2 then angry.push(t)
-                               end
-                       end
-
-                       var l
-                       if angry.length>0 then
-                               l = angry
-                       else if lonely.length>0 then
-                               l = lonely
-                       else
-                               l = edges
-                       end
-                       for i in l do i.shocked=5
-
-                       if angry.length>0 then
-                               game.statusbar.set_tmp("Angry monsters!", "red")
-                       else if lonely.length>0 then
-                               game.statusbar.set_tmp("Lonely monsters!", "red")
-                       else if not grid.won then
-                               game.statusbar.set_tmp("Unconnected monsters!", "red")
-                       else
-                               game.statusbar.set_tmp("Not enough monsters!", "red")
-                       end
-                       return
-               end
-
-               game.snd_whip.play
-               game.play_next
-       end
-end
-
-class MusicButton
-       super TextButton
-       init(game: Game)
-       do
-               super(game, "MUSIC", 470, 412, "purple", "Mute the music", "Unmute the music")
-               toggled = game.music_muted
-       end
-       redef fun click2(ev)
-       do
-               game.music_muted = self.toggled
-               if game.music_muted then game.music.pause else game.music.play
-               app.data_store["music_muted"] = game.music_muted
-       end
-end
-
-class SFXButton
-       super TextButton
-       init(game: Game)
-       do
-               super(game, "SOUND FX", 470, 382, "purple", "Mute the sound effects", "Unmute the sound effects")
-               toggled = game.sfx_muted
-       end
-
-       redef fun click2(ev)
-       do
-               game.sfx_muted = self.toggled
-               if not game.sfx_muted then game.snd_whip.play # Because the automatic one was muted
-               app.data_store["sfx_muted"] = game.sfx_muted
-       end
-end
-
-class MenuButton
-       super TextButton
-       init(game: Game)
-       do
-               super(game, "MENU", 470, 442, "purple", "Exit to the main menu", null)
-               shortcut = "back"
-       end
-
-       redef fun click2(ev)
-       do
-               game.menu
-       end
-end
-
-class ResetButton
-       super TextButton
-       init(game: Game)
-       do
-               super(game,"RESET", 440, 61, "purple", "Clear the grid",null)
-       end
-
-       var count = 0
-
-       redef fun click2(ev)
-       do
-               self.count += 1
-               if self.count==1 then
-                       game.statusbar.set_tmp("Click again to reset","white")
-               else if self.count==2 then
-                       game.grid.reset(false)
-                       if game.editing then
-                               game.statusbar.set_tmp("Click again to clear all","white")
-                       end
-               else if game.editing then
-                       game.grid.reset(true)
-               end
-               game.dirty_all = true
-       end
-
-       redef fun enter2
-       do
-               self.count = 0
-       end
-end
-
-class EditButton
-       super TextButton
-       init(game: Game)
-       do
-               super(game,"EDIT", 540, 24, "purple", "Return to the editor",null)
-       end
-
-       redef fun click2(ev)
-       do
-               var ge = game.grid_edit
-               assert ge != null
-               game.edit_grid(ge)
-       end
-end
-
-class WonButton
-       super TextButton
-       init(game: Game)
-       do
-               super(game,"WON", 440, 24, "cyan", "", null)
-               enabled = false
-       end
-       redef fun click2(ev)
-       do
-               var ge = game.grid_edit
-               if not self.enabled then
-                       game.statusbar.set_tmp("Solve the level first!", "red")
-               else if ge != null then
-                       game.snd_whip.play
-                       game.edit_grid(ge)
-               else
-                       game.snd_whip.play
-                       game.menu
-               end
-       end
-
-       redef fun update
-       do
-               var w = game.grid.won
-               if self.enabled != w then
-                       self.dirty = true
-                       self.enabled = w
-                       if w then
-                               game.snd_win.play
-                               game.statusbar.set_tmp("Level solved!", "cyan")
-                       end
-               end
-       end
-end
-
-class TestButton
-       super TextButton
-       init(game: Game)
-       do
-               super(game,"TEST", 440, 24, "cyan", "Try to play the level", null)
-       end
-
-       redef fun click2(ev)
-       do
-               game.grid_edit = game.grid
-               game.play_grid(game.grid.copy(false))
-       end
-end
-
-class SaveButton
-       super TextButton
-       init(game: Game)
-       do
-               super(game, "SAVE", 540, 24, "purple", "Save the level", null)
-       end
-
-       redef fun click2(ev)
-       do
-               var res = game.grid.save
-               print "SAVE: {res}"
-       end
-end
-
-class LoadButton
-       super TextButton
-       init(game: Game)
-       do
-               super(game,"LOAD", 540, 61, "purple", "Load an user level", null)
-       end
-
-       redef fun click2(ev)
-       do
-               var grid2 = new Grid(game.gw,game.gh,game.monsters)
-               if grid2.load("") then
-                       game.grid = grid2
-               end
-               game.dirty_all = true
-       end
-end
-
-class ContinueButton
-       super TextButton
-       init(game: Game)
-       do
-               super(game,"CONTINUE", 440, 24, "purple", "Continue playing", null)
-       end
-
-       redef fun click2(ev)
-       do
-               game.play_next
-       end
-end
-
-class StartButton
-       super TextButton
-       var level: Level
-       init(game: Game, level: Level)
-       do
-               self.level = level
-               if level.number == 0 then
-                       super(game,"START", 440, 24, "purple", "Play the first level", null)
-               else
-                       super(game,"CONTINUE", 440, 24, "purple", "Continue from level "+level.name, null)
-               end
-       end
-
-       redef fun click2(ev)
-       do
-               game.play(level)
-       end
-end
-
-#
-
-redef class App
-
-       # The game
-       var game: Game
-
-       # Wanted screen width
-       var screen_width = 640
-
-       # Wanted screen height
-       var screen_height = 480
-
-       redef fun on_create
-       do
-               super
-               game = new Game
-               game.font.hspace = -2
-               if args.length > 0 then
-                       game.play(game.levels[args.first.to_i])
-               end
-               # img loading?
-       end
-
-       redef fun on_pause
-       do
-               super
-               game.save
-       end
-
-       redef fun frame_core(display)
-       do
-               game.step
-               game.draw(display)
-       end
-
-       redef fun input(input_event)
-       do
-               #print input_event
-               if input_event isa QuitEvent then # close window button
-                       quit = true # orders system to quit
-               else if input_event isa PointerEvent then
-                       var ev = new Event(input_event.x.to_i, input_event.y.to_i, "")
-                       if input_event.is_motion then
-                               game.onMouseMove(ev)
-                       else if input_event.pressed then
-                               game.onMouseDown(ev)
-                       else
-                               game.onMouseUp(ev)
-                       end
-                       return true
-               else if input_event isa KeyEvent and input_event.is_down then
-                       var ev = new Event(0, 0, input_event.key_name)
-                       game.onKeyDown(ev)
-                       return true
-               end
-
-               return false
-       end
-end
-
-redef class PointerEvent
-       fun is_motion: Bool do return false
-end
-
-redef class KeyEvent
-       fun key_name: String
-       do
-               var c = to_c
-               if c != null then return c.to_s
-               return "unknown"
-       end
-end
-
-redef class Level
-       # Save the score and grid of the level
-       fun save
-       do
-               app.data_store["s{str}"] = if score > 0 then score else null
-               var saved = game.grid.save
-               saved_str = saved
-               app.data_store["g{str}"] = saved
-               print "SAVE: {name}: {saved}"
-       end
-
-       # The saved player grid (to continue games)
-       var saved_str: nullable String = null
-end
diff --git a/contrib/friendz/src/friendz_android.nit b/contrib/friendz/src/friendz_android.nit
deleted file mode 100644 (file)
index 4f40ca7..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-# Monsterz - Chains of Friends
-#
-# 2010-2014 (c) Jean Privat <jean@pryen.org>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the Do What The Fuck You Want To
-# Public License, Version 2, as published by Sam Hocevar. See
-# http://sam.zoy.org/projects/COPYING.WTFPL for more details.
-
-# android version of the game
-module friendz_android
-
-import friendz
-import mnit::android
-import android::landscape
-
-redef class App
-       # Zoom applied for the device display from the game logic coordinates
-       var zoom = 1.0
-
-       redef fun on_create
-       do
-               super
-               var h = screen_height
-               display.set_viewport(0,0,h*display.width/display.height,h)
-
-               zoom = display.height.to_f / h.to_f
-               default_mediaplayer.looping = true
-       end
-
-       redef fun input(input_event)
-       do
-               if input_event isa KeyEvent then
-                       return false
-               else
-                       return super
-               end
-       end
-end
-
-redef class AndroidPointerEvent
-       redef fun is_motion do return is_move
-
-       redef fun x do return super / app.zoom
-       redef fun y do return super / app.zoom
-end
diff --git a/contrib/friendz/src/friendz_linux.nit b/contrib/friendz/src/friendz_linux.nit
deleted file mode 100644 (file)
index e8ada20..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-# Monsterz - Chains of Friends
-#
-# 2010-2014 (c) Jean Privat <jean@pryen.org>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the Do What The Fuck You Want To
-# Public License, Version 2, as published by Sam Hocevar. See
-# http://sam.zoy.org/projects/COPYING.WTFPL for more details.
-
-# Linux (SDL) version of the game
-module friendz_linux
-
-import friendz
-import mnit::linux
-
-redef class Display
-       redef fun wanted_width do return app.screen_width
-       redef fun wanted_height do return app.screen_height
-end
-
-redef class SDLDisplay
-       redef fun enable_mouse_motion_events do return true
-end
-
-redef class SDLMouseMotionEvent
-       redef fun is_motion do return true
-end
diff --git a/contrib/friendz/src/grid.nit b/contrib/friendz/src/grid.nit
deleted file mode 100644 (file)
index 6f1c883..0000000
+++ /dev/null
@@ -1,571 +0,0 @@
-# Monsterz - Chains of Friends
-#
-# 2010-2014 (c) Jean Privat <jean@pryen.org>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the Do What The Fuck You Want To
-# Public License, Version 2, as published by Sam Hocevar. See
-# http://sam.zoy.org/projects/COPYING.WTFPL for more details.
-
-# Game login on the grid of monsters
-module grid
-
-# Grid of monsters.
-class Grid
-       # width of the current grid
-       var width: Int is noinit
-
-       # maximum width of the grid
-       var max_width: Int
-
-       # height of the current grid
-       var height: Int is noinit
-
-       # maximum height of the grid
-       var max_height: Int
-
-       # nm is the number of monster + 1 for the empty tile
-       var nb_monsters: Int
-
-       # the data grid
-       private var grid = new Array[Array[Tile]]
-
-       init do clear
-
-       # Reinitialize the grid with new empty tiles and monsters info
-       fun clear
-       do
-               self.number = 0
-               self.error = 0
-               self.won = false
-               for i in [0..max_width[ do
-                       self.grid[i] = new Array[Tile]
-                       for j in [0..max_height[ do
-                               var t = new Tile(self, i, j)
-                               self.grid[i][j] = t
-                       end
-               end
-               self.monsters = new Array[MonsterInfo]
-               for i in [0..nb_monsters] do
-                       self.monsters[i] = new MonsterInfo
-               end
-               self.resize(max_width,max_height)
-       end
-
-       # Clear all monsters
-       # if `fixed` is false, fixed monsters remains
-       fun reset(fixed: Bool): Bool
-       do
-               var r = false
-               for i in [0..width[ do
-                       for j in [0..height[ do
-                               var t = self.grid[i][j]
-                               if fixed then t.fixed = false
-                               if not t.fixed and t.kind>0 then
-                                       t.update(0)
-                                       r = true
-                               end
-                       end
-               end
-               return r
-       end
-
-       # Total number of monsters in the grid
-       var number = 0
-
-       # Number of monsters alone or with >=3 next
-       var error = 0
-
-       # information about each kind of monsters
-       var monsters = new Array[MonsterInfo]
-
-       # Last result of win.
-       var won = false
-
-       # Check that the monster of `kind` form a complete chain.
-       # if not null, `t` is used as a starting tile to check the chain
-       fun check_chain(kind: Int, t: nullable Tile): Bool
-       do
-               var m = monsters[kind]
-               if m.angry > 0 or m.lonely > 0 or m.single > 2 then
-                       # easy case for no chain
-                       # print "easy {kind} chain: false"
-                       m.chain = false
-                       return false
-               else
-                       if t == null then
-                               # Search for a starting
-                               for x in [0..width[ do for y in [0..height[ do
-                                       var t2 = get(x,y)
-                                       if t2 == null or t2.kind != kind then continue
-                                       t = t2
-                                       break label found
-                               end label found
-                               if t == null then
-                                       assert m.number == 0
-                                       m.chain = true
-                                       return m.chain
-                               end
-                               # print "get neighbor {t}"
-                       end
-                       assert t.kind == kind
-                       var c = count_chain(t, 1000.rand)
-                       # print "old {kind} chain? {c} / {m.number}"
-                       m.chain = c == m.number
-                       return m.chain
-               end
-       end
-
-       # The total number of monsters connected to the chain of `t`
-       # `mark` is a uniq number used to mark tiles
-       fun count_chain(t: Tile, mark: Int): Int
-       do
-               t.chain_mark = mark
-               var res = 1
-               for i in [-1..1] do
-                       for j in [-1..1] do
-                               if (i==0 and j==0) or (i!=0 and j!=0) then continue
-                               var t2 = get(t.x+i,t.y+j)
-                               if t2 == null then continue
-                               if t2.chain_mark == mark or t2.kind != t.kind then continue
-                               res += count_chain(t2, mark)
-                       end
-               end
-               return res
-       end
-
-       # Resize the grid. Do not touch the content.
-       fun resize(w,h: Int)
-       do
-               self.width = w
-               self.height = h
-       end
-
-       # Try to get the tila at `x`,`y`.
-       # Returns null if the position is out of bound.
-       fun get(x,y: Int): nullable Tile
-       do
-               if x<0 or x>=self.width or y<0 or y>=self.height then return null
-               return self.grid[x][y]
-       end
-
-
-       var fixed_shaped = """[
-       [{x:1,y:0},{x:2,y:0},{x:1,y:1},{x:2,y:1}],
-       [{x:0,y:0},{x:0,y:1},{x:0,y:2}],
-       [{x:1,y:2},{x:2,y:2},{x:3,y:2}],
-       [{x:4,y:1},{x:4,y:2}],
-       [{x:3,y:0},{x:4,y:0}],
-       [{x:3,y:1}]
-       ]"""
-
-       # Set shapes for the fixed blocks.
-       fun metalize
-       do
-               for i in [0..width[ do
-                       for j in [0..height[ do
-                               var t = self.grid[i][j]
-                               if t.fixed then t.shape = null
-                       end
-               end
-               for shape in fixed_shaped.split(",") do
-                       for i in [0..width[ do
-                               for j in [0..height[ do
-                                       var ts = new Array[Tile]
-                                       for l in [0..shape.length[ do
-                                               #var t = self.get(i+shape[l].x-shape[0].x,j+shape[l].y-shape[0].y)
-                                               var t = self.get(i,j)
-                                               if t != null and t.fixed and t.shape == null then ts.push(t)
-                                       end
-                                       if ts.length == shape.length then
-                                               for l in [0..shape.length[ do
-                                                       ts[l].shape = shape[l]
-                                               end
-                                       end
-                               end
-                       end
-               end
-       end
-
-       # Return the serialization of the fixed tiles. */
-       fun save: String
-       do
-               var res = ""
-               var str = ".abcdefghi#ABCDEFGHI"
-               for y in [0..height[ do
-                       var rle = 0
-                       var last: nullable Int = null
-                       for x in [0..width[ do
-                               var t = self.grid[x][y]
-                               var tk = t.kind
-                               if t.fixed then tk += 10
-                               if tk == last and rle<9 then
-                                       rle += 1
-                               else
-                                       if last != null then
-                                               if rle>1 then res += rle.to_s
-                                               res += str.chars[last].to_s
-                                       end
-                                       rle = 1
-                                       last = tk
-                               end
-                       end
-                       if last != null then
-                               if rle>1 then res += rle.to_s
-                               res += str.chars[last].to_s
-                       end
-                       res += "|"
-               end
-               return res
-       end
-
-       # Load a new grid from a seialization.
-       fun load(str: String): Bool
-       do
-               self.clear
-               var l = str.length
-               var x = 0
-               var y = 0
-               var mx = 1
-               var my = 1
-               var rle = 1
-               for i in [0..l[ do
-                       var z = rle
-                       while z > 0 do
-                               z -= 1
-                               rle = 1
-                               var c = str.chars[i]
-                               if c == '|' then
-                                       if x > mx then mx = x
-                                       x = 0
-                                       y += 1
-                               else if c == '.' then
-                                       x += 1
-                               else if c == '#' then
-                                       var t = self.get(x,y)
-                                       assert t != null
-                                       t.fixed = true
-                                       x += 1
-                               else if c >= 'A' and c <= 'I' then
-                                       var t = self.get(x,y)
-                                       assert t != null
-                                       t.update(c.code_point-'A'.code_point+1)
-                                       t.fixed = true
-                                       x += 1
-                               else if c >= 'a' and c <= 'i' then
-                                       var t = self.get(x,y)
-                                       assert t != null
-                                       t.update(c.code_point-'a'.code_point+1)
-                                       x += 1
-                               else if c >= '1' and c <= '9' then
-                                       rle = c.to_i
-                               else
-                                       abort
-                               end
-                       end
-               end
-               if x>0 then y += 1
-               if x > mx then mx = x
-               if y > my then my = y
-               if mx<3 or my<3 or mx>max_width or my>max_height then
-                       return false
-               end
-               self.resize(mx,my)
-               self.metalize
-               return true
-       end
-
-       # A ASCII version of the grid.
-       redef fun to_s: String
-       do
-               var ansicols = once ["37;1","31","36;1","32;1","35;1","33;1","33","34;1","31;1","37"]
-               var b = new FlatBuffer
-               b.append("{width}x{height}\n")
-               for j in [0..height[ do
-                       for i in [0..width[ do
-                               var t = grid[i][j]
-                               var k = t.kind
-                               var c = ' '
-                               if k == 0 then
-                                       if t.fixed then c = '#'
-                               else
-                                       b.add(0x1b.code_point)
-                                       b.add('[')
-                                       b.append ansicols[k]
-                                       c = (k + 'a'.code_point - 1).code_point
-                                       if t.fixed then c = c.to_upper
-                                       b.append("m")
-                               end
-                               b.add(c)
-                               if k != 0 then
-                                       b.add(0x1b.code_point)
-                                       b.append("[0m")
-
-                               end
-                       end
-                       b.append "|\n"
-               end
-               return b.to_s
-       end
-
-       # Return a copy of the current grid.
-       # if (!no_fixed) copy only the fixed tiles.
-       fun copy(no_fixed: Bool): Grid
-       do
-               var g = new Grid(self.max_width, self.max_height, self.nb_monsters)
-               g.resize(width, height)
-               for y in [0..height[ do
-                       for x in [0..width[ do
-                               var t = self.grid[x][y]
-                               if no_fixed or t.fixed then
-                                       var t2 = g.grid[x][y]
-                                       t2.update(t.kind)
-                                       t2.fixed = t.fixed
-                               end
-                       end
-               end
-               g.metalize
-               return g
-       end
-
-       # Internal check of the validity of tile and monster informations
-       fun check_grid
-       do
-               var m2 = new Array[MonsterInfo]
-               for m in [0..nb_monsters] do
-                       m2[m] = new MonsterInfo
-               end
-               for x in [0..width[ do
-                       for y in [0..height[ do
-                               var n = 0
-                               var f = 0
-                               var t = get(x,y)
-                               assert t != null
-                               assert t.x == x
-                               assert t.y == y
-                               var k = t.kind
-                               if k == 0 then continue
-
-                               for i in [-1..1] do
-                                       for j in [-1..1] do
-                                               if i == j or (i != 0 and j != 0) then continue
-                                               var t2 = get(x+i, y+j)
-                                               if t2 == null then continue
-                                               if t2.kind == k then
-                                                       n += 1
-                                               else if t2.kind == 0 and not t2.fixed then
-                                                       f += 1
-                                               end
-                                       end
-                               end
-                               assert n == t.nexts else
-                                       print self
-                                       print "{t} says {t.nexts} nexts, found {n}"
-                               end
-                               #assert f == t.frees else
-
-                               var m = m2[k]
-                               m.number += 1
-                               if n == 0 then
-                                       m.lonely += 1
-                               else if n == 1 then
-                                       m.single += 1
-                               else if n > 2 then
-                                       m.angry += 1
-                               end
-                       end
-               end
-               for m in [1..nb_monsters] do
-                       assert m2[m].number == monsters[m].number
-                       assert m2[m].lonely == monsters[m].lonely
-                       assert m2[m].single == monsters[m].single
-                       assert m2[m].angry == monsters[m].angry
-               end
-       end
-end
-
-# Information about each kind of monsters
-class MonsterInfo
-       # number of monsters of this kind on board
-       var number = 0
-       # number of monsters of this kind to place, -1 if no limit
-       var remains: Int = -1
-       # number of monsters that have exactly 1 next
-       var single = 0
-       # number of monsters that have exactly 0 next
-       var lonely = 0
-       # number of monsters that have 3 or more next
-       var angry = 0
-       # Are all monsters form a wining chain?
-       var chain = false
-end
-
-# A localized tile of a grid, can contain a monster and be fixed.
-class Tile
-       # The grid of the tile.
-       var grid: Grid
-
-       # The x coordinate in the grid (starting from 0).
-       var x: Int
-
-       # The y coordinate in the grid (starting from 0).
-       var y: Int
-
-       # The kind of monster in the grid. 0 means empty.
-       var kind = 0
-
-       # blink time to live (0 means no blinking).
-       var blink = 0
-
-       # shocked time to live (0 means not shocked)
-       var shocked = 0
-
-       # number of neighbors of the same kind.
-       var nexts = 0
-
-       # number of free non fixed next tiles
-       var frees = 0
-
-       # is the tile editable (metal block)
-       var fixed = false
-
-       redef fun to_s
-       do
-               var s
-               if fixed then
-                       s = "#ABCDEFGHI"
-               else
-                       s = ".abcdefghi"
-               end
-               return "\{{x},{y}:{s.chars[kind]}\}"
-       end
-
-       # Shape for metal block
-       var shape: nullable Object = null
-
-       # Flag for `count_chain` computation.
-       private var chain_mark = 0
-
-       # Set a new kind of monster on tile
-       # Return true is the move made the grid unsolvable (bad move)
-       fun update(nkind: Int): Bool
-       do
-               var t = self
-               var g = self.grid
-               var res = false
-               var okind = t.kind
-               if okind == nkind then return false
-
-
-               # First, remove it and update info.
-               if okind > 0 then
-                       var m = g.monsters[okind]
-                       var n = t.nexts
-                       if n > 2 then
-                               g.error -= 1
-                               m.angry -= 1
-                       else if n == 1 then
-                               m.single -= 1
-                       else if n == 0 then
-                               g.error -= 1
-                               m.lonely -= 1
-                       end
-                       m.number -= 1
-                       g.number -= 1
-               end
-               t.nexts = 0
-               t.blink = 5
-               t.frees = 0
-
-               var a_neigbor: nullable Tile = null
-               # update neighbors
-               for i in [-1..1] do
-                       for j in [-1..1] do
-                               if (i==0 and j==0) or (i!=0 and j!=0) then continue
-                               var t2 = g.get(t.x+i,t.y+j)
-                               if t2 == null then continue
-                               if t2.kind == 0 then
-                                       if not t2.fixed then t.frees += 1
-                                       continue
-                               end
-                               var m = g.monsters[t2.kind]
-
-                               if t2.kind == okind then
-                                       if a_neigbor == null then a_neigbor = t2
-                                       # same than old, thus dec neighbors
-                                       t2.nexts -=1
-                                       var n = t2.nexts
-                                       if n == 2 then
-                                               g.error -= 1
-                                               m.angry -= 1
-                                       else if n == 1 then
-                                               m.single += 1
-                                               g.error += 1
-                                       else if n == 0 then
-                                               m.single -= 1
-                                               m.lonely += 1
-                                       end
-                                       # print "+ {t} one less next: {t2} ; +({i}x{j})"
-                               end
-
-                               if t2.kind == nkind then
-                                       # Same than new, thus inc neighbors
-                                       t2.nexts += 1
-                                       t.nexts += 1
-                                       var n = t2.nexts
-                                       if n > 3 then
-                                               res = true
-                                       else if n == 3 then
-                                               g.error += 1
-                                               m.angry += 1
-                                               res = true
-                                       else if n == 2 then
-                                               m.single -= 1
-                                               g.error -= 1
-                                       else if n == 1 then
-                                               m.single += 1
-                                               m.lonely -= 1
-                                       end
-                                       # print "+ {t} one more next: {t2}"
-                               end
-                       end
-               end
-
-               # Add and update neighbors info
-               t.kind = nkind
-               if nkind > 0 then
-                       var m = g.monsters[nkind]
-                       var n = t.nexts
-                       if n > 2 then
-                               g.error += 1
-                               m.angry += 1
-                       else if n == 1 then
-                               m.single += 1
-                               g.error += 1
-                       else if n == 0 then
-                               g.error += 1
-                               m.lonely += 1
-                       end
-                       m.number+=1
-                       g.number+=1
-
-                       g.check_chain(nkind, t)
-               end
-
-               # check if the old kind broke, or create a chain
-               if okind > 0 then
-                       g.check_chain(okind, a_neigbor)
-               end
-
-               # update win status
-               g.won = true
-               for m in g.monsters do
-                       if m.number > 0 and not m.chain then g.won = false
-               end
-
-               #grid.check_grid
-
-               return res
-       end
-end
-
diff --git a/contrib/friendz/src/level.nit b/contrib/friendz/src/level.nit
deleted file mode 100644 (file)
index b09f1f2..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-# Monsterz - Chains of Friends
-#
-# 2010-2014 (c) Jean Privat <jean@pryen.org>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the Do What The Fuck You Want To
-# Public License, Version 2, as published by Sam Hocevar. See
-# http://sam.zoy.org/projects/COPYING.WTFPL for more details.
-
-# Level managment
-module level
-
-import grid
-
-# A level in the game
-class Level
-       # The associated game
-       var game: Game
-
-       init(game: Game, i: Int, code: String)
-       do
-               self.game = game
-               var ls = code.split(";")
-               self.number = i
-               self.str = ls[0]
-               self.gold = ls[1].to_i
-               if ls.length >= 3 then
-                       self.status = ls[2]
-               end
-               self.is_tutorial = i<=4
-               self.is_challenge = i>=25
-               if self.is_tutorial then
-                       self.name = "T{i+1}"
-                       self.fullname = "Tutorial level {i+1}"
-               else if not self.is_challenge then
-                       self.name = (i-4).to_s
-                       self.fullname = "Level {i-4}"
-               else
-                       self.name = "C{i-24}"
-                       self.fullname = "Challenge level {i-24}"
-               end
-       end
-
-       # number the level (0 for first)
-       var number: Int
-
-       # initial grid position
-       var str: String
-
-       # top score to get gold
-       var gold: Int
-
-       # Help message if any
-       var status: String = ""
-
-       # Is the level a tutorial level?
-       var is_tutorial: Bool
-
-       # Is the level a challenge level?
-       var is_challenge: Bool
-
-       # The short name of the level (eg. "T1")
-       var name: String
-
-       # The long name of the level (eg. "Tutorial level 1")
-       var fullname: String
-
-       # The player best wining score.
-       # 0 it not yet won
-       var score = 0
-
-       var l_disabled = 1
-       var l_open = 2
-       var l_won = 3
-       var l_gold = 4
-
-       fun get_state: Int
-       do
-               if self.score == 0 then
-                       if self.number == 0 or game.levels[self.number-1].score > 0 then return l_open
-                       if self.number == 25 and game.levels[19].score > 0 then return l_open else return l_disabled
-               else if self.score < self.gold or not game.levels[9].score > 0 then
-                       return l_won
-               else return l_gold
-       end
-
-       # Returns true if g is a wining condition for the level.
-       fun check_won(g: Grid): Bool
-       do
-               var w = g.won and (not self.is_challenge or g.number >= self.gold)
-               if not w then return false
-               if g.number > self.score then
-                       self.score = g.number
-               end
-               return true
-       end
-end
-
-# main game object
-class Game
-       # Game version
-       var version = "1.99"
-
-       # Names of kind of monsters @constant
-       var colors: Array[nullable String] = [null, "Red", "Cyan", "Green", "Purple", "Yellow", "Orange", "Blue", "Pink", "White"]
-
-       # max grid width
-       var gw = 16
-
-       # max grid height
-       var gh = 16
-
-       # Number of monster kinds (+1 for empty) @constant
-       var monsters = 9
-
-       # The grid to play on
-       var grid = new Grid(gw, gh, monsters)
-
-       # LEVELS ******************************************************************
-
-       # Raw level description
-       var levels_code: Array[String] = [
-       ".3#|A2.A|3#.|;6;Connect two monsters",
-       ".#.|A.#|#.A|;5;Diagonals do not count",
-       "2.A|A#.|2.A|;8;Connect all monsters",
-       "3A.|3.A|2.A.|;10;Only 1 or 2 neighbors",
-       "2.A.|.B.B|2.A.|;12;Build two chains",
-
-       "A.A#|4.|#.#.|A3.|;11",
-       "A2.#A|5.|2.A2.|4.#|4.A|;17",
-       "A2.B2.|.B2.A.|6.|.AB2.B|6.|6.|;36",
-       "A5.|B5.|#.A3.|6.|2.A.B.|.A4.|;26",
-       "8.|BA2.B.A.|2.C.C.B.|6.#.|;29",
-
-       ".B3.B|6.|.#3.#|.C3.B|.#4.|6.|.C3.C|;30",
-       ".A.#4.|.C3.A.E|.A6.|6.C.|8.|2.6#|6.E#|5.C2#|;54",
-       ".A5.A|.A.#3.A|2.#A.#.#|.#.#4.|2.A3.#.|8.|4.A2.A|2.A2.A.#|;37",
-       "AB3.C|2.AC2.|6.|.B.CB.|6.|;30",
-       "AC5#CA|2.#3.#2.|4.#4.|7.#.|5.#.#.|9.|2.G6.|6.2#.|9.|H#F#G#F#H|;72",
-
-       "AG3.C|2.AC2.|6.|.G2.G.|2.C3.|6.|;32",
-       "7.#2.|3.#.#4.|.#8.|7.D2.|2.#.3#3.|2.#3.2#FC|9..|2.2#3.FCD|9..|;71",
-       "2.#A4.|6.B.|.C6.|.A.A.AC.|#7.|5.B2.|8.|#A5.C|;56",
-       "9.3.|8.#3.|2.B.#3.BA2.|2.AC4.DC2.|2.EA8.|8.#3.|.2#3.#5.|7.#4.|2#3.#B5.|5.CD5.|.2#9.|3.E8.|;119",
-       "9.7.|.2#B8#E2#.|.E8.#3.#.|.#3.4#.#.#.#.|.#.#.#4.#.#.#.|.C.#3.2#.#.#.#.|.#.#.4#3.#.#.|.D8.3#.#.|.#.#.4#5.A.|.A5.#2.#.3#.|.3#.#.2#.#2.2#.|.D3.#4.2#2.#.|.#.3#.#.4#.#.|.#5.#6.#.|.3#C6#B3#.|9.7.|;130",
-
-       "8.|.#C2.C#.|.#E2.E#.|8.|8.|.B#2.#A.|.#C2.C#.|8.|8.|.BF2.FA.|.2#2.2#.|8.|8.|.2#2.2#.|.A#2.B#.|8.|;92",
-       ".A9..|D9.F.|7.CA3.|3.E8.|9.2.H|9.2.#|7.G4.|4.BG2.F3.|2.B6.E2.|9.G2.|.H8.C.|8.D3.|;140",
-       "2.F9..|2.C9..|9..C2.|8.AG3.|9.4.|4.2#5.F.|7.E4.#|3.A9.|.G.CF4.C.#.|9.2.E.|;125",
-       "9.HCB|.DH9.|.GC9.|9.3.|4.G7.|3.#8.|9.3.|3.B4.D3.|.G9..|8.#3.|2.C2.2#5.|9.3.|;135",
-       "9.6.A|6.C9.|2.A.B4.E3.#I.|9.I.#4.|9.7.|2.E3.C9.|7.B8.|5.G6.G3.|6.C6.G2.|9..H3.B.|.CH.#5.#2.C2.|4.H3.#3.H3.|.B3.F5.F4.|.D.D4.D5.D.|9.7.|6.C9.|;244",
-
-       "E6.|7.|.F.E.F.|.F.#.E.|.F.E.E.|7.|6.F|;48",
-       "3.2#3.|2.A2.A2.|.C4.C.|8.|3.2#3.|2.A2.A2.|.C4.C.|8.|;56",
-       "3.#3.A4.|5.#6.|3.#5.#2.|.#4.#4.#|4.#7.|#6.#4.|8.#3.|.#9..|.#3.#4.#.|3.2#3.#3.|;74",
-       "2.A7.|2.D7.|2.A4.A2.|2.G4.G2.|2.A4.D2.|2.D7.|2.A7.|2.G7.|2.D7.|2.G7.|;95",
-       "E9.6.|9.H4.#.|9.E2.#3.|9.F2.#2.#|9.3.H2.#|HEF9.3.#|9.7.|6.#9.|6.#2.H3.HEF|.6#2.E6.|9.F6.|5#9.2.|4.#9.#.|.F#3.7#.#.|9.5.#.|9.7.|;225"
-       ]
-
-       # The loaded levels
-       var levels = new Array[Level]
-
-       # Load levels
-       # used duting `init`
-       fun load_levels
-       do
-               # Transform level strings into level objects. */
-               for i in [0..levels_code.length[ do
-                       var l = new Level(self,i, levels_code[i])
-                       levels[i] = l
-               end
-       end
-
-       # The current played level (if any)
-       var level: nullable Level = null
-
-       init
-       do
-               load_levels
-       end
-end
-
diff --git a/contrib/friendz/src/solver.nit b/contrib/friendz/src/solver.nit
deleted file mode 100644 (file)
index 18a8ade..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-# Monsterz - Chains of Friends
-#
-# 2010-2014 (c) Jean Privat <jean@pryen.org>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the Do What The Fuck You Want To
-# Public License, Version 2, as published by Sam Hocevar. See
-# http://sam.zoy.org/projects/COPYING.WTFPL for more details.
-
-# Basic game solver
-module solver
-
-intrude import grid
-import ai::backtrack
-
-# The modelization of the friendzs problem.
-class FriendzProblem
-       super BacktrackProblem[Grid, Action]
-
-       redef var initial_state
-
-       redef fun actions(state, node)
-       do
-               var last_action = node.action
-               if state.won then return null
-               if last_action != null then
-                       var res = state.frees(last_action.tile)
-                       if not res.is_empty or last_action.tile.nexts != 2 then
-                               var a = new Array[Action]
-                               for t in res do a.add t.to_action(last_action.kind)
-                               return a
-                       end
-               end
-               return state.look_start
-       end
-
-       redef fun apply_action(state, action)
-       do
-               action.tile.update(action.kind)
-       end
-
-       redef fun backtrack(state, action)
-       do
-               action.tile.update(0)
-       end
-
-       redef fun is_goal(state)
-       do
-               return state.won
-       end
-end
-
-redef class Grid
-       # Return true if grid accepts kind at tile t.
-       # Accepts means that
-       # * the tile is playble (free and not fixed)
-       # * the new monster will not be angry
-       # * the new monster will not make neighbor angry
-       fun accepts(t: Tile, kind: Int): Bool
-       do
-               var grid = t.grid
-               if t.kind != 0 or t.fixed then return false
-               #if t.x<0 or t.x>=grid.width or t.y<0 or t.y>=grid.height then return false
-               var cpt = 0
-               for i in [-1..1] do
-                       for j in [-1..1] do
-                               if i==0 and j==0 or i!=0 and j!=0 then continue
-                               var x2 = t.x+i
-                               var y2 = t.y+j
-                               if x2<0 or x2>=grid.width or y2<0 or y2>=grid.height then continue
-                               var t2 = grid.grid[x2][y2]
-                               if t2.kind == kind then
-                                       if t2.nexts >= 2 then return false
-                                       cpt += 1
-                                       if cpt>=3 then return false
-                               end
-                       end
-               end
-               return true
-       end
-
-       # Return the list of accepting neighbors of t
-       # see `accepts`
-       fun frees(t: Tile): Array[Tile]
-       do
-               var grid = t.grid
-               var res = new Array[Tile]
-               for i in [-1..1] do
-                       for j in [-1..1] do
-                               if i==0 and j==0 or i!=0 and j!=0 then continue
-                               var x2 = t.x+i
-                               var y2 = t.y+j
-                               if x2<0 or x2>=grid.width or y2<0 or y2>=grid.height then continue
-                               var t2 = grid.grid[x2][y2]
-                               if accepts(t2, t.kind) then res.push(t2)
-                       end
-               end
-               return res
-       end
-
-       # Search free tiles next to lonely monsters
-       fun look_start: Array[Action]
-       do
-               var grid = self
-               var start = new Array[Tile]
-               var min = 1
-               var kind = 0
-
-               for x in [0..grid.width[ do
-                       for y in [0..grid.height[ do
-                               var t = grid.grid[x][y]
-                               var k = t.kind
-                               if k == 0 or grid.monsters[k].chain then continue
-                               var n = t.nexts
-
-                               if n > min then continue
-
-                               var fs = frees(t)
-                               var l = fs.length
-                               if l == 0 then continue
-
-                               if n == 0 then
-                                       if min == 1 or start.length > l then
-                                               start = fs
-                                               kind = k
-                                       end
-                               else if kind == 0 or kind == k then
-                                       start.add_all fs
-                                       kind = k
-                               end
-
-                               min = n
-                       end
-               end
-               var res = new Array[Action]
-               for t in start do
-                       res.add t.to_action(kind)
-               end
-               #print "-------------"
-               #print grid
-               #dump
-               #print "START: {tile} -> {start.join(",")}"
-               #print "-------------"
-               return res
-       end
-
-       # compute and print some metrics about the problem
-       fun size_problem
-       do
-               var grid = self
-               var free = 0
-               for x in [0..grid.width[ do
-                       for y in [0..grid.height[ do
-                               var t = grid.grid[x][y]
-                               if t.kind == 0 and not t.fixed then free += 1
-                       end
-               end
-               print "FREE: {free}"
-               var ms = 0
-               for m in grid.monsters do
-                       if m.number > 0 then ms += 1
-               end
-               print "KINDS: {ms}"
-               print "SIZE: {(ms+1).to_f.pow(free.to_f)}"
-       end
-end
-
-class Action
-       var tile: Tile
-       var kind: Int
-       redef fun to_s do return "{tile}->{kind}"
-end
-
-redef class Tile
-       fun to_action(kind_to_play: Int): Action do return new Action(self, kind_to_play)
-end
diff --git a/contrib/friendz/src/solver_cmd.nit b/contrib/friendz/src/solver_cmd.nit
deleted file mode 100644 (file)
index 5a28c8b..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# Monsterz - Chains of Friends
-#
-# 2010-2014 (c) Jean Privat <jean@pryen.org>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the Do What The Fuck You Want To
-# Public License, Version 2, as published by Sam Hocevar. See
-# http://sam.zoy.org/projects/COPYING.WTFPL for more details.
-
-# Solver of levels on the command-line
-module solver_cmd
-
-import solver
-import level
-
-
-if args.is_empty then
-       print "Usage: solver_cmd levelnumber"
-       exit 0
-end
-var l = args.first.to_i
-var game = new Game
-var g = game.grid
-
-g.load(game.levels[l].str)
-g.size_problem
-
-var p = new FriendzProblem(g)
-var s = p.solve
-while s.is_running do
-       var r = s.run_steps(500000)
-       if r != null then
-               print "WON"
-               break
-       else if s.is_running then
-               print s
-               print g
-       end
-end
-print s
-printn g