Initial import of pacman-1.3 from http://archive.ubuntu.com/ubuntu/ubuntu/pool/univer...
authorMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 11 Apr 2023 22:31:00 +0000 (22:31 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 11 Apr 2023 22:31:00 +0000 (22:31 +0000)
21 files changed:
COPYING [new file with mode: 0755]
ChangeLog [new file with mode: 0755]
Levels/README [new file with mode: 0755]
Levels/level01.dat [new file with mode: 0755]
Levels/level02.dat [new file with mode: 0755]
Levels/level03.dat [new file with mode: 0755]
Levels/level04.dat [new file with mode: 0755]
Levels/level05.dat [new file with mode: 0755]
Levels/level06.dat [new file with mode: 0755]
Levels/level07.dat [new file with mode: 0755]
Levels/level08.dat [new file with mode: 0755]
Levels/level09.dat [new file with mode: 0755]
Levels/template.dat [new file with mode: 0755]
Makefile [new file with mode: 0755]
README [new file with mode: 0755]
pacman [new file with mode: 0755]
pacman.c [new file with mode: 0755]
pacman.h [new file with mode: 0755]
pacmanedit [new file with mode: 0755]
pacmanedit.c [new file with mode: 0755]
screenshot.png [new file with mode: 0755]

diff --git a/COPYING b/COPYING
new file mode 100755 (executable)
index 0000000..d511905
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100755 (executable)
index 0000000..c47665f
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,32 @@
+Pacman for Console
+
+
+
+2014-04-26 - 1.3
+
+    - improved Makefile: notably a better parameterization allowing a non-admin installation - Thanks to G.raud
+    - wrote much better comments in code for pacman.c and pacmanedit.c
+    - fixed bug stopping location of Levels from being changed - Thanks to Doncho Gunchev
+
+2006-12-12 - 1.2
+
+    - added a simple level editor
+    - fixed error messages on GCC 2.96 - Thanks to Gerald Schnabel
+    - added introduction screen
+    - invincibility is deactivates once level is complete
+
+2006-12-08 - 1.1
+
+    - fixed warning messages on GCC 4.1
+    - changed background color of blue ghosts to make them more visible
+
+2006-06-09 - 1.0
+
+    - initial release
+
+
+Future Releases:
+----------------
+1) Different sized mazes
+2) Multiplayer
+3) World domination
diff --git a/Levels/README b/Levels/README
new file mode 100755 (executable)
index 0000000..e531167
--- /dev/null
@@ -0,0 +1,40 @@
+The included level editor (pacmanedit) isn't very difficult to learn to use,
+the status bar tells you everything you need to know but here are the keys
+
+UDLR or WSAD:  Move cursor
+F:             Fills all blank spaces with pellets
+C:             Clears all pellets from board
+Q:             Saves and quits
+CTRL+C:                Quits WITHOUT saving
+
+Key            Inserts
+-----------------------
+0 or space:    Blank
+1:             Wall
+2:             Pellet
+3:             Powerup
+4:             Ghost/Spawning Wall
+5:             Blinky
+6:             Inkey
+7:             Clyde
+8:             Pinky
+9:             Pacman
+
+
+*) The spawning wall is a wall that the ghosts can go through but Pacman
+   cannot. These can be used to make levels REALLY difficult. Check level 09
+
+*) Borders shouldn't need to be used, but give it a more Pacman-like feel.
+   If a ghost or Pacman are able to reach the very edge of the board, he will
+   be teleported to the opposite side of the level, both X and Y just like in
+   the regular game.
+
+*) See any included level__.dat file for examples.
+
+
+To edit a new or existing level, type:
+       $ pacmanedit new_or_old_level.dat
+
+
+To load a custom level, run pacman with the level file as the parameter:
+       $ pacman levelfile.dat
diff --git a/Levels/level01.dat b/Levels/level01.dat
new file mode 100755 (executable)
index 0000000..62a32ed
--- /dev/null
@@ -0,0 +1,30 @@
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 2 1 1 1 1 2 1 1 1 1 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 2 1
+1 3 1 0 0 1 2 1 0 0 0 1 2 1 1 2 1 0 0 0 1 2 1 0 0 1 3 1
+1 2 1 0 0 1 2 1 0 0 0 1 2 1 1 2 1 0 0 0 1 2 1 0 0 1 2 1
+1 2 1 1 1 1 2 1 1 1 1 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 2 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 2 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 2 1 1 2 1 1 1 1 2 1
+1 2 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 2 1 1 2 1 1 1 1 2 1
+1 2 2 2 2 2 2 1 1 2 2 2 2 1 1 2 2 2 2 1 1 2 2 2 2 2 2 1
+1 1 1 1 1 1 2 1 1 1 1 1 0 1 1 0 1 1 1 1 1 2 1 1 1 1 1 1
+0 0 0 0 0 1 2 1 1 1 1 1 0 1 1 0 1 1 1 1 1 2 1 0 0 0 0 0
+0 0 0 0 0 1 2 1 1 0 0 0 0 0 0 0 0 0 0 1 1 2 1 0 0 0 0 0
+0 0 0 0 0 1 2 1 1 0 1 1 1 4 4 1 1 1 0 1 1 2 1 0 0 0 0 0
+1 1 1 1 1 1 2 1 1 0 1 0 0 0 6 5 0 1 0 0 0 2 1 1 1 1 1 1
+0 0 0 0 0 0 2 0 0 0 1 0 8 7 0 0 0 1 0 1 1 2 0 0 0 0 0 0
+1 1 1 1 1 1 2 1 1 0 1 1 1 1 1 1 1 1 0 1 1 2 1 1 1 1 1 1
+0 0 0 0 0 1 2 1 1 0 0 0 0 0 0 0 0 0 0 1 1 2 1 0 0 0 0 0
+1 1 1 1 1 1 2 1 1 0 1 1 1 1 1 1 1 1 0 1 1 2 1 1 1 1 1 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 2 1 1 1 1 2 1 1 1 1 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 2 1
+1 2 1 1 1 1 2 1 1 1 1 1 2 1 1 2 1 1 1 1 1 2 1 1 1 1 2 1
+1 3 2 2 1 1 2 2 2 2 2 2 2 2 9 2 2 2 2 2 2 2 1 1 2 2 3 1
+1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1
+1 1 1 2 1 1 2 1 1 2 1 1 1 1 1 1 1 1 2 1 1 2 1 1 2 1 1 1
+1 2 2 2 2 2 2 1 1 2 2 2 2 1 1 2 2 2 2 1 1 2 2 2 2 2 2 1
+1 2 1 1 1 1 1 1 1 1 1 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 2 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1
diff --git a/Levels/level02.dat b/Levels/level02.dat
new file mode 100755 (executable)
index 0000000..997e691
--- /dev/null
@@ -0,0 +1,30 @@
+1 1 1 1 1 1 1 1 1 0 0 0 1 0 1 0 0 0 1 1 1 1 1 1 1 1 1 1
+1 2 2 2 2 2 2 3 1 0 0 0 1 2 1 0 0 0 1 3 2 2 2 2 2 2 2 1
+1 2 1 1 1 1 1 2 1 0 0 0 1 2 1 0 0 0 1 2 1 1 1 1 1 1 2 1
+1 2 1 0 0 0 1 2 1 1 1 1 1 2 1 1 1 1 1 2 1 0 0 0 0 1 2 1
+1 2 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 2 1
+1 2 2 2 2 2 2 2 1 1 1 1 1 2 1 1 1 1 1 2 2 2 2 2 2 2 2 1
+1 2 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 2 1
+1 2 1 1 1 1 1 1 2 1 1 1 1 0 1 1 1 1 1 2 1 1 1 1 1 1 2 1
+1 2 2 2 2 2 2 2 2 1 1 1 1 0 1 1 1 1 1 2 2 2 2 2 2 2 2 1
+1 1 1 1 2 1 1 1 2 1 0 0 0 0 0 0 0 0 1 2 1 1 1 2 1 1 1 1
+0 0 0 1 2 1 0 1 2 1 0 1 1 4 4 1 1 0 1 2 1 0 1 2 1 0 0 0
+0 0 0 1 2 1 0 1 2 1 0 1 0 0 0 0 1 0 1 2 1 0 1 2 1 0 0 0
+0 0 0 1 2 1 0 1 2 3 0 1 5 6 7 8 1 0 3 2 1 0 1 2 1 0 0 0
+1 1 1 1 2 1 1 1 2 1 0 1 1 4 4 1 1 0 1 2 1 1 1 2 1 1 1 1
+0 2 2 2 2 2 2 2 2 1 0 0 0 0 0 0 0 0 1 2 2 2 2 2 2 2 2 0
+1 1 1 1 2 1 1 1 2 1 1 1 1 1 0 1 1 1 1 2 1 1 1 2 1 1 1 1
+0 0 0 1 2 1 1 1 2 1 1 1 1 1 0 1 1 1 1 2 1 1 1 2 1 0 0 0
+0 0 0 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 0 0 0
+0 0 0 1 2 1 1 1 1 1 2 1 1 1 1 1 1 2 1 1 1 1 1 2 1 0 0 0
+0 0 0 1 2 1 0 0 0 1 2 1 0 0 0 0 1 2 1 0 0 0 1 2 1 0 0 0
+1 1 1 1 2 1 1 1 1 1 2 1 1 1 1 1 1 2 1 1 1 1 1 2 1 1 1 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 9 2 2 2 2 2 2 2 2 2 2 2 2 3 1
+1 2 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 2 1 2 1
+1 2 1 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1
+1 2 2 3 1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 2 1 1 2 1 2 2 2 1
+1 2 1 1 1 2 1 2 1 0 0 0 1 2 1 0 0 0 1 2 1 1 2 1 1 1 2 1
+1 2 1 1 1 2 1 2 1 0 0 0 1 2 1 1 1 1 1 2 1 1 2 1 1 1 2 1
+1 2 2 2 2 2 2 2 1 0 0 0 1 2 2 2 2 2 2 2 1 1 2 2 2 2 2 1
+1 1 1 1 1 1 1 1 1 0 0 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+2
diff --git a/Levels/level03.dat b/Levels/level03.dat
new file mode 100755 (executable)
index 0000000..9df4cf6
--- /dev/null
@@ -0,0 +1,30 @@
+1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+0 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 3 2 2 0
+1 2 1 1 1 1 2 1 1 1 1 2 1 2 1 2 1 1 1 1 1 1 1 1 2 1 1 1
+1 2 1 0 0 1 2 1 0 0 1 2 1 2 1 2 2 2 2 2 1 2 2 2 2 2 2 1
+1 2 1 1 1 1 2 1 1 1 1 2 1 2 1 2 1 1 1 2 1 2 1 1 1 1 2 1
+1 2 2 2 2 2 2 2 2 2 2 9 1 2 2 2 2 2 2 2 1 2 1 0 0 1 2 1
+1 2 1 1 1 1 2 1 1 1 1 2 1 1 1 1 1 1 1 2 1 2 1 0 0 1 2 1
+1 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 1 1 2 1
+1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 2 2 2 2 2 2 1
+1 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 1 1 2 1 1
+1 2 1 2 1 1 1 1 1 2 1 1 1 1 1 1 1 2 1 2 2 2 2 1 1 2 2 1
+1 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 1 1 2 1
+1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 2 1 2 1 2 1 2 2 2 2 1 2 1
+0 2 1 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 1 1 2 1 2 0
+1 1 1 2 1 1 1 1 1 1 1 2 1 2 1 2 2 2 2 2 2 2 2 1 2 1 2 1
+1 2 2 2 2 2 1 2 2 2 1 2 1 2 1 1 2 1 1 1 2 1 2 1 2 1 2 1
+1 2 1 1 1 2 2 2 1 2 1 2 1 2 2 1 2 1 0 1 2 1 2 2 2 1 2 1
+1 2 1 0 1 2 1 2 1 2 1 2 2 1 2 2 2 1 0 1 2 1 2 1 3 2 2 1
+1 2 1 1 1 2 1 2 1 2 1 1 2 1 1 1 1 1 0 1 2 1 2 1 1 1 2 1
+1 3 2 2 2 2 1 2 1 2 2 2 2 2 2 2 2 1 1 1 2 1 2 2 2 2 2 1
+1 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1 2 2 2 2 2 1 2 1 1 1 1 1
+0 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 1 2 1 2 1 2 2 2 2 2 0
+1 1 1 1 1 1 2 1 1 1 1 2 1 1 1 1 2 1 2 1 2 1 1 1 1 1 2 1
+0 0 1 1 1 1 2 1 0 0 1 2 2 2 2 2 2 1 2 1 2 2 2 2 2 2 2 1
+0 1 0 0 0 0 2 1 0 0 1 2 1 1 1 1 2 1 2 1 2 1 1 1 1 1 1 1
+1 1 4 1 1 1 2 1 0 0 1 2 1 2 2 2 2 1 2 2 2 2 2 2 2 2 2 1
+1 0 0 0 0 1 2 1 1 1 1 2 1 2 1 1 1 1 1 1 2 1 1 1 1 1 2 1
+1 5 6 7 8 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+3
diff --git a/Levels/level04.dat b/Levels/level04.dat
new file mode 100755 (executable)
index 0000000..279d915
--- /dev/null
@@ -0,0 +1,30 @@
+1 0 1 0 0 0 1 0 1 1 1 1 1 4 1 1 1 1 0 1 0 1 1 1 1 1 1 1
+0 2 1 0 0 0 1 3 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 0
+1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+0 2 1 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 0
+1 2 4 2 1 1 1 2 1 2 1 1 1 1 2 1 1 1 1 2 1 2 1 1 1 1 4 1
+1 2 1 2 2 2 2 2 1 2 1 1 1 1 2 1 1 1 1 2 1 2 1 0 4 0 5 1
+1 2 1 1 1 1 1 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 0 1 0 6 1
+1 2 2 2 3 2 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 0 1 0 7 1
+1 2 1 2 1 2 1 2 1 1 2 2 2 2 2 1 2 2 2 2 2 2 2 0 4 0 8 1
+1 2 1 2 1 2 4 2 1 2 2 1 1 1 1 1 2 1 1 1 1 2 1 1 1 1 1 1
+0 2 1 2 1 2 1 2 2 2 1 1 2 2 2 3 2 2 2 2 1 2 1 2 2 2 2 0
+1 1 1 2 2 2 1 2 1 2 2 2 2 1 1 1 1 1 1 2 1 2 1 2 1 1 1 1
+0 2 1 1 1 1 1 2 1 1 1 2 1 1 2 2 2 2 1 2 2 2 1 2 2 2 2 0
+1 2 1 2 3 2 1 2 2 2 1 2 2 2 2 1 1 2 1 1 1 1 1 1 1 1 1 1
+0 2 1 2 1 2 1 1 1 2 1 1 1 1 2 1 1 2 2 2 1 2 9 2 2 2 2 0
+1 1 1 2 1 2 2 2 1 2 2 2 2 2 2 1 1 1 1 2 1 2 1 1 1 1 1 1
+0 2 1 2 1 1 1 2 1 1 1 1 1 2 1 1 1 1 1 2 1 2 2 2 2 2 2 0
+1 2 2 2 2 2 2 2 1 0 0 0 1 2 2 2 2 2 1 2 1 1 1 1 1 1 1 1
+1 1 1 2 1 1 1 1 1 1 1 0 1 2 1 1 1 2 2 2 1 0 0 1 2 2 2 1
+0 2 2 2 2 2 2 2 2 2 1 0 1 2 2 2 2 1 1 1 1 1 1 1 2 1 2 0
+1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 2 1 2 2 2 2 2 2 2 1 1 1
+0 2 2 2 2 2 2 2 1 2 2 2 2 2 2 1 2 1 3 1 1 1 1 1 2 1 2 0
+1 1 1 1 1 1 1 2 1 1 1 1 1 1 2 1 2 1 2 2 2 2 2 2 2 1 2 1
+0 2 2 2 2 2 1 2 1 2 2 2 2 2 2 1 2 1 2 1 1 1 1 1 2 1 2 0
+1 1 1 1 1 3 1 2 2 2 1 2 1 2 1 1 2 1 2 1 2 2 2 1 2 1 1 1
+0 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1 2 1 2 1 2 1 2 0
+1 1 1 1 1 1 1 2 1 2 1 2 1 2 1 1 2 1 2 1 2 1 2 1 2 1 2 1
+1 2 2 2 2 2 2 2 1 2 2 2 1 2 2 2 2 1 2 1 2 1 2 2 2 2 2 1
+1 0 1 1 1 1 1 0 1 1 1 1 1 4 1 1 1 1 0 1 0 1 1 1 1 1 1 1
+4
diff --git a/Levels/level05.dat b/Levels/level05.dat
new file mode 100755 (executable)
index 0000000..bf46a4e
--- /dev/null
@@ -0,0 +1,30 @@
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 2 1 1 1 2 2 1 2 2 2 1 2 2 1 1 1 2 1 2 2 1 2 1 1 1 2 1
+1 2 1 0 0 1 2 1 2 2 2 1 2 1 2 2 2 2 1 2 2 1 2 1 1 1 2 1
+1 2 1 1 1 1 2 1 2 2 2 1 2 2 1 1 2 2 1 1 1 1 2 1 1 1 2 1
+1 2 1 0 0 1 2 1 2 2 2 1 2 2 3 2 1 2 1 2 2 1 2 1 1 1 2 1
+1 2 1 1 1 2 2 2 1 1 1 2 2 1 1 1 2 2 1 2 2 1 2 2 2 2 2 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 1 1 1 1 1
+1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 0 4 0 0 5 1
+0 0 0 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 4 0 0 6 1
+0 0 0 1 2 1 1 1 1 2 1 2 1 1 1 2 1 2 1 1 1 1 0 4 0 0 7 1
+0 0 0 1 2 2 2 2 2 2 1 2 1 2 2 2 1 2 1 0 0 1 0 4 0 0 8 1
+1 1 1 1 2 1 1 1 1 2 1 2 1 2 1 2 1 2 1 0 0 1 0 1 1 1 1 1
+0 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 1 1 2 2 2 2 2 0
+1 1 1 1 2 1 1 1 1 2 1 2 1 2 1 2 1 2 1 2 2 2 2 1 1 1 1 1
+0 0 0 1 2 1 2 2 2 2 2 2 2 3 2 2 2 2 2 2 1 1 2 2 2 2 2 1
+0 0 0 1 2 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 2 1 1 1 2 1
+0 0 0 1 2 1 2 1 0 0 0 0 0 0 0 1 2 1 2 2 2 2 2 2 2 1 2 1
+1 1 1 1 2 1 2 1 1 1 1 1 1 1 1 1 2 1 2 1 1 1 2 1 2 1 2 1
+1 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1
+1 2 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 2 1 1 1 1 2 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 2 2 1 1 1 2 1 2 2 2 1 2 2 1 1 1 2 1 2 2 1 2 2 1 1 1 1
+1 2 1 2 2 2 2 1 2 3 2 1 2 1 2 2 2 2 1 2 1 2 2 1 0 0 0 1
+1 2 2 1 1 2 2 1 2 2 2 1 2 1 2 2 2 2 1 1 2 2 2 2 1 1 0 1
+1 2 2 2 2 1 2 1 2 2 2 1 2 1 2 2 2 2 1 2 1 2 2 2 2 2 1 1
+0 2 1 1 1 2 2 2 1 1 1 2 2 2 1 1 1 2 1 2 2 1 2 1 1 1 2 0
+1 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 9 2 2 2 2 2 2 3 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1
+5
diff --git a/Levels/level06.dat b/Levels/level06.dat
new file mode 100755 (executable)
index 0000000..b91421e
--- /dev/null
@@ -0,0 +1,30 @@
+1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 0 1 0 1 0 1 1 1 1 1
+0 2 1 2 2 2 1 2 1 2 2 2 2 2 2 2 9 1 2 1 2 1 2 1 3 2 2 0
+1 2 1 1 1 2 1 2 1 1 1 1 1 1 1 2 1 1 2 1 2 1 2 1 2 1 2 1
+1 2 2 2 2 2 1 2 1 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 2 1 2 1
+1 2 1 1 1 1 1 2 1 2 1 1 1 2 1 2 1 2 1 2 2 1 2 1 2 1 2 1
+1 2 1 2 2 2 2 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1 2 1
+1 2 1 2 1 1 1 1 1 2 1 2 1 2 2 2 2 2 1 2 2 2 2 1 2 2 2 1
+1 2 1 2 1 3 2 2 2 2 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1
+0 2 1 2 1 2 1 1 1 2 1 2 2 2 2 2 1 2 2 3 2 2 1 2 2 2 2 0
+1 1 1 2 1 2 1 2 2 2 2 2 1 1 1 1 1 2 1 1 1 2 1 2 1 1 1 1
+0 2 2 2 1 2 1 2 1 2 1 1 1 2 2 2 1 2 2 2 2 2 1 2 2 1 2 0
+1 1 1 1 1 2 1 2 1 2 1 2 2 2 1 2 1 1 1 2 1 1 1 1 2 1 2 1
+1 2 2 2 2 2 1 2 1 2 1 2 1 1 1 2 2 2 1 2 2 2 2 2 2 1 2 1
+1 2 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 2 1 2 1 2 1 1 2 1 2 1
+1 2 1 2 2 2 2 2 1 1 1 1 4 1 2 2 2 2 1 2 1 2 2 1 2 1 2 1
+0 2 2 2 1 1 1 2 2 1 0 1 5 1 1 1 1 1 1 2 1 1 2 1 2 1 2 0
+1 1 1 1 1 1 1 1 2 1 1 1 4 1 1 1 2 2 2 2 2 2 2 2 2 1 2 1
+1 2 2 2 2 2 3 1 2 2 2 2 2 2 2 2 2 1 2 1 1 1 1 1 2 1 2 1
+1 2 1 1 1 1 2 1 1 1 2 1 1 2 1 1 1 1 2 2 2 1 6 1 2 1 2 1
+1 2 2 2 2 1 2 1 2 2 2 2 2 2 2 2 2 2 2 1 2 1 4 1 2 1 2 1
+1 1 1 1 2 1 2 1 2 1 1 2 1 1 1 2 1 1 1 1 2 1 0 1 2 1 2 1
+0 2 2 2 2 1 2 1 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 1 2 0
+1 1 1 1 2 1 2 1 1 1 1 2 1 2 1 1 2 1 1 1 1 1 1 1 1 1 1 1
+1 1 2 2 2 1 2 1 2 2 2 2 1 2 2 2 2 1 2 2 2 2 2 2 2 2 2 1
+1 1 4 4 1 1 2 1 2 1 2 1 1 1 1 1 2 1 2 1 1 1 1 1 1 1 2 1
+1 1 7 8 1 1 2 1 2 1 2 2 2 3 2 2 2 1 2 1 2 2 2 3 2 2 2 1
+1 1 1 1 1 2 2 1 2 1 1 2 1 1 1 1 2 1 2 1 2 1 1 1 1 1 1 1
+0 2 2 2 1 2 1 2 2 2 1 2 2 2 2 2 2 1 2 1 2 1 2 2 2 2 2 0
+1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1 1 0 1 0 1 0 1 1 1 1 1
+6
diff --git a/Levels/level07.dat b/Levels/level07.dat
new file mode 100755 (executable)
index 0000000..359dfe9
--- /dev/null
@@ -0,0 +1,30 @@
+1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 4 4 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 2 1 1 1 1 2 1 1 4 1 1 2 1 1 2 1 1 4 1 1 2 1 1 1 1 2 1
+1 3 1 0 0 1 2 1 1 0 1 1 2 0 0 2 1 1 0 1 1 2 1 0 0 1 3 1
+1 2 1 0 0 1 2 1 1 0 1 1 2 1 1 2 1 1 0 1 1 2 1 0 0 1 2 1
+1 2 1 1 1 1 2 1 1 4 1 1 2 1 1 2 1 1 4 1 1 2 1 1 1 1 2 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 2 1 4 1 1 2 1 1 2 1 1 1 1 1 1 1 1 2 1 1 2 1 1 4 1 2 1
+1 2 1 4 1 1 2 1 1 2 1 1 1 1 1 1 1 1 2 1 1 2 1 1 4 1 2 1
+1 2 2 2 2 2 2 1 1 2 2 2 2 1 1 2 2 2 2 1 1 2 2 2 2 2 2 1
+1 1 1 1 1 1 2 1 1 1 1 1 0 1 1 0 1 1 1 1 1 2 1 1 1 1 1 1
+0 0 0 0 0 1 2 1 1 1 1 1 0 1 1 0 1 1 1 1 1 2 1 0 0 0 0 0
+0 0 0 0 0 1 2 1 1 0 0 0 0 0 0 0 0 0 0 1 1 2 1 0 0 0 0 0
+0 0 0 0 0 1 2 1 1 0 1 1 1 4 4 1 1 1 0 1 1 2 1 0 0 0 0 0
+1 1 1 1 1 1 2 1 1 0 1 0 0 0 6 5 0 1 0 0 0 2 1 1 1 1 1 1
+0 0 0 0 0 0 2 0 0 0 1 0 8 7 0 0 0 1 0 1 1 2 0 0 0 0 0 0
+1 1 1 1 1 1 2 1 1 0 1 1 1 4 4 1 1 1 0 1 1 2 1 1 1 1 1 1
+0 0 0 0 0 1 2 1 1 0 0 0 0 0 0 0 0 0 0 1 1 2 1 0 0 0 0 0
+1 1 1 1 1 1 2 1 1 0 1 1 1 1 1 1 1 1 0 1 1 2 1 1 1 1 1 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 4 4 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 2 1 4 1 1 2 1 1 4 1 1 2 1 1 2 1 1 4 1 1 2 1 1 4 1 2 1
+1 2 1 4 1 1 2 1 1 4 1 1 2 1 1 2 1 1 4 1 1 2 1 1 4 1 2 1
+1 2 2 2 4 4 2 2 2 2 2 2 2 2 9 2 2 2 2 2 2 2 4 4 2 2 2 1
+1 1 1 2 1 1 2 1 1 2 1 1 4 1 1 4 1 1 2 1 1 2 1 1 2 1 1 1
+1 1 1 2 1 1 2 1 1 2 1 1 4 1 1 4 1 1 2 1 1 2 1 1 2 1 1 1
+1 2 2 2 2 2 2 4 4 2 2 2 2 0 0 2 2 2 2 4 4 2 2 2 2 2 2 1
+1 2 1 1 1 1 4 1 1 1 1 1 2 1 1 2 1 1 1 1 1 4 1 1 1 1 2 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 4 2 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+7
diff --git a/Levels/level08.dat b/Levels/level08.dat
new file mode 100755 (executable)
index 0000000..38c8b9e
--- /dev/null
@@ -0,0 +1,30 @@
+1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 0 1 0 1
+0 2 2 2 2 2 2 2 2 2 2 2 4 2 4 2 4 2 2 2 2 2 2 2 2 4 2 0
+1 4 1 4 1 1 1 1 1 1 1 2 1 2 1 2 1 2 1 1 1 1 1 1 1 1 4 1
+1 0 1 2 2 2 1 2 2 2 1 2 1 2 1 2 1 2 1 2 2 2 1 1 2 2 2 1
+1 0 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 4 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 4 2 1 2 1
+1 7 4 2 1 2 2 2 1 2 2 2 1 2 1 2 4 2 1 2 1 2 1 2 2 1 2 1
+1 4 1 2 1 4 1 1 1 4 1 1 1 2 1 2 1 2 1 2 1 2 1 2 4 1 2 1
+1 2 2 2 2 2 2 2 2 2 1 2 2 2 1 2 1 2 1 2 1 2 1 2 2 1 2 1
+1 2 1 1 1 1 1 1 1 2 1 2 1 1 1 2 1 2 1 2 1 2 1 4 2 1 2 1
+1 2 2 2 2 2 2 2 2 2 2 9 2 2 2 2 1 2 1 2 1 2 1 2 2 4 2 1
+1 2 1 1 1 1 1 1 1 1 1 2 1 4 1 1 1 2 1 2 1 2 1 2 1 1 2 1
+1 2 1 2 2 2 2 2 2 2 1 2 1 4 1 2 2 2 1 2 1 2 1 2 1 2 2 1
+1 2 1 2 1 4 1 1 1 2 1 2 1 2 2 2 1 1 1 2 1 2 2 2 1 2 1 1
+1 2 1 2 1 2 2 2 1 2 1 2 1 2 1 1 1 2 2 2 1 4 1 1 1 2 1 1
+1 2 1 2 2 2 1 2 1 2 4 2 1 2 2 2 1 2 1 1 1 2 2 2 1 2 2 1
+1 2 1 1 1 4 1 2 1 2 1 2 1 1 1 2 1 2 1 2 2 2 1 2 2 1 2 1
+1 2 2 2 2 2 2 2 1 2 1 2 2 2 2 2 1 2 1 2 1 1 1 1 2 1 2 1
+1 2 1 1 1 1 1 4 1 2 1 2 1 1 1 1 1 2 1 2 1 0 0 1 2 1 2 1
+1 2 2 2 2 2 2 2 2 2 1 2 4 2 2 2 2 2 1 2 1 1 1 1 2 1 2 1
+1 1 1 1 1 4 1 1 1 1 1 2 1 1 1 1 1 2 1 2 2 1 2 2 2 1 2 1
+0 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 0
+1 1 1 1 1 4 1 1 1 2 1 2 1 2 1 2 1 1 2 1 2 1 2 1 2 1 1 1
+0 2 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 2 2 2 2 2 2 2 2 2 0
+1 1 1 1 1 1 1 1 1 4 1 2 1 2 1 2 1 0 1 4 4 1 1 1 1 4 1 1
+1 8 4 2 2 2 2 2 2 2 2 2 4 2 4 2 1 0 1 5 6 1 2 2 2 2 2 1
+1 4 1 1 1 1 1 1 1 1 1 2 1 2 1 2 1 1 1 1 1 1 2 1 1 1 2 1
+1 2 2 2 2 2 2 2 2 2 2 2 1 2 1 2 2 2 2 2 2 1 2 2 2 1 2 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 0 1 0 1
+8
diff --git a/Levels/level09.dat b/Levels/level09.dat
new file mode 100755 (executable)
index 0000000..1989ce5
--- /dev/null
@@ -0,0 +1,30 @@
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+1 2 2 2 2 2 2 2 2 2 9 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 1
+1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1
+1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 2 1 4 1 1 1 1 1 1 1 1 1 4 1 1 1 1 1 1 1 1 1 1 1 1 4 1
+1 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1
+1 2 1 4 1 4 1 4 1 4 1 4 1 1 1 1 1 1 1 1 1 1 1 1 4 1 2 1
+1 2 2 2 1 2 2 2 1 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 4 1 2 1 1 1 1 1 1 1 1 1 1 2 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 2 3 2 2 2 2 2 2 2 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 1 1 4 1 1 1 4 1 2 1
+1 3 1 2 1 2 1 2 1 2 1 2 1 2 1 2 2 2 2 2 2 2 2 2 2 1 2 1
+1 2 1 2 1 2 1 3 1 2 1 2 1 2 1 4 1 4 1 2 1 4 1 1 4 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 2 2 2 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 2 2 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 2 1 1 1 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 2 1 2 2 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 2 1 2 2 2 1 2 2 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 2 1 4 1 4 1 4 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 2 3 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1
+1 4 1 4 1 4 1 4 1 2 1 2 1 2 1 2 2 2 1 2 1 2 1 1 2 1 2 1
+1 0 1 0 1 0 1 0 1 2 1 2 1 2 1 1 1 1 1 2 1 2 1 1 2 1 2 1
+1 5 1 6 1 7 1 8 1 2 3 2 4 2 2 2 2 2 2 2 2 2 2 2 2 2 3 1
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+9
diff --git a/Levels/template.dat b/Levels/template.dat
new file mode 100755 (executable)
index 0000000..327747d
--- /dev/null
@@ -0,0 +1,30 @@
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
+1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+1
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100755 (executable)
index 0000000..d60ec49
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,30 @@
+prefix=/usr/local
+bindir=$(prefix)/bin
+datarootdir=$(prefix)/share
+
+all:
+       gcc pacman.c     -o pacman     -DDATAROOTDIR=\"$(datarootdir)\" $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -lncurses
+       gcc pacmanedit.c -o pacmanedit -DDATAROOTDIR=\"$(datarootdir)\" $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -lncurses
+
+install:    all
+       mkdir -p $(DESTDIR)$(bindir)
+       mkdir -p $(DESTDIR)$(datarootdir)/pacman
+       cp -fR Levels/ $(DESTDIR)$(datarootdir)/pacman/
+       -chown root:games $(DESTDIR)$(bindir)/pacman
+       -chown root:games $(DESTDIR)$(datarootdir)/pacman -R
+       chmod 750 $(DESTDIR)$(bindir)/pacman
+       chmod 750 $(DESTDIR)$(bindir)/pacmanedit
+       chmod 750 $(DESTDIR)$(datarootdir)/pacman/ -R
+
+uninstall:
+       rm -f $(DESTDIR)$(bindir)/pacman
+       rm -f $(DESTDIR)$(bindir)/pacmanedit
+       rm -f $(DESTDIR)$(datarootdir)/pacman/Levels/level0[1-9].dat
+       rm -f $(DESTDIR)$(datarootdir)/pacman/Levels/README
+       rm -f $(DESTDIR)$(datarootdir)/pacman/Levels/template.dat
+       if [ -e $(DESTDIR)$(datarootdir)/pacman/Levels/ ] ; then rmdir $(DESTDIR)$(datarootdir)/pacman/Levels/ ; fi
+       if [ -e $(DESTDIR)$(datarootdir)/pacman/ ] ; then rmdir $(DESTDIR)$(datarootdir)/pacman/ ; fi
+
+clean: uninstall
+       rm -f pacman
+       rm -f pacmanedit
diff --git a/README b/README
new file mode 100755 (executable)
index 0000000..8f338df
--- /dev/null
+++ b/README
@@ -0,0 +1,56 @@
+
+Pacman For Console
+------------------
+Okay, so basically, I got tired of enabling flash on my browser so that I could play Pacman.
+That, and I was extremely bored one night. So I decided to make my own Pacman... for Console.
+
+Licenseing Information
+----------------------
+See COPYING for details on the GNU/GPL
+
+Compile/Install
+---------------
+To make... gee... let's see. type 'make'
+To install... type 'make install'
+To run...type 'pacman [level_#]'          where # is 1-9, for a premade level
+    OR   type 'pacmac [level_file_name]'  for a custom level you made
+To uninstall... type 'make uninstall'
+    i.e.:
+        make && su -c "make install"
+        pacman 3                                        # Start @ level 3
+        pacman /usr/share/pacman/Levels/level07.dat     # Play only level 7
+        echo ":-( I don't like it." && make uninstall   # Uninstall :-(
+
+The ASCII art:
+--------------
+C      -       Pacman - That's you.
+&      -       Ghosts - Boo.
+.      -       Pellet - Yummy. Collect all of them to pass to the next level.
+*      -       Power pellet - Makes you invincible for a short while.
+       -       Wall - No one can walk through it.
+       -       Blocker - A.K.A. Ghost wall. Only the Ghosts can walk through this.
+
+
+13 Basics Playing Rules
+-----------------------
+In case you don't know the rules of Pacman (rules I programmed in), here are most of them
+1) Pacman must collect all the pellets of food in the maze. 1 point per pellet.
+2) Big pellets make Pacman invincible for a short amount of time.
+3) If Pacman touches a ghost without being invincible, he dies and loses 1 life.
+4) If Pacman touches a ghost while invincible, the ghost is sent back to its starting point.
+5) Points are awarded for each ghost eaten in a row while invincible: 20, 40, 80, 160 (10*2^x).
+6) Pacman cannot go through the Ghost Walls (Blockers).
+7) Ghosts cannot turn completely around unless there is no other option.
+8) While Pacman is invincible, Ghosts will be a bit slower and tend to stay away from him.
+9) While Pacman is NOT invincible, Ghosts will tend to come toward him.
+10) Pacman starts with 3 extra lives, once all three are gone, the game is over.
+11) Extra lives are awarded at 1000 points, 2000, 4000, 8000... (500*2^x).
+12) If any character reaches a border of the maze, it will be transported to the opposite side.
+13) Each character can only go in one X or Y direction at a time.
+
+To make your own levels, see Levels/README
+
+Contact Information
+-------------------
+Send comments and levels you have made to: michaelbillars@gmail.com
+I would love to include more levels.
diff --git a/pacman b/pacman
new file mode 100755 (executable)
index 0000000..b9682e1
Binary files /dev/null and b/pacman differ
diff --git a/pacman.c b/pacman.c
new file mode 100755 (executable)
index 0000000..fda4a6d
--- /dev/null
+++ b/pacman.c
@@ -0,0 +1,750 @@
+/****************************************************
+* Pacman For Console V1.3                           *
+* By: Mike Billars (michael@gmail.com)              *
+* Date: 2014-04-26                                  *
+*                                                   *
+* Please see file COPYING for details on licensing  *
+*       and redistribution of this program          *
+*                                                   *
+****************************************************/
+
+/***********
+* INCLUDES *
+***********/
+#include <stdio.h>
+#include <curses.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/timeb.h>
+#include "pacman.h"
+
+#define EXIT_MSG "Good bye!"
+#define END_MSG "Game Over"
+#define QUIT_MSG "Bye"
+#define LEVEL_ERR "Cannot find level file: "
+#define LEVEL_WIDTH 28
+#define LEVEL_HEIGHT 29
+
+/*************
+* PROTOTYPES *
+*************/
+void IntroScreen();                                     //Show introduction screen and menu
+void CheckCollision();                                  //See if Pacman and Ghosts collided
+void CheckScreenSize();                                 //Make sure resolution is at least 32x29
+void CreateWindows(int y, int x, int y0, int x0);       //Make ncurses windows
+void Delay();                                           //Slow down game for better control
+void DrawWindow();                                      //Refresh display
+void ExitProgram(const char *message);                  //Exit and display something
+void GetInput();                                        //Get user input
+void InitCurses();                                      //Start up ncurses
+void LoadLevel(char *levelfile);                        //Load level into memory
+void MainLoop();                                        //Main program function
+void MoveGhosts();                                      //Update Ghosts' location
+void MovePacman();                                      //Update Pacman's location
+void PauseGame();                                       //Pause
+
+
+/*******************
+* GLOBAL VARIABLES *
+*******************/
+//I know global variables are bad, but it's just sooo easy!
+
+//Windows used by ncurses
+WINDOW * win;
+WINDOW * status;
+
+//For colors
+enum { Wall = 1, Normal, Pellet, PowerUp, GhostWall, Ghost1, Ghost2, Ghost3, Ghost4, BlueGhost, Pacman };
+
+int Loc[5][2] = { 0 };                    //Location of Ghosts and Pacman
+int Dir[5][2] = { 0 };                    //Direction of Ghosts and Pacman
+int StartingPoints[5][2] = { 0 };         //Default location in case Pacman/Ghosts die
+int Invincible = 0;                       //Check for invincibility
+int Food = 0;                             //Number of pellets left in level
+int Level[29][28] = { 0 };                //Main level array
+int LevelNumber = 0;                      //What level number are we on?
+int GhostsInARow = 0;                     //Keep track of how many points to give for eating ghosts
+int tleft = 0;                            //How long left for invincibility
+
+/****************************************************************
+* Function:    main()                                           *
+* Parameters:  argc, argv (passed from command line)            *
+* Returns:     Success                                          *
+* Description: Initiate the program and call the subfunctions   *
+****************************************************************/
+int main(int argc, char *argv[100]) {
+
+    int j = 0;
+    srand( (unsigned)time( NULL ) );
+
+    InitCurses();                   //Must be called to start ncurses
+    CheckScreenSize();              //Make sure screen is big enough
+    CreateWindows(29, 28, 1, 1);    //Create the main and status windows
+
+    //If they specified a level to load
+    if((argc > 1) && (strlen(argv[1]) > 1)) {
+        argv[1][99] = '\0';
+        LoadLevel(argv[1]);         //Load it and...
+        MainLoop();                 //Start the game
+    }
+
+    //If they did not enter a level, display intro screen then use default levels
+    else {
+        IntroScreen();              //Show intro "movie"
+        j = 1;                      //Set initial level to 1
+
+        if(argc > 1) j = argv[1][0] - '0';    //They specified a level on which to start (1-9)
+
+        //Load 9 levels, 1 by 1, if you can beat all 9 levels in a row, you're awesome
+        for(LevelNumber = j; LevelNumber < 10; LevelNumber++) {
+
+            //Replace level string underscore with the actual level number (see pacman.h)
+            LevelFile[strlen(LevelFile) - 6] = '0';
+            LevelFile[strlen(LevelFile) - 5] = LevelNumber + '0';
+
+            LoadLevel(LevelFile);   //Load level into memory
+            Invincible = 0;         //Reset invincibility with each new level
+            MainLoop();             //Start the level
+
+        }
+
+    }
+
+    //Game has ended, deactivate and end program
+    ExitProgram(EXIT_MSG);
+
+    //This doesn't need to be here, but just to be proper
+    return(0);
+}
+
+/****************************************************************
+* Function:    CheckCollision()                                 *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Check and handle if Pacman collided with a ghost *
+****************************************************************/
+void CheckCollision() {
+
+    //Temporary variable
+    int a = 0;
+
+    //Check each ghost, one at a time for collision
+    for(a = 0; a < 4; a++) {
+
+        //Ghost X and Y location is equal to Pacman X and Y location (collision)
+        if((Loc[a][0] == Loc[4][0]) && (Loc[a][1] == Loc[4][1])) {
+
+            //Pacman is invincible, ghost dies
+            if(Invincible == 1) {
+
+                Points = Points + GhostsInARow * 20;    //Increase points by an increasing value
+
+                //Display the points earned for eating the ghost
+                mvwprintw(win, Loc[4][0], Loc[4][1] - 1, "%d", (GhostsInARow * 20));
+                GhostsInARow *= 2;
+
+                wrefresh(win);      //Update display
+                usleep(1000000);    //and pause for a second
+
+                //Reset the ghost's position to the starting location
+                Loc[a][0] = StartingPoints[a][0]; Loc[a][1] = StartingPoints[a][1];
+            }
+
+            //Pacman is vulnerable, Pacman dies
+            else {
+
+                //Display an X in position
+                wattron(win, COLOR_PAIR(Pacman));
+                mvwprintw(win, Loc[4][0], Loc[4][1], "X");
+                wrefresh(win);
+
+                //Subtract one life and pause for 1 second
+                Lives--;
+                usleep(1000000);
+
+                //If no more lives, game over
+                if(Lives == -1) ExitProgram(END_MSG);
+
+                //If NOT game over...
+
+                //Reset Pacman's and ghosts' positions
+                for(a = 0; a < 5; a++) {
+                    Loc[a][0] = StartingPoints[a][0];
+                    Loc[a][1] = StartingPoints[a][1];
+                }
+
+                //Reset directions
+                Dir[0][0] =  1; Dir[0][1] =  0;
+                Dir[1][0] = -1; Dir[1][1] =  0;
+                Dir[2][0] =  0; Dir[2][1] = -1;
+                Dir[3][0] =  0; Dir[3][1] =  1;
+                Dir[4][0] =  0; Dir[4][1] = -1;
+
+                DrawWindow();       //Redraw window
+                usleep(1000000);    //Pause for 1 second before continuing game
+            }
+        }
+    }
+}
+
+/****************************************************************
+* Function:    CheckScreenSize()                                *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Make sure the virtual console is big enough      *
+****************************************************************/
+void CheckScreenSize() {
+
+        //Make sure the window is big enough
+        int h, w; getmaxyx(stdscr, h, w);
+
+        if((h < 32) || (w < 29)) {
+                endwin();
+                fprintf(stderr, "\nSorry.\n");
+                fprintf(stderr, "To play Pacman for Console, your console window must be at least 32x29\n");
+                fprintf(stderr, "Please resize your window/resolution and re-run the game.\n\n");
+                exit(0);
+        }
+
+}
+
+/****************************************************************
+* Function:    CreateWindows()                                  *
+* Parameters:  y, x, y0, x0 (coords and size of window)         *
+* Returns:     none                                             *
+* Description: Create the main game windows                     *
+****************************************************************/
+void CreateWindows(int y, int x, int y0, int x0) {
+    //Create two new windows, for status bar and for main level
+    win = newwin(y, x, y0, x0);
+    status = newwin(3, 27, 29, 1);
+}
+
+/****************************************************************
+* Function:    Delay()                                          *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Pause the game and still get keyboard input      *
+****************************************************************/
+void Delay() {
+
+    //Needed to get time
+    struct timeb t_start, t_current;
+    ftime(&t_start);
+
+    //Slow down the game a little bit
+    do {
+        GetInput();                 //Still get the input from keyboard
+        ftime(&t_current);          //Update time and check if enough time has overlapped
+    } while (abs(t_start.millitm - t_current.millitm) < SpeedOfGame);
+}
+
+/****************************************************************
+* Function:    DrawWindow()                                     *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Redraw each window to update the screen          *
+****************************************************************/
+void DrawWindow() {
+
+    //Temporary variables
+    int a = 0; int b = 0;
+    char chr = ' ';                 //Variable used to display certain characters
+    int attr;                       //Variable that displays normal/bold character
+
+    //Display level array
+    for(a = 0; a < 29; a++) for(b = 0; b < 28; b++) {
+        //Determine which character is in location and display it
+        switch(Level[a][b]) {
+        case 0: chr = ' '; attr = A_NORMAL; wattron(win, COLOR_PAIR(Normal));    break;
+        case 1: chr = ' '; attr = A_NORMAL; wattron(win, COLOR_PAIR(Wall));      break;
+        case 2: chr = '.'; attr = A_NORMAL; wattron(win, COLOR_PAIR(Pellet));    break;
+        case 3: chr = '*'; attr = A_BOLD;   wattron(win, COLOR_PAIR(PowerUp));   break;
+        case 4: chr = ' '; attr = A_NORMAL; wattron(win, COLOR_PAIR(GhostWall)); break;
+        }
+
+        //Display character. "attr" is ORed with chr as documented for mvwaddch,
+        //    this will make the character bold/normal
+        mvwaddch(win, a, b, chr | attr);
+    }
+
+    //Display number of lives, score, and level
+
+    attr = A_NORMAL;                //Reset attribute in case it's set to "BOLD"
+
+    //Switch window to status, and change color
+    wmove(status, 1, 1);
+    wattron(status, COLOR_PAIR(Pacman));
+
+    //Display number of lives
+    for(a = 0; a < Lives; a++)
+        wprintw(status, "C ");
+    wprintw(status, "  ");
+
+    //Display level number and score
+    wattron(status, COLOR_PAIR(Normal));
+    mvwprintw(status, 2, 2, "Level: %d     Score: %d ", LevelNumber, Points);
+
+    wrefresh(status);               //Update status window
+
+    //Display ghosts if Pacman is not invincible
+    if(Invincible == 0) {
+        wattron(win, COLOR_PAIR(Ghost1)); mvwaddch(win, Loc[0][0], Loc[0][1], '&');
+        wattron(win, COLOR_PAIR(Ghost2)); mvwaddch(win, Loc[1][0], Loc[1][1], '&');
+        wattron(win, COLOR_PAIR(Ghost3)); mvwaddch(win, Loc[2][0], Loc[2][1], '&');
+        wattron(win, COLOR_PAIR(Ghost4)); mvwaddch(win, Loc[3][0], Loc[3][1], '&');
+    }
+
+    //OR display vulnerable ghosts
+    else {
+        wattron(win, COLOR_PAIR(BlueGhost));
+        mvwaddch(win, Loc[0][0], Loc[0][1], tleft + '0');
+        mvwaddch(win, Loc[1][0], Loc[1][1], tleft + '0');
+        mvwaddch(win, Loc[2][0], Loc[2][1], tleft + '0');
+        mvwaddch(win, Loc[3][0], Loc[3][1], tleft + '0');
+    }
+
+    //Display Pacman
+    wattron(win, COLOR_PAIR(Pacman)); mvwaddch(win, Loc[4][0], Loc[4][1], 'C');
+
+    wrefresh(win);                  //Update main window
+}
+
+/****************************************************************
+* Function:    ExitProgram()                                    *
+* Parameters:  message: text to display before exiting          *
+* Returns:     none                                             *
+* Description: Gracefully end program                           *
+****************************************************************/
+void ExitProgram(const char *message) {
+    endwin();                       //Uninitialize ncurses and destroy windows
+    printf("%s\n", message);        //Display message
+    exit(0);                        //End program, return 0
+}
+
+/****************************************************************
+* Function:    GetInput()                                       *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Get input from user and take appropriate action  *
+****************************************************************/
+void GetInput() {
+
+    int ch;                         //Key pushed
+    static int chtmp;               //Buffered key
+    int tmp;
+
+    ch = getch();                   //Figure out which key is pressed
+
+    //If they are not pressing something, use previous input
+    if(ch == ERR) ch = chtmp;
+    chtmp = ch;
+
+    //Determine which button is pushed
+    switch (ch) {
+    case KEY_UP:    case 'w': case 'W':            //Move pacman up
+        if(Loc[4][0] <= 0) tmp = LEVEL_HEIGHT - 1;
+        else tmp = Loc[4][0] - 1;
+        if((Level[tmp][Loc[4][1]] != 1)
+        && (Level[tmp][Loc[4][1]] != 4))
+            { Dir[4][0] = -1; Dir[4][1] =  0; }
+        break;
+
+    case KEY_DOWN:  case 's': case 'S':            //Move pacman down
+        if(Loc[4][0] >= 28) tmp = 0;
+        else tmp = Loc[4][0] + 1;
+        if((Level[tmp][Loc[4][1]] != 1)
+        && (Level[tmp][Loc[4][1]] != 4))
+            { Dir[4][0] =  1; Dir[4][1] =  0; }
+        break;
+
+    case KEY_LEFT:  case 'a': case 'A':            //Move pacman left
+        if(Loc[4][1] <= 0) tmp = LEVEL_WIDTH - 1;
+        else tmp = Loc[4][1] - 1;
+        if((Level[Loc[4][0]][tmp] != 1)
+        && (Level[Loc[4][0]][tmp] != 4))
+            { Dir[4][0] =  0; Dir[4][1] = -1; }
+        break;
+
+    case KEY_RIGHT: case 'd': case 'D':            //Move pacman right
+        if(Loc[4][1] >= 27) tmp = 0;
+        else tmp = Loc[4][1] + 1;
+        if((Level[Loc[4][0]][tmp] != 1)
+        && (Level[Loc[4][0]][tmp] != 4))
+            { Dir[4][0] =  0; Dir[4][1] =  1; }
+        break;
+
+    case 'p': case 'P':                            //Pause game
+        PauseGame();
+        chtmp = getch();            //Update buffered input
+        break;
+
+    case 'q': case 'Q':                            //End program
+        ExitProgram(QUIT_MSG);
+        break;
+
+    }
+}
+
+/****************************************************************
+* Function:    InitCurses()                                     *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Initialize ncurses and set defined colors        *
+****************************************************************/
+void InitCurses() {
+
+    initscr();                      //Needed for ncurses windows
+    start_color();                  //Activate colors in console
+    curs_set(0);                    //    Don't remember
+    keypad(stdscr, TRUE);           //Activate arrow keys
+    nodelay(stdscr, TRUE);          //Allow getch to work without pausing
+    nonl();                         //    Don't remember
+    cbreak();                       //    Don't remember
+    noecho();                       //Don't display input key
+
+    //Make custom text colors
+    init_pair(Normal,    COLOR_WHITE,   COLOR_BLACK);
+    init_pair(Wall,      COLOR_WHITE,   COLOR_WHITE);
+    init_pair(Pellet,    COLOR_WHITE,   COLOR_BLACK);
+    init_pair(PowerUp,   COLOR_BLUE,    COLOR_BLACK);
+    init_pair(GhostWall, COLOR_WHITE,   COLOR_CYAN);
+    init_pair(Ghost1,    COLOR_RED,     COLOR_BLACK);
+    init_pair(Ghost2,    COLOR_CYAN,    COLOR_BLACK);
+    init_pair(Ghost3,    COLOR_MAGENTA, COLOR_BLACK);
+    init_pair(Ghost4,    COLOR_YELLOW,  COLOR_BLACK);
+    init_pair(BlueGhost, COLOR_BLUE,    COLOR_RED);
+    init_pair(Pacman,    COLOR_YELLOW,  COLOR_BLACK);
+}
+
+/****************************************************************
+* Function:    IntroScreen()                                    *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Display the introduction animation               *
+****************************************************************/
+void IntroScreen() {
+    int a = 0;
+    int b = 23;
+
+    a=getch(); a=getch(); a=getch();//Clear the buffer
+
+    mvwprintw(win, 20, 8, "Press any key...");
+
+    //Scroll Pacman to middle of screen
+    for(a = 0; a < 13; a++) {
+        if(getch()!=ERR) return;    
+        wattron(win, COLOR_PAIR(Pacman));
+        mvwprintw(win, 8, a, " C");
+        wrefresh(win);
+        usleep(100000);
+    }
+
+    //Show "Pacman"
+    wattron(win, COLOR_PAIR(Pacman));
+    mvwprintw(win, 8, 12, "PACMAN");
+    wrefresh(win);
+    usleep(1000000);
+
+    //Ghosts chase Pacman
+    for(a = 0; a < 23; a++) {
+        if(getch()!=ERR) return;
+        wattron(win, COLOR_PAIR(Pellet)); mvwprintw(win, 13, 23, "*");
+        wattron(win, COLOR_PAIR(Pacman)); mvwprintw(win, 13, a, " C");
+        wattron(win, COLOR_PAIR(Ghost1)); mvwprintw(win, 13, a-3, " &");
+        wattron(win, COLOR_PAIR(Ghost3)); mvwprintw(win, 13, a-5, " &");
+        wattron(win, COLOR_PAIR(Ghost2)); mvwprintw(win, 13, a-7, " &");
+        wattron(win, COLOR_PAIR(Ghost4)); mvwprintw(win, 13, a-9, " &");
+        wrefresh(win);
+        usleep(100000);
+    }
+
+    usleep(150000);
+
+    //Pacman eats powerup and chases Ghosts
+    for(a = 25; a > 2; a--) {
+        if(getch()!=ERR) return;
+        wattron(win, COLOR_PAIR(Pellet)); mvwprintw(win, 13, 23, " ");
+
+        //Make ghosts half as fast so Pacman can catch them
+        if(a%2) b--;
+
+        wattron(win, COLOR_PAIR(BlueGhost)); mvwprintw(win, 13, b-9, "& & & &");
+
+        //Erase the old positions of ghosts
+        wattron(win, COLOR_PAIR(Pacman)); mvwprintw(win, 13, b-9+1, " ");
+        wattron(win, COLOR_PAIR(Pacman)); mvwprintw(win, 13, b-9+3, " ");
+        wattron(win, COLOR_PAIR(Pacman)); mvwprintw(win, 13, b-9+5, " ");
+        wattron(win, COLOR_PAIR(Pacman)); mvwprintw(win, 13, b-9+7, " ");
+
+        wattron(win, COLOR_PAIR(Pacman)); mvwprintw(win, 13, a-3, "C          ");
+
+        wattron(win, COLOR_PAIR(Pellet)); mvwprintw(win, 13, 23, " ");
+        wrefresh(win);
+        usleep(100000);
+    }
+
+}
+
+/****************************************************************
+* Function:    LoadLevel()                                      *
+* Parameters:  levelfile: name of file to load                  *
+* Returns:     none                                             *
+* Description: Open level file and load it into memory          *
+****************************************************************/
+void LoadLevel(char levelfile[100]) {
+
+    int a = 0; int b = 0;
+    size_t l;
+    char error[sizeof(LEVEL_ERR)+255] = LEVEL_ERR;    //Let's assume an error
+    FILE *fin;                      //New file variable
+    Food = 0;                       //Used to count how many food pellets must be eaten
+
+    //Reset defaults
+    Dir[0][0] =  1; Dir[0][1] =  0;
+    Dir[1][0] = -1; Dir[1][1] =  0;
+    Dir[2][0] =  0; Dir[2][1] = -1;
+    Dir[3][0] =  0; Dir[3][1] =  1;
+    Dir[4][0] =  0; Dir[4][1] = -1;
+
+        //Open file
+        fin = fopen(levelfile, "r");
+
+        //Make sure it didn't fail
+        if(!(fin)) {
+            l = sizeof(error)-strlen(error)-1;
+            strncat(error, levelfile, l);
+            if(strlen(levelfile) > l) {
+                error[sizeof(error)-2] = '.';
+                error[sizeof(error)-3] = '.';
+                error[sizeof(error)-4] = '.';
+            }
+            ExitProgram(error);
+        }
+
+        //Open file and load the level into the array
+        for(a = 0; a < 29; a++) {
+                for(b = 0; b < 28; b++) {
+                        fscanf(fin, "%d", &Level[a][b]);    //Get character from file
+            if(Level[a][b] == 2) { Food++; }    //If it's a pellet, increase the pellet count
+
+            //Store ghosts' and Pacman's locations
+            if(Level[a][b] == 5) { Loc[0][0] = a; Loc[0][1] = b; Level[a][b] = 0;}
+            if(Level[a][b] == 6) { Loc[1][0] = a; Loc[1][1] = b; Level[a][b] = 0;}
+            if(Level[a][b] == 7) { Loc[2][0] = a; Loc[2][1] = b; Level[a][b] = 0;}
+            if(Level[a][b] == 8) { Loc[3][0] = a; Loc[3][1] = b; Level[a][b] = 0;}
+            if(Level[a][b] == 9) { Loc[4][0] = a; Loc[4][1] = b; Level[a][b] = 0;}
+                }
+        }
+
+    //All done, now get the difficulty level (AKA level number)
+        fscanf(fin, "%d", &LevelNumber);
+
+    //Save initial character positions in case Pacman or Ghosts die
+    for(a = 0; a < 5; a++) {
+        StartingPoints[a][0] = Loc[a][0]; StartingPoints[a][1] = Loc[a][1];
+    }
+
+}
+
+/****************************************************************
+* Function:    MainLoop()                                       *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Control the main execution of the game           *
+****************************************************************/
+void MainLoop() {
+
+    DrawWindow();                    //Draw the screen
+    wrefresh(win); wrefresh(status); //Refresh it just to make sure
+    usleep(1000000);                 //Pause for a second so they know they're about to play
+
+    /* Move Pacman. Move ghosts. Check for extra life awarded
+    from points. Pause for a brief moment. Repeat until all pellets are eaten */
+    do {
+        MovePacman();    DrawWindow();    CheckCollision();
+        MoveGhosts();    DrawWindow();    CheckCollision();
+        if(Points > FreeLife) { Lives++; FreeLife *= 2;}
+        Delay();
+    } while (Food > 0);
+
+    DrawWindow();                   //Redraw window and...
+    usleep(1000000);                //Pause, level complete
+
+}
+
+/****************************************************************
+* Function:    MoveGhosts()                                     *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Move all ghosts and check for wall collisions    *
+****************************************************************/
+void MoveGhosts() {
+
+    //Set up some temporary variables
+    int a = 0; int b = 0; int c = 0;
+    int checksides[] = { 0, 0, 0, 0, 0, 0 };
+    static int SlowerGhosts = 0;
+    int tmp;
+
+    /* Move ghosts slower when they are vulnerable. This will allow
+    the ghosts to move only x times for every y times Pacman moves */
+    if(Invincible == 1) {
+        SlowerGhosts++;
+        if(SlowerGhosts > HowSlow)
+            SlowerGhosts = 0;
+    }
+
+    //If ghosts are not vulnerable OR the ghosts can move now
+    if((Invincible == 0) || SlowerGhosts < HowSlow)
+
+    //Loop through each ghost, one at a time
+    for(a = 0; a < 4; a++) {
+
+        //Switch sides? (Transport to other side of screen)
+             if((Loc[a][0] ==  0) && (Dir[a][0] == -1)) Loc[a][0] = 28;
+        else if((Loc[a][0] == 28) && (Dir[a][0] ==  1)) Loc[a][0] =  0;
+        else if((Loc[a][1] ==  0) && (Dir[a][1] == -1)) Loc[a][1] = 27;
+        else if((Loc[a][1] == 27) && (Dir[a][1] ==  1)) Loc[a][1] =  0;
+        else {
+
+        //Determine which directions we can go
+        for(b = 0; b < 4; b++) checksides[b] = 0;
+        if(Loc[a][0] == 28) tmp = 0;
+        else tmp = Loc[a][0] + 1;
+        if(Level[tmp][Loc[a][1]] != 1) checksides[0] = 1;
+        if(Loc[a][0] == 0) tmp = 28;
+        else tmp = Loc[a][0] - 1;
+        if(Level[tmp][Loc[a][1]] != 1) checksides[1] = 1;
+        if(Loc[a][1] == 27) tmp = 0;
+        else tmp = Loc[a][1] + 1;
+        if(Level[Loc[a][0]][tmp] != 1) checksides[2] = 1;
+        if(Loc[a][1] == 0) tmp = 27;
+        else tmp = Loc[a][1] - 1;
+        if(Level[Loc[a][0]][tmp] != 1) checksides[3] = 1;
+
+        //Don't do 180 unless we have to
+        c = 0; for(b = 0; b < 4; b++) if(checksides[b] == 1) c++;
+        if(c > 1) {
+                 if(Dir[a][0] ==  1) checksides[1] = 0;
+            else if(Dir[a][0] == -1) checksides[0] = 0;
+            else if(Dir[a][1] ==  1) checksides[3] = 0;
+            else if(Dir[a][1] == -1) checksides[2] = 0;
+        }
+
+        c = 0;
+        do {
+            //Decide direction, based somewhat-randomly
+            b = (int)(rand() / (1625000000 / 4));
+
+            /* Tend to mostly chase Pacman if he is vulnerable
+            or run away when he is invincible */
+            if(checksides[b] == 1) {
+                     if(b == 0) { Dir[a][0] =  1; Dir[a][1] =  0; }
+                else if(b == 1) { Dir[a][0] = -1; Dir[a][1] =  0; }
+                else if(b == 2) { Dir[a][0] =  0; Dir[a][1] =  1; }
+                else if(b == 3) { Dir[a][0] =  0; Dir[a][1] = -1; }
+            }
+            else {
+                if(Invincible == 0) {
+                //Chase Pacman
+                     if((Loc[4][0] > Loc[a][0]) && (checksides[0] == 1)) { Dir[a][0] =  1; Dir[a][1] =  0; c = 1; }
+                else if((Loc[4][0] < Loc[a][0]) && (checksides[1] == 1)) { Dir[a][0] = -1; Dir[a][1] =  0; c = 1; }
+                else if((Loc[4][1] > Loc[a][1]) && (checksides[2] == 1)) { Dir[a][0] =  0; Dir[a][1] =  1; c = 1; }
+                else if((Loc[4][1] < Loc[a][1]) && (checksides[3] == 1)) { Dir[a][0] =  0; Dir[a][1] = -1; c = 1; }
+                }
+
+                else {
+                //Run away from Pacman
+                     if((Loc[4][0] > Loc[a][0]) && (checksides[1] == 1)) { Dir[a][0] = -1; Dir[a][1] =  0; c = 1; }
+                else if((Loc[4][0] < Loc[a][0]) && (checksides[0] == 1)) { Dir[a][0] =  1; Dir[a][1] =  0; c = 1; }
+                else if((Loc[4][1] > Loc[a][1]) && (checksides[3] == 1)) { Dir[a][0] =  0; Dir[a][1] = -1; c = 1; }
+                else if((Loc[4][1] < Loc[a][1]) && (checksides[2] == 1)) { Dir[a][0] =  0; Dir[a][1] =  1; c = 1; }
+                }
+            }
+
+        } while ((checksides[b] == 0) && (c == 0));
+
+        //Move Ghost
+        Loc[a][0] += Dir[a][0];
+        Loc[a][1] += Dir[a][1];
+        }
+    }
+}
+
+/****************************************************************
+* Function:    MovePacman()                                     *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Move Pacman and check for wall collisions        *
+****************************************************************/
+void MovePacman() {
+
+    static int itime = 0;
+
+    //Switch sides? (Transport to other side of screen)
+         if((Loc[4][0] ==  0) && (Dir[4][0] == -1)) Loc[4][0] = 28;
+    else if((Loc[4][0] == 28) && (Dir[4][0] ==  1)) Loc[4][0] =  0;
+    else if((Loc[4][1] ==  0) && (Dir[4][1] == -1)) Loc[4][1] = 27;
+    else if((Loc[4][1] == 27) && (Dir[4][1] ==  1)) Loc[4][1] =  0;
+
+    //Or
+    else {
+        //Move Pacman
+        Loc[4][0] += Dir[4][0];
+        Loc[4][1] += Dir[4][1];
+
+        //If he hit a wall, move back
+        if((Level[Loc[4][0]][Loc[4][1]] == 1) || (Level[Loc[4][0]][Loc[4][1]] == 4)) {
+            Loc[4][0] -= Dir[4][0];    Loc[4][1] -= Dir[4][1];
+        }
+    }
+
+    //What is Pacman eating?
+    switch (Level[Loc[4][0]][Loc[4][1]]) {
+        case 2:    //Pellet
+            Level[Loc[4][0]][Loc[4][1]] = 0;
+            Points++;
+            Food--;
+            break;
+        case 3:    //PowerUp
+            Level[Loc[4][0]][Loc[4][1]] = 0;
+            Invincible = 1;
+            if(GhostsInARow == 0) GhostsInARow = 1;
+            itime = time(0);
+            break;
+    }
+
+    //Is he invincible?
+    if(Invincible == 1)  tleft = (11 - LevelNumber - time(0) + itime);
+
+    //Is invincibility up yet?
+    if(tleft < 0) { Invincible = 0; GhostsInARow = 0; tleft = 0; }
+
+}
+
+/****************************************************************
+* Function:    PauseGame()                                      *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Pause game until user presses a button           *
+****************************************************************/
+void PauseGame() {
+
+    int chtmp;
+
+    //Display pause dialog
+    wattron(win, COLOR_PAIR(Pacman));
+    mvwprintw(win, 12, 10, "********");
+    mvwprintw(win, 13, 10, "*PAUSED*");
+    mvwprintw(win, 14, 10, "********");
+    wrefresh(win);
+    
+    //And wait until key is pressed
+    do {
+        chtmp = getch();            //Get input
+    } while (chtmp == ERR);
+
+}
diff --git a/pacman.h b/pacman.h
new file mode 100755 (executable)
index 0000000..b460e42
--- /dev/null
+++ b/pacman.h
@@ -0,0 +1,12 @@
+// Some variables that you may want to change
+
+#ifndef DATAROOTDIR
+#    define DATAROOTDIR "/usr/local/share"
+#endif
+#define LEVELS_FILE DATAROOTDIR "/pacman/Levels/level__.dat"
+char LevelFile[] = LEVELS_FILE;     //Locations of default levels
+int FreeLife = 1000;                //Starting points for free life
+int Points = 0;                     //Initial points
+int Lives = 3;                      //Number of lives you start with
+int HowSlow = 3;                    //How slow vulnerable ghost move
+int SpeedOfGame = 175;              //How much of a delay is in the game
diff --git a/pacmanedit b/pacmanedit
new file mode 100755 (executable)
index 0000000..ebe8842
Binary files /dev/null and b/pacmanedit differ
diff --git a/pacmanedit.c b/pacmanedit.c
new file mode 100755 (executable)
index 0000000..c99305e
--- /dev/null
@@ -0,0 +1,406 @@
+/****************************************************
+* Pacman For Console Level Editor                   *
+* By: Mike Billars (michaelbillars@gmail.com)       *
+* Date: 2014-04-26                                  *
+*                                                   *
+* Please see file COPYING for details on licensing  *
+*       and redistribution of this program          *
+*                                                   *
+****************************************************/
+
+/***********
+* INCLUDES *
+***********/
+#include <stdio.h>
+#include <curses.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*************
+* PROTOTYPES *
+*************/
+void CheckScreenSize();                                 //Make sure resolution is at least 32x29
+void CreateWindows(int y, int x, int y0, int x0);       //Make ncurses windows
+void DrawWindow();                                      //Refresh display
+void ExitProgram(char message[255]);                    //Exit gracefully
+void GetInput();                                        //Get user input
+void InitCurses();                                      //Start up ncurses
+void LoadLevel();                                       //Load level into memory
+void MainLoop();                                        //Main loop
+void SaveLevel();                                       //Save level to specified file
+
+/*******************
+* GLOBAL VARIABLES *
+*******************/
+//I know global variables are bad, but it's just sooo easy!
+
+//Windows used by ncurses
+WINDOW * win;
+WINDOW * status;
+
+//For colors
+enum { Wall = 1, Normal, Pellet, PowerUp, GhostWall, Ghost1, Ghost2, Ghost3, Ghost4, BlueGhost, Pacman, Cursor};
+
+int Level[29][28] = { 0 };                              //Main level array
+int Loc[6][2] = { 0 };                                  //Ghosts, Pacman, and cursor locations
+int tleft = 0;                                          //How long left for invincibility
+char filename[255] = "";                                //Name of file to load/save
+
+/****************************************************************
+* Function:    main()                                           *
+* Parameters:  argc, argv (passed from command line)            *
+* Returns:     Success                                          *
+* Description: Initiate the program and call the subfunctions   *
+****************************************************************/
+int main(int argc, char *argv[100]) {
+
+    //Make sure they entered a filename to open/save
+    if((argc > 1) && (strlen(argv[1]) >= 1)) {
+
+        strcpy(filename, argv[1]);                      //Copy command line parameter into string
+        LoadLevel();                                    //Load the file
+
+        InitCurses();                                   //Initialize ncurses
+        CheckScreenSize();                              //Make sure the screen is big enough
+        CreateWindows(29, 28, 1, 1);                    //
+
+        DrawWindow();
+        Loc[5][0]=13;
+        Loc[5][1]=13;
+        MainLoop();
+    }
+    else
+        ExitProgram("You must specify a file to use (load and save)");
+
+}
+
+/****************************************************************
+* Function:    CheckScreenSize()                                *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Make sure the virtual console is big enough      *
+****************************************************************/
+void CheckScreenSize() {
+
+    //Make sure the window is big enough
+    int h, w; getmaxyx(stdscr, h, w);
+
+    if((h < 32) || (w < 29)) {
+        endwin();
+        fprintf(stderr, "\nSorry.\n");
+        fprintf(stderr, "To edit levels for Pacman for Console, your console window\n");
+        fprintf(stderr, "must be at least 32x29 Please resize your window/resolution\n");
+        fprintf(stderr, "and re-run the program.\n\n");
+        ExitProgram("");
+    }
+}
+
+/****************************************************************
+* Function:    CreateWindows()                                  *
+* Parameters:  y, x, y0, x0 (coords and size of window)         *
+* Returns:     none                                             *
+* Description: Create the main game windows                     *
+****************************************************************/
+void CreateWindows(int y, int x, int y0, int x0) {
+    //Create two new windows, for status bar and for main level
+    win = newwin(y, x, y0, x0);
+    status = newwin(3, 28, 29, 1);
+}
+
+/****************************************************************
+* Function:    DrawWindow()                                     *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Redraw each window to update the screen          *
+****************************************************************/
+void DrawWindow() {
+    int a = 0; int b = 0;
+    char chr = ' ';
+    int attr;
+
+    //Display level array
+    for(a = 0; a < 29; a++) for(b = 0; b < 28; b++) {
+        switch(Level[a][b]) {
+        case 0: chr = ' '; attr = A_NORMAL; wattron(win, COLOR_PAIR(Normal));    break;
+        case 1: chr = ' '; attr = A_NORMAL; wattron(win, COLOR_PAIR(Wall));      break;
+        case 2: chr = '.'; attr = A_NORMAL; wattron(win, COLOR_PAIR(Pellet));    break;
+        case 3: chr = '*'; attr = A_BOLD;   wattron(win, COLOR_PAIR(PowerUp));   break;
+        case 4: chr = ' '; attr = A_NORMAL; wattron(win, COLOR_PAIR(GhostWall)); break;
+        case 5: chr = '&'; attr = A_NORMAL; wattron(win, COLOR_PAIR(Ghost1));    break;
+        case 6: chr = '&'; attr = A_NORMAL; wattron(win, COLOR_PAIR(Ghost2));    break;
+        case 7: chr = '&'; attr = A_NORMAL; wattron(win, COLOR_PAIR(Ghost3));    break;
+        case 8: chr = '&'; attr = A_NORMAL; wattron(win, COLOR_PAIR(Ghost4));    break;
+        case 9: chr = 'C'; attr = A_NORMAL; wattron(win, COLOR_PAIR(Pacman));    break;
+        }
+        mvwaddch(win, a, b, chr | attr);
+    }
+
+    //Display the cursor
+    wattron(win,COLOR_PAIR(Cursor));
+    mvwaddch(win, Loc[5][0], Loc[5][1], 'X');
+
+    //Display info in status
+    wmove(status, 1, 1);
+    wattron(status, COLOR_PAIR(Normal));
+    mvwprintw(status, 1,  0, "0)     1)       2)     3)");
+    mvwprintw(status, 2,  0, "4)     5-8)     9)     F/C/Q");
+
+    wattron(status, COLOR_PAIR(Normal));    mvwaddch(status, 1,  3, ' ');
+    wattron(status, COLOR_PAIR(Wall));      mvwaddch(status, 1, 10, ' ');
+    wattron(status, COLOR_PAIR(Pellet));    mvwaddch(status, 1, 19, '.');
+    wattron(status, COLOR_PAIR(PowerUp));   mvwaddch(status, 1, 26 , '*' | A_BOLD);
+    wattron(status, COLOR_PAIR(GhostWall)); mvwaddch(status, 2,  3, ' ');
+    wattron(status, COLOR_PAIR(Ghost1));    mvwaddch(status, 2, 12, '&');
+    wattron(status, COLOR_PAIR(Pacman));    mvwaddch(status, 2, 19, 'C');
+
+    wrefresh(status);
+    wrefresh(win);
+}
+
+/****************************************************************
+* Function:    ExitProgram()                                    *
+* Parameters:  message: text to display before exiting          *
+* Returns:     none                                             *
+* Description: Gracefully end program                           *
+****************************************************************/
+void ExitProgram(char message[255]) {
+
+    endwin();
+
+    //Must save file
+    if(message[0]=='s') {
+        printf("\n\nFile saved as: %s\n", filename);
+    }
+
+    else
+        printf("%s\n\n", message);
+
+    exit(0);
+}
+
+/****************************************************************
+* Function:    GetInput()                                       *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Get input from user and take appropriate action  *
+****************************************************************/
+void GetInput() {
+    int ch;
+    int a=0;
+    int b=0;
+
+    static int chtmp;
+
+    ch = getch();
+
+    //Buffer input
+    do {
+        DrawWindow();
+        ch = getch();
+    } while (ch == ERR);
+
+    switch (ch) {
+    case KEY_UP:    case 'w': case 'W':
+        Loc[5][0]--;
+        if(Loc[5][0]<0) { Loc[5][0]=28; }
+        break;
+
+    case KEY_DOWN:  case 's': case 'S':
+        Loc[5][0]++;
+        if(Loc[5][0]>28) { Loc[5][0]=0; }
+        break;
+
+    case KEY_LEFT:  case 'a': case 'A':
+        Loc[5][1]--;
+        if(Loc[5][1]<0) { Loc[5][1]=27; }
+        break;
+
+    case KEY_RIGHT: case 'd': case 'D':
+        Loc[5][1]++;
+        if(Loc[5][1]>27) { Loc[5][1]=0; }
+        break;
+
+    case 'q': case 'Q':
+        //Save and exit
+        SaveLevel();
+        ExitProgram("s");
+        break;
+
+    //Draw a blank space
+    case '0': case ' ':
+        Level[Loc[5][0]][Loc[5][1]]=0;
+        break;
+
+    //Draw a wall
+    case '1':
+        Level[Loc[5][0]][Loc[5][1]]=1;
+        break;
+
+    //Draw a pellet
+    case '2':
+        Level[Loc[5][0]][Loc[5][1]]=2;
+        break;
+
+    //Draw a powerup
+    case '3':
+        Level[Loc[5][0]][Loc[5][1]]=3;
+        break;
+
+    //Draw a ghost/spawning wall
+    case '4':
+        Level[Loc[5][0]][Loc[5][1]]=4;
+        break;
+
+    //Draw a ghost/pacman
+    case '5': case '6': case '7':
+    case '8': case '9':
+        //Move ghost/pacman to new location
+        Level[Loc[5][0]][Loc[5][1]]=ch-'0';
+
+        //Erase character from previous location and replace with BLANK
+        if(Level[Loc[ch-'0'-5][0]][Loc[ch-'0'-5][1]]==ch-'0')
+            Level[Loc[ch-'0'-5][0]][Loc[ch-'0'-5][1]]=0;
+
+        //Set Loc variable to new location
+        Loc[ch-'0'-5][0]=Loc[5][0];
+        Loc[ch-'0'-5][1]=Loc[5][1];
+
+        break;
+
+    //Fill blank spaces with pellets
+    case 'f': case 'F':
+        for(a=0; a<29; a++)
+        for(b=0; b<28; b++)
+            if(Level[a][b]==0) Level[a][b]=2;
+        break;
+
+    //Fill pellet spaces with blanks
+    case 'c': case 'C':
+        for(a=0; a<29; a++)
+        for(b=0; b<28; b++)
+            if(Level[a][b]==2) Level[a][b]=0;
+        break;
+
+    }
+}
+
+/****************************************************************
+* Function:    InitCurses()                                     *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Initialize ncurses and set defined colors        *
+****************************************************************/
+void InitCurses() {
+
+    initscr();                      //Needed for ncurses windows
+    start_color();                  //Activate colors in console
+    curs_set(0);                    //      Don't remember
+    keypad(stdscr, TRUE);           //Activate arrow keys
+    nodelay(stdscr, TRUE);          //Allow getch to work without pausing
+    nonl();                         //      Don't remember
+    cbreak();                       //      Don't remember
+    noecho();                       //Don't display input key
+
+    //Make custom text colors
+    init_pair(Normal,    COLOR_WHITE,   COLOR_BLACK);
+    init_pair(Wall,      COLOR_WHITE,   COLOR_WHITE);
+    init_pair(Pellet,    COLOR_WHITE,   COLOR_BLACK);
+    init_pair(PowerUp,   COLOR_BLUE,    COLOR_BLACK);
+    init_pair(GhostWall, COLOR_WHITE,   COLOR_CYAN);
+    init_pair(Ghost1,    COLOR_RED,     COLOR_BLACK);
+    init_pair(Ghost2,    COLOR_CYAN,    COLOR_BLACK);
+    init_pair(Ghost3,    COLOR_MAGENTA, COLOR_BLACK);
+    init_pair(Ghost4,    COLOR_YELLOW,  COLOR_BLACK);
+    init_pair(BlueGhost, COLOR_BLUE,    COLOR_RED);
+    init_pair(Pacman,    COLOR_YELLOW,  COLOR_BLACK);
+    init_pair(Cursor,    COLOR_BLUE,    COLOR_YELLOW);
+}
+
+/****************************************************************
+* Function:    LoadLevel()                                      *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Open level file and load it into memory          *
+****************************************************************/
+void LoadLevel() {
+
+    int a = 0; int b = 0;
+    FILE *fin;
+
+    //Open file
+    fin = fopen(filename, "r");
+
+    //File doesn't exist, start new
+    if(!(fin)) {
+        for(a=0; a<28; a++) { Level[a][0]=1; Level[a][27]=1; }
+        for(a=0; a<28; a++) { Level[0][a]=1; Level[28][a]=1; }
+        Loc[0][0]=2; Loc[0][1]=2;
+        Loc[1][0]=2; Loc[1][1]=4;
+        Loc[2][0]=2; Loc[2][1]=6;
+        Loc[3][0]=2; Loc[3][1]=8;
+        Loc[4][0]=19; Loc[4][1]=19;
+        Level[Loc[0][0]][Loc[0][1]]=5;
+        Level[Loc[1][0]][Loc[1][1]]=6;
+        Level[Loc[2][0]][Loc[2][1]]=7;
+        Level[Loc[3][0]][Loc[3][1]]=8;
+        Level[Loc[4][0]][Loc[4][1]]=9;
+    }
+    else {
+
+        //Open file and load the level into the array
+        for(a = 0; a < 29; a++)
+        for(b = 0; b < 28; b++) {
+            fscanf(fin, "%d", &Level[a][b]);
+            if(Level[a][b] == 5) { Loc[0][0]=a; Loc[0][1]=b; }
+            if(Level[a][b] == 6) { Loc[1][0]=a; Loc[1][1]=b; }
+            if(Level[a][b] == 7) { Loc[2][0]=a; Loc[2][1]=b; }
+            if(Level[a][b] == 8) { Loc[3][0]=a; Loc[3][1]=b; }
+            if(Level[a][b] == 9) { Loc[4][0]=a; Loc[4][1]=b; }
+        }
+    }
+}
+
+/****************************************************************
+* Function:    MainLoop()                                       *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Control the main execution of the game           *
+****************************************************************/
+void MainLoop() {
+    do {
+        GetInput();
+        DrawWindow();
+    } while (1);
+}
+
+/****************************************************************
+* Function:    SaveLevel()                                      *
+* Parameters:  none                                             *
+* Returns:     none                                             *
+* Description: Save current level array to a specified file     *
+****************************************************************/
+void SaveLevel() {
+
+    int a=0;
+    int b=0;
+    FILE *fout;
+
+    //Open file
+    fout = fopen(filename, "w");
+
+    //Check for write permissions
+    if(!(fout)) {
+        ExitProgram("Cannot write file. :-(");
+    }
+
+    else {
+        for(a = 0; a < 29; a++) {
+            for(b = 0; b < 28; b++) {
+                fprintf(fout, "%d ", Level[a][b]);
+            }
+            fprintf(fout, "\n");
+        }
+        fprintf(fout, "1");
+        fclose(fout);
+    }
+}
diff --git a/screenshot.png b/screenshot.png
new file mode 100755 (executable)
index 0000000..6310785
Binary files /dev/null and b/screenshot.png differ