--- /dev/null
+ 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.
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+
+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.
--- /dev/null
+/****************************************************
+* 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);
+
+}
--- /dev/null
+// 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
--- /dev/null
+/****************************************************
+* 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);
+ }
+}