packages feed

dow 0.2.5 → 0.2.6

raw patch · 19 files changed

+3033/−3030 lines, 19 filesdep ~elereasetup-changed

Dependency ranges changed: elerea

Files

CHANGES view
@@ -1,22 +1,22 @@-0.2.5 - 140928-* fixed compilation with GLFW-0.5.2.*--0.2.4 - 111122-* adjusted for version 2.5.0 of the library-* moved random number generator into the example--0.2.3 - 110402-* adjusted for version 2.2.0 of the library--0.2.2 - 101203-* removed mtl dependency (which also fixed a crash)--0.2.1 - 100718-* adjusted for version 2 of the library--0.2.0 - 100424-* sanitised enemy movement-* added enter as an alternative fire key--0.1.0 - 100211-* first public version+0.2.5 - 140928
+* fixed compilation with GLFW-0.5.2.*
+
+0.2.4 - 111122
+* adjusted for version 2.5.0 of the library
+* moved random number generator into the example
+
+0.2.3 - 110402
+* adjusted for version 2.2.0 of the library
+
+0.2.2 - 101203
+* removed mtl dependency (which also fixed a crash)
+
+0.2.1 - 100718
+* adjusted for version 2 of the library
+
+0.2.0 - 100424
+* sanitised enemy movement
+* added enter as an alternative fire key
+
+0.1.0 - 100211
+* first public version
LICENSE view
@@ -1,28 +1,28 @@-Copyright (c) 2010, Patai Gergely-All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:--1. Redistributions of source code must retain the above copyright notice,-   this list of conditions and the following disclaimer.--2. Redistributions in binary form must reproduce the above copyright-   notice, this list of conditions and the following disclaimer in the-   documentation and/or other materials provided with the distribution.--3. Neither the name of the author nor the names of its contributors may be-   used to endorse or promote products derived from this software without-   specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE-POSSIBILITY OF SUCH DAMAGE.+Copyright (c) 2010, Patai Gergely
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the author nor the names of its contributors may be
+   used to endorse or promote products derived from this software without
+   specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
README view
@@ -1,12 +1,12 @@-Dungeons of Wor-===============--Dungeons of Wor is a homage to the classic arcade game, Wizard of Wor.-It uses the artwork and levels from the arcade version, but the-gameplay mechanics differ from the original in several ways.--Controls:--  player one and menu - arrows + right control/enter-  player two          - WASD + left control-  quit at any time    - escape+Dungeons of Wor
+===============
+
+Dungeons of Wor is a homage to the classic arcade game, Wizard of Wor.
+It uses the artwork and levels from the arcade version, but the
+gameplay mechanics differ from the original in several ways.
+
+Controls:
+
+  player one and menu - arrows + right control/enter
+  player two          - WASD + left control
+  quit at any time    - escape
Setup.hs view
@@ -1,3 +1,3 @@-import Distribution.Simple--main = defaultMain+import Distribution.Simple
+
+main = defaultMain
data/charset.txt view
@@ -1,443 +1,443 @@- -........-........-........-........-........-........-........-........-........-........--A-...##...-..####..-.######.-.##..##.-.##..##.-.##..##.-.######.-.######.-.##..##.-.##..##.--B-.#####..-.######.-.##..##.-.##..##.-.#####..-.######.-.##..##.-.##..##.-.######.-.#####..--C-..####..-.######.-.##..##.-.##.....-.##.....-.##.....-.##.....-.##..##.-.######.-..####..--D-.#####..-.######.-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.######.-.#####..--E-.######.-.######.-.##.....-.##.....-.#####..-.#####..-.##.....-.##.....-.######.-.######.--F-.######.-.######.-.##.....-.##.....-.#####..-.#####..-.##.....-.##.....-.##.....-.##.....--G-..####..-.######.-.##.....-.##.....-.##.....-.##.###.-.##.###.-.##..##.-.######.-..####..--H-.##..##.-.##..##.-.##..##.-.##..##.-.######.-.######.-.##..##.-.##..##.-.##..##.-.##..##.--I-..####..-..####..-...##...-...##...-...##...-...##...-...##...-...##...-..####..-..####..--J-.....##.-.....##.-.....##.-.....##.-.....##.-.....##.-.##..##.-.##..##.-.######.-..####..--K-.##..##.-.##..##.-.##.###.-.#####..-.####...-.####...-.##.##..-.##.###.-.##..##.-.##..##.--L-.##.....-.##.....-.##.....-.##.....-.##.....-.##.....-.##.....-.##.....-.######.-.######.--M-##....##-###..###-###..###-##.##.##-##.##.##-##....##-##....##-##....##-##....##-##....##--N-.##..##.-.##..##.-.###.##.-.######.-.######.-.##.###.-.##..##.-.##..##.-.##..##.-.##..##.--O-..####..-.######.-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.######.-..####..--P-.#####..-.######.-.##..##.-.##..##.-.######.-.#####..-.##.....-.##.....-.##.....-.##.....--Q-..####..-.######.-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.##.###.-.##..#..-..###.#.--R-.#####..-.######.-.##..##.-.##..##.-.######.-.#####..-.##.###.-.##..##.-.##..##.-.##..##.--S-..####..-.######.-.##..##.-.##.....-.#####..-..#####.-.....##.-.##..##.-.######.-..####..--T-.######.-.######.-...##...-...##...-...##...-...##...-...##...-...##...-...##...-...##...--U-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.######.-..####..--V-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.######.-..####..-..####..-...##...-...##...--W-##....##-##....##-##....##-##.##.##-##.##.##-##.##.##-########-###..###-##....##-##....##--X-.##..##.-.##..##.-.##..##.-.##..##.-..####..-.######.-.##..##.-.##..##.-.##..##.-.##..##.--Y-.##..##.-.##..##.-.######.-..####..-...##...-...##...-...##...-...##...-...##...-...##...--Z-.######.-.######.-.....##.-....###.-...###..-..###...-.###....-.##.....-.######.-.######.--0-..####..-.######.-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.##..##.-.######.-..####..--1-...##...-..###...-...##...-...##...-...##...-...##...-...##...-...##...-..####..-..####..--2-..####..-.######.-.##..##.-.....##.-..#####.-.#####..-.##.....-.##.....-.######.-.######.--3-..####..-.######.-.##..##.-.....##.-...###..-...####.-.....##.-.##..##.-.######.-..####..--4-.##..##.-.##..##.-.##..##.-.##..##.-.######.-.######.-.....##.-.....##.-.....##.-.....##.--5-.#####..-.#####..-.##.....-.##.....-.#####..-.######.-.....##.-.##..##.-.######.-..####..--6-..####..-.#####..-.##.....-.##.....-.#####..-.######.-.##..##.-.##..##.-.######.-..####..--7-.######.-.######.-.....##.-....###.-....##..-...###..-...##...-..###...-..##....-..##....--8-..####..-.######.-.##..##.-.##..##.-..####..-.######.-.##..##.-.##..##.-.######.-..####..--9-..####..-.######.-.##..##.-.##..##.-.######.-..#####.-.....##.-.....##.-..#####.-..####..+ 
+........
+........
+........
+........
+........
+........
+........
+........
+........
+........
+
+A
+...##...
+..####..
+.######.
+.##..##.
+.##..##.
+.##..##.
+.######.
+.######.
+.##..##.
+.##..##.
+
+B
+.#####..
+.######.
+.##..##.
+.##..##.
+.#####..
+.######.
+.##..##.
+.##..##.
+.######.
+.#####..
+
+C
+..####..
+.######.
+.##..##.
+.##.....
+.##.....
+.##.....
+.##.....
+.##..##.
+.######.
+..####..
+
+D
+.#####..
+.######.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.######.
+.#####..
+
+E
+.######.
+.######.
+.##.....
+.##.....
+.#####..
+.#####..
+.##.....
+.##.....
+.######.
+.######.
+
+F
+.######.
+.######.
+.##.....
+.##.....
+.#####..
+.#####..
+.##.....
+.##.....
+.##.....
+.##.....
+
+G
+..####..
+.######.
+.##.....
+.##.....
+.##.....
+.##.###.
+.##.###.
+.##..##.
+.######.
+..####..
+
+H
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.######.
+.######.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+
+I
+..####..
+..####..
+...##...
+...##...
+...##...
+...##...
+...##...
+...##...
+..####..
+..####..
+
+J
+.....##.
+.....##.
+.....##.
+.....##.
+.....##.
+.....##.
+.##..##.
+.##..##.
+.######.
+..####..
+
+K
+.##..##.
+.##..##.
+.##.###.
+.#####..
+.####...
+.####...
+.##.##..
+.##.###.
+.##..##.
+.##..##.
+
+L
+.##.....
+.##.....
+.##.....
+.##.....
+.##.....
+.##.....
+.##.....
+.##.....
+.######.
+.######.
+
+M
+##....##
+###..###
+###..###
+##.##.##
+##.##.##
+##....##
+##....##
+##....##
+##....##
+##....##
+
+N
+.##..##.
+.##..##.
+.###.##.
+.######.
+.######.
+.##.###.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+
+O
+..####..
+.######.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.######.
+..####..
+
+P
+.#####..
+.######.
+.##..##.
+.##..##.
+.######.
+.#####..
+.##.....
+.##.....
+.##.....
+.##.....
+
+Q
+..####..
+.######.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##.###.
+.##..#..
+..###.#.
+
+R
+.#####..
+.######.
+.##..##.
+.##..##.
+.######.
+.#####..
+.##.###.
+.##..##.
+.##..##.
+.##..##.
+
+S
+..####..
+.######.
+.##..##.
+.##.....
+.#####..
+..#####.
+.....##.
+.##..##.
+.######.
+..####..
+
+T
+.######.
+.######.
+...##...
+...##...
+...##...
+...##...
+...##...
+...##...
+...##...
+...##...
+
+U
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.######.
+..####..
+
+V
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.######.
+..####..
+..####..
+...##...
+...##...
+
+W
+##....##
+##....##
+##....##
+##.##.##
+##.##.##
+##.##.##
+########
+###..###
+##....##
+##....##
+
+X
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+..####..
+.######.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+
+Y
+.##..##.
+.##..##.
+.######.
+..####..
+...##...
+...##...
+...##...
+...##...
+...##...
+...##...
+
+Z
+.######.
+.######.
+.....##.
+....###.
+...###..
+..###...
+.###....
+.##.....
+.######.
+.######.
+
+0
+..####..
+.######.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.######.
+..####..
+
+1
+...##...
+..###...
+...##...
+...##...
+...##...
+...##...
+...##...
+...##...
+..####..
+..####..
+
+2
+..####..
+.######.
+.##..##.
+.....##.
+..#####.
+.#####..
+.##.....
+.##.....
+.######.
+.######.
+
+3
+..####..
+.######.
+.##..##.
+.....##.
+...###..
+...####.
+.....##.
+.##..##.
+.######.
+..####..
+
+4
+.##..##.
+.##..##.
+.##..##.
+.##..##.
+.######.
+.######.
+.....##.
+.....##.
+.....##.
+.....##.
+
+5
+.#####..
+.#####..
+.##.....
+.##.....
+.#####..
+.######.
+.....##.
+.##..##.
+.######.
+..####..
+
+6
+..####..
+.#####..
+.##.....
+.##.....
+.#####..
+.######.
+.##..##.
+.##..##.
+.######.
+..####..
+
+7
+.######.
+.######.
+.....##.
+....###.
+....##..
+...###..
+...##...
+..###...
+..##....
+..##....
+
+8
+..####..
+.######.
+.##..##.
+.##..##.
+..####..
+.######.
+.##..##.
+.##..##.
+.######.
+..####..
+
+9
+..####..
+.######.
+.##..##.
+.##..##.
+.######.
+..#####.
+.....##.
+.....##.
+..#####.
+..####..
data/levels.txt view
@@ -1,329 +1,329 @@-"arena"-+---------------------+-|                     |-| +-+ +---+ +---+ +-+ |-|     |         |     |-+ +---+         +---+ +-<                     >-+ +-+             +-+ +-|   |             |   |-| + +-+ +-----+ +-+ + |-| |                 | |-| + +   + +-+ +   + + |-|   |   |     |   |   |-+*+-+---+-----+---+-+*+--"pit"-+---------------------+-|                     |-|                     |-|                     |-+                     +-<                     >-+                     +-|                     |-|                     |-|                     |-|                     |-|                     |-+*+-----------------+*+--"b1"-+-----+---------+-----+-|     |         |     |-| +-+ + +-+ +-+ + +-+ |-| |                 | |-+ + + +---+ +---+ + + +-<   |     | |     |   >-+   | +-+ + + +-+ |   +-|   | |         | |   |-| +-+ + +-+ +-+ + +-+ |-| |       | |       | |-| + +-+ + + + + +-+ + |-|       |     |       |-+*+-----+-----+-----+*+--"b2"-+---------------------+-|                     |-| + + + + + + + + + + |-| | | | | | | | | | | |-+ + + | + | | + | + + +-<     |   | |   |     >-+-+ + +-+ + + +-+ + +-+-|   |             |   |-| + +-+   + +   +-+ + |-| |   |   | |   |   | |-| + + + +-+ +-+ + + + |-|   |             |   |-+*+-+-------------+-+*+--"b3"-+---+-------------+---+-|   |             |   |-| + + +-+ +-+ +-+ + + |-| |   |         |   | |-+ + + | +-+ +-+ | + + +-<   | |   | |   | |   >-+---+ +-+ | | +-+ +---+-|         | |         |-| + +---+ + + +---+ + |-| |                 | |-| + +   + +-+ +   + + |-|   |   |     |   |   |-+*+-+---+-----+---+-+*+--"b4"-+-------+-----+-------+-|       |     |       |-| +---+ + + + + +---+ |-| |       | |       | |-+ + +---+ + + +---+ + +-<   |             |   >-+-+ | + +-+ +-+ + | +-+-|   | |         | |   |-| + + + +-----+ + + + |-| |                 | |-| +   + +-+ +-+ +   + |-|     |         |     |-+*+---+---------+---+*+--"b5"-+-----+---------+-----+-|     |         |     |-| +-+ + +-+ +-+ + +-+ |-|         | |         |-+ +---+ + + + + +---+ +-<       |     |       >-+-+ +-+ + + + + +-+ +-+-|     |   | |   |     |-| +-+ | +-+ +-+ | +-+ |-|     |         |     |-| +-+ + + +-+ + + +-+ |-|       |     |       |-+*+-----+-----+-----+*+--"b6"-+---+-------------+---+-|   |             |   |-| + + +-+ +-+ +-+ + + |-| |                 | |-+ + + +-+ +-+ +-+ + + +-<   |   |     |   |   >-+-+ |   +-+ +-+   | +-+-|   |   |     |   |   |-| + +-+ + +-+ + +-+ + |-| |                 | |-| +   + +-+ +-+ +   + |-|     |         |     |-+*+---+---------+---+*+--"b7"-+-----+---------+-----+-|     |         |     |-| +-+ + +-+ +-+ + +-+ |-| |                 | |-+ + +-+ +-+ +-+ +-+ + +-<   |     | |     |   >-+-+ + + + | | + + + +-+-|     | | | | | |     |-| +-+ + | + + | + +-+ |-|       |     |       |-| +-+ +-+ + + +-+ +-+ |-|         | |         |-+*+-------+-+-------+*+--"b8"-+---------------------+-|                     |-| +-+   +-+ +-+   +-+ |-| |     |     |     | |-+ + +-+ + +-+ + +-+ + +-<   |             |   >-+-+ + + + +-+ + + + +-+-|     | |     | |     |-| +-+ | +-+ +-+ | +-+ |-|     |         |     |-| +-+ + + +-+ + + +-+ |-|       |     |       |-+*+-----+-----+-----+*+--"b9"-+---------------------+-|                     |-| +---+ + +-+ + +---+ |-|       |     |       |-+ +-+ +-+ +-+ +-+ +-+ +-<     |         |     >-+-+ + + +-+ +-+ + + +-+-|   |   |     |   |   |-| +-+ + + + + + + +-+ |-| |   |   | |   |   | |-| + +-+ + + + + +-+ + |-|       |     |       |-+*+-----+-----+-----+*+--"b10"-+-----+---------+-----+-|     |         |     |-| +-+ + +-+ +-+ + +-+ |-|       |     |       |-+ +---+ + +-+ + +---+ +-<                     >-+-+ + + + + + + + + +-+-|   | | | | | | | |   |-| +-+ + | + + | + +-+ |-|       |     |       |-| +-+ + +-+ +-+ + +-+ |-|     |         |     |-+*+---+---------+---+*+--"b11"-+-----+---------+-----+-|     |         |     |-| +-+ | + +-+ + | +-+ |-|     | |     | |     |-+ +-+ + +-+ +-+ + +-+ +-<   |             |   >-+-+ + + + +-+ + + + +-+-|     | |     | |     |-| +---+ + +-+ + +---+ |-|                     |-| +-+   + +-+ +   +-+ |-|       |     |       |-+*+-----+-----+-----+*+--"b12"-+---+-------------+---+-|   |             |   |-| + + +-+ +-+ +-+ + + |-| |   |         |   | |-+ + +-+ + +-+ + +-+ + +-<       |     |       >-+-+ + + | +-+ | + + +-+-|   | | |     | | |   |-| + | + + + + + + | + |-| | |     | |     | | |-| + + + +-+ +-+ + + + |-|     |         |     |-+*+---+---------+---+*+--"w1"-+---------------------+-|                     |-| +     +     +     + |-| |     |     |     | |-+ +-+ +-+ + + +-+ +-+ +-<   |     | |     |   >-+   + +   | |   + +   +-|     |   | |   |     |-| +-+ +-+ + + +-+ +-+ |-| |     |     |     | |-| +     +     +     + |-|                     |-+*+-----------------+*+--"w2"-+---------------------+-|                     |-|       +-+ +-+       |-|       |     |       |-+     +-+     +-+     +-<     |         |     >-+   +-+   + +   +-+   +-|   |     | |     |   |-| +-+   +-+ +-+   +-+ |-|       |     |       |-|     +-+     +-+     |-|                     |-+*+-----------------+*+--"w3"-+---------------------+-|                     |-|   +   +-+ +-+   +   |-|   |     | |     |   |-+ +-+-+ + + + + +-+-+ +-<   |   |     |   |   >-+ + + +-+-+ +-+-+ + + +-| |     |     |     | |-| +-+   +     +   +-+ |-|   |             |   |-|   +---+     +---+   |-|                     |-+*+-----------------+*+--"w4"-+---------------------+-|                     |-| +   + +     + +   + |-| |   | |     | |   | |-+ | + + | + + | + + | +-< | |   | | | |   | | >-+ + | + + | | + + | + +-|   | |   | |   | |   |-|   + | + + + + | +   |-|     | |     | |     |-|     + +     + +     |-|                     |-+*+-----------------+*+--"w5"-+---------------------+-|                     |-| +-+     + +     +-+ |-|   |     | |     |   |-+   | +---+ +---+ |   +-<   | |         | |   >-+ +-+ + +     + + +-+ +-|       |     |       |-|   +---+     +---+   |-|   |             |   |-|   +             +   |-|                     |-+*+-----------------+*+--"w6"-+---------------------+-|                     |-| +-+   + +-+ +   +-+ |-|       |     |       |-+ + +-+ + +-+ + +-+ + +-< |                 | >-+ |   +-+     +-+   | +-| |                 | |-| + +-+ + +-+ + +-+ + |-|       |     |       |-| +-+   + +-+ +   +-+ |-|                     |-+*+-----------------+*+--"w7"-+---------------------+-|                     |-| +-+     + +     +-+ |-|   |     | |     |   |-+   +-+ +-+ +-+ +-+   +-<     | |     | |     >-+     | |     | |     +-|     | |     | |     |-|   +-+ +-+ +-+ +-+   |-|   |     | |     |   |-| +-+     + +     +-+ |-|                     |-+*+-----------------+*+--"w8"-+---------------------+-|                     |-| +-+   +-+ +-+   +-+ |-|   |             |   |-+   +-+   +-+   +-+   +-<     |         |     >-+     +-+     +-+     +-|       |     |       |-|   +   +-+ +-+   +   |-|   |     | |     |   |-|   +     + +     +   |-|                     |-+*+-----------------+*++"arena"
++---------------------+
+|                     |
+| +-+ +---+ +---+ +-+ |
+|     |         |     |
++ +---+         +---+ +
+<                     >
++ +-+             +-+ +
+|   |             |   |
+| + +-+ +-----+ +-+ + |
+| |                 | |
+| + +   + +-+ +   + + |
+|   |   |     |   |   |
++*+-+---+-----+---+-+*+
+
+"pit"
++---------------------+
+|                     |
+|                     |
+|                     |
++                     +
+<                     >
++                     +
+|                     |
+|                     |
+|                     |
+|                     |
+|                     |
++*+-----------------+*+
+
+"b1"
++-----+---------+-----+
+|     |         |     |
+| +-+ + +-+ +-+ + +-+ |
+| |                 | |
++ + + +---+ +---+ + + +
+<   |     | |     |   >
++   | +-+ + + +-+ |   +
+|   | |         | |   |
+| +-+ + +-+ +-+ + +-+ |
+| |       | |       | |
+| + +-+ + + + + +-+ + |
+|       |     |       |
++*+-----+-----+-----+*+
+
+"b2"
++---------------------+
+|                     |
+| + + + + + + + + + + |
+| | | | | | | | | | | |
++ + + | + | | + | + + +
+<     |   | |   |     >
++-+ + +-+ + + +-+ + +-+
+|   |             |   |
+| + +-+   + +   +-+ + |
+| |   |   | |   |   | |
+| + + + +-+ +-+ + + + |
+|   |             |   |
++*+-+-------------+-+*+
+
+"b3"
++---+-------------+---+
+|   |             |   |
+| + + +-+ +-+ +-+ + + |
+| |   |         |   | |
++ + + | +-+ +-+ | + + +
+<   | |   | |   | |   >
++---+ +-+ | | +-+ +---+
+|         | |         |
+| + +---+ + + +---+ + |
+| |                 | |
+| + +   + +-+ +   + + |
+|   |   |     |   |   |
++*+-+---+-----+---+-+*+
+
+"b4"
++-------+-----+-------+
+|       |     |       |
+| +---+ + + + + +---+ |
+| |       | |       | |
++ + +---+ + + +---+ + +
+<   |             |   >
++-+ | + +-+ +-+ + | +-+
+|   | |         | |   |
+| + + + +-----+ + + + |
+| |                 | |
+| +   + +-+ +-+ +   + |
+|     |         |     |
++*+---+---------+---+*+
+
+"b5"
++-----+---------+-----+
+|     |         |     |
+| +-+ + +-+ +-+ + +-+ |
+|         | |         |
++ +---+ + + + + +---+ +
+<       |     |       >
++-+ +-+ + + + + +-+ +-+
+|     |   | |   |     |
+| +-+ | +-+ +-+ | +-+ |
+|     |         |     |
+| +-+ + + +-+ + + +-+ |
+|       |     |       |
++*+-----+-----+-----+*+
+
+"b6"
++---+-------------+---+
+|   |             |   |
+| + + +-+ +-+ +-+ + + |
+| |                 | |
++ + + +-+ +-+ +-+ + + +
+<   |   |     |   |   >
++-+ |   +-+ +-+   | +-+
+|   |   |     |   |   |
+| + +-+ + +-+ + +-+ + |
+| |                 | |
+| +   + +-+ +-+ +   + |
+|     |         |     |
++*+---+---------+---+*+
+
+"b7"
++-----+---------+-----+
+|     |         |     |
+| +-+ + +-+ +-+ + +-+ |
+| |                 | |
++ + +-+ +-+ +-+ +-+ + +
+<   |     | |     |   >
++-+ + + + | | + + + +-+
+|     | | | | | |     |
+| +-+ + | + + | + +-+ |
+|       |     |       |
+| +-+ +-+ + + +-+ +-+ |
+|         | |         |
++*+-------+-+-------+*+
+
+"b8"
++---------------------+
+|                     |
+| +-+   +-+ +-+   +-+ |
+| |     |     |     | |
++ + +-+ + +-+ + +-+ + +
+<   |             |   >
++-+ + + + +-+ + + + +-+
+|     | |     | |     |
+| +-+ | +-+ +-+ | +-+ |
+|     |         |     |
+| +-+ + + +-+ + + +-+ |
+|       |     |       |
++*+-----+-----+-----+*+
+
+"b9"
++---------------------+
+|                     |
+| +---+ + +-+ + +---+ |
+|       |     |       |
++ +-+ +-+ +-+ +-+ +-+ +
+<     |         |     >
++-+ + + +-+ +-+ + + +-+
+|   |   |     |   |   |
+| +-+ + + + + + + +-+ |
+| |   |   | |   |   | |
+| + +-+ + + + + +-+ + |
+|       |     |       |
++*+-----+-----+-----+*+
+
+"b10"
++-----+---------+-----+
+|     |         |     |
+| +-+ + +-+ +-+ + +-+ |
+|       |     |       |
++ +---+ + +-+ + +---+ +
+<                     >
++-+ + + + + + + + + +-+
+|   | | | | | | | |   |
+| +-+ + | + + | + +-+ |
+|       |     |       |
+| +-+ + +-+ +-+ + +-+ |
+|     |         |     |
++*+---+---------+---+*+
+
+"b11"
++-----+---------+-----+
+|     |         |     |
+| +-+ | + +-+ + | +-+ |
+|     | |     | |     |
++ +-+ + +-+ +-+ + +-+ +
+<   |             |   >
++-+ + + + +-+ + + + +-+
+|     | |     | |     |
+| +---+ + +-+ + +---+ |
+|                     |
+| +-+   + +-+ +   +-+ |
+|       |     |       |
++*+-----+-----+-----+*+
+
+"b12"
++---+-------------+---+
+|   |             |   |
+| + + +-+ +-+ +-+ + + |
+| |   |         |   | |
++ + +-+ + +-+ + +-+ + +
+<       |     |       >
++-+ + + | +-+ | + + +-+
+|   | | |     | | |   |
+| + | + + + + + + | + |
+| | |     | |     | | |
+| + + + +-+ +-+ + + + |
+|     |         |     |
++*+---+---------+---+*+
+
+"w1"
++---------------------+
+|                     |
+| +     +     +     + |
+| |     |     |     | |
++ +-+ +-+ + + +-+ +-+ +
+<   |     | |     |   >
++   + +   | |   + +   +
+|     |   | |   |     |
+| +-+ +-+ + + +-+ +-+ |
+| |     |     |     | |
+| +     +     +     + |
+|                     |
++*+-----------------+*+
+
+"w2"
++---------------------+
+|                     |
+|       +-+ +-+       |
+|       |     |       |
++     +-+     +-+     +
+<     |         |     >
++   +-+   + +   +-+   +
+|   |     | |     |   |
+| +-+   +-+ +-+   +-+ |
+|       |     |       |
+|     +-+     +-+     |
+|                     |
++*+-----------------+*+
+
+"w3"
++---------------------+
+|                     |
+|   +   +-+ +-+   +   |
+|   |     | |     |   |
++ +-+-+ + + + + +-+-+ +
+<   |   |     |   |   >
++ + + +-+-+ +-+-+ + + +
+| |     |     |     | |
+| +-+   +     +   +-+ |
+|   |             |   |
+|   +---+     +---+   |
+|                     |
++*+-----------------+*+
+
+"w4"
++---------------------+
+|                     |
+| +   + +     + +   + |
+| |   | |     | |   | |
++ | + + | + + | + + | +
+< | |   | | | |   | | >
++ + | + + | | + + | + +
+|   | |   | |   | |   |
+|   + | + + + + | +   |
+|     | |     | |     |
+|     + +     + +     |
+|                     |
++*+-----------------+*+
+
+"w5"
++---------------------+
+|                     |
+| +-+     + +     +-+ |
+|   |     | |     |   |
++   | +---+ +---+ |   +
+<   | |         | |   >
++ +-+ + +     + + +-+ +
+|       |     |       |
+|   +---+     +---+   |
+|   |             |   |
+|   +             +   |
+|                     |
++*+-----------------+*+
+
+"w6"
++---------------------+
+|                     |
+| +-+   + +-+ +   +-+ |
+|       |     |       |
++ + +-+ + +-+ + +-+ + +
+< |                 | >
++ |   +-+     +-+   | +
+| |                 | |
+| + +-+ + +-+ + +-+ + |
+|       |     |       |
+| +-+   + +-+ +   +-+ |
+|                     |
++*+-----------------+*+
+
+"w7"
++---------------------+
+|                     |
+| +-+     + +     +-+ |
+|   |     | |     |   |
++   +-+ +-+ +-+ +-+   +
+<     | |     | |     >
++     | |     | |     +
+|     | |     | |     |
+|   +-+ +-+ +-+ +-+   |
+|   |     | |     |   |
+| +-+     + +     +-+ |
+|                     |
++*+-----------------+*+
+
+"w8"
++---------------------+
+|                     |
+| +-+   +-+ +-+   +-+ |
+|   |             |   |
++   +-+   +-+   +-+   +
+<     |         |     >
++     +-+     +-+     +
+|       |     |       |
+|   +   +-+ +-+   +   |
+|   |     | |     |   |
+|   +     + +     +   |
+|                     |
++*+-----------------+*+
data/sprites.txt view
@@ -1,1065 +1,1065 @@-r 255   0   0 255-b  65 161 255 255-y 237 202   0 255--[blue-worrior-walk]--"            bbb     "-"           r bbb    "-"             bbb  b "-"          bbbbb     "-"            bbb bb  "-"            bbbbbbb "-"           bbrrbrbb "-"  b b     bbbrrbrb  "-" rbrbrrrrrrrrrrbrb  "-"  b b   rrrrrrbbbb  "-"          bbbbb bb  "-"            bbbb    "-"           bbbbb    "-"          bbbbbb    "-"         bbb  bb    "-"        bbb   bbb   "-"        bb     bb   "-"      bbbb   bbbb   "--"            bbb     "-"           r bbb    "-"             bbb  b "-"          bbbbb     "-"            bbb bb  "-"            bbbbbbb "-"           bbrrbrbb "-"  b b     bbbrrbrb  "-" rbrbrrrrrrrrrrbrb  "-"  b b   rrrrrrbbbb  "-"          bbbbb bb  "-"           bbbb     "-"            bb      "-"            bb      "-"            bb      "-"            bb      "-"            bb      "-"          bbbb      "--"            bbb     "-"           r bbb    "-"             bbb  b "-"          bbbbb     "-"            bbb bb  "-"            bbbbbbb "-"           bbrrbrbb "-"  b b     bbbrrbrb  "-" rbrbrrrrrrrrrrbrb  "-"  b b   rrrrrrbbbb  "-"          bbbbb bb  "-"           bbbb     "-"            bbbb    "-"            bbbbb   "-"           bb bbb   "-"           bb  bbb  "-"           bb    b  "-"         bbbb  bbb  "--[blue-worrior-shoot]--"             bbb    "-"            r bbb r "-"              bbb   "-"           bbbbb    "-"   y         bbb bb "-" rr          brrbbb "-"  yy  b b   bbbrrbb "-" yyyyrbrbrrrrrrrrbb "-" ryy  b b  rrrrrbbb "-"            bbbbbbb "-"            bbbbbbb "-"           bbbbbb   "-"          bbbbbbb   "-"     b   bbb bbb    "-"      b bbb  bbb    "-"      bbbb    bbb   "-"       bb      bb   "-"             bbbb   "--" r r          bbb   "-"  ryy        r bbbr "-" ryyyy         bbb  "-"  yyyy      bbbbb   "-" r    rb      bbbb  "-"      brb      bbbb "-"    y  brr    bbrbb "-"         rrr bbrrrb "-"  r       rrrrrrrbb "-"            rrrrbbb "-"            bbbbbbb "-"    b    bbbbbbbbb  "-"     b  bbbbbbbbbb  "-"     bbbbb     bbb  "-"      bb       bbb  "-"              bbb   "-"              bbb   "-"           bbbbb    "--"  r   y       bbb   "-"             r bbbr "-" y r           bbb  "-"   yy  r    bbbbb   "-"  yyyy        bbb b "-" r yyy        bbbbb "-"  r   rbr    bbbrbb "-"      brrrrr bbrrrb "-"        rrrrrrrrrbb "-"           rrrrrbbb "-"            bbbbbbb "-"          bbbbbbb   "-"     b   bbbbbbbb   "-"      b bbb   bbb   "-"      bbbb    bbb   "-"       bb     bb    "-"              bb    "-"           bbbbb    "--"             bbb    "-"   y        r bbb r "-"     r        bbb   "-"           bbbbb    "-"   y         bbb bb "-" rr          brrbbb "-"  yy  b b   bbbrrbb "-" yyyyrbrbrrrrrrrrbb "-" ryy  b b  rrrrrbbb "-"            bbbbbbb "-"            bbbbbbb "-"          bbbbbbb   "-"          bbbbbbb   "-"         bbb  bbb   "-"      bb bb   bbb   "-"       bbb     bb   "-"        bb     bb   "-"             bbbb   "--[yellow-worrior-walk]--"            yyy     "-"           r yyy    "-"             yyy  y "-"          yyyyy     "-"            yyy yy  "-"            yyyyyyy "-"           yyrryryy "-"  y y     yyyrryry  "-" ryryrrrrrrrrrryry  "-"  y y   rrrrrryyyy  "-"          yyyyy yy  "-"            yyyy    "-"           yyyyy    "-"          yyyyyy    "-"         yyy  yy    "-"        yyy   yyy   "-"        yy     yy   "-"      yyyy   yyyy   "--"            yyy     "-"           r yyy    "-"             yyy  y "-"          yyyyy     "-"            yyy yy  "-"            yyyyyyy "-"           yyrryryy "-"  y y     yyyrryry  "-" ryryrrrrrrrrrryry  "-"  y y   rrrrrryyyy  "-"          yyyyy yy  "-"           yyyy     "-"            yy      "-"            yy      "-"            yy      "-"            yy      "-"            yy      "-"          yyyy      "--"            yyy     "-"           r yyy    "-"             yyy  y "-"          yyyyy     "-"            yyy yy  "-"            yyyyyyy "-"           yyrryryy "-"  y y     yyyrryry  "-" ryryrrrrrrrrrryry  "-"  y y   rrrrrryyyy  "-"          yyyyy yy  "-"           yyyy     "-"            yyyy    "-"            yyyyy   "-"           yy yyy   "-"           yy  yyy  "-"           yy    y  "-"         yyyy  yyy  "--[yellow-worrior-shoot]--"             yyy    "-"            r yyy r "-"              yyy   "-"           yyyyy    "-"   y         yyy yy "-" rr          yrryyy "-"  yy  y y   yyyrryy "-" yyyyryryrrrrrrrryy "-" ryy  y y  rrrrryyy "-"            yyyyyyy "-"            yyyyyyy "-"           yyyyyy   "-"          yyyyyyy   "-"     y   yyy yyy    "-"      y yyy  yyy    "-"      yyyy    yyy   "-"       yy      yy   "-"             yyyy   "--" r r   b      yyy   "-"  ryy        r yyyr "-" ryyyy         yyy  "-"  yyyy      yyyyy   "-" r    ry      yyyy  "-"      yry      yyyy "-"    b  yrr    yyryy "-"         rrr yyrrry "-"  r       rrrrrrryy "-"            rrrryyy "-"            yyyyyyy "-"    y    yyyyyyyyy  "-"     y  yyyyyyyyyy  "-"     yyyyy     yyy  "-"      yy       yyy  "-"              yyy   "-"              yyy   "-"           yyyyy    "--"  b   y       yyy   "-"             r yyyr "-" y r           yyy  "-"   yy  r    yyyyy   "-"  yyyy        yyy y "-" r yyy        yyyyy "-"  b   ryr    yyyryy "-"      yrrrrr yyrrry "-"        rrrrrrrrryy "-"           rrrrryyy "-"            yyyyyyy "-"          yyyyyyy   "-"     y   yyyyyyyy   "-"      y yyy   yyy   "-"      yyyy    yyy   "-"       yy     yy    "-"              yy    "-"           yyyyy    "--"             yyy    "-"   y        r yyy r "-"     r        yyy   "-"           yyyyy    "-"   y         yyy yy "-" rr          yrryyy "-"  yy  y y   yyyrryy "-" yyyyryryrrrrrrrryy "-" ryy  y y  rrrrryyy "-"            yyyyyyy "-"  b         yyyyyyy "-"          yyyyyyy   "-"          yyyyyyy   "-"         yyy  yyy   "-"      yy yy   yyy   "-"       yyy     yy   "-"        yy     yy   "-"             yyyy   "--[burwor-walk]--"                b   "-"               bbb  "-"               bbb  "-"           b   bbbb "-"     bbbbbb    bbbb "-"    bbrrbbb b  bbb  "-" bbbbrrrbbbb   bbb  "-" bbbbbbbbbbbb  bb   "-" bbbbbbbbbb    b    "-"  bbbb  bbb   b     "-"        bbb  b      "-"   bbb   bbbb    bb "-"   bbbb  bbbbb bbbb "-"    bbbbbbbbbbbbbb  "-"    bbb bbbbbb bbb  "-"     bb  bbbbb bb   "-"      bb       b    "-"   bbbbbb     bbbbb "--"                 bb "-"     bbbbbbb    bb  "-"    bbrrbbb    bbbb "-" bbbbrrrbbbbb  bbbb "-" bbbbbbbbbbb    bbb "-"  b b bbbbbbb  bbb  "-" bbbbbbbbbb    bb   "-"  bbbb  bbbb  bb    "-"        bbb   b     "-"        bbbb b      "-"   bbbbbbbbbbbb     "-"  bbbbbbbbbbbbbb    "-"   bbb  bbbbbbbbb   "-"    bb       bbbb   "-"     bb       bb    "-"  bbbbbb       b    "-"              bbb   "-"                 bb "--"     bbbbbbb   bbb  "-"    bbrrbbb   bbbbb "-" bbbbrrrbbbbb bbb   "-" bbbbbbbbbbb  bb    "-"  b b bbbbbbb bb    "-"      bbbbb    bb   "-"  bbbb  bbbb   bb   "-"        bbb   b     "-"       bbbbb b      "-"     bbbbbbbbbb     "-"   bbbbbbbbbbbbbb   "-"  bbbb        bbbb  "-"   bb          bb   "-"    bb        bb    "-"   bbbb      bbbb   "-"  b              b  "-" b                b "-"                    "--[burwor-shoot]--"                b   "-"               bbb  "-"            b  bbb  "-"      bbbbbb   bbbb "-"     bbrrbbb b bbbb "-"  bbbbrrrbbbb  bbbb "-"  bbbbbbbbbbb  bbb  "-"  rbrbrbbbbbbb bbb  "-" rbbbbbbbbbb   bb   "-"   bbbb  bbb   b    "-" r       bbbb b     "-"   bbb   bbbbb   bb "-"   bbbb  bbbbb bbbb "-"    bbbbbbbbbbbbbb  "-"    bbb bbbbbb bbb  "-"     bb  bbbbb bb   "-"      bb       b    "-"   bbbbbb     bbbbb "--"               b    "-"               bb   "-"            b  bbb  "-"      bbbbbb   bbbb "-"     bbrrbbb b bbbb "-"  bbbbrrrbbbb  bbbb "-"  bbbbbbbbbbb  bbb  "-"  rbrbbbbbbbbb bbb  "-" rrrrrrbbbbb   bb   "-"   bbbb  bbb   b    "-" r       bbbb b     "-"   bbb   bbbbb   bb "-"   bbbb  bbbbb bbbb "-"    bbbbbbbbbbbbbb  "-"  r bbb bbbbbb bbb  "-"     bb  bbbbb bb   "-"      bb       b    "-" r bbbbbb     bbbbb "--"       bbbbbb    b  "-"      bbrrbb    bbb "-"   bbbbrrrbbbb bbbb "-"   bbbbbbbbbb  bbbb "-" r  brbrbbbbbb bbbb "-"  rrrrrrrbbb   bbbb "-" rryrrrrbbbbb  bbb  "-"  y bbbb bbb   bb   "-"         bbbb bb    "-" r     bbbbbbbb     "-"   bbbbbbbbbbbb     "-"  bbbbbbbbbbbbbb    "-"   bbb  bbbbbbbbb   "-" y  bb       bbbb   "-"     bb       bb    "-"  bbbbbb       b    "-"         r    bbb   "-"      r          bb "--"        bbbbbb    b "-"       bbrrbb    bb "-"    bbbbrrrbbbb bbb "-"    bbbbbbbbbb  bbb "-" y   brbrbbbbbb bbb "-"  rrrrrrrrbbb   bbb "-" rrryrrrrbbbbb  bb  "-"   y bbbb bbb  bb   "-"          bbbbbb    "-"      bbbbbbbbb     "-"    bbbbbbbbbbbbb   "-"   bbbbb      bbbb  "-"    bb         bb   "-"     bb       bb    "-"    bbbb     bbbb   "-"   b       r     b  "-"  b  y            b "-"         r          "--[garwor-walk]--"               rr   "-"       yyyyy    rrr "-"      yyyyyyy    rr "-"    yyyy  yyyy    y "-"  yyyyyyb yyyyy   y "-"  yyyyyyyyyyyyyy  y "-"    yryryyyyyyyy  y "-"  rrrrrryyyyyyyyy y "-" r yryryy yyyyyyy y "-"    yyyy yyyyyyyy y "-"         yyyyyyyyyy "-"        yyyyyyyyyyy "-"      yyyyyyyyyyyy  "-"     y   yyyyyyyy   "-"          yyyyy     "-"          yyy  y    "-"          yy   y    "-"        yyy   yy    "--"      yyyyy      rr "-"     yyyyyy    rrr  "-"   yyyy  yyy   rr   "-" yyyyyyb yyyy  y    "-" yyyyyyyyyyyy  y    "-"   yryryryyyyy yyyy "-"   rrrrrryyyyy    y "-"  yryryryyyyyyy   y "-"   yyyyyyyyyyyyy yy "-"       yyyyyyyyy y  "-"       yyyyyyyyyyy  "-"       yyyyyyyyyyy  "-"      y yyyyyyyyy   "-"     y  yyyyyyyy    "-"         yyyyy      "-"          yy  yyy   "-"           y    y   "-"         yyy        "--"       yyyyy    rrr "-"      yyyyyy   rrr  "-"    yyyy  yyy  rrr  "-"  yyyyyyb yyyy  y   "-"  yyyyyyyyyyyy  yyy "-"    yryryryyyyy   y "-"  rrrrrrrryyyyy   y "-" r yryryryyyyyyy  y "-"    yyyyyyyyyyyy  y "-"        yyyyyyyyy y "-"        yyyyyyyyyyy "-"       yyyyyyyyyyyy "-"         yyyyyyyyy  "-"          yyyyyyy   "-"         yyyyyy     "-"        yy  yy      "-"         yy  y      "-"          y yy      "--[garwor-shoot]--"               rr   "-"        yyyyy   rrr "-"       yyyyyyy   rr "-"     yyyy  yyyy   y "-"   yyyyyyb yyyyy  y "-" b yyyyyyyyyyyyyy y "-"    ryryryyyyyyyy y "-"  rrrrrrryyyyyyyyy  "-" y  rryryy yyyyyyy  "-"    yyyyy yyyyyyyyy "-"  r       yyyyyyyyy "-"         yyyyyyyyyy "-"       yyyyyyyyyyy  "-"      y   yyyyyyyy  "-"           yyyyy    "-"           yyy  y   "-"           yy   y   "-"         yyy   yy   "--"        yyyyy   r   "-"       yyyyyy  rrr  "-"     yyyy  yyy rrr  "-"   yyyyyyb yyyy rr  "-" r yyyyyyyyyyyy y   "-"     yryryryyyyy y  "-" by  rrrrrryyyyy  y "-" yyrrrrrrryyyyyyy y "-" ryb rrryyyyyyyyy y "-" yy  yyyyyyyyyyyyyy "-"  b      yyyyyyyyyy "-"         yyyyyyyyyy "-"        y yyyyyyyyy "-"       y  yyyyyyyy  "-"           yyyyy    "-"            yy  yyy "-"             y    y "-"           yyy      "--"        yyyyy   rrr "-"       yyyyyy  rrr  "-" r   yyyy  yyy rrr  "-"   yyyyyyb yyyyrr   "-" y yyyyyyyyyyyy y   "-" b   yryryryyyyy y  "-" bb rrrrrrryyyyy  y "-" yrrrrrrrryyyyyyy y "-"  yb rrryyyyyyyyy y "-" yr  yyyyyyyyyyyyyy "-" rr      yyyyyyyyyy "-"  ryy    yyyyyyyyyy "-"   yb   y yyyyyyyyy "-"       y  yyyyyyyy  "-"           yyyyy    "-"            yy  yyy "-"             y    y "-"           yyy      "--"        yyyyy  rr   "-" r     yyyyyy   rrr "-"     yyyy  yyy   rr "-"   yyyyyyb yyyy   y "-" b yyyyyyyyyyyy   y "-"     yryryryyyyy  y "-"  rrrrrrrrryyyyy  y "-"   rrrrrrryyyyyyy y "-" y   rrryyyyyyyyy y "-"   b yyyyyyyyyyyy y "-" r       yyyyyyyyyy "-"       yyyyyyyyyyyy "-"    b    yyyyyyyyy  "-"          yyyyyyy   "-"         yyyyyy     "-"        yy  yy      "-"         yy  y      "-"          y yy      "--[thorwor-walk]--"                rr  "-"      yy       rr   "-"     y  r     rrr   "-"    y  rrr    r     "-"      rrrrr   rr    "-"     rr rrrr   r    "-"    rr  rrrr   rrr  "-"    rr brrrrr    r  "-"  rrrrrrrrrrrr   rr "-" rrrrrrrrrrrrrrrrrr "-"    rrrrrrrrrrrrrr  "-" rr    rrrrrrrrrrr  "-" rrrrrrrrrrrrrrrr   "-"    rrrr  r  r  r   "-"          r  r  r   "-"         rr rr rr   "-"         r  r  r    "-"        bb bb bb    "--"                rr  "-"      yy        r   "-"     y  r       r   "-"    y  rrr      rr  "-"      rrrrr      r  "-"     rr rrrr     r  "-"    rr  rrrr     r  "-"   rrr brrrrr    rr "-" rrrrrrrrrrrrr   rr "-" rr  rrrrrrrrrrrrrr "-"   b  rrrrrrrrrrrr  "-"       rrrrrrrrrrr  "-" r b rrrrrrrrrrrr   "-" rrrrrrrr r  r  r   "-"   rrrr   r  r  r   "-"          r  r  r   "-"          r  r  r   "-"         bb bb bb   "--"    y y    rrrr     "-"       y      rrr   "-"        r       r   "-"       rrr      r   "-"    rrrrrrr     r   "-"     rr rrrr    rr  "-"    rr  rrrr     r  "-"  rrrr brrrrr    rr "-" rr  rrrrrrrrr   rr "-" r b  rrrrrrrrrrrrr "-"   b   rrrrrrrrrrr  "-"       rrrrrrrrrrr  "-"      rrrrrrrrrrr   "-" r b  rrr r  r  r   "-" rr  rrr  r  r  r   "-"  rrrrr   rr rr rr  "-"           r  r  r  "-"          bb bb bb  "--[thorwor-shoot]--"          yyy     r "-"         rr  yy   r "-"        rrrr   yyr  "-"       rr rrr  rr   "-"   rrrrr  rrrr  rr  "-"  r   r  brrrr    r "-" r b   rrrrrrr    r "-"       rrrrrrr    r "-"   yyyyyrrrrrrr  rr "-"     yyyrrrrrrrrrrr "-" r b   rrrrrrrrrrr  "-"  r   rrrrrrrrrrrr  "-"  rr rrr rrrrrrrr   "-"    rrr   r  r  r   "-"          r  r  r   "-"         rr rr rr   "-"         r  r  r    "-"         bb bb bb   "--"            yy   r  "-"        rrrr  y  r  "-"    rrrrrr rr  yr   "-"  rr rrr   rr   y   "-"    b rr brrr  ry   "-" y  b  rrrrrrr r y  "-" yy     rrrrrr  r   "-"  yyyyyyrrrrrrr  r  "-"    yyyyrrrrrrr   r "-" r b  yrrrrrrrrr rr "-"  r   rrrrrrrrrrrrr "-"  rr rrrrrrrrrrrrrr "-"    rrr  rrrrrrrrr  "-"          r  rr rr  "-"          rr  r  r  "-"           rr rr rr "-"            r  r  r "-"           bb bb bb "--"            yy   r  "-"        rrrr  y rrr "-"    rrrrrr rr y r r "-"  rr rrr   rr y r   "-"    b rr brrr y r   "-" yy    rrrrrrr y r  "-"   yy   rrrrrr  yr  "-"    yyyyrrrrrrr  r  "-"     yyyrrrrrrr  r  "-" r b   rrrrrrrrr rr "-"  r   rrrrrrrrrrrrr "-"  rr rrrrrrrrrrrrrr "-"    rrr  rrrrrrrrr  "-"           r  r  r  "-"           r  r  r  "-"          rr rr rr  "-"          r  r  r   "-"          bb bb bb  "--"            y   rrr "-"        rrrr y rr r "-"    rrrrrr rr yr  r "-"  rr rrr   rr  y rr "-" y  b rr brrr  yr   "-" yy    rrrrrrr y r  "-"  yyyy  rrrrrr    r "-"    yyy rrrrrrr   r "-"     yyyrrrrrrr   r "-" r b  yrrrrrrrrr rr "-"  r   rrrrrrrrrrrrr "-"  rr rrrrrrrrrrrrrr "-"    rrr  rrrrrrrrr  "-"          r  rr rr  "-"          rr  r  r  "-"           rr rr rr "-"            r  r  r "-"           bb bb bb "--[worluk-walk]--"      bb     bb  yy "-" yy     b   b   yyy "-" yyy   yryyyry  yyy "-" yyyy yrrryrrryyyyy "-" yyyyyrrrryrrrryyyy "-" bbyyy yryyyryyyyyb "-"  bbyyy  yyy  yyybb "-"  bybbyy byb yybb b "-"  b  ybybbbbbyby  b "-"   b   bbbbbbby   b "-"    b   bbbbb    b  "-"        bbbbb       "-"        bbbbb       "-"      bbbbbbbbb     "-"     b  bbbbb  b    "-"     b   bbb   b    "-"     b    b    b    "-"   bbb         bbb  "--"       b    b       "-"       b   b        "-"      yryyyry       "-"  y  yrrryrrry      "-" bby rrrryrrrr  yyy "-" ybyy yryyyry  yyyy "-" ybbyy  yyy  yyyybb "-" ybybyy byb yybbbby "-" ybyybybbbbbybyybby "-" yybyybbbbbbbyyybyy "-"  yybyybbbbbyyybyy  "-"   yyy bbbbb yyyy   "-"       bbbbb        "-"    bbbbbbbbb       "-"    b  bbbbb b      "-"     b  bbb   b     "-"      b  b     b    "-"    bbb        bbb  "--"                    "-"         b   b      "-"        b   b       "-"       yryyyry      "-"      yrrryrrry     "-"      rrrryrrrr     "-"       yryyyry      "-"    yyy  yyy  yyy   "-" bbbbbby byb ybbbbb "-"  byyyybbbbbbbyybb  "-"  ybyyyybbbbbyybyyy "-"  yybyy bbbbb byyyy "-" yyyyy  bbbbb  yyyy "-" yyyybbbbbbbbbbbyyy "-" yyy b  bbbbb  byyy "-" yy   b  bbb  b  yy "-"       b  b  b      "-"     bbbb   bbbb    "--[wizard-walk]--"         bbbb       "-"       bbbbb        "-"      b    b        "-"      by y bbb      "-"      bb  bbbbb     "-"     bbbb bbbbbbb   "-"    bb  bbbbb   bb  "-"    b    bbbb    bb "-"   bb    bbbbb    r "-" rr      bbbbb    r "-"        bbbbbb      "-"       bbbbbbb      "-"     bbbbbbbbbb     "-"     bbbbbbbbbb     "-"      bbbbbbbbbb    "-"      bbbbbbbbbbb   "-"       bbbbbbbbbbb  "-"      bbbbbbbbbbbb  "--"      bbbb          "-"     b  bbb         "-"     by ybb         "-"     bb  bbbb       "-"      bb bbbbb      "-"     bbbbbbb bb     "-"      b bbbb  bb    "-"     b   bbbb  bb   "-"    bb   bbbbb  r   "-"  rr    bbbbbb  r   "-"       bbbbbbb      "-"      bbbbbbb       "-"     bbbbbbbbb      "-"      bbbbbbbbb     "-"       bbbbbbbbb    "-"        bbbbbbbbb   "-"        bbbbbbbb    "-"      bbbbb         "--"         bbb        "-"      bbbbb         "-"     b bbbb         "-"     by bbb         "-"     bb  bbbb       "-"      bb bbbbb      "-"      bbbbbb bb     "-"        bbbbb bb    "-"       b bbbbbbb    "-"      bb bbbbbr     "-"    rr  bbbbbrr     "-"       bbbbbbbb     "-"      bbbbbbbb      "-"      bbbbbbbb      "-"       bbbbbb       "-"       bbbbbb       "-"      bbbbbbbb      "-"      bbbbbbbb      "--"       bbbb         "-"      b  bbb        "-"      by ybb        "-"      bb  bbb       "-"       bb bbbbb     "-"       bbbbbbbbb    "-"       bbbbbb  bb   "-"      bb bbbb   b   "-"     bb   bbbb  bb  "-"   rr   bbbbbb   r  "-"      bbbbbbbb   r  "-"     bbbbbbbbb      "-"     bbbbbbbb       "-"      bbbbbbb       "-"      bbbbbbb       "-"       bbbbbbb      "-"     bbbbbbbbb      "-"         bbbbb      "--[wizard-shoot]--"         bbbb       "-"        b   bb      "-"   r    by ybb      "-" rrrr   bb  b       "-"    rb   b  b  rrrr "-"    bb bbbb bbb rrb "-"    bbbbbbbbbbbbrbb "-"     bbbbbbbb bbbb  "-"         bbbb  bb   "-"         bbbb       "-"        bbbbb       "-"       bbbbbbb      "-"      bbbbbbbb      "-"     bbbbbbbbb      "-"     bbbbbbbbbb     "-"     bbbbbbbbbb     "-"    bbbbbbbbbbb     "-"   bbbbbbbbbbbbb    "--"           bbb      "-"          bb bbb    "-"          by ybbb   "-"          b   bb    "-" rrrr  bbbbb  b     "-"    rr bbbbb bbbb   "-"     rr   bbrrrrrb  "-"     rr   bbbbb rrr "-"          bbbb   rr "-"          bbb       "-"         bbbbb      "-"        bbbbbb      "-"       bbbbbbb      "-"       bbbbbb       "-"       bbbbbb       "-"      bbbbbbbb      "-"      bbbbbbbbb     "-"    bbbbbbbbbbbb    "--"             bbbb   "-"            bbbbbb  "-"    rrrbb    ybbbbb "-" yy   rbbbb    bbb  "-"    rr   bbbbbbbb   "-" yyy rrbbbbbbbbbbb  "-"      rbb    bbbbb  "-"       b      bbbb  "-"              bbbb  "-"             bbbb   "-"           bbbbbb   "-"          bbbbbbb   "-"         bbbbbbb    "-"         bbbbbbb    "-"         bbbbbbb    "-"        bbbbbbbbb   "-"        bbbbbbbbbb  "-"      bbbbbbbbbbbbb "--[worrior-flash]--"         rrbbbrr    "-"         ryrbbbr    "-"        rrrrbbbr    "-"        rbbbbbrrrr  "-"        rrrbbbrbbr  "-"          rbbbbbbb  "-" r r     rbbyybybb  "-"rbrbrrrrrbbbyybybr  "-"ybybyyyyyyyyyybbbr  "-"rbrbrrryyyyyybbbbr  "-" r r  rrrbbbbbrbbr  "-"         rbbbbrrrr  "-"         rbbbbbr    "-"        rbbbbbbr    "-"       rbbbrrbbr    "-"      rbbbr rbbbr   "-"    rrrbbr  rrbbr   "-"    rbbbbr rbbbbr   "--"         rryyyrr    "-"         rbryyyr    "-"        rrrryyyr    "-"        ryyyyyrrrr  "-"        rrryyyryyr  "-"          ryyyyyyy  "-" r r     ryybbybyy  "-"ryryrrrrryyybbybyr  "-"bybybbbbbbbbbbyyyr  "-"ryryrrrbbbbbbyyyyr  "-" r r  rrryyyyyryyr  "-"         ryyyyrrrr  "-"         ryyyyyr    "-"        ryyyyyyr    "-"       ryyyrryyr    "-"      ryyyr ryyyr   "-"    rrryyr  rryyr   "-"    ryyyyr ryyyyr   "--[blue-worrior-death]--"                    "-"              b     "-"b b          bb     "-"bybyyyyyy    bb y   "-"b b   yyy    bbbbb  "-"           b   bb   "-"        y   y  r    "-"       rbb y   b    "-"             r y    "-"         b b  b b   "-"        b ry   y    "-"     bb  y   yb r   "-"    bbb    b        "-"   bbb         bbb  "-"   bb         bbbb  "-" bbbb         bb b  "-"                 b  "-"                    "--[yellow-worrior-death]--"              y     "-"y y          yy     "-"ybybbbbbb    yy b   "-"y y   bbb    yyyyy  "-"         y    yyyy  "-"           y   yy   "-"        b   b  r    "-"       ryy b   y    "-"             r b    "-"         y y  y y   "-"        y rb   b    "-"     yy  b   by r   "-"    yyy    y        "-"   yyy         yyy  "-"   yy         yyyy  "-" yyyy         yy y  "-"                 y  "-"                    "--[common-death]--"      y  b          "-" b r   y   y b      "-"    y b r    r      "-"    r  b  b         "-"  y           r     "-"    b     by        "-"r     ry   r b r    "-"   r    b y         "-"   y   b   b y      "-"b     b  b     b    "-"         y  y       "-" r   y r      r     "-"   b  b  y  r b     "-" y r   y   r   b    "-"   b y   r   r b    "-"     r  y   b b     "-"      b   y         "-"                    "--"         r   y      "-"     y      b       "-" y  r    b    y     "-"      b     y   b   "-"    b        y      "-" r       b   r      "-"    y      y     b  "-"b     b  r     r    "-"   r           y    "-"        y           "-" r   y   r     b    "-"   b   y      r  b  "-"   b    y  b    y   "-"b     r       r     "-"   y b   b     r    "-"       r      y     "-"    b      b        "-"       r            "--[explosion]--"                    "-"                    "-"                    "-"    r     b         "-"r   rr r            "-" rrrrrrr  r         "-"  rrrrrrrrr         "-"  rrrbrrbrrr        "-"rrrrbbbbbrr         "-"rrrbbbbbbrr         "-" rrrrrbbbrr         "-"  rr rrrrr          "-"b r   rrr  b        "-"      rrr           "-"       r            "-"                    "-"                    "-"                    "--"   b                "-"    b               "-"    bbb             "-"     bb   b         "-"     bbbbbb     r   "-"     brbbbb  bb     "-"    bbrrrbbbbbbb    "-"    bbrrrrrrrrbb    "-"r  bbrrrrrrrrrb     "-" bbbbrrrrrrrrbb     "-" bbbrrrrrrrrrbb     "-"  bbrrrrrrrrrrbb    "-"  bbrrbbrrrbrrb     "-"    bbbbbbbbbbb     "-"  bb bb  bb b bbb   "-"  b         b   b   "-"bb          b       "-"                    "--"         y          "-"y       y       y   "-" y     y       y    "-"  y    y      y     "-"   yy yyy yy  y     "-"    yyrrrryyy y     "-"   yyrrrrrryyy      "-"   yyrrrrrrryy   y  "-"  yyrrrrrrrryy      "-"  yyrrrrrrrryy      "-"  yyrrrrrrrryy      "-"  yyyrrrrrrrryy     "-" y  yryyyrrrry      "-"y   yy  yyrryyy     "-"         yyyy yyy   "-"         y      y   "-"        y           "-"       y            "+r 255   0   0 255
+b  65 161 255 255
+y 237 202   0 255
+
+[blue-worrior-walk]
+
+"            bbb     "
+"           r bbb    "
+"             bbb  b "
+"          bbbbb     "
+"            bbb bb  "
+"            bbbbbbb "
+"           bbrrbrbb "
+"  b b     bbbrrbrb  "
+" rbrbrrrrrrrrrrbrb  "
+"  b b   rrrrrrbbbb  "
+"          bbbbb bb  "
+"            bbbb    "
+"           bbbbb    "
+"          bbbbbb    "
+"         bbb  bb    "
+"        bbb   bbb   "
+"        bb     bb   "
+"      bbbb   bbbb   "
+
+"            bbb     "
+"           r bbb    "
+"             bbb  b "
+"          bbbbb     "
+"            bbb bb  "
+"            bbbbbbb "
+"           bbrrbrbb "
+"  b b     bbbrrbrb  "
+" rbrbrrrrrrrrrrbrb  "
+"  b b   rrrrrrbbbb  "
+"          bbbbb bb  "
+"           bbbb     "
+"            bb      "
+"            bb      "
+"            bb      "
+"            bb      "
+"            bb      "
+"          bbbb      "
+
+"            bbb     "
+"           r bbb    "
+"             bbb  b "
+"          bbbbb     "
+"            bbb bb  "
+"            bbbbbbb "
+"           bbrrbrbb "
+"  b b     bbbrrbrb  "
+" rbrbrrrrrrrrrrbrb  "
+"  b b   rrrrrrbbbb  "
+"          bbbbb bb  "
+"           bbbb     "
+"            bbbb    "
+"            bbbbb   "
+"           bb bbb   "
+"           bb  bbb  "
+"           bb    b  "
+"         bbbb  bbb  "
+
+[blue-worrior-shoot]
+
+"             bbb    "
+"            r bbb r "
+"              bbb   "
+"           bbbbb    "
+"   y         bbb bb "
+" rr          brrbbb "
+"  yy  b b   bbbrrbb "
+" yyyyrbrbrrrrrrrrbb "
+" ryy  b b  rrrrrbbb "
+"            bbbbbbb "
+"            bbbbbbb "
+"           bbbbbb   "
+"          bbbbbbb   "
+"     b   bbb bbb    "
+"      b bbb  bbb    "
+"      bbbb    bbb   "
+"       bb      bb   "
+"             bbbb   "
+
+" r r          bbb   "
+"  ryy        r bbbr "
+" ryyyy         bbb  "
+"  yyyy      bbbbb   "
+" r    rb      bbbb  "
+"      brb      bbbb "
+"    y  brr    bbrbb "
+"         rrr bbrrrb "
+"  r       rrrrrrrbb "
+"            rrrrbbb "
+"            bbbbbbb "
+"    b    bbbbbbbbb  "
+"     b  bbbbbbbbbb  "
+"     bbbbb     bbb  "
+"      bb       bbb  "
+"              bbb   "
+"              bbb   "
+"           bbbbb    "
+
+"  r   y       bbb   "
+"             r bbbr "
+" y r           bbb  "
+"   yy  r    bbbbb   "
+"  yyyy        bbb b "
+" r yyy        bbbbb "
+"  r   rbr    bbbrbb "
+"      brrrrr bbrrrb "
+"        rrrrrrrrrbb "
+"           rrrrrbbb "
+"            bbbbbbb "
+"          bbbbbbb   "
+"     b   bbbbbbbb   "
+"      b bbb   bbb   "
+"      bbbb    bbb   "
+"       bb     bb    "
+"              bb    "
+"           bbbbb    "
+
+"             bbb    "
+"   y        r bbb r "
+"     r        bbb   "
+"           bbbbb    "
+"   y         bbb bb "
+" rr          brrbbb "
+"  yy  b b   bbbrrbb "
+" yyyyrbrbrrrrrrrrbb "
+" ryy  b b  rrrrrbbb "
+"            bbbbbbb "
+"            bbbbbbb "
+"          bbbbbbb   "
+"          bbbbbbb   "
+"         bbb  bbb   "
+"      bb bb   bbb   "
+"       bbb     bb   "
+"        bb     bb   "
+"             bbbb   "
+
+[yellow-worrior-walk]
+
+"            yyy     "
+"           r yyy    "
+"             yyy  y "
+"          yyyyy     "
+"            yyy yy  "
+"            yyyyyyy "
+"           yyrryryy "
+"  y y     yyyrryry  "
+" ryryrrrrrrrrrryry  "
+"  y y   rrrrrryyyy  "
+"          yyyyy yy  "
+"            yyyy    "
+"           yyyyy    "
+"          yyyyyy    "
+"         yyy  yy    "
+"        yyy   yyy   "
+"        yy     yy   "
+"      yyyy   yyyy   "
+
+"            yyy     "
+"           r yyy    "
+"             yyy  y "
+"          yyyyy     "
+"            yyy yy  "
+"            yyyyyyy "
+"           yyrryryy "
+"  y y     yyyrryry  "
+" ryryrrrrrrrrrryry  "
+"  y y   rrrrrryyyy  "
+"          yyyyy yy  "
+"           yyyy     "
+"            yy      "
+"            yy      "
+"            yy      "
+"            yy      "
+"            yy      "
+"          yyyy      "
+
+"            yyy     "
+"           r yyy    "
+"             yyy  y "
+"          yyyyy     "
+"            yyy yy  "
+"            yyyyyyy "
+"           yyrryryy "
+"  y y     yyyrryry  "
+" ryryrrrrrrrrrryry  "
+"  y y   rrrrrryyyy  "
+"          yyyyy yy  "
+"           yyyy     "
+"            yyyy    "
+"            yyyyy   "
+"           yy yyy   "
+"           yy  yyy  "
+"           yy    y  "
+"         yyyy  yyy  "
+
+[yellow-worrior-shoot]
+
+"             yyy    "
+"            r yyy r "
+"              yyy   "
+"           yyyyy    "
+"   y         yyy yy "
+" rr          yrryyy "
+"  yy  y y   yyyrryy "
+" yyyyryryrrrrrrrryy "
+" ryy  y y  rrrrryyy "
+"            yyyyyyy "
+"            yyyyyyy "
+"           yyyyyy   "
+"          yyyyyyy   "
+"     y   yyy yyy    "
+"      y yyy  yyy    "
+"      yyyy    yyy   "
+"       yy      yy   "
+"             yyyy   "
+
+" r r   b      yyy   "
+"  ryy        r yyyr "
+" ryyyy         yyy  "
+"  yyyy      yyyyy   "
+" r    ry      yyyy  "
+"      yry      yyyy "
+"    b  yrr    yyryy "
+"         rrr yyrrry "
+"  r       rrrrrrryy "
+"            rrrryyy "
+"            yyyyyyy "
+"    y    yyyyyyyyy  "
+"     y  yyyyyyyyyy  "
+"     yyyyy     yyy  "
+"      yy       yyy  "
+"              yyy   "
+"              yyy   "
+"           yyyyy    "
+
+"  b   y       yyy   "
+"             r yyyr "
+" y r           yyy  "
+"   yy  r    yyyyy   "
+"  yyyy        yyy y "
+" r yyy        yyyyy "
+"  b   ryr    yyyryy "
+"      yrrrrr yyrrry "
+"        rrrrrrrrryy "
+"           rrrrryyy "
+"            yyyyyyy "
+"          yyyyyyy   "
+"     y   yyyyyyyy   "
+"      y yyy   yyy   "
+"      yyyy    yyy   "
+"       yy     yy    "
+"              yy    "
+"           yyyyy    "
+
+"             yyy    "
+"   y        r yyy r "
+"     r        yyy   "
+"           yyyyy    "
+"   y         yyy yy "
+" rr          yrryyy "
+"  yy  y y   yyyrryy "
+" yyyyryryrrrrrrrryy "
+" ryy  y y  rrrrryyy "
+"            yyyyyyy "
+"  b         yyyyyyy "
+"          yyyyyyy   "
+"          yyyyyyy   "
+"         yyy  yyy   "
+"      yy yy   yyy   "
+"       yyy     yy   "
+"        yy     yy   "
+"             yyyy   "
+
+[burwor-walk]
+
+"                b   "
+"               bbb  "
+"               bbb  "
+"           b   bbbb "
+"     bbbbbb    bbbb "
+"    bbrrbbb b  bbb  "
+" bbbbrrrbbbb   bbb  "
+" bbbbbbbbbbbb  bb   "
+" bbbbbbbbbb    b    "
+"  bbbb  bbb   b     "
+"        bbb  b      "
+"   bbb   bbbb    bb "
+"   bbbb  bbbbb bbbb "
+"    bbbbbbbbbbbbbb  "
+"    bbb bbbbbb bbb  "
+"     bb  bbbbb bb   "
+"      bb       b    "
+"   bbbbbb     bbbbb "
+
+"                 bb "
+"     bbbbbbb    bb  "
+"    bbrrbbb    bbbb "
+" bbbbrrrbbbbb  bbbb "
+" bbbbbbbbbbb    bbb "
+"  b b bbbbbbb  bbb  "
+" bbbbbbbbbb    bb   "
+"  bbbb  bbbb  bb    "
+"        bbb   b     "
+"        bbbb b      "
+"   bbbbbbbbbbbb     "
+"  bbbbbbbbbbbbbb    "
+"   bbb  bbbbbbbbb   "
+"    bb       bbbb   "
+"     bb       bb    "
+"  bbbbbb       b    "
+"              bbb   "
+"                 bb "
+
+"     bbbbbbb   bbb  "
+"    bbrrbbb   bbbbb "
+" bbbbrrrbbbbb bbb   "
+" bbbbbbbbbbb  bb    "
+"  b b bbbbbbb bb    "
+"      bbbbb    bb   "
+"  bbbb  bbbb   bb   "
+"        bbb   b     "
+"       bbbbb b      "
+"     bbbbbbbbbb     "
+"   bbbbbbbbbbbbbb   "
+"  bbbb        bbbb  "
+"   bb          bb   "
+"    bb        bb    "
+"   bbbb      bbbb   "
+"  b              b  "
+" b                b "
+"                    "
+
+[burwor-shoot]
+
+"                b   "
+"               bbb  "
+"            b  bbb  "
+"      bbbbbb   bbbb "
+"     bbrrbbb b bbbb "
+"  bbbbrrrbbbb  bbbb "
+"  bbbbbbbbbbb  bbb  "
+"  rbrbrbbbbbbb bbb  "
+" rbbbbbbbbbb   bb   "
+"   bbbb  bbb   b    "
+" r       bbbb b     "
+"   bbb   bbbbb   bb "
+"   bbbb  bbbbb bbbb "
+"    bbbbbbbbbbbbbb  "
+"    bbb bbbbbb bbb  "
+"     bb  bbbbb bb   "
+"      bb       b    "
+"   bbbbbb     bbbbb "
+
+"               b    "
+"               bb   "
+"            b  bbb  "
+"      bbbbbb   bbbb "
+"     bbrrbbb b bbbb "
+"  bbbbrrrbbbb  bbbb "
+"  bbbbbbbbbbb  bbb  "
+"  rbrbbbbbbbbb bbb  "
+" rrrrrrbbbbb   bb   "
+"   bbbb  bbb   b    "
+" r       bbbb b     "
+"   bbb   bbbbb   bb "
+"   bbbb  bbbbb bbbb "
+"    bbbbbbbbbbbbbb  "
+"  r bbb bbbbbb bbb  "
+"     bb  bbbbb bb   "
+"      bb       b    "
+" r bbbbbb     bbbbb "
+
+"       bbbbbb    b  "
+"      bbrrbb    bbb "
+"   bbbbrrrbbbb bbbb "
+"   bbbbbbbbbb  bbbb "
+" r  brbrbbbbbb bbbb "
+"  rrrrrrrbbb   bbbb "
+" rryrrrrbbbbb  bbb  "
+"  y bbbb bbb   bb   "
+"         bbbb bb    "
+" r     bbbbbbbb     "
+"   bbbbbbbbbbbb     "
+"  bbbbbbbbbbbbbb    "
+"   bbb  bbbbbbbbb   "
+" y  bb       bbbb   "
+"     bb       bb    "
+"  bbbbbb       b    "
+"         r    bbb   "
+"      r          bb "
+
+"        bbbbbb    b "
+"       bbrrbb    bb "
+"    bbbbrrrbbbb bbb "
+"    bbbbbbbbbb  bbb "
+" y   brbrbbbbbb bbb "
+"  rrrrrrrrbbb   bbb "
+" rrryrrrrbbbbb  bb  "
+"   y bbbb bbb  bb   "
+"          bbbbbb    "
+"      bbbbbbbbb     "
+"    bbbbbbbbbbbbb   "
+"   bbbbb      bbbb  "
+"    bb         bb   "
+"     bb       bb    "
+"    bbbb     bbbb   "
+"   b       r     b  "
+"  b  y            b "
+"         r          "
+
+[garwor-walk]
+
+"               rr   "
+"       yyyyy    rrr "
+"      yyyyyyy    rr "
+"    yyyy  yyyy    y "
+"  yyyyyyb yyyyy   y "
+"  yyyyyyyyyyyyyy  y "
+"    yryryyyyyyyy  y "
+"  rrrrrryyyyyyyyy y "
+" r yryryy yyyyyyy y "
+"    yyyy yyyyyyyy y "
+"         yyyyyyyyyy "
+"        yyyyyyyyyyy "
+"      yyyyyyyyyyyy  "
+"     y   yyyyyyyy   "
+"          yyyyy     "
+"          yyy  y    "
+"          yy   y    "
+"        yyy   yy    "
+
+"      yyyyy      rr "
+"     yyyyyy    rrr  "
+"   yyyy  yyy   rr   "
+" yyyyyyb yyyy  y    "
+" yyyyyyyyyyyy  y    "
+"   yryryryyyyy yyyy "
+"   rrrrrryyyyy    y "
+"  yryryryyyyyyy   y "
+"   yyyyyyyyyyyyy yy "
+"       yyyyyyyyy y  "
+"       yyyyyyyyyyy  "
+"       yyyyyyyyyyy  "
+"      y yyyyyyyyy   "
+"     y  yyyyyyyy    "
+"         yyyyy      "
+"          yy  yyy   "
+"           y    y   "
+"         yyy        "
+
+"       yyyyy    rrr "
+"      yyyyyy   rrr  "
+"    yyyy  yyy  rrr  "
+"  yyyyyyb yyyy  y   "
+"  yyyyyyyyyyyy  yyy "
+"    yryryryyyyy   y "
+"  rrrrrrrryyyyy   y "
+" r yryryryyyyyyy  y "
+"    yyyyyyyyyyyy  y "
+"        yyyyyyyyy y "
+"        yyyyyyyyyyy "
+"       yyyyyyyyyyyy "
+"         yyyyyyyyy  "
+"          yyyyyyy   "
+"         yyyyyy     "
+"        yy  yy      "
+"         yy  y      "
+"          y yy      "
+
+[garwor-shoot]
+
+"               rr   "
+"        yyyyy   rrr "
+"       yyyyyyy   rr "
+"     yyyy  yyyy   y "
+"   yyyyyyb yyyyy  y "
+" b yyyyyyyyyyyyyy y "
+"    ryryryyyyyyyy y "
+"  rrrrrrryyyyyyyyy  "
+" y  rryryy yyyyyyy  "
+"    yyyyy yyyyyyyyy "
+"  r       yyyyyyyyy "
+"         yyyyyyyyyy "
+"       yyyyyyyyyyy  "
+"      y   yyyyyyyy  "
+"           yyyyy    "
+"           yyy  y   "
+"           yy   y   "
+"         yyy   yy   "
+
+"        yyyyy   r   "
+"       yyyyyy  rrr  "
+"     yyyy  yyy rrr  "
+"   yyyyyyb yyyy rr  "
+" r yyyyyyyyyyyy y   "
+"     yryryryyyyy y  "
+" by  rrrrrryyyyy  y "
+" yyrrrrrrryyyyyyy y "
+" ryb rrryyyyyyyyy y "
+" yy  yyyyyyyyyyyyyy "
+"  b      yyyyyyyyyy "
+"         yyyyyyyyyy "
+"        y yyyyyyyyy "
+"       y  yyyyyyyy  "
+"           yyyyy    "
+"            yy  yyy "
+"             y    y "
+"           yyy      "
+
+"        yyyyy   rrr "
+"       yyyyyy  rrr  "
+" r   yyyy  yyy rrr  "
+"   yyyyyyb yyyyrr   "
+" y yyyyyyyyyyyy y   "
+" b   yryryryyyyy y  "
+" bb rrrrrrryyyyy  y "
+" yrrrrrrrryyyyyyy y "
+"  yb rrryyyyyyyyy y "
+" yr  yyyyyyyyyyyyyy "
+" rr      yyyyyyyyyy "
+"  ryy    yyyyyyyyyy "
+"   yb   y yyyyyyyyy "
+"       y  yyyyyyyy  "
+"           yyyyy    "
+"            yy  yyy "
+"             y    y "
+"           yyy      "
+
+"        yyyyy  rr   "
+" r     yyyyyy   rrr "
+"     yyyy  yyy   rr "
+"   yyyyyyb yyyy   y "
+" b yyyyyyyyyyyy   y "
+"     yryryryyyyy  y "
+"  rrrrrrrrryyyyy  y "
+"   rrrrrrryyyyyyy y "
+" y   rrryyyyyyyyy y "
+"   b yyyyyyyyyyyy y "
+" r       yyyyyyyyyy "
+"       yyyyyyyyyyyy "
+"    b    yyyyyyyyy  "
+"          yyyyyyy   "
+"         yyyyyy     "
+"        yy  yy      "
+"         yy  y      "
+"          y yy      "
+
+[thorwor-walk]
+
+"                rr  "
+"      yy       rr   "
+"     y  r     rrr   "
+"    y  rrr    r     "
+"      rrrrr   rr    "
+"     rr rrrr   r    "
+"    rr  rrrr   rrr  "
+"    rr brrrrr    r  "
+"  rrrrrrrrrrrr   rr "
+" rrrrrrrrrrrrrrrrrr "
+"    rrrrrrrrrrrrrr  "
+" rr    rrrrrrrrrrr  "
+" rrrrrrrrrrrrrrrr   "
+"    rrrr  r  r  r   "
+"          r  r  r   "
+"         rr rr rr   "
+"         r  r  r    "
+"        bb bb bb    "
+
+"                rr  "
+"      yy        r   "
+"     y  r       r   "
+"    y  rrr      rr  "
+"      rrrrr      r  "
+"     rr rrrr     r  "
+"    rr  rrrr     r  "
+"   rrr brrrrr    rr "
+" rrrrrrrrrrrrr   rr "
+" rr  rrrrrrrrrrrrrr "
+"   b  rrrrrrrrrrrr  "
+"       rrrrrrrrrrr  "
+" r b rrrrrrrrrrrr   "
+" rrrrrrrr r  r  r   "
+"   rrrr   r  r  r   "
+"          r  r  r   "
+"          r  r  r   "
+"         bb bb bb   "
+
+"    y y    rrrr     "
+"       y      rrr   "
+"        r       r   "
+"       rrr      r   "
+"    rrrrrrr     r   "
+"     rr rrrr    rr  "
+"    rr  rrrr     r  "
+"  rrrr brrrrr    rr "
+" rr  rrrrrrrrr   rr "
+" r b  rrrrrrrrrrrrr "
+"   b   rrrrrrrrrrr  "
+"       rrrrrrrrrrr  "
+"      rrrrrrrrrrr   "
+" r b  rrr r  r  r   "
+" rr  rrr  r  r  r   "
+"  rrrrr   rr rr rr  "
+"           r  r  r  "
+"          bb bb bb  "
+
+[thorwor-shoot]
+
+"          yyy     r "
+"         rr  yy   r "
+"        rrrr   yyr  "
+"       rr rrr  rr   "
+"   rrrrr  rrrr  rr  "
+"  r   r  brrrr    r "
+" r b   rrrrrrr    r "
+"       rrrrrrr    r "
+"   yyyyyrrrrrrr  rr "
+"     yyyrrrrrrrrrrr "
+" r b   rrrrrrrrrrr  "
+"  r   rrrrrrrrrrrr  "
+"  rr rrr rrrrrrrr   "
+"    rrr   r  r  r   "
+"          r  r  r   "
+"         rr rr rr   "
+"         r  r  r    "
+"         bb bb bb   "
+
+"            yy   r  "
+"        rrrr  y  r  "
+"    rrrrrr rr  yr   "
+"  rr rrr   rr   y   "
+"    b rr brrr  ry   "
+" y  b  rrrrrrr r y  "
+" yy     rrrrrr  r   "
+"  yyyyyyrrrrrrr  r  "
+"    yyyyrrrrrrr   r "
+" r b  yrrrrrrrrr rr "
+"  r   rrrrrrrrrrrrr "
+"  rr rrrrrrrrrrrrrr "
+"    rrr  rrrrrrrrr  "
+"          r  rr rr  "
+"          rr  r  r  "
+"           rr rr rr "
+"            r  r  r "
+"           bb bb bb "
+
+"            yy   r  "
+"        rrrr  y rrr "
+"    rrrrrr rr y r r "
+"  rr rrr   rr y r   "
+"    b rr brrr y r   "
+" yy    rrrrrrr y r  "
+"   yy   rrrrrr  yr  "
+"    yyyyrrrrrrr  r  "
+"     yyyrrrrrrr  r  "
+" r b   rrrrrrrrr rr "
+"  r   rrrrrrrrrrrrr "
+"  rr rrrrrrrrrrrrrr "
+"    rrr  rrrrrrrrr  "
+"           r  r  r  "
+"           r  r  r  "
+"          rr rr rr  "
+"          r  r  r   "
+"          bb bb bb  "
+
+"            y   rrr "
+"        rrrr y rr r "
+"    rrrrrr rr yr  r "
+"  rr rrr   rr  y rr "
+" y  b rr brrr  yr   "
+" yy    rrrrrrr y r  "
+"  yyyy  rrrrrr    r "
+"    yyy rrrrrrr   r "
+"     yyyrrrrrrr   r "
+" r b  yrrrrrrrrr rr "
+"  r   rrrrrrrrrrrrr "
+"  rr rrrrrrrrrrrrrr "
+"    rrr  rrrrrrrrr  "
+"          r  rr rr  "
+"          rr  r  r  "
+"           rr rr rr "
+"            r  r  r "
+"           bb bb bb "
+
+[worluk-walk]
+
+"      bb     bb  yy "
+" yy     b   b   yyy "
+" yyy   yryyyry  yyy "
+" yyyy yrrryrrryyyyy "
+" yyyyyrrrryrrrryyyy "
+" bbyyy yryyyryyyyyb "
+"  bbyyy  yyy  yyybb "
+"  bybbyy byb yybb b "
+"  b  ybybbbbbyby  b "
+"   b   bbbbbbby   b "
+"    b   bbbbb    b  "
+"        bbbbb       "
+"        bbbbb       "
+"      bbbbbbbbb     "
+"     b  bbbbb  b    "
+"     b   bbb   b    "
+"     b    b    b    "
+"   bbb         bbb  "
+
+"       b    b       "
+"       b   b        "
+"      yryyyry       "
+"  y  yrrryrrry      "
+" bby rrrryrrrr  yyy "
+" ybyy yryyyry  yyyy "
+" ybbyy  yyy  yyyybb "
+" ybybyy byb yybbbby "
+" ybyybybbbbbybyybby "
+" yybyybbbbbbbyyybyy "
+"  yybyybbbbbyyybyy  "
+"   yyy bbbbb yyyy   "
+"       bbbbb        "
+"    bbbbbbbbb       "
+"    b  bbbbb b      "
+"     b  bbb   b     "
+"      b  b     b    "
+"    bbb        bbb  "
+
+"                    "
+"         b   b      "
+"        b   b       "
+"       yryyyry      "
+"      yrrryrrry     "
+"      rrrryrrrr     "
+"       yryyyry      "
+"    yyy  yyy  yyy   "
+" bbbbbby byb ybbbbb "
+"  byyyybbbbbbbyybb  "
+"  ybyyyybbbbbyybyyy "
+"  yybyy bbbbb byyyy "
+" yyyyy  bbbbb  yyyy "
+" yyyybbbbbbbbbbbyyy "
+" yyy b  bbbbb  byyy "
+" yy   b  bbb  b  yy "
+"       b  b  b      "
+"     bbbb   bbbb    "
+
+[wizard-walk]
+
+"         bbbb       "
+"       bbbbb        "
+"      b    b        "
+"      by y bbb      "
+"      bb  bbbbb     "
+"     bbbb bbbbbbb   "
+"    bb  bbbbb   bb  "
+"    b    bbbb    bb "
+"   bb    bbbbb    r "
+" rr      bbbbb    r "
+"        bbbbbb      "
+"       bbbbbbb      "
+"     bbbbbbbbbb     "
+"     bbbbbbbbbb     "
+"      bbbbbbbbbb    "
+"      bbbbbbbbbbb   "
+"       bbbbbbbbbbb  "
+"      bbbbbbbbbbbb  "
+
+"      bbbb          "
+"     b  bbb         "
+"     by ybb         "
+"     bb  bbbb       "
+"      bb bbbbb      "
+"     bbbbbbb bb     "
+"      b bbbb  bb    "
+"     b   bbbb  bb   "
+"    bb   bbbbb  r   "
+"  rr    bbbbbb  r   "
+"       bbbbbbb      "
+"      bbbbbbb       "
+"     bbbbbbbbb      "
+"      bbbbbbbbb     "
+"       bbbbbbbbb    "
+"        bbbbbbbbb   "
+"        bbbbbbbb    "
+"      bbbbb         "
+
+"         bbb        "
+"      bbbbb         "
+"     b bbbb         "
+"     by bbb         "
+"     bb  bbbb       "
+"      bb bbbbb      "
+"      bbbbbb bb     "
+"        bbbbb bb    "
+"       b bbbbbbb    "
+"      bb bbbbbr     "
+"    rr  bbbbbrr     "
+"       bbbbbbbb     "
+"      bbbbbbbb      "
+"      bbbbbbbb      "
+"       bbbbbb       "
+"       bbbbbb       "
+"      bbbbbbbb      "
+"      bbbbbbbb      "
+
+"       bbbb         "
+"      b  bbb        "
+"      by ybb        "
+"      bb  bbb       "
+"       bb bbbbb     "
+"       bbbbbbbbb    "
+"       bbbbbb  bb   "
+"      bb bbbb   b   "
+"     bb   bbbb  bb  "
+"   rr   bbbbbb   r  "
+"      bbbbbbbb   r  "
+"     bbbbbbbbb      "
+"     bbbbbbbb       "
+"      bbbbbbb       "
+"      bbbbbbb       "
+"       bbbbbbb      "
+"     bbbbbbbbb      "
+"         bbbbb      "
+
+[wizard-shoot]
+
+"         bbbb       "
+"        b   bb      "
+"   r    by ybb      "
+" rrrr   bb  b       "
+"    rb   b  b  rrrr "
+"    bb bbbb bbb rrb "
+"    bbbbbbbbbbbbrbb "
+"     bbbbbbbb bbbb  "
+"         bbbb  bb   "
+"         bbbb       "
+"        bbbbb       "
+"       bbbbbbb      "
+"      bbbbbbbb      "
+"     bbbbbbbbb      "
+"     bbbbbbbbbb     "
+"     bbbbbbbbbb     "
+"    bbbbbbbbbbb     "
+"   bbbbbbbbbbbbb    "
+
+"           bbb      "
+"          bb bbb    "
+"          by ybbb   "
+"          b   bb    "
+" rrrr  bbbbb  b     "
+"    rr bbbbb bbbb   "
+"     rr   bbrrrrrb  "
+"     rr   bbbbb rrr "
+"          bbbb   rr "
+"          bbb       "
+"         bbbbb      "
+"        bbbbbb      "
+"       bbbbbbb      "
+"       bbbbbb       "
+"       bbbbbb       "
+"      bbbbbbbb      "
+"      bbbbbbbbb     "
+"    bbbbbbbbbbbb    "
+
+"             bbbb   "
+"            bbbbbb  "
+"    rrrbb    ybbbbb "
+" yy   rbbbb    bbb  "
+"    rr   bbbbbbbb   "
+" yyy rrbbbbbbbbbbb  "
+"      rbb    bbbbb  "
+"       b      bbbb  "
+"              bbbb  "
+"             bbbb   "
+"           bbbbbb   "
+"          bbbbbbb   "
+"         bbbbbbb    "
+"         bbbbbbb    "
+"         bbbbbbb    "
+"        bbbbbbbbb   "
+"        bbbbbbbbbb  "
+"      bbbbbbbbbbbbb "
+
+[worrior-flash]
+
+"         rrbbbrr    "
+"         ryrbbbr    "
+"        rrrrbbbr    "
+"        rbbbbbrrrr  "
+"        rrrbbbrbbr  "
+"          rbbbbbbb  "
+" r r     rbbyybybb  "
+"rbrbrrrrrbbbyybybr  "
+"ybybyyyyyyyyyybbbr  "
+"rbrbrrryyyyyybbbbr  "
+" r r  rrrbbbbbrbbr  "
+"         rbbbbrrrr  "
+"         rbbbbbr    "
+"        rbbbbbbr    "
+"       rbbbrrbbr    "
+"      rbbbr rbbbr   "
+"    rrrbbr  rrbbr   "
+"    rbbbbr rbbbbr   "
+
+"         rryyyrr    "
+"         rbryyyr    "
+"        rrrryyyr    "
+"        ryyyyyrrrr  "
+"        rrryyyryyr  "
+"          ryyyyyyy  "
+" r r     ryybbybyy  "
+"ryryrrrrryyybbybyr  "
+"bybybbbbbbbbbbyyyr  "
+"ryryrrrbbbbbbyyyyr  "
+" r r  rrryyyyyryyr  "
+"         ryyyyrrrr  "
+"         ryyyyyr    "
+"        ryyyyyyr    "
+"       ryyyrryyr    "
+"      ryyyr ryyyr   "
+"    rrryyr  rryyr   "
+"    ryyyyr ryyyyr   "
+
+[blue-worrior-death]
+
+"                    "
+"              b     "
+"b b          bb     "
+"bybyyyyyy    bb y   "
+"b b   yyy    bbbbb  "
+"           b   bb   "
+"        y   y  r    "
+"       rbb y   b    "
+"             r y    "
+"         b b  b b   "
+"        b ry   y    "
+"     bb  y   yb r   "
+"    bbb    b        "
+"   bbb         bbb  "
+"   bb         bbbb  "
+" bbbb         bb b  "
+"                 b  "
+"                    "
+
+[yellow-worrior-death]
+
+"              y     "
+"y y          yy     "
+"ybybbbbbb    yy b   "
+"y y   bbb    yyyyy  "
+"         y    yyyy  "
+"           y   yy   "
+"        b   b  r    "
+"       ryy b   y    "
+"             r b    "
+"         y y  y y   "
+"        y rb   b    "
+"     yy  b   by r   "
+"    yyy    y        "
+"   yyy         yyy  "
+"   yy         yyyy  "
+" yyyy         yy y  "
+"                 y  "
+"                    "
+
+[common-death]
+
+"      y  b          "
+" b r   y   y b      "
+"    y b r    r      "
+"    r  b  b         "
+"  y           r     "
+"    b     by        "
+"r     ry   r b r    "
+"   r    b y         "
+"   y   b   b y      "
+"b     b  b     b    "
+"         y  y       "
+" r   y r      r     "
+"   b  b  y  r b     "
+" y r   y   r   b    "
+"   b y   r   r b    "
+"     r  y   b b     "
+"      b   y         "
+"                    "
+
+"         r   y      "
+"     y      b       "
+" y  r    b    y     "
+"      b     y   b   "
+"    b        y      "
+" r       b   r      "
+"    y      y     b  "
+"b     b  r     r    "
+"   r           y    "
+"        y           "
+" r   y   r     b    "
+"   b   y      r  b  "
+"   b    y  b    y   "
+"b     r       r     "
+"   y b   b     r    "
+"       r      y     "
+"    b      b        "
+"       r            "
+
+[explosion]
+
+"                    "
+"                    "
+"                    "
+"    r     b         "
+"r   rr r            "
+" rrrrrrr  r         "
+"  rrrrrrrrr         "
+"  rrrbrrbrrr        "
+"rrrrbbbbbrr         "
+"rrrbbbbbbrr         "
+" rrrrrbbbrr         "
+"  rr rrrrr          "
+"b r   rrr  b        "
+"      rrr           "
+"       r            "
+"                    "
+"                    "
+"                    "
+
+"   b                "
+"    b               "
+"    bbb             "
+"     bb   b         "
+"     bbbbbb     r   "
+"     brbbbb  bb     "
+"    bbrrrbbbbbbb    "
+"    bbrrrrrrrrbb    "
+"r  bbrrrrrrrrrb     "
+" bbbbrrrrrrrrbb     "
+" bbbrrrrrrrrrbb     "
+"  bbrrrrrrrrrrbb    "
+"  bbrrbbrrrbrrb     "
+"    bbbbbbbbbbb     "
+"  bb bb  bb b bbb   "
+"  b         b   b   "
+"bb          b       "
+"                    "
+
+"         y          "
+"y       y       y   "
+" y     y       y    "
+"  y    y      y     "
+"   yy yyy yy  y     "
+"    yyrrrryyy y     "
+"   yyrrrrrryyy      "
+"   yyrrrrrrryy   y  "
+"  yyrrrrrrrryy      "
+"  yyrrrrrrrryy      "
+"  yyrrrrrrrryy      "
+"  yyyrrrrrrrryy     "
+" y  yryyyrrrry      "
+"y   yy  yyrryyy     "
+"         yyyy yyy   "
+"         y      y   "
+"        y           "
+"       y            "
dow.cabal view
@@ -1,47 +1,47 @@-Name:                dow-Version:             0.2.5-Cabal-Version:       >= 1.2-Synopsis:            Dungeons of Wor-Category:            game, reactivity, FRP-Description:--  Dungeons of Wor is a homage to the classic arcade game, Wizard of-  Wor.  It uses the artwork and levels from the Astrocade version, but-  the gameplay mechanics differ from the original in several ways.-  .-  This game is also an experiment in functional reactive programming,-  so it might be a useful resource to anyone interested in this topic.-  It was coded using the simple version of Elerea, which provides-  discrete streams as first-class values.--Author:              Patai Gergely-Maintainer:          Patai Gergely (patai.gergely@gmail.com)-Copyright:           (c) 2010-2011, Patai Gergely-License:             BSD3-License-File:        LICENSE-Stability:           experimental-Build-Type:          Simple-Extra-Source-Files:-  src/Actor.hs-  src/Game.hs-  src/GraphUtils.hs-  src/HighScore.hs-  src/Level.hs-  src/Render.hs-  src/Sprites.hs-  src/Text.hs-  src/Utils.hs-  src/Vector.hs--Data-Files:-  README-  CHANGES-  data/charset.txt-  data/levels.txt-  data/sprites.txt--Executable dow-  HS-Source-Dirs:    src-  Main-IS:           Main.hs-  Build-Depends:     base >= 4 && < 5, elerea >= 2.5.0, OpenGL >= 2.4, GLFW >= 0.5.2 && < 0.5.3, array, directory, mersenne-random-  GHC-Options:       -O2 -fno-warn-deprecated-flags+Name:                dow
+Version:             0.2.6
+Cabal-Version:       >= 1.6
+Synopsis:            Dungeons of Wor
+Category:            game, reactivity, FRP
+Description:
+
+  Dungeons of Wor is a homage to the classic arcade game, Wizard of
+  Wor.  It uses the artwork and levels from the Astrocade version, but
+  the gameplay mechanics differ from the original in several ways.
+  .
+  This game is also an experiment in functional reactive programming,
+  so it might be a useful resource to anyone interested in this topic.
+  It was coded using the simple version of Elerea, which provides
+  discrete streams as first-class values.
+
+Author:              Patai Gergely
+Maintainer:          Patai Gergely (patai.gergely@gmail.com)
+Copyright:           (c) 2010-2011, Patai Gergely
+License:             BSD3
+License-File:        LICENSE
+Stability:           experimental
+Build-Type:          Simple
+Extra-Source-Files:
+  src/Actor.hs
+  src/Game.hs
+  src/GraphUtils.hs
+  src/HighScore.hs
+  src/Level.hs
+  src/Render.hs
+  src/Sprites.hs
+  src/Text.hs
+  src/Utils.hs
+  src/Vector.hs
+
+Data-Files:
+  README
+  CHANGES
+  data/charset.txt
+  data/levels.txt
+  data/sprites.txt
+
+Executable dow
+  HS-Source-Dirs:    src
+  Main-IS:           Main.hs
+  Build-Depends:     base >= 4 && < 5, elerea == 2.9.*, OpenGL >= 2.4, GLFW >= 0.5.2 && < 0.5.3, array, directory, mersenne-random
+  GHC-Options:       -O2 -fno-warn-deprecated-flags
src/Actor.hs view
@@ -1,117 +1,117 @@-module Actor where--import Data.Array-import Data.List-import Data.Maybe-import Graphics.Rendering.OpenGL hiding (position)--import Level-import Sprites-import Vector--data Skin = Skin-            { walkAnimation :: [TextureObject]-            , shootAnimation :: [TextureObject]-            , deathAnimation :: [TextureObject]-            }--data ActorType = BlueWorrior | YellowWorrior | Burwor | Garwor | Thorwor | Worluk | Wizard-               deriving (Eq, Ord, Enum, Ix, Show)--data Action = Entering Direction Bool | Walking | Shooting | KilledBy ActorType deriving Eq--data Actor = Actor-             { actorType :: ActorType-             , position :: Vec-             , facing :: Direction-             , action :: Action-             , animation :: [TextureObject]-             , skin :: Skin-             , speed :: Int-             , animSpeed :: Int-             , tick :: Int-             }--mkActor :: Array ActorType Skin -> ActorType -> Vec -> Actor-mkActor skins atype pos =-  Actor { actorType = atype-        , position = pos-        , facing = East-        , action = Walking-        , animation = walkAnimation (skins ! atype)-        , skin = skins ! atype-        , speed = 1-        , animSpeed = 2-        , tick = 0-        }--createSkins :: SpriteStore -> Array ActorType Skin-createSkins sprites = array (BlueWorrior,Wizard)-  [(BlueWorrior,-    Skin { walkAnimation = cycle (anim "blue-worrior-walk")-         , shootAnimation = anim "blue-worrior-shoot"-         , deathAnimation = concat (replicate 5 (anim "worrior-flash")) ++-                            anim "blue-worrior-death" ++ anim "common-death"-         }-   )-  ,(YellowWorrior,-    Skin { walkAnimation = cycle (anim "yellow-worrior-walk")-         , shootAnimation = anim "yellow-worrior-shoot"-         , deathAnimation = concat (replicate 5 (anim "worrior-flash")) ++-                            anim "yellow-worrior-death" ++ anim "common-death"-         }-   )-  ,(Burwor,-    Skin { walkAnimation = cycle (anim "burwor-walk")-         , shootAnimation = anim "burwor-shoot"-         , deathAnimation = anim "explosion" ++ anim "common-death"-         }-   )-  ,(Garwor,-    Skin { walkAnimation = cycle (anim "garwor-walk")-         , shootAnimation = anim "garwor-shoot"-         , deathAnimation = anim "explosion" ++ anim "common-death"-         }-   )-  ,(Thorwor,-    Skin { walkAnimation = cycle (anim "thorwor-walk")-         , shootAnimation = anim "thorwor-shoot"-         , deathAnimation = anim "explosion" ++ anim "common-death"-         }-   )-  ,(Worluk,-    Skin { walkAnimation = cycle (anim "worluk-walk")-         , shootAnimation = []-         , deathAnimation = anim "explosion" ++ anim "common-death"-         }-   )-  ,(Wizard,-    Skin { walkAnimation = cycle (anim "wizard-walk")-         , shootAnimation = anim "wizard-shoot"-         , deathAnimation = []-         }-   )]-  where anim name = maybe (error ("Cannot find animation " ++ name)) snd-                    (find ((==name).fst) sprites)--isDead :: Actor -> Bool-isDead a = case action a of-  KilledBy _ -> True-  _          -> False--isAlive :: Actor -> Bool-isAlive = not . isDead--justDied :: Actor -> Bool-justDied Actor { action = KilledBy _, animation = [_], tick = 0 } = True-justDied _ = False--actorValue :: Actor -> Int-actorValue a = case actorType a of-  Burwor        -> 100-  Garwor        -> 200-  Thorwor       -> 500-  Worluk        -> 1000-  Wizard        -> 2500-  BlueWorrior   -> 1000-  YellowWorrior -> 1000+module Actor where
+
+import Data.Array
+import Data.List
+import Data.Maybe
+import Graphics.Rendering.OpenGL hiding (position)
+
+import Level
+import Sprites
+import Vector
+
+data Skin = Skin
+            { walkAnimation :: [TextureObject]
+            , shootAnimation :: [TextureObject]
+            , deathAnimation :: [TextureObject]
+            }
+
+data ActorType = BlueWorrior | YellowWorrior | Burwor | Garwor | Thorwor | Worluk | Wizard
+               deriving (Eq, Ord, Enum, Ix, Show)
+
+data Action = Entering Direction Bool | Walking | Shooting | KilledBy ActorType deriving Eq
+
+data Actor = Actor
+             { actorType :: ActorType
+             , position :: Vec
+             , facing :: Direction
+             , action :: Action
+             , animation :: [TextureObject]
+             , skin :: Skin
+             , speed :: Int
+             , animSpeed :: Int
+             , tick :: Int
+             }
+
+mkActor :: Array ActorType Skin -> ActorType -> Vec -> Actor
+mkActor skins atype pos =
+  Actor { actorType = atype
+        , position = pos
+        , facing = East
+        , action = Walking
+        , animation = walkAnimation (skins ! atype)
+        , skin = skins ! atype
+        , speed = 1
+        , animSpeed = 2
+        , tick = 0
+        }
+
+createSkins :: SpriteStore -> Array ActorType Skin
+createSkins sprites = array (BlueWorrior,Wizard)
+  [(BlueWorrior,
+    Skin { walkAnimation = cycle (anim "blue-worrior-walk")
+         , shootAnimation = anim "blue-worrior-shoot"
+         , deathAnimation = concat (replicate 5 (anim "worrior-flash")) ++
+                            anim "blue-worrior-death" ++ anim "common-death"
+         }
+   )
+  ,(YellowWorrior,
+    Skin { walkAnimation = cycle (anim "yellow-worrior-walk")
+         , shootAnimation = anim "yellow-worrior-shoot"
+         , deathAnimation = concat (replicate 5 (anim "worrior-flash")) ++
+                            anim "yellow-worrior-death" ++ anim "common-death"
+         }
+   )
+  ,(Burwor,
+    Skin { walkAnimation = cycle (anim "burwor-walk")
+         , shootAnimation = anim "burwor-shoot"
+         , deathAnimation = anim "explosion" ++ anim "common-death"
+         }
+   )
+  ,(Garwor,
+    Skin { walkAnimation = cycle (anim "garwor-walk")
+         , shootAnimation = anim "garwor-shoot"
+         , deathAnimation = anim "explosion" ++ anim "common-death"
+         }
+   )
+  ,(Thorwor,
+    Skin { walkAnimation = cycle (anim "thorwor-walk")
+         , shootAnimation = anim "thorwor-shoot"
+         , deathAnimation = anim "explosion" ++ anim "common-death"
+         }
+   )
+  ,(Worluk,
+    Skin { walkAnimation = cycle (anim "worluk-walk")
+         , shootAnimation = []
+         , deathAnimation = anim "explosion" ++ anim "common-death"
+         }
+   )
+  ,(Wizard,
+    Skin { walkAnimation = cycle (anim "wizard-walk")
+         , shootAnimation = anim "wizard-shoot"
+         , deathAnimation = []
+         }
+   )]
+  where anim name = maybe (error ("Cannot find animation " ++ name)) snd
+                    (find ((==name).fst) sprites)
+
+isDead :: Actor -> Bool
+isDead a = case action a of
+  KilledBy _ -> True
+  _          -> False
+
+isAlive :: Actor -> Bool
+isAlive = not . isDead
+
+justDied :: Actor -> Bool
+justDied Actor { action = KilledBy _, animation = [_], tick = 0 } = True
+justDied _ = False
+
+actorValue :: Actor -> Int
+actorValue a = case actorType a of
+  Burwor        -> 100
+  Garwor        -> 200
+  Thorwor       -> 500
+  Worluk        -> 1000
+  Wizard        -> 2500
+  BlueWorrior   -> 1000
+  YellowWorrior -> 1000
src/Game.hs view
@@ -1,292 +1,292 @@-{-# LANGUAGE RecursiveDo #-}--module Game where--import Control.Applicative-import Control.Monad-import Control.Monad.Fix-import Data.Array-import Data.List-import Data.Maybe-import FRP.Elerea.Simple--import Actor-import GraphUtils-import HighScore-import Level-import Sprites-import Utils-import Vector--numberOfLives = 5--data LevelState = LevelState-                  { level :: Level-                  , actors :: [Actor]-                  , bullets :: [(ActorType,Vec)]-                  , shooters :: [ActorType]-                  }--keySet1 = fst-keySet2 = snd--keyDir (True,_,_,_,_) = Just North-keyDir (_,True,_,_,_) = Just South-keyDir (_,_,True,_,_) = Just West-keyDir (_,_,_,True,_) = Just East-keyDir _              = Nothing--keyShoot (_,_,_,_,s) = s--keyAny k = keyShoot k || isJust (keyDir k)--game highScore storeScore (renderGame,renderMenu) closeAction newActor levels keyPress = do-  let firstTrue s = do-        mask <- delay False =<< transfer False (||) s-        return (liftA2 (&&) (not <$> mask) s)--      mkGame 0 = playGame storeScore renderGame newActor levels keyPress 1-      mkGame 1 = playGame storeScore renderGame newActor levels keyPress 2-      mkGame _ = return (pure (void closeAction),pure True)--  keys <- memo (keySet1 <$> keyPress)-  (output,_) <- switcher . flip fmap highScore $ \score -> do-    (menu,pick) <- displayMenu (renderMenu score) ["ONE PLAYER GAME","TWO PLAYER GAME","QUIT"] keys-    picked <- firstTrue (keyShoot <$> keys)-    gameSource <- generator (toMaybe <$> picked <*> (mkGame <$> pick))-    fullOutput <- menu --> gameSource-    return (fst =<< fullOutput,snd =<< fullOutput)--  return output--displayMenu renderMenu items keys = do-  let val False = 0-      val True  = 1--  up <- edge ((==Just North) . keyDir <$> keys)-  down <- edge ((==Just South) . keyDir <$> keys)-  item <- transfer2 0 (\u d i -> (i + val d - val u) `mod` length items) up down--  return ((renderMenu items <$> item,pure False),item)--playGame storeScore renderFun newActor levels keyPress numPlayers = mdo-  let startLevel level enemyCount = playLevel newActor keyPress level numPlayers lives' enemyCount-      players = take numPlayers [YellowWorrior,BlueWorrior]--      pickLevel cnt rnd = case () of-        _ | cnt == 4         -> findLevel (=="arena")-        _ | cnt < 8          -> findLevel ((=='b').head)-        _ | cnt `mod` 6 == 1 -> findLevel (=="pit")-        otherwise            -> findLevel ((=='w').head)-        where findLevel p = pickOne (filter (p.levelName) levels)-              pickOne xs = xs !! (rnd `mod` length xs)--      accumScore player state prev = max 0 $ prev +-                                     (sum . map killScore . actors) state --                                     10 * (length . filter (==player) . shooters) state-        where killScore a = if justDied a && action a == KilledBy player then actorValue a else 0--      accumLives player state prev = max 0 $ prev + (sum . map lifeLost . actors) state-        where lifeLost a = if justDied a && actorType a == player then -1 else 0--  levelNoise <- noise-  (state,trigLevel) <- switcher (startLevel <$> (pickLevel <$> levelCount <*> levelNoise) <*> levelCount)-  trigLevel' <- delay False trigLevel-  levelCount <- transfer 1 (\win cnt -> if win then cnt+1 else cnt) trigLevel'-  scores <- memo =<< (sequence <$> forM players (\t -> transfer 0 (accumScore t) state))-  lives <- memo =<< (sequence <$> forM players (\t -> transfer numberOfLives (accumLives t) state))-  lives' <- delay (replicate numPlayers numberOfLives) lives--  gameOver <- memo (all (==0) <$> lives)--  return (liftA2 (>>)-          ((\c s -> when c (storeScore s)) <$> gameOver <*> scores)-          (renderFun <$> state <*> levelCount <*> scores <*> lives)-         ,gameOver-         )--playLevel newActor keyPress level numPlayers lives enemyCount = mdo-  let mkEnemy etype = enemy (newActor etype) (if etype == Worluk then 2 else 1) level bullets--      mkShot c plr = if c && canShoot-                     then (:[]) <$> bullet (actorType plr) (position plr) (facing plr)-                     else return []-        where canShoot = case action plr of-                Walking  -> True-                Shooting -> True-                _        -> False--      spawnEnemies oldEnemies = concatMap (spawnEnemy (length oldEnemies == 1)) oldEnemies-      spawnEnemy isLast enemy = if justDied enemy then-                                    case actorType enemy of-                                      Burwor  -> [mkEnemy Garwor <$> (position <$> head players)]-                                      Garwor  -> [mkEnemy Thorwor <$> (position <$> head players)]-                                      Thorwor -> if isLast then [mkEnemy Worluk <$> (position <$> head players)] else []-                                      _       -> []-                                else []--      (lw,lh) = levelSize level-      playerInit = take numPlayers [(YellowWorrior,keySet1,1),(BlueWorrior,keySet2,0)]--  (players,bulletSources) <- fmap unzip $ forM (zip playerInit [0..]) $ \((worType,keySet,pix),lix) -> do-    shoot <- edge (keyShoot . keySet <$> keyPress)--    (player,_respawn) <- switcher . flip fmap lives $ \ls -> do-      let (pedir,py,px) = entrances level !! pix-          playerInit = (newActor worType (V (px*fieldSize) ((lh-py-1)*fieldSize)))-                         { action = Entering pedir False-                         , facing = [East,West] !! pix-                         }-          respawn plr = ls !! lix > 1 && null (animation plr)--      if ls !! lix == 0-        then return (pure (playerInit { animation = [] }),pure False)-        else do plr <- transfer3 playerInit (movePlayer level) (keyDir . keySet <$> keyPress) shoot enemies'-                return (plr, respawn <$> plr)--    bulletSource <- generator (mkShot <$> shoot <*> player)-    return (player,bulletSource)--  newBullets <- memo (concat <$> sequence bulletSources)-  bullets <- collection newBullets (notHitAnything level <$> enemies')-  let shooters = fmap (map fst) . sequence =<< newBullets--  initialEnemies <- replicateM enemyCount (mkEnemy Burwor (V (-3*fieldSize) (-3*fieldSize)))-  spawnedEnemies <- generator (sequence <$> (sequence . spawnEnemies =<< enemies'))-  enemySource <- delay initialEnemies spawnedEnemies-  enemies <- collection enemySource (pure (not . null . animation))-  enemies' <- delay [] enemies--  return (LevelState level <$> (liftA2 (++) (sequence players) enemies) <*> bullets <*> shooters-         ,null <$> enemies-         )--bullet src pos dir = fmap ((,) src) <$> stateful pos (+3*dirVec dir)--enemy newActor moveSpeed level bullets (V playerX playerY) = mdo-  let actorInit = (newActor (fromIntegral fieldSize*startPos)) { speed = moveSpeed, animSpeed = 4 }-      startPos = if abs (startX-playerX `div` fieldSize) < 3 && abs (startY-playerY `div` fieldSize) < 3-                 then V ((startX + lw `div` 2) `mod` lw) ((startY + lh `div` 2) `mod` lh)-                 else V startX startY-      (lw,lh) = levelSize level--  startX <- (`mod` lw) <$> getRandom-  startY <- (`mod` lh) <$> getRandom-  startDir <- toEnum . (`mod` 4) <$> getRandom-  dirNoise <- noise--  actorInput <- startDir --> newDir level <$> dirNoise <*> actor'-  actor <- transfer2 actorInit (moveEnemy level) actorInput bullets-  actor' <- delay actorInit actor-  return actor--notHitAnything lev es (_,pos@(V px py)) =-  (sy <  fieldMid-bs || North `elem` legals) &&-  (sx <  fieldMid-bs || East  `elem` legals) &&-  (sy > -fieldMid+bs || South `elem` legals) &&-  (sx > -fieldMid+bs || West  `elem` legals) &&-  not hitExplosion-  where legals = legalMovesAt lev (fieldPos pos)-        (sx,sy) = fieldSub pos-        bs = 3--        hitExplosion = any hitBy es-        hitBy e = isDead e && abs (ex-px) < fieldMid && abs (ey-py) < fieldMid-          where V ex ey = position e--newDir lev rnd act = if canMove lev act && (isHalfway || rnd `mod` 1000 < 500)-                     then Nothing-                     else Just pickedDir-  where legal = legalMovesAt lev (fieldPos (position act))-        dirPool = if length legal < 2 then legal else legal \\ [turnBack (facing act)]-        pickedDir = dirPool !! (rnd `mod` length dirPool)-        isHalfway = halfway (fieldSub (position act)) (facing act)--movePlayer level mov shoot enemies plr = case action plr of-  Entering dir False -> let startMoving = isJust mov-                        in plr { action = Entering dir startMoving-                               , position = position plr + if startMoving then dirVec dir else 0-                               }-  Entering dir True -> if fieldSub (position plr) == (0,0)-                       then plr { action = Walking }-                       else plr { position = position plr + dirVec dir }-  _ -> case mov of-    Nothing  -> if action plr' /= Walking then animate plr' else plr'-    Just dir -> animate (if isAlive plr then move level dir plr' else plr')-  where plr' = case killed of-          _ | isDead plr -> plr-          Just enemy     -> plr { animation = deathAnimation (skin plr)-                                , action = KilledBy (actorType enemy)-                                , animSpeed = 6-                                }-          _ | shoot      -> plr { animation = shootAnimation (skin plr)-                                , action = Shooting-                                }-          otherwise      -> plr-        killed = find ((==getXY plr).getXY) [enemy | enemy <- enemies, isAlive enemy]-        getXY = fieldPos.position--moveEnemy level dir bs act = animate (mv act')-  where act' = case hit of-          Just (killer,_) -> act { animation = deathAnimation (skin act)-                                 , action = KilledBy killer-                                 }-          Nothing -> act-        mv = if isAlive act' then move level dir else id-        hit = find hitBy bs-        V px py = position act-        hitBy (_,(V bx by)) = abs (bx-px) < fieldMid && abs (by-py) < fieldMid--move :: Level -> Direction -> Actor -> Actor-move lev dir ent = mv ent $ fmap snd . find fst $-                   [(isHalfway dir || isAtMid && dirIsLegal, dir)-                   ,(not isAtMid && dirIsLegal, dir')-                   ,(isHalfway entDir || legalMove entDir, entDir)-                   ]-  where mv e Nothing  = e-        mv e (Just d) = e { position = position e + fromIntegral (speed e) * dirVec d-                          , facing = d-                          }--        dirIsLegal = legalMove dir-        legalMove d = d `elem` legalMovesAt lev (fieldPos (position ent))--        isAtMid = atFieldMid sub dir-        isHalfway = halfway sub--        sub@(sx,sy) = fieldSub (position ent)--        entDir = facing ent-        dir' = case entDir of-          North | sy > 0 -> South-          East  | sx > 0 -> West-          South | sy < 0 -> North-          West  | sx < 0 -> East-          otherwise      -> entDir--canMove :: Level -> Actor -> Bool-canMove lev ent = halfway || facing ent `elem` legalMovesAt lev (fieldPos (position ent))-  where (sx,sy) = fieldSub (position ent)-        halfway = sx /= 0 || sy /= 0--legalMovesAt lev pos = legalMoves lev ! ix pos-  where ix (x,y) = (snd (levelSize lev)-1-y,x)--animate :: Actor -> Actor-animate ent = let ent' = ent { tick = (tick ent+1) `mod` animSpeed ent }-                  adv = if tick ent' == 0 then 1 else 0-                  animation' = drop adv (animation ent') in-  case action ent' of-    Entering _ _ -> ent'-    Walking -> ent' { animation = animation' }-    Shooting -> if null animation'-                then ent' { animation = walkAnimation (skin ent')-                          , action = Walking-                          }-                else ent' { animation = animation' }-    KilledBy _ -> ent' { animation = animation' }--dirVec North = V 0 1-dirVec East  = V 1 0-dirVec South = V 0 (-1)-dirVec West  = V (-1) 0+{-# LANGUAGE RecursiveDo #-}
+
+module Game where
+
+import Control.Applicative
+import Control.Monad
+import Control.Monad.Fix
+import Data.Array
+import Data.List
+import Data.Maybe
+import FRP.Elerea.Simple
+
+import Actor
+import GraphUtils
+import HighScore
+import Level
+import Sprites
+import Utils
+import Vector
+
+numberOfLives = 5
+
+data LevelState = LevelState
+                  { level :: Level
+                  , actors :: [Actor]
+                  , bullets :: [(ActorType,Vec)]
+                  , shooters :: [ActorType]
+                  }
+
+keySet1 = fst
+keySet2 = snd
+
+keyDir (True,_,_,_,_) = Just North
+keyDir (_,True,_,_,_) = Just South
+keyDir (_,_,True,_,_) = Just West
+keyDir (_,_,_,True,_) = Just East
+keyDir _              = Nothing
+
+keyShoot (_,_,_,_,s) = s
+
+keyAny k = keyShoot k || isJust (keyDir k)
+
+game highScore storeScore (renderGame,renderMenu) closeAction newActor levels keyPress = do
+  let firstTrue s = do
+        mask <- delay False =<< transfer False (||) s
+        return (liftA2 (&&) (not <$> mask) s)
+
+      mkGame 0 = playGame storeScore renderGame newActor levels keyPress 1
+      mkGame 1 = playGame storeScore renderGame newActor levels keyPress 2
+      mkGame _ = return (pure (void closeAction),pure True)
+
+  keys <- memo (keySet1 <$> keyPress)
+  (output,_) <- switcher . flip fmap highScore $ \score -> do
+    (menu,pick) <- displayMenu (renderMenu score) ["ONE PLAYER GAME","TWO PLAYER GAME","QUIT"] keys
+    picked <- firstTrue (keyShoot <$> keys)
+    gameSource <- generator (toMaybe <$> picked <*> (mkGame <$> pick))
+    fullOutput <- menu --> gameSource
+    return (fst =<< fullOutput,snd =<< fullOutput)
+
+  return output
+
+displayMenu renderMenu items keys = do
+  let val False = 0
+      val True  = 1
+
+  up <- edge ((==Just North) . keyDir <$> keys)
+  down <- edge ((==Just South) . keyDir <$> keys)
+  item <- transfer2 0 (\u d i -> (i + val d - val u) `mod` length items) up down
+
+  return ((renderMenu items <$> item,pure False),item)
+
+playGame storeScore renderFun newActor levels keyPress numPlayers = mdo
+  let startLevel level enemyCount = playLevel newActor keyPress level numPlayers lives' enemyCount
+      players = take numPlayers [YellowWorrior,BlueWorrior]
+
+      pickLevel cnt rnd = case () of
+        _ | cnt == 4         -> findLevel (=="arena")
+        _ | cnt < 8          -> findLevel ((=='b').head)
+        _ | cnt `mod` 6 == 1 -> findLevel (=="pit")
+        otherwise            -> findLevel ((=='w').head)
+        where findLevel p = pickOne (filter (p.levelName) levels)
+              pickOne xs = xs !! (rnd `mod` length xs)
+
+      accumScore player state prev = max 0 $ prev +
+                                     (sum . map killScore . actors) state -
+                                     10 * (length . filter (==player) . shooters) state
+        where killScore a = if justDied a && action a == KilledBy player then actorValue a else 0
+
+      accumLives player state prev = max 0 $ prev + (sum . map lifeLost . actors) state
+        where lifeLost a = if justDied a && actorType a == player then -1 else 0
+
+  levelNoise <- noise
+  (state,trigLevel) <- switcher (startLevel <$> (pickLevel <$> levelCount <*> levelNoise) <*> levelCount)
+  trigLevel' <- delay False trigLevel
+  levelCount <- transfer 1 (\win cnt -> if win then cnt+1 else cnt) trigLevel'
+  scores <- memo =<< (sequence <$> forM players (\t -> transfer 0 (accumScore t) state))
+  lives <- memo =<< (sequence <$> forM players (\t -> transfer numberOfLives (accumLives t) state))
+  lives' <- delay (replicate numPlayers numberOfLives) lives
+
+  gameOver <- memo (all (==0) <$> lives)
+
+  return (liftA2 (>>)
+          ((\c s -> when c (storeScore s)) <$> gameOver <*> scores)
+          (renderFun <$> state <*> levelCount <*> scores <*> lives)
+         ,gameOver
+         )
+
+playLevel newActor keyPress level numPlayers lives enemyCount = mdo
+  let mkEnemy etype = enemy (newActor etype) (if etype == Worluk then 2 else 1) level bullets
+
+      mkShot c plr = if c && canShoot
+                     then (:[]) <$> bullet (actorType plr) (position plr) (facing plr)
+                     else return []
+        where canShoot = case action plr of
+                Walking  -> True
+                Shooting -> True
+                _        -> False
+
+      spawnEnemies oldEnemies = concatMap (spawnEnemy (length oldEnemies == 1)) oldEnemies
+      spawnEnemy isLast enemy = if justDied enemy then
+                                    case actorType enemy of
+                                      Burwor  -> [mkEnemy Garwor <$> (position <$> head players)]
+                                      Garwor  -> [mkEnemy Thorwor <$> (position <$> head players)]
+                                      Thorwor -> if isLast then [mkEnemy Worluk <$> (position <$> head players)] else []
+                                      _       -> []
+                                else []
+
+      (lw,lh) = levelSize level
+      playerInit = take numPlayers [(YellowWorrior,keySet1,1),(BlueWorrior,keySet2,0)]
+
+  (players,bulletSources) <- fmap unzip $ forM (zip playerInit [0..]) $ \((worType,keySet,pix),lix) -> do
+    shoot <- edge (keyShoot . keySet <$> keyPress)
+
+    (player,_respawn) <- switcher . flip fmap lives $ \ls -> do
+      let (pedir,py,px) = entrances level !! pix
+          playerInit = (newActor worType (V (px*fieldSize) ((lh-py-1)*fieldSize)))
+                         { action = Entering pedir False
+                         , facing = [East,West] !! pix
+                         }
+          respawn plr = ls !! lix > 1 && null (animation plr)
+
+      if ls !! lix == 0
+        then return (pure (playerInit { animation = [] }),pure False)
+        else do plr <- transfer3 playerInit (movePlayer level) (keyDir . keySet <$> keyPress) shoot enemies'
+                return (plr, respawn <$> plr)
+
+    bulletSource <- generator (mkShot <$> shoot <*> player)
+    return (player,bulletSource)
+
+  newBullets <- memo (concat <$> sequence bulletSources)
+  bullets <- collection newBullets (notHitAnything level <$> enemies')
+  let shooters = fmap (map fst) . sequence =<< newBullets
+
+  initialEnemies <- replicateM enemyCount (mkEnemy Burwor (V (-3*fieldSize) (-3*fieldSize)))
+  spawnedEnemies <- generator (sequence <$> (sequence . spawnEnemies =<< enemies'))
+  enemySource <- delay initialEnemies spawnedEnemies
+  enemies <- collection enemySource (pure (not . null . animation))
+  enemies' <- delay [] enemies
+
+  return (LevelState level <$> (liftA2 (++) (sequence players) enemies) <*> bullets <*> shooters
+         ,null <$> enemies
+         )
+
+bullet src pos dir = fmap ((,) src) <$> stateful pos (+3*dirVec dir)
+
+enemy newActor moveSpeed level bullets (V playerX playerY) = mdo
+  let actorInit = (newActor (fromIntegral fieldSize*startPos)) { speed = moveSpeed, animSpeed = 4 }
+      startPos = if abs (startX-playerX `div` fieldSize) < 3 && abs (startY-playerY `div` fieldSize) < 3
+                 then V ((startX + lw `div` 2) `mod` lw) ((startY + lh `div` 2) `mod` lh)
+                 else V startX startY
+      (lw,lh) = levelSize level
+
+  startX <- (`mod` lw) <$> getRandom
+  startY <- (`mod` lh) <$> getRandom
+  startDir <- toEnum . (`mod` 4) <$> getRandom
+  dirNoise <- noise
+
+  actorInput <- startDir --> newDir level <$> dirNoise <*> actor'
+  actor <- transfer2 actorInit (moveEnemy level) actorInput bullets
+  actor' <- delay actorInit actor
+  return actor
+
+notHitAnything lev es (_,pos@(V px py)) =
+  (sy <  fieldMid-bs || North `elem` legals) &&
+  (sx <  fieldMid-bs || East  `elem` legals) &&
+  (sy > -fieldMid+bs || South `elem` legals) &&
+  (sx > -fieldMid+bs || West  `elem` legals) &&
+  not hitExplosion
+  where legals = legalMovesAt lev (fieldPos pos)
+        (sx,sy) = fieldSub pos
+        bs = 3
+
+        hitExplosion = any hitBy es
+        hitBy e = isDead e && abs (ex-px) < fieldMid && abs (ey-py) < fieldMid
+          where V ex ey = position e
+
+newDir lev rnd act = if canMove lev act && (isHalfway || rnd `mod` 1000 < 500)
+                     then Nothing
+                     else Just pickedDir
+  where legal = legalMovesAt lev (fieldPos (position act))
+        dirPool = if length legal < 2 then legal else legal \\ [turnBack (facing act)]
+        pickedDir = dirPool !! (rnd `mod` length dirPool)
+        isHalfway = halfway (fieldSub (position act)) (facing act)
+
+movePlayer level mov shoot enemies plr = case action plr of
+  Entering dir False -> let startMoving = isJust mov
+                        in plr { action = Entering dir startMoving
+                               , position = position plr + if startMoving then dirVec dir else 0
+                               }
+  Entering dir True -> if fieldSub (position plr) == (0,0)
+                       then plr { action = Walking }
+                       else plr { position = position plr + dirVec dir }
+  _ -> case mov of
+    Nothing  -> if action plr' /= Walking then animate plr' else plr'
+    Just dir -> animate (if isAlive plr then move level dir plr' else plr')
+  where plr' = case killed of
+          _ | isDead plr -> plr
+          Just enemy     -> plr { animation = deathAnimation (skin plr)
+                                , action = KilledBy (actorType enemy)
+                                , animSpeed = 6
+                                }
+          _ | shoot      -> plr { animation = shootAnimation (skin plr)
+                                , action = Shooting
+                                }
+          otherwise      -> plr
+        killed = find ((==getXY plr).getXY) [enemy | enemy <- enemies, isAlive enemy]
+        getXY = fieldPos.position
+
+moveEnemy level dir bs act = animate (mv act')
+  where act' = case hit of
+          Just (killer,_) -> act { animation = deathAnimation (skin act)
+                                 , action = KilledBy killer
+                                 }
+          Nothing -> act
+        mv = if isAlive act' then move level dir else id
+        hit = find hitBy bs
+        V px py = position act
+        hitBy (_,(V bx by)) = abs (bx-px) < fieldMid && abs (by-py) < fieldMid
+
+move :: Level -> Direction -> Actor -> Actor
+move lev dir ent = mv ent $ fmap snd . find fst $
+                   [(isHalfway dir || isAtMid && dirIsLegal, dir)
+                   ,(not isAtMid && dirIsLegal, dir')
+                   ,(isHalfway entDir || legalMove entDir, entDir)
+                   ]
+  where mv e Nothing  = e
+        mv e (Just d) = e { position = position e + fromIntegral (speed e) * dirVec d
+                          , facing = d
+                          }
+
+        dirIsLegal = legalMove dir
+        legalMove d = d `elem` legalMovesAt lev (fieldPos (position ent))
+
+        isAtMid = atFieldMid sub dir
+        isHalfway = halfway sub
+
+        sub@(sx,sy) = fieldSub (position ent)
+
+        entDir = facing ent
+        dir' = case entDir of
+          North | sy > 0 -> South
+          East  | sx > 0 -> West
+          South | sy < 0 -> North
+          West  | sx < 0 -> East
+          otherwise      -> entDir
+
+canMove :: Level -> Actor -> Bool
+canMove lev ent = halfway || facing ent `elem` legalMovesAt lev (fieldPos (position ent))
+  where (sx,sy) = fieldSub (position ent)
+        halfway = sx /= 0 || sy /= 0
+
+legalMovesAt lev pos = legalMoves lev ! ix pos
+  where ix (x,y) = (snd (levelSize lev)-1-y,x)
+
+animate :: Actor -> Actor
+animate ent = let ent' = ent { tick = (tick ent+1) `mod` animSpeed ent }
+                  adv = if tick ent' == 0 then 1 else 0
+                  animation' = drop adv (animation ent') in
+  case action ent' of
+    Entering _ _ -> ent'
+    Walking -> ent' { animation = animation' }
+    Shooting -> if null animation'
+                then ent' { animation = walkAnimation (skin ent')
+                          , action = Walking
+                          }
+                else ent' { animation = animation' }
+    KilledBy _ -> ent' { animation = animation' }
+
+dirVec North = V 0 1
+dirVec East  = V 1 0
+dirVec South = V 0 (-1)
+dirVec West  = V (-1) 0
src/GraphUtils.hs view
@@ -1,31 +1,31 @@-module GraphUtils where--import Data.Word-import Foreign.Marshal-import Foreign.Ptr-import Graphics.Rendering.OpenGL--createTexture :: Int -> Int -> Bool -> (Ptr Word8 -> IO ()) -> IO TextureObject-createTexture width height looped fill = allocaArray (width*height*4) $ \tex -> do-  fill tex-  [tid] <- genObjectNames 1-  textureBinding Texture2D $= Just tid-  if looped-    then do textureWrapMode Texture2D S $= (Repeated,Repeat)-            textureWrapMode Texture2D T $= (Repeated,Repeat)-    else do textureWrapMode Texture2D S $= (Mirrored,Clamp)-            textureWrapMode Texture2D T $= (Mirrored,Clamp)-  build2DMipmaps Texture2D RGBA' (fromIntegral width) (fromIntegral height) (PixelData RGBA UnsignedByte tex)-  return tid--vertex3 :: GLfloat -> GLfloat -> GLfloat -> IO ()-vertex3 x y z = vertex $ Vertex3 x y z--texCoord2 :: GLfloat -> GLfloat -> IO ()-texCoord2 x y = texCoord $ TexCoord2 x y--explodeList :: Int -> [a] -> [a]-explodeList = concatMap . replicate--explodeMatrix :: Int -> [[a]] -> [[a]]-explodeMatrix n = map (explodeList n) . explodeList n+module GraphUtils where
+
+import Data.Word
+import Foreign.Marshal
+import Foreign.Ptr
+import Graphics.Rendering.OpenGL
+
+createTexture :: Int -> Int -> Bool -> (Ptr Word8 -> IO ()) -> IO TextureObject
+createTexture width height looped fill = allocaArray (width*height*4) $ \tex -> do
+  fill tex
+  [tid] <- genObjectNames 1
+  textureBinding Texture2D $= Just tid
+  if looped
+    then do textureWrapMode Texture2D S $= (Repeated,Repeat)
+            textureWrapMode Texture2D T $= (Repeated,Repeat)
+    else do textureWrapMode Texture2D S $= (Mirrored,Clamp)
+            textureWrapMode Texture2D T $= (Mirrored,Clamp)
+  build2DMipmaps Texture2D RGBA' (fromIntegral width) (fromIntegral height) (PixelData RGBA UnsignedByte tex)
+  return tid
+
+vertex3 :: GLfloat -> GLfloat -> GLfloat -> IO ()
+vertex3 x y z = vertex $ Vertex3 x y z
+
+texCoord2 :: GLfloat -> GLfloat -> IO ()
+texCoord2 x y = texCoord $ TexCoord2 x y
+
+explodeList :: Int -> [a] -> [a]
+explodeList = concatMap . replicate
+
+explodeMatrix :: Int -> [[a]] -> [[a]]
+explodeMatrix n = map (explodeList n) . explodeList n
src/HighScore.hs view
@@ -1,36 +1,36 @@-module HighScore where--import Control.Monad-import System.Directory-import System.IO--loadScore :: IO Int-loadScore = do-  dir <- getAppDir--  let fileName = dir ++ "/highscore"-  fileChk <- doesFileExist fileName-  unless fileChk $ do-    hdl <- openFile fileName WriteMode-    hPutStr hdl "0"-    hClose hdl--  hdl <- openFile fileName ReadMode-  score <- hGetLine hdl-  hClose hdl--  return (read score)--saveScore :: Int -> IO ()-saveScore score = do-  dir <- getAppDir-  hdl <- openFile (dir ++ "/highscore") WriteMode-  hPutStr hdl (show score)-  hClose hdl--getAppDir :: IO FilePath-getAppDir = do-  dir <- getAppUserDataDirectory "dow"-  dirChk <- doesDirectoryExist dir-  unless dirChk $ createDirectory dir+module HighScore where
+
+import Control.Monad
+import System.Directory
+import System.IO
+
+loadScore :: IO Int
+loadScore = do
+  dir <- getAppDir
+
+  let fileName = dir ++ "/highscore"
+  fileChk <- doesFileExist fileName
+  unless fileChk $ do
+    hdl <- openFile fileName WriteMode
+    hPutStr hdl "0"
+    hClose hdl
+
+  hdl <- openFile fileName ReadMode
+  score <- hGetLine hdl
+  hClose hdl
+
+  return (read score)
+
+saveScore :: Int -> IO ()
+saveScore score = do
+  dir <- getAppDir
+  hdl <- openFile (dir ++ "/highscore") WriteMode
+  hPutStr hdl (show score)
+  hClose hdl
+
+getAppDir :: IO FilePath
+getAppDir = do
+  dir <- getAppUserDataDirectory "dow"
+  dirChk <- doesDirectoryExist dir
+  unless dirChk $ createDirectory dir
   return dir
src/Level.hs view
@@ -1,93 +1,93 @@-module Level where--import Control.Monad-import Data.Array-import Data.List--import Vector--data Level = Level-             { levelName :: String-             , levelSize :: (Int,Int)-             , legalMoves :: Array (Int,Int) [Direction]-             , doors :: [(Direction,Int)]-             , entrances :: [(Direction,Int,Int)]-             } deriving Show--data Direction = North | East | South | West-               deriving (Eq, Enum, Show)--fieldSize :: Int-fieldSize = 16--fieldMid :: Int-fieldMid = fieldSize `div` 2--fieldPos :: Vec -> (Int,Int)-fieldPos (V x y) = ((x+fieldMid) `div` fieldSize, (y+fieldMid) `div` fieldSize)--fieldSub :: Vec -> (Int,Int)-fieldSub (V x y) = (mkSub x, mkSub y)-  where mkSub c = let s = c `mod` fieldSize in if s >= fieldMid then s-fieldSize else s--atFieldMid :: (Int,Int) -> Direction -> Bool-atFieldMid (sx,sy) dir = 0 == if isVertical dir then sx else sy--halfway :: (Int,Int) -> Direction -> Bool-halfway (sx,sy) dir = 0 /= if isVertical dir then sy else sx--dirFromInt :: Int -> Direction-dirFromInt = toEnum . (`mod` 4)--turnRight :: Direction -> Direction-turnRight = dirFromInt . (+1) . fromEnum--turnBack :: Direction -> Direction-turnBack = dirFromInt . (+2) . fromEnum--turnLeft :: Direction -> Direction-turnLeft = dirFromInt . (+3) . fromEnum--isVertical :: Direction -> Bool-isVertical North = True-isVertical South = True-isVertical _     = False--parseLevel :: [String] -> Maybe (Level,[String])-parseLevel lines = do-  let lines' = dropWhile null lines-      nameLine = head lines'-      (mazeLines,rest) = span (not . null) (tail lines')-      width = length (head mazeLines) `div` 2-      height = length mazeLines `div` 2--      mkEntrance (North,x) = (South,-1,x)-      mkEntrance (South,x) = (North,height,x)-      mkEntrance (East,y) = (West,y,width)-      mkEntrance (West,y) = (East,y,-1)--      makeMoves lines = concat . odds $ zipWith3 f lines (tail lines) (tail (tail lines))-        where f n c s = odds $ zipWith4 f' (tail n) (tail s) c (tail (tail c))-              f' n s w e = (if n == ' ' then [North] else []) ++-                           (if s == ' ' then [South] else []) ++-                           (if w == ' ' then [West] else []) ++-                           (if e == ' ' then [East] else [])--      odds (x:_:xs) = x : odds xs-      odds xs = xs--      chars `onEdgeOf` lines =-        [(d,i `div` 2) |-         (d,f) <- [(North,head),(South,last),(West,map head),(East,map last)],-         i <- findIndices (`elem` chars) (f lines)]--  guard $ not (null lines')-  guard $ length mazeLines > 2-  guard $ head nameLine == '"'--  return (Level { levelName = takeWhile (/= '"') (tail nameLine)-                , levelSize = (width,height)-                , legalMoves = listArray ((0,0),(height-1,width-1)) (makeMoves mazeLines)-                , doors = "<>^v" `onEdgeOf` mazeLines-                , entrances = map mkEntrance ("*" `onEdgeOf` mazeLines)-                }, rest)+module Level where
+
+import Control.Monad
+import Data.Array
+import Data.List
+
+import Vector
+
+data Level = Level
+             { levelName :: String
+             , levelSize :: (Int,Int)
+             , legalMoves :: Array (Int,Int) [Direction]
+             , doors :: [(Direction,Int)]
+             , entrances :: [(Direction,Int,Int)]
+             } deriving Show
+
+data Direction = North | East | South | West
+               deriving (Eq, Enum, Show)
+
+fieldSize :: Int
+fieldSize = 16
+
+fieldMid :: Int
+fieldMid = fieldSize `div` 2
+
+fieldPos :: Vec -> (Int,Int)
+fieldPos (V x y) = ((x+fieldMid) `div` fieldSize, (y+fieldMid) `div` fieldSize)
+
+fieldSub :: Vec -> (Int,Int)
+fieldSub (V x y) = (mkSub x, mkSub y)
+  where mkSub c = let s = c `mod` fieldSize in if s >= fieldMid then s-fieldSize else s
+
+atFieldMid :: (Int,Int) -> Direction -> Bool
+atFieldMid (sx,sy) dir = 0 == if isVertical dir then sx else sy
+
+halfway :: (Int,Int) -> Direction -> Bool
+halfway (sx,sy) dir = 0 /= if isVertical dir then sy else sx
+
+dirFromInt :: Int -> Direction
+dirFromInt = toEnum . (`mod` 4)
+
+turnRight :: Direction -> Direction
+turnRight = dirFromInt . (+1) . fromEnum
+
+turnBack :: Direction -> Direction
+turnBack = dirFromInt . (+2) . fromEnum
+
+turnLeft :: Direction -> Direction
+turnLeft = dirFromInt . (+3) . fromEnum
+
+isVertical :: Direction -> Bool
+isVertical North = True
+isVertical South = True
+isVertical _     = False
+
+parseLevel :: [String] -> Maybe (Level,[String])
+parseLevel lines = do
+  let lines' = dropWhile null lines
+      nameLine = head lines'
+      (mazeLines,rest) = span (not . null) (tail lines')
+      width = length (head mazeLines) `div` 2
+      height = length mazeLines `div` 2
+
+      mkEntrance (North,x) = (South,-1,x)
+      mkEntrance (South,x) = (North,height,x)
+      mkEntrance (East,y) = (West,y,width)
+      mkEntrance (West,y) = (East,y,-1)
+
+      makeMoves lines = concat . odds $ zipWith3 f lines (tail lines) (tail (tail lines))
+        where f n c s = odds $ zipWith4 f' (tail n) (tail s) c (tail (tail c))
+              f' n s w e = (if n == ' ' then [North] else []) ++
+                           (if s == ' ' then [South] else []) ++
+                           (if w == ' ' then [West] else []) ++
+                           (if e == ' ' then [East] else [])
+
+      odds (x:_:xs) = x : odds xs
+      odds xs = xs
+
+      chars `onEdgeOf` lines =
+        [(d,i `div` 2) |
+         (d,f) <- [(North,head),(South,last),(West,map head),(East,map last)],
+         i <- findIndices (`elem` chars) (f lines)]
+
+  guard $ not (null lines')
+  guard $ length mazeLines > 2
+  guard $ head nameLine == '"'
+
+  return (Level { levelName = takeWhile (/= '"') (tail nameLine)
+                , levelSize = (width,height)
+                , legalMoves = listArray ((0,0),(height-1,width-1)) (makeMoves mazeLines)
+                , doors = "<>^v" `onEdgeOf` mazeLines
+                , entrances = map mkEntrance ("*" `onEdgeOf` mazeLines)
+                }, rest)
src/Main.hs view
@@ -1,89 +1,92 @@-module Main where--import Control.Applicative-import Control.Monad-import Control.Monad.Fix-import Data.IORef-import Data.List-import FRP.Elerea.Simple-import Graphics.UI.GLFW-import Graphics.Rendering.OpenGL--import Actor-import Game-import HighScore-import Level-import Render-import Sprites-import Text--import Paths_dow (getDataFileName)--main = do-  initialize-  openWindow (Size 640 480) [DisplayRGBBits 8 8 8, DisplayAlphaBits 8, DisplayDepthBits 24] Window-  windowTitle $= "Dungeons of Wor"--  aspectRatio <- newIORef 1-  levels <- loadLevels =<< getDataFileName "data/levels.txt"-  sprites <- loadSprites =<< getDataFileName "data/sprites.txt"-  charset <- loadCharset =<< getDataFileName "data/charset.txt"-  render <- getRenderFunctions aspectRatio charset--  let skins = createSkins sprites-      newActor = mkActor skins--  windowSizeCallback $= setViewport aspectRatio--  closed <- newIORef False-  let closeAction = writeIORef closed True >> return True-  windowCloseCallback $= closeAction--  clearColor $= Color4 0 0 0 1-  blend $= Enabled-  blendFunc $= (SrcAlpha,OneMinusSrcAlpha)-  textureFilter Texture2D $= ((Linear',Just Nearest),Linear')-  textureFunction $= Combine4--  let noKeys = (False,False,False,False,False)-  (keyPress,keySink) <- external (noKeys,noKeys)-  (highScore,highScoreSink) <- external =<< loadScore-  let storeScore scores = do-        oldScore <- loadScore-        let newScore = maximum (oldScore:scores)-        saveScore newScore-        highScoreSink newScore--  renderAction <- start $ game highScore storeScore render closeAction newActor levels keyPress--  fix $ \loop -> do-    readKeys keySink-    join renderAction-    sleep 0.02-    stop <- readIORef closed-    esc <- getKey ESC-    when (not stop && esc /= Press) loop--  closeWindow--loadLevels file = unfoldr parseLevel . lines <$> readFile file--loadSprites file = do-  dat <- lines <$> readFile file-  parseSprites dat--readKeys sink = do-  let pr = (==Press)-  kn1 <- getKey UP-  ks1 <- getKey DOWN-  kw1 <- getKey LEFT-  ke1 <- getKey RIGHT-  kt1a <- getKey RCTRL-  kt1b <- getKey ENTER-  kn2 <- getKey 'W'-  ks2 <- getKey 'S'-  kw2 <- getKey 'A'-  ke2 <- getKey 'D'-  kt2 <- getKey LCTRL-  sink ((pr kn1, pr ks1, pr kw1, pr ke1, pr kt1a || pr kt1b),-        (pr kn2, pr ks2, pr kw2, pr ke2, pr kt2))+module Main where
+
+import Control.Applicative
+import Control.Monad
+import Control.Monad.Fix
+import Data.IORef
+import Data.List
+import FRP.Elerea.Simple
+import Graphics.UI.GLFW
+import Graphics.Rendering.OpenGL
+
+import Actor
+import Game
+import HighScore
+import Level
+import Render
+import Sprites
+import Text
+
+import Paths_dow (getDataFileName)
+
+main = do
+  initialize
+  openWindow (Size 640 480) [DisplayRGBBits 8 8 8, DisplayAlphaBits 8, DisplayDepthBits 24] Window
+  windowTitle $= "Dungeons of Wor"
+
+  aspectRatio <- newIORef 1
+  levels <- loadLevels =<< getDataFileName "data/levels.txt"
+  sprites <- loadSprites =<< getDataFileName "data/sprites.txt"
+  charset <- loadCharset =<< getDataFileName "data/charset.txt"
+  render <- getRenderFunctions aspectRatio charset
+
+  let skins = createSkins sprites
+      newActor = mkActor skins
+
+  windowSizeCallback $= setViewport aspectRatio
+
+  closed <- newIORef False
+  let closeAction = writeIORef closed True >> return True
+  windowCloseCallback $= closeAction
+
+  clearColor $= Color4 0 0 0 1
+  blend $= Enabled
+  blendFunc $= (SrcAlpha,OneMinusSrcAlpha)
+  textureFilter Texture2D $= ((Linear',Just Nearest),Linear')
+  textureFunction $= Combine4
+
+  let noKeys = (False,False,False,False,False)
+  (keyPressGen,keySink) <- external (noKeys,noKeys)
+  (highScoreGen,highScoreSink) <- external =<< loadScore
+  let storeScore scores = do
+        oldScore <- loadScore
+        let newScore = maximum (oldScore:scores)
+        saveScore newScore
+        highScoreSink newScore
+
+  renderAction <- start $ do
+    keyPress <- keyPressGen
+    highScore <- highScoreGen
+    game highScore storeScore render closeAction newActor levels keyPress
+
+  fix $ \loop -> do
+    readKeys keySink
+    join renderAction
+    sleep 0.02
+    stop <- readIORef closed
+    esc <- getKey ESC
+    when (not stop && esc /= Press) loop
+
+  closeWindow
+
+loadLevels file = unfoldr parseLevel . lines <$> readFile file
+
+loadSprites file = do
+  dat <- lines <$> readFile file
+  parseSprites dat
+
+readKeys sink = do
+  let pr = (==Press)
+  kn1 <- getKey UP
+  ks1 <- getKey DOWN
+  kw1 <- getKey LEFT
+  ke1 <- getKey RIGHT
+  kt1a <- getKey RCTRL
+  kt1b <- getKey ENTER
+  kn2 <- getKey 'W'
+  ks2 <- getKey 'S'
+  kw2 <- getKey 'A'
+  ke2 <- getKey 'D'
+  kt2 <- getKey LCTRL
+  sink ((pr kn1, pr ks1, pr kw1, pr ke1, pr kt1a || pr kt1b),
+        (pr kn2, pr ks2, pr kw2, pr ke2, pr kt2))
src/Render.hs view
@@ -1,251 +1,251 @@-module Render-       ( getAspectRatio-       , getRenderFunctions-       , setViewport-       ) where--import Control.Monad-import Data.Array-import Data.Char-import Data.IORef-import Foreign.Marshal-import Graphics.UI.GLFW-import Graphics.Rendering.OpenGL hiding (position)--import Actor as A-import Game-import GraphUtils-import Level-import Text-import Vector--hudHeight = 0.2--solid :: GLfloat-solid = 1--fullLevelSize = addBorder . levelSize-  where addBorder (w,h) = (w+2,h+2)--getAspectRatio level = fromIntegral lh / fromIntegral lw + hudHeight-  where (lw,lh) = fullLevelSize level--setViewport ref size@(Size w h) = do-  lr <- readIORef ref--  let r = (fromIntegral h/fromIntegral w)-      r' = recip r-      lr' = recip lr-      s = 2*min (max 1 (min lr' r')) (max (r/lr) lr')--  viewport $= (Position 0 0,size)--  matrixMode $= Projection-  loadIdentity-  scale (s*min 1 r) (s*min 1 r') (1 :: GLfloat)-  translate $ Vector3 (-0.5) (-0.5*lr) (0 :: GLfloat)--  matrixMode $= Modelview 0--setAspectRatio ref val = do-  writeIORef ref val-  setViewport ref =<< get windowSize--getRenderFunctions aspectRatio charset = do-  let displayText = uncurry displayString charset--  rgbOverlay <- createTexture 24 24 True $ flip pokeArray $-                concat [if b then [95,95,95,255] else c | y <- [0..23], x <- [0..23],-                        let c = case x `div` 4 `mod` 3 of-                              0 -> [255,191,191,255]-                              1 -> [191,255,191,255]-                              2 -> [191,191,255,255]-                            b = x `mod` 4 == 0 || x < 12 && y `mod` 12 == 0 || x >= 12 && y `mod` 12 == 6-                       ]--  return (renderGame aspectRatio displayText rgbOverlay-         ,renderMenu aspectRatio displayText rgbOverlay-         )--renderMenu aspectRatio displayText rgbOverlay score items item = do-  let charSize = 0.006-      textCol = Color4 1 0 0 solid-      activeCol = Color4 0.93 0.79 0 solid-      menu = "DUNGEONS OF WOR":"":"":items++["","","HIGH SCORE "++show score]--  setAspectRatio aspectRatio 1--  clear [ColorBuffer]-  loadIdentity--  texture Texture2D $= Enabled-  forM_ (zip menu [-3..]) $ \(text,i) -> do-    color $ if i == item then activeCol else textCol-    displayText (0.5-(fromIntegral (length text)*4*charSize))-                (0.5+charSize*(7*fromIntegral (length items-1-2*i)))-                charSize text--  renderOverlay rgbOverlay--  flush-  swapBuffers--renderGame aspectRatio displayText rgbOverlay levelState levelCount scores lives = do-  let curLevel = level levelState-      (lw,lh) = fullLevelSize curLevel-      height = fromIntegral lh / fromIntegral lw-      magn = 1 / fromIntegral lw--  setAspectRatio aspectRatio (getAspectRatio curLevel)--  clear [ColorBuffer]-  loadIdentity--  renderHud displayText height scores lives (actors levelState) levelCount curLevel-  preservingMatrix $ do-    translate $ Vector3 0 hudHeight (0 :: GLfloat)-    scale magn magn (1 :: GLfloat)--    renderLevel curLevel-    renderBullets (bullets levelState)-    renderActors (actors levelState)--  renderOverlay rgbOverlay--  flush-  swapBuffers--renderOverlay rgbOverlay = do-  texture Texture2D $= Enabled-  textureBinding Texture2D $= Just rgbOverlay-  blendFunc $= (Zero,SrcColor)-  color $ Color4 1 1 1 solid-  let pscale = 100-  renderPrimitive Quads $ do-    texCoord2 0 0-    vertex3 0 0 0-    texCoord2 pscale 0-    vertex3 1 0 0-    texCoord2 pscale pscale-    vertex3 1 1 0-    texCoord2 0 pscale-    vertex3 0 1 0-  blendFunc $= (SrcAlpha,OneMinusSrcAlpha)--renderLevel level = do-  let (lw,lh) = fullLevelSize level-      height = fromIntegral lh / fromIntegral lw-      entries = [((y,x),[]) | (_,y,x) <- entrances level]--  texture Texture2D $= Disabled-  color $ Color4 0.2 0.5 1 solid-  forM_ (entries ++ assocs (legalMoves level)) $ \((y,x),ms) -> do-    let xc = fromIntegral (x+1)-        yc = fromIntegral (lh-y-2)-    unless (North `elem` ms) $ drawRectangle xc (yc+0.95) 1 0.05-    unless (South `elem` ms) $ drawRectangle xc yc 1 0.05-    unless (East `elem` ms) $ drawRectangle (xc+0.95) yc 0.05 1-    unless (West `elem` ms) $ drawRectangle xc yc 0.05 1--renderActors as = do-  let players = filter ((`elem` [BlueWorrior,YellowWorrior]) . actorType) as-  texture Texture2D $= Enabled-  color $ Color4 1 1 1 solid-  forM_ as $ \a -> do-    let V x y = A.position a-        x' = fromIntegral x / fromIntegral fieldSize-        y' = fromIntegral y / fromIntegral fieldSize-        dist = case actorType a of-          Garwor  -> 2*fieldSize-          Thorwor -> fieldSize-          _       -> maxBound-        visible = any ((\(V px py) -> abs (x-px) < dist || abs (y-py) < dist) . A.position) players--    when (visible && (not . null . animation) a) $-      drawSprite (head (animation a)) (1.1+x') (1.1+y') 0.8 0.8 (facing a)--renderBullets bs = do-  texture Texture2D $= Disabled-  color $ Color4 1 0.3 0.1 solid-  forM_ bs $ \(_,V x y) -> do-    let x' = fromIntegral x / fromIntegral fieldSize-        y' = fromIntegral y / fromIntegral fieldSize-    drawRectangle (1.45+x') (1.45+y') 0.1 0.1--renderHud displayText height scores lives actors levelCount level = do-  let r = Color4 1 0 0 solid-      b = Color4 0.25 0.63 1 solid-      y = Color4 0.93 0.79 0 solid-      d = Color4 0 0 0 solid-      charSize = 0.0028-      radarTitle = if levelCount == 1 then "RADAR" else-                     case levelName level of-                       "pit"   -> "THE PIT"-                       "arena" -> "THE ARENA"-                       _       -> "DUNGEON " ++ show levelCount-      (levelW,levelH) = levelSize level-      scoreB = hudHeight / 4-      scoreW = 0.3-      scoreH = scoreB*3-      radarB = charSize-      radarW = radarF*fromIntegral levelW-      radarH = hudHeight-radarB*4-charSize*10-      radarF = radarH/fromIntegral levelH-      snum1 = show (scores !! 0)-      snum2 = show (scores !! 1)-      lnum1 = show (lives !! 0)-      lnum2 = show (lives !! 1)-      numPlayers = length lives--  texture Texture2D $= Disabled-  color b-  drawRectangle 0 0 scoreW scoreH-  drawRectangle (0.5-radarW/2-radarB) 0 (radarW+radarB*2) (radarH+radarB*2)-  color y-  drawRectangle (1-scoreW) 0 scoreW scoreH-  color d-  drawRectangle scoreB scoreB (scoreW-2*scoreB) (scoreH-2*scoreB)-  drawRectangle (1-scoreW+scoreB) scoreB (scoreW-2*scoreB) (scoreH-2*scoreB)-  drawRectangle (0.5-radarW/2) radarB radarW radarH-  forM_ actors $ \actor -> do-    let (fx,fy) = fieldPos (position actor)-        rx = 0.5-radarW/2+radarF*fromIntegral fx-        ry = radarB+radarF*fromIntegral fy-    case actorType actor of-      Burwor -> color b >> drawRectangle rx ry radarF radarF-      Garwor -> color y >> drawRectangle rx ry radarF radarF-      Thorwor -> color r >> drawRectangle rx ry radarF radarF-      _ -> return ()--  texture Texture2D $= Enabled-  color y-  displayText (1-scoreB-(fromIntegral (length snum1)*8*charSize)) (scoreB+scoreH/2-scoreB-5*charSize) charSize snum1-  displayText (1-scoreW-3*radarB-(fromIntegral (length lnum1)*8*charSize)) (scoreB+scoreH/2-scoreB-5*charSize) charSize lnum1-  when (numPlayers > 1) $ do-    color b-    displayText (scoreW-scoreB-(fromIntegral (length snum2)*8*charSize)) (scoreB+scoreH/2-scoreB-5*charSize) charSize snum2-    displayText (scoreW+3*radarB) (scoreB+scoreH/2-scoreB-5*charSize) charSize lnum2-  color r-  displayText (0.5-(fromIntegral (length radarTitle)*4*charSize)) (radarH+radarB*3) charSize radarTitle--drawRectangle :: GLfloat -> GLfloat -> GLfloat -> GLfloat -> IO ()-drawRectangle x y sx sy = renderPrimitive Quads $ mapM_ vertex-  [Vertex3 x y 0, Vertex3 (x+sx) y 0, Vertex3 (x+sx) (y+sy) 0, Vertex3 x (y+sy) 0]--drawSprite :: TextureObject -> GLfloat -> GLfloat -> GLfloat -> GLfloat -> Direction -> IO ()-drawSprite tid x y sx sy dir = do-  let (u1,v1,u2,v2,u3,v3,u4,v4) = case dir of-        North -> (1,1,1,0,0,0,0,1)-        East  -> (1,1,0,1,0,0,1,0)-        South -> (0,1,0,0,1,0,1,1)-        West  -> (0,1,1,1,1,0,0,0)-  textureBinding Texture2D $= Just tid-  renderPrimitive Quads $ do-    texCoord2 u1 v1-    vertex3 x y 0-    texCoord2 u2 v2-    vertex3 (x+sx) y 0-    texCoord2 u3 v3-    vertex3 (x+sx) (y+sy) 0-    texCoord2 u4 v4-    vertex3 x (y+sy) 0+module Render
+       ( getAspectRatio
+       , getRenderFunctions
+       , setViewport
+       ) where
+
+import Control.Monad
+import Data.Array
+import Data.Char
+import Data.IORef
+import Foreign.Marshal
+import Graphics.UI.GLFW
+import Graphics.Rendering.OpenGL hiding (position)
+
+import Actor as A
+import Game
+import GraphUtils
+import Level
+import Text
+import Vector
+
+hudHeight = 0.2
+
+solid :: GLfloat
+solid = 1
+
+fullLevelSize = addBorder . levelSize
+  where addBorder (w,h) = (w+2,h+2)
+
+getAspectRatio level = fromIntegral lh / fromIntegral lw + hudHeight
+  where (lw,lh) = fullLevelSize level
+
+setViewport ref size@(Size w h) = do
+  lr <- readIORef ref
+
+  let r = (fromIntegral h/fromIntegral w)
+      r' = recip r
+      lr' = recip lr
+      s = 2*min (max 1 (min lr' r')) (max (r/lr) lr')
+
+  viewport $= (Position 0 0,size)
+
+  matrixMode $= Projection
+  loadIdentity
+  scale (s*min 1 r) (s*min 1 r') (1 :: GLfloat)
+  translate $ Vector3 (-0.5) (-0.5*lr) (0 :: GLfloat)
+
+  matrixMode $= Modelview 0
+
+setAspectRatio ref val = do
+  writeIORef ref val
+  setViewport ref =<< get windowSize
+
+getRenderFunctions aspectRatio charset = do
+  let displayText = uncurry displayString charset
+
+  rgbOverlay <- createTexture 24 24 True $ flip pokeArray $
+                concat [if b then [95,95,95,255] else c | y <- [0..23], x <- [0..23],
+                        let c = case x `div` 4 `mod` 3 of
+                              0 -> [255,191,191,255]
+                              1 -> [191,255,191,255]
+                              2 -> [191,191,255,255]
+                            b = x `mod` 4 == 0 || x < 12 && y `mod` 12 == 0 || x >= 12 && y `mod` 12 == 6
+                       ]
+
+  return (renderGame aspectRatio displayText rgbOverlay
+         ,renderMenu aspectRatio displayText rgbOverlay
+         )
+
+renderMenu aspectRatio displayText rgbOverlay score items item = do
+  let charSize = 0.006
+      textCol = Color4 1 0 0 solid
+      activeCol = Color4 0.93 0.79 0 solid
+      menu = "DUNGEONS OF WOR":"":"":items++["","","HIGH SCORE "++show score]
+
+  setAspectRatio aspectRatio 1
+
+  clear [ColorBuffer]
+  loadIdentity
+
+  texture Texture2D $= Enabled
+  forM_ (zip menu [-3..]) $ \(text,i) -> do
+    color $ if i == item then activeCol else textCol
+    displayText (0.5-(fromIntegral (length text)*4*charSize))
+                (0.5+charSize*(7*fromIntegral (length items-1-2*i)))
+                charSize text
+
+  renderOverlay rgbOverlay
+
+  flush
+  swapBuffers
+
+renderGame aspectRatio displayText rgbOverlay levelState levelCount scores lives = do
+  let curLevel = level levelState
+      (lw,lh) = fullLevelSize curLevel
+      height = fromIntegral lh / fromIntegral lw
+      magn = 1 / fromIntegral lw
+
+  setAspectRatio aspectRatio (getAspectRatio curLevel)
+
+  clear [ColorBuffer]
+  loadIdentity
+
+  renderHud displayText height scores lives (actors levelState) levelCount curLevel
+  preservingMatrix $ do
+    translate $ Vector3 0 hudHeight (0 :: GLfloat)
+    scale magn magn (1 :: GLfloat)
+
+    renderLevel curLevel
+    renderBullets (bullets levelState)
+    renderActors (actors levelState)
+
+  renderOverlay rgbOverlay
+
+  flush
+  swapBuffers
+
+renderOverlay rgbOverlay = do
+  texture Texture2D $= Enabled
+  textureBinding Texture2D $= Just rgbOverlay
+  blendFunc $= (Zero,SrcColor)
+  color $ Color4 1 1 1 solid
+  let pscale = 100
+  renderPrimitive Quads $ do
+    texCoord2 0 0
+    vertex3 0 0 0
+    texCoord2 pscale 0
+    vertex3 1 0 0
+    texCoord2 pscale pscale
+    vertex3 1 1 0
+    texCoord2 0 pscale
+    vertex3 0 1 0
+  blendFunc $= (SrcAlpha,OneMinusSrcAlpha)
+
+renderLevel level = do
+  let (lw,lh) = fullLevelSize level
+      height = fromIntegral lh / fromIntegral lw
+      entries = [((y,x),[]) | (_,y,x) <- entrances level]
+
+  texture Texture2D $= Disabled
+  color $ Color4 0.2 0.5 1 solid
+  forM_ (entries ++ assocs (legalMoves level)) $ \((y,x),ms) -> do
+    let xc = fromIntegral (x+1)
+        yc = fromIntegral (lh-y-2)
+    unless (North `elem` ms) $ drawRectangle xc (yc+0.95) 1 0.05
+    unless (South `elem` ms) $ drawRectangle xc yc 1 0.05
+    unless (East `elem` ms) $ drawRectangle (xc+0.95) yc 0.05 1
+    unless (West `elem` ms) $ drawRectangle xc yc 0.05 1
+
+renderActors as = do
+  let players = filter ((`elem` [BlueWorrior,YellowWorrior]) . actorType) as
+  texture Texture2D $= Enabled
+  color $ Color4 1 1 1 solid
+  forM_ as $ \a -> do
+    let V x y = A.position a
+        x' = fromIntegral x / fromIntegral fieldSize
+        y' = fromIntegral y / fromIntegral fieldSize
+        dist = case actorType a of
+          Garwor  -> 2*fieldSize
+          Thorwor -> fieldSize
+          _       -> maxBound
+        visible = any ((\(V px py) -> abs (x-px) < dist || abs (y-py) < dist) . A.position) players
+
+    when (visible && (not . null . animation) a) $
+      drawSprite (head (animation a)) (1.1+x') (1.1+y') 0.8 0.8 (facing a)
+
+renderBullets bs = do
+  texture Texture2D $= Disabled
+  color $ Color4 1 0.3 0.1 solid
+  forM_ bs $ \(_,V x y) -> do
+    let x' = fromIntegral x / fromIntegral fieldSize
+        y' = fromIntegral y / fromIntegral fieldSize
+    drawRectangle (1.45+x') (1.45+y') 0.1 0.1
+
+renderHud displayText height scores lives actors levelCount level = do
+  let r = Color4 1 0 0 solid
+      b = Color4 0.25 0.63 1 solid
+      y = Color4 0.93 0.79 0 solid
+      d = Color4 0 0 0 solid
+      charSize = 0.0028
+      radarTitle = if levelCount == 1 then "RADAR" else
+                     case levelName level of
+                       "pit"   -> "THE PIT"
+                       "arena" -> "THE ARENA"
+                       _       -> "DUNGEON " ++ show levelCount
+      (levelW,levelH) = levelSize level
+      scoreB = hudHeight / 4
+      scoreW = 0.3
+      scoreH = scoreB*3
+      radarB = charSize
+      radarW = radarF*fromIntegral levelW
+      radarH = hudHeight-radarB*4-charSize*10
+      radarF = radarH/fromIntegral levelH
+      snum1 = show (scores !! 0)
+      snum2 = show (scores !! 1)
+      lnum1 = show (lives !! 0)
+      lnum2 = show (lives !! 1)
+      numPlayers = length lives
+
+  texture Texture2D $= Disabled
+  color b
+  drawRectangle 0 0 scoreW scoreH
+  drawRectangle (0.5-radarW/2-radarB) 0 (radarW+radarB*2) (radarH+radarB*2)
+  color y
+  drawRectangle (1-scoreW) 0 scoreW scoreH
+  color d
+  drawRectangle scoreB scoreB (scoreW-2*scoreB) (scoreH-2*scoreB)
+  drawRectangle (1-scoreW+scoreB) scoreB (scoreW-2*scoreB) (scoreH-2*scoreB)
+  drawRectangle (0.5-radarW/2) radarB radarW radarH
+  forM_ actors $ \actor -> do
+    let (fx,fy) = fieldPos (position actor)
+        rx = 0.5-radarW/2+radarF*fromIntegral fx
+        ry = radarB+radarF*fromIntegral fy
+    case actorType actor of
+      Burwor -> color b >> drawRectangle rx ry radarF radarF
+      Garwor -> color y >> drawRectangle rx ry radarF radarF
+      Thorwor -> color r >> drawRectangle rx ry radarF radarF
+      _ -> return ()
+
+  texture Texture2D $= Enabled
+  color y
+  displayText (1-scoreB-(fromIntegral (length snum1)*8*charSize)) (scoreB+scoreH/2-scoreB-5*charSize) charSize snum1
+  displayText (1-scoreW-3*radarB-(fromIntegral (length lnum1)*8*charSize)) (scoreB+scoreH/2-scoreB-5*charSize) charSize lnum1
+  when (numPlayers > 1) $ do
+    color b
+    displayText (scoreW-scoreB-(fromIntegral (length snum2)*8*charSize)) (scoreB+scoreH/2-scoreB-5*charSize) charSize snum2
+    displayText (scoreW+3*radarB) (scoreB+scoreH/2-scoreB-5*charSize) charSize lnum2
+  color r
+  displayText (0.5-(fromIntegral (length radarTitle)*4*charSize)) (radarH+radarB*3) charSize radarTitle
+
+drawRectangle :: GLfloat -> GLfloat -> GLfloat -> GLfloat -> IO ()
+drawRectangle x y sx sy = renderPrimitive Quads $ mapM_ vertex
+  [Vertex3 x y 0, Vertex3 (x+sx) y 0, Vertex3 (x+sx) (y+sy) 0, Vertex3 x (y+sy) 0]
+
+drawSprite :: TextureObject -> GLfloat -> GLfloat -> GLfloat -> GLfloat -> Direction -> IO ()
+drawSprite tid x y sx sy dir = do
+  let (u1,v1,u2,v2,u3,v3,u4,v4) = case dir of
+        North -> (1,1,1,0,0,0,0,1)
+        East  -> (1,1,0,1,0,0,1,0)
+        South -> (0,1,0,0,1,0,1,1)
+        West  -> (0,1,1,1,1,0,0,0)
+  textureBinding Texture2D $= Just tid
+  renderPrimitive Quads $ do
+    texCoord2 u1 v1
+    vertex3 x y 0
+    texCoord2 u2 v2
+    vertex3 (x+sx) y 0
+    texCoord2 u3 v3
+    vertex3 (x+sx) (y+sy) 0
+    texCoord2 u4 v4
+    vertex3 x (y+sy) 0
src/Sprites.hs view
@@ -1,63 +1,63 @@-module Sprites-       ( SpriteStore-       , parseSprites-       ) where--import Control.Applicative-import Control.Monad.Fix-import Control.Monad-import Data.Array-import Data.Word-import Foreign.Marshal-import Foreign.Ptr-import Graphics.Rendering.OpenGL--import GraphUtils--type SpriteStore = [(String, [TextureObject])]--parseSprites :: [String] -> IO SpriteStore-parseSprites dat = do-  let (coldat,sprdat) = span (\l -> not (null l) && (head l /= '[')) dat-      colmap :: Array Char [Word8]-      colmap = listArray (' ','~') (repeat [0,0,0,0]) // map mkcol coldat-      mkcol (c:dat) = (c,[r,g,b,a])-        where [(r,dat')] = reads dat-              [(g,dat'')] = reads dat'-              [(b,dat''')] = reads dat''-              [(a,dat'''')] = reads dat'''--  flip fix sprdat $ \addGroup dat ->-    createSpriteGroup colmap dat >>= \res -> case res of-      Just (name,g,dat') -> do-        gs <- addGroup dat'-        return ((name,g):gs)-      Nothing -> return []--createSpriteGroup colmap dat = do-  let dat' = dropWhile null dat-      gname = takeWhile (/=']') (tail (head dat'))--  if null dat'-    then return Nothing-    else do-    (sps,dat'') <- flip fix (tail dat',[]) $ \addSprites (dat,tids) ->-      createSprite colmap dat >>= \res -> case res of-        Just (tid,dat') -> do-          addSprites (dat',tid:tids)-        Nothing -> return (tids,dat)-    return (Just (gname,reverse sps,dat''))--createSprite colmap dat = do-  let dat' = dropWhile null dat--  if null dat' || head (head dat') /= '"'-    then return Nothing-    else do-    let (spdat,dat'') = span (\l -> not (null l) && (head l == '"')) dat'-        spdat' = explodeMatrix 3 (map (takeWhile (/='"') . tail) spdat)-        spw = length (head spdat')-        sph = length spdat'--    tid <- createTexture spw sph False $ flip pokeArray [comp | lin <- spdat', pix <- lin, comp <- colmap ! pix]-    return (Just (tid,dat''))+module Sprites
+       ( SpriteStore
+       , parseSprites
+       ) where
+
+import Control.Applicative
+import Control.Monad.Fix
+import Control.Monad
+import Data.Array
+import Data.Word
+import Foreign.Marshal
+import Foreign.Ptr
+import Graphics.Rendering.OpenGL
+
+import GraphUtils
+
+type SpriteStore = [(String, [TextureObject])]
+
+parseSprites :: [String] -> IO SpriteStore
+parseSprites dat = do
+  let (coldat,sprdat) = span (\l -> not (null l) && (head l /= '[')) dat
+      colmap :: Array Char [Word8]
+      colmap = listArray (' ','~') (repeat [0,0,0,0]) // map mkcol coldat
+      mkcol (c:dat) = (c,[r,g,b,a])
+        where [(r,dat')] = reads dat
+              [(g,dat'')] = reads dat'
+              [(b,dat''')] = reads dat''
+              [(a,dat'''')] = reads dat'''
+
+  flip fix sprdat $ \addGroup dat ->
+    createSpriteGroup colmap dat >>= \res -> case res of
+      Just (name,g,dat') -> do
+        gs <- addGroup dat'
+        return ((name,g):gs)
+      Nothing -> return []
+
+createSpriteGroup colmap dat = do
+  let dat' = dropWhile null dat
+      gname = takeWhile (/=']') (tail (head dat'))
+
+  if null dat'
+    then return Nothing
+    else do
+    (sps,dat'') <- flip fix (tail dat',[]) $ \addSprites (dat,tids) ->
+      createSprite colmap dat >>= \res -> case res of
+        Just (tid,dat') -> do
+          addSprites (dat',tid:tids)
+        Nothing -> return (tids,dat)
+    return (Just (gname,reverse sps,dat''))
+
+createSprite colmap dat = do
+  let dat' = dropWhile null dat
+
+  if null dat' || head (head dat') /= '"'
+    then return Nothing
+    else do
+    let (spdat,dat'') = span (\l -> not (null l) && (head l == '"')) dat'
+        spdat' = explodeMatrix 3 (map (takeWhile (/='"') . tail) spdat)
+        spw = length (head spdat')
+        sph = length spdat'
+
+    tid <- createTexture spw sph False $ flip pokeArray [comp | lin <- spdat', pix <- lin, comp <- colmap ! pix]
+    return (Just (tid,dat''))
src/Text.hs view
@@ -1,57 +1,57 @@-module Text-       ( loadCharset-       , displayString-       ) where--import Control.Applicative-import Control.Monad-import Data.Array-import Data.List-import Data.Word-import Foreign.Marshal-import Foreign.Ptr-import Graphics.Rendering.OpenGL--import GraphUtils--loadCharset file = do-  dat <- lines <$> readFile file-  let cs = unfoldr parseChar dat-      cpos = map (\n -> (n `mod` 8,n `div` 8)) [0..]-      cdat = array (' ','Z') (zip (map fst cs) cpos)--      mkpix '#' = [255,255,255,255]-      mkpix _   = [255,255,255,0]--  tid <- createTexture 256 256 False $ \tex -> do-    pokeArray tex $ concat (replicate (256*256) [255,255,255,0])-    forM_ (zip cs cpos) $ \((_,cimg),(x,y)) -> do-      forM_ (zip cimg [0..]) $ \(crow,ry) -> pokeArray (advancePtr tex ((x*32+1)*4+(y*32+1+ry)*256*4)) (concatMap mkpix crow)--  return (tid,cdat)--parseChar dat = if null dat' then Nothing else Just ((c,explodeMatrix 3 img),dat'')-  where dat' = dropWhile null dat-        c = head (head dat')-        (img,dat'') = span (not . null) (tail dat')--displayString tid cdat x y m s = do-  textureBinding Texture2D $= Just tid--  let displayChar c x = do-        let (cx,cy) = cdat ! c-            u = fromIntegral (cx*32+1)/256-            v = fromIntegral (cy*32+1)/256-        texCoord2 u (v+ch)-        vertex3 x y 0-        texCoord2 (u+cw) (v+ch)-        vertex3 (x+8*m) y 0-        texCoord2 (u+cw) v-        vertex3 (x+8*m) (y+10*m) 0-        texCoord2 u v-        vertex3 x (y+10*m) 0-      cw = 24/256-      ch = 30/256--  renderPrimitive Quads $ forM_ (zip s [0..]) $ \(c,i) ->-    displayChar c (x+i*8*m)+module Text
+       ( loadCharset
+       , displayString
+       ) where
+
+import Control.Applicative
+import Control.Monad
+import Data.Array
+import Data.List
+import Data.Word
+import Foreign.Marshal
+import Foreign.Ptr
+import Graphics.Rendering.OpenGL
+
+import GraphUtils
+
+loadCharset file = do
+  dat <- lines <$> readFile file
+  let cs = unfoldr parseChar dat
+      cpos = map (\n -> (n `mod` 8,n `div` 8)) [0..]
+      cdat = array (' ','Z') (zip (map fst cs) cpos)
+
+      mkpix '#' = [255,255,255,255]
+      mkpix _   = [255,255,255,0]
+
+  tid <- createTexture 256 256 False $ \tex -> do
+    pokeArray tex $ concat (replicate (256*256) [255,255,255,0])
+    forM_ (zip cs cpos) $ \((_,cimg),(x,y)) -> do
+      forM_ (zip cimg [0..]) $ \(crow,ry) -> pokeArray (advancePtr tex ((x*32+1)*4+(y*32+1+ry)*256*4)) (concatMap mkpix crow)
+
+  return (tid,cdat)
+
+parseChar dat = if null dat' then Nothing else Just ((c,explodeMatrix 3 img),dat'')
+  where dat' = dropWhile null dat
+        c = head (head dat')
+        (img,dat'') = span (not . null) (tail dat')
+
+displayString tid cdat x y m s = do
+  textureBinding Texture2D $= Just tid
+
+  let displayChar c x = do
+        let (cx,cy) = cdat ! c
+            u = fromIntegral (cx*32+1)/256
+            v = fromIntegral (cy*32+1)/256
+        texCoord2 u (v+ch)
+        vertex3 x y 0
+        texCoord2 (u+cw) (v+ch)
+        vertex3 (x+8*m) y 0
+        texCoord2 (u+cw) v
+        vertex3 (x+8*m) (y+10*m) 0
+        texCoord2 u v
+        vertex3 x (y+10*m) 0
+      cw = 24/256
+      ch = 30/256
+
+  renderPrimitive Quads $ forM_ (zip s [0..]) $ \(c,i) ->
+    displayChar c (x+i*8*m)
src/Utils.hs view
@@ -1,43 +1,43 @@-{-# LANGUAGE RecursiveDo #-}--module Utils where--import Control.Applicative-import Control.Monad-import Control.Monad.Fix-import Data.Maybe-import Data.Traversable hiding (sequence)-import FRP.Elerea.Simple-import System.Random.Mersenne--infix 2 -->--edge s = do-  s' <- delay False s-  return $ s' >>= \x -> if x then return False else s--x0 --> s = transfer x0 store s-    where store Nothing  x = x-          store (Just x) _ = x--collection source isAlive = mdo-  sig <- delay [] (map snd <$> collWithVals')-  coll <- memo (liftA2 (++) source sig)-  let collWithVals = zip <$> (sequence =<< coll) <*> coll-  collWithVals' <- memo (filter <$> ((.fst) <$> isAlive) <*> collWithVals)-  return $ map fst <$> collWithVals'--switcher gen = mdo-  trig <- memo (snd =<< pw)-  trig' <- delay True trig-  ss <- generator (toMaybe <$> trig' <*> gen)-  pw <- undefined --> ss-  return (fst =<< pw,trig)--toMaybe b s = if b then Just <$> s else pure Nothing--noise :: MTRandom a => SignalGen (Signal a)-noise = effectful randomIO--getRandom :: MTRandom a => SignalGen a+{-# LANGUAGE RecursiveDo #-}
+
+module Utils where
+
+import Control.Applicative
+import Control.Monad
+import Control.Monad.Fix
+import Data.Maybe
+import Data.Traversable hiding (sequence)
+import FRP.Elerea.Simple
+import System.Random.Mersenne
+
+infix 2 -->
+
+edge s = do
+  s' <- delay False s
+  return $ s' >>= \x -> if x then return False else s
+
+x0 --> s = transfer x0 store s
+    where store Nothing  x = x
+          store (Just x) _ = x
+
+collection source isAlive = mdo
+  sig <- delay [] (map snd <$> collWithVals')
+  coll <- memo (liftA2 (++) source sig)
+  let collWithVals = zip <$> (sequence =<< coll) <*> coll
+  collWithVals' <- memo (filter <$> ((.fst) <$> isAlive) <*> collWithVals)
+  return $ map fst <$> collWithVals'
+
+switcher gen = mdo
+  trig <- memo (snd =<< pw)
+  trig' <- delay True trig
+  ss <- generator (toMaybe <$> trig' <*> gen)
+  pw <- undefined --> ss
+  return (fst =<< pw,trig)
+
+toMaybe b s = if b then Just <$> s else pure Nothing
+
+noise :: MTRandom a => SignalGen (Signal a)
+noise = effectful randomIO
+
+getRandom :: MTRandom a => SignalGen a
 getRandom = execute randomIO
src/Vector.hs view
@@ -1,11 +1,11 @@-module Vector where--data Vec = V !Int !Int deriving (Show, Eq)--instance Num Vec where-  V x1 y1 + V x2 y2 = V (x1+x2) (y1+y2)-  V x1 y1 - V x2 y2 = V (x1-x2) (y1-y2)-  V x1 y1 * V x2 y2 = V (x1*x2) (y1*y2)-  abs (V x y) = V (abs x) (abs y)-  signum (V x y) = V (signum x) (signum y)-  fromInteger x = V (fromInteger x) (fromInteger x)+module Vector where
+
+data Vec = V !Int !Int deriving (Show, Eq)
+
+instance Num Vec where
+  V x1 y1 + V x2 y2 = V (x1+x2) (y1+y2)
+  V x1 y1 - V x2 y2 = V (x1-x2) (y1-y2)
+  V x1 y1 * V x2 y2 = V (x1*x2) (y1*y2)
+  abs (V x y) = V (abs x) (abs y)
+  signum (V x y) = V (signum x) (signum y)
+  fromInteger x = V (fromInteger x) (fromInteger x)