pax_global_header00006660000000000000000000000064151066225460014521gustar00rootroot0000000000000052 comment=449001a74a98e3e0e051f5fff84925b071da000d gplanarity-master/000077500000000000000000000000001510662254600145305ustar00rootroot00000000000000gplanarity-master/COPYING000066400000000000000000000430761510662254600155750ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, 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 Library 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 Appendix: 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. Copyright (C) 19yy 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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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. , 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 Library General Public License instead of this License. gplanarity-master/Makefile000066400000000000000000000070021510662254600161670ustar00rootroot00000000000000# Fuck Automake # Fuck the horse it rode in on # and Fuck its little dog Libtool too TARGET = gPlanarity CC = gcc LD = gcc export INSTALL = install PREFIX = /usr/local BINDIR = $(PREFIX)/bin ETCDIR = /etc/$(TARGET) MANDIR = $(PREFIX)/man #DISABLE_NLS = true # White space delimited list of locales you want to support. Defaults to all # available ones. #export WANT_LINGUAS := cs # All subdirs with Makefiles SUBDIRS = # By default, enable NLS ifeq ($(origin DISABLE_NLS), undefined) export GT_DOMAIN = $(TARGET) export GT_DIR = $(PREFIX)/share/locale ADD_DEF += -DUGT_DOMAIN="$(GT_DOMAIN)" -DUGT_DIR="$(GT_DIR)" -DENABLE_NLS SUBDIRS += po endif SRC = dialog_finish.c gameboard_logic.c dialog_pause.c gameboard_logic_button.c\ gameboard.c gameboard_logic_buttonbar.c gameboard_draw_box.c\ gameboard_logic_mouse.c gameboard_draw_button.c gameboard_logic_push.c\ gameboard_draw_buttonbar.c graph.c gameboard_draw_curtain.c\ graph_score.c graph_arrange.c gameboard_draw_edge.c graph_generate.c\ gameboard_draw_intersection.c graph_generate_mesh1.c gameboard_draw_main.c\ gameboard_draw_score.c main.c gameboard_draw_selection.c\ timer.c gameboard_draw_vertex.c levelstate.c dialog_level.c\ dialog_level_icons.c gameboard_draw_text.c random.c graph_generate_data.c\ gameboard_logic_fade.c graph_generate_mesh2.c graph_region.c OBJ = dialog_finish.o gameboard_logic.o dialog_pause.o gameboard_logic_button.o\ gameboard.o gameboard_logic_buttonbar.o gameboard_draw_box.o\ gameboard_logic_mouse.o gameboard_draw_button.o gameboard_logic_push.o\ gameboard_draw_buttonbar.o graph.o gameboard_draw_curtain.o\ graph_score.o graph_arrange.o gameboard_draw_edge.o graph_generate.o\ gameboard_draw_intersection.o graph_generate_mesh1.o gameboard_draw_main.o\ gameboard_draw_score.o main.o gameboard_draw_selection.o\ timer.o gameboard_draw_vertex.o levelstate.o dialog_level.o\ dialog_level_icons.o gameboard_draw_text.o random.o graph_generate_data.o\ gameboard_logic_fade.o graph_generate_mesh2.o graph_region.o CAIROVER = >= 1.0.0 GTKVER = >= 3.24.0 GCF = `pkg-config --cflags "gtk+-3.0 $(GTKVER) cairo $(CAIROVER) freetype2 fontconfig"` LDF = `pkg-config --libs "gtk+-3.0 $(GTKVER) cairo $(CAIROVER) freetype2 fontconfig"` all: all-local all-recursive all-local: pkg-config --cflags "gtk+-3.0 $(GTKVER) cairo $(CAIROVER) freetype2 fontconfig" 1>/dev/null $(MAKE) target CFLAGS='-O2 -ffast-math $(GCF) $(ADD_DEF)' all-recursive: for D in $(SUBDIRS); do make -C $$D || exit 1; done debug: pkg-config --cflags "gtk+-3.0 $(GTKVER) cairo $(CAIROVER) freetype2 fontconfig" 1>/dev/null $(MAKE) target CFLAGS='-g -Wall -W -Wno-unused-parameter -D__NO_MATH_INLINES $(GCF) $(ADD_DEF) $(CLFAGS)' profile: pkg-config --cflags "gtk+-3.0 $(GTKVER) cairo $(CAIROVER) freetype2 fontconfig" 1>/dev/null $(MAKE) target CFLAGS='-pg -g -O2 -ffast-math $(GCF) $(ADD_DEF) $(CFLAGS)' clean: clean-local clean-recursive clean-local: rm -f $(OBJ) *.d *.d.* gmon.out $(TARGET) clean-recursive: for D in $(SUBDIRS); do make -C $$D clean || exit 1; done distclean: clean rm -f *~ %.d: %.c $(CC) -M $(CFLAGS) $< > $@.$$$$; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm -f $@.$$$$ ifeq ($(MAKECMDGOALS),target) include $(SRC:.c=.d) endif target: $(OBJ) ./touch-version $(LD) $(OBJ) $(CFLAGS) -o $(TARGET) $(LIBS) -lm $(LDF) install: install-local install-recursive install-local: target $(INSTALL) -d -m 0755 $(BINDIR) $(INSTALL) -m 0755 $(TARGET) $(BINDIR) install-recursive: for D in $(SUBDIRS); do make -C $$D install || exit 1; done gplanarity-master/dialog_finish.c000066400000000000000000000134671510662254600175060ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include #include "graph.h" #include "timer.h" #include "gameboard.h" #include "gameboard_draw_button.h" #include "levelstate.h" #include "dialog_finish.h" #include "dialog_level.h" #include "main.h" static void finish_post (Gameboard *g){ // back to buttonbar activity! g->finish_dialog_active=0; pop_curtain(g); levelstate_next(); levelstate_go(); enter_game(g); } static void finish_level (Gameboard *g){ // back to buttonbar activity! g->finish_dialog_active=0; pop_curtain(g); level_dialog(g,1); } static void finish_quit (Gameboard *g){ gtk_main_quit(); } static void local_go (Gameboard *g){ undeploy_buttons(g,finish_post); } static void local_level (Gameboard *g){ undeploy_buttons(g,finish_level); } static void local_quit (Gameboard *g){ undeploy_buttons(g,finish_quit); } /* initialize the rather weird little animation engine */ static void setup_finish_buttons(Gameboard *g,int bw, int bh){ int i; int w=g->g.width; int h=g->g.height; buttonstate *states=g->b.states; states[0].rollovertext=_("exit gPlanarity"); states[1].rollovertext=_("level selection menu"); states[10].rollovertext=_("play next level!"); states[0].callback = local_quit; states[1].callback = local_level; states[10].callback = local_go; for(i=0;ix = b->x_target = w/2 - bw/2 + FINISH_BUTTON_BORDER; b->y_active = h/2 + bh/2 - FINISH_BUTTON_Y; b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE; b->sweepdeploy = 0; } { buttonstate *b=states+1; b->x = b->x_target = w/2; b->y_active = h/2 + bh/2 - FINISH_BUTTON_Y; b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE; b->sweepdeploy = SWEEP_DELTA; } { buttonstate *b=states+10; b->x = b->x_target = w/2 + bw/2 - FINISH_BUTTON_BORDER; b->y_active = h/2 + bh/2 - FINISH_BUTTON_Y; b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE; b->sweepdeploy = SWEEP_DELTA*2; } for(i=0;ig.width; int h= g->g.height; cairo_t *c = cairo_create(g->background); borderbox_path(c, w/2 - FINISHBOX_WIDTH/2, h/2 - FINISHBOX_HEIGHT/2, FINISHBOX_WIDTH, FINISHBOX_HEIGHT); cairo_set_source_rgb(c,1,1,1); cairo_fill(c); centerbox(c, w/2 - FINISHBOX_WIDTH/2, h/2 - FINISHBOX_HEIGHT/2, FINISHBOX_WIDTH, SCOREHEIGHT); centerbox(c, w/2 - FINISHBOX_WIDTH/2 , h/2 + FINISHBOX_HEIGHT/2 - SCOREHEIGHT, FINISHBOX_WIDTH, SCOREHEIGHT); { char *time = get_timer_string(); char buffer[160]; int time_bonus=graphscore_get_bonus(&g->g); int y; set_font(c,18,18,0,1); cairo_set_source_rgba (c, TEXT_COLOR); y=h/2-FINISHBOX_HEIGHT/2+SCOREHEIGHT/2; render_text_centered(c,_("Level Complete!"), w/2,y);y+=45; set_font(c,16,16,0,0); snprintf(buffer,160,_("Elapsed: %s"),time); render_bordertext_centered(c,buffer, w/2,y);y+=24; snprintf(buffer,160,_("Base score: %d points"),graphscore_get_raw_score(&g->g)); render_bordertext_centered(c,buffer, w/2,y);y+=24; if(graphscore_get_multiplier_percent(&g->g)>100){ cairo_save(c); set_font(c,16,16,0,1); cairo_set_source_rgba (c, HIGH_COLOR); snprintf(buffer,160,_("Objective Exceeded! %d%%"),graphscore_get_multiplier_percent(&g->g)); render_bordertext_centered(c,buffer, w/2,y);y+=24; cairo_restore(c); } snprintf(buffer,160,_("Time bonus: %d points"),time_bonus); render_bordertext_centered(c,buffer, w/2,y);y+=35; set_font(c,16,16,0,1); snprintf(buffer,160,_("Final score: %d points"),graphscore_get_score(&g->g)+time_bonus); render_bordertext_centered(c,buffer, w/2,y);y+=24; if(graphscore_get_score(&g->g)+time_bonus >= levelstate_get_hiscore()){ cairo_set_source_rgba (c, HIGH_COLOR); render_bordertext_centered(c,_("A high score!"), w/2,y);y+=43; cairo_set_source_rgba (c, TEXT_COLOR); }else{ snprintf(buffer,160,_("Previous best: %ld points"),levelstate_get_hiscore()); render_bordertext_centered(c,buffer, w/2,y);y+=43; } render_bordertext_centered(c,_("Total score to date:"), w/2,y); y+=21; snprintf(buffer,160,_("%ld points"),levelstate_total_hiscore()); render_bordertext_centered(c,buffer, w/2,y); } cairo_destroy(c); } void finish_level_dialog(Gameboard *g){ g->finish_dialog_active=1; // set up new buttons setup_finish_buttons(g,FINISHBOX_WIDTH, FINISHBOX_HEIGHT); // draw pausebox push_curtain(g,draw_finishbox); // deploy new buttons deploy_buttons(g,0); } gplanarity-master/dialog_finish.h000066400000000000000000000023341510662254600175020ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef DIALOG_FINISH_H #define DIALOG_FINISH_H #include "gameboard.h" #define FINISH_BUTTON_BORDER 35 #define FINISH_BUTTON_Y 25 #define FINISHBOX_WIDTH 270 #define FINISHBOX_HEIGHT 330 extern void finish_level_dialog(Gameboard *g); #endif /* DIALOG_FINISH_H */ gplanarity-master/dialog_level.c000066400000000000000000000100031510662254600173140ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include #include "graph.h" #include "timer.h" #include "gameboard.h" #include "gameboard_draw_button.h" #include "dialog_level.h" #include "levelstate.h" #include "main.h" static void unlevel_post (Gameboard *g){ g->level_dialog_active=0; pop_curtain(g); levelstate_go(); prepare_reenter_game(g); reenter_game(g); } static void unlevel_quit (Gameboard *g){ gtk_main_quit(); } static void local_go (Gameboard *g){ undeploy_buttons(g,unlevel_post); } static void local_quit (Gameboard *g){ undeploy_buttons(g,unlevel_quit); } /* initialize the rather weird little animation engine */ static void setup_level_buttons(Gameboard *g,int bw, int bh){ int i; int w=g->g.width; int h=g->g.height; buttonstate *states=g->b.states; states[0].rollovertext=_("exit gPlanarity"); states[2].rollovertext=_("reset level"); states[10].rollovertext=_("play level!"); states[0].callback = local_quit; states[2].callback = local_reset; states[10].callback = local_go; for(i=0;ix = b->x_target = w/2 - bw/2 + LEVEL_BUTTON_BORDER; b->y_active = h/2 + bh/2 - LEVEL_BUTTON_Y; b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE; b->sweepdeploy = 0; } { buttonstate *b=states+2; b->x = b->x_target = w/2; b->y_active = h/2 + bh/2 - LEVEL_BUTTON_Y; b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE; b->sweepdeploy = SWEEP_DELTA; } { buttonstate *b=states+10; b->x = b->x_target = w/2 + bw/2 - LEVEL_BUTTON_BORDER; b->y_active = h/2 + bh/2 - LEVEL_BUTTON_Y; b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE; b->sweepdeploy = SWEEP_DELTA; } rollover_extents(g,states); rollover_extents(g,states+2); rollover_extents(g,states+10); } static void draw_levelbox(Gameboard *g){ int w= g->g.width; int h= g->g.height; cairo_t *c = cairo_create(g->background); borderbox_path(c, w/2 - LEVELBOX_WIDTH/2, h/2 - LEVELBOX_HEIGHT/2, LEVELBOX_WIDTH, LEVELBOX_HEIGHT); cairo_set_source_rgb(c,1,1,1); cairo_fill(c); centerbox(c, w/2 - LEVELBOX_WIDTH/2, h/2 - LEVELBOX_HEIGHT/2, LEVELBOX_WIDTH, SCOREHEIGHT); centerbox(c, w/2 - LEVELBOX_WIDTH/2, h/2 + LEVELBOX_HEIGHT/2 - SCOREHEIGHT, LEVELBOX_WIDTH, SCOREHEIGHT); set_font(c,18,18,0,1); cairo_set_source_rgba (c, TEXT_COLOR); render_text_centered(c,_("Available Levels"), w/2,h/2-LEVELBOX_HEIGHT/2+SCOREHEIGHT/2); cairo_destroy(c); } void level_dialog(Gameboard *g, int advance){ g->level_dialog_active=1; levelstate_write(); if(advance) levelstate_next(); // set up new buttons setup_level_buttons(g,LEVELBOX_WIDTH, LEVELBOX_HEIGHT); level_icons_init(g); // draw pausebox push_curtain(g,draw_levelbox); // deploy new buttons deploy_buttons(g,0); } gplanarity-master/dialog_level.h000066400000000000000000000030261510662254600173300ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef DIALOG_LEVEL_H #define DIALOG_LEVEL_H #include "gameboard.h" #define LEVEL_BUTTON_BORDER 35 #define LEVEL_BUTTON_Y 25 #define LEVELBOX_WIDTH 560 #define LEVELBOX_HEIGHT 370 #define ICON_DELTA 20 extern void level_dialog(Gameboard *g,int advance); extern void render_level_icons(Gameboard *g, cairo_t *c, int ex,int ey, int ew, int eh); extern void level_icons_init(Gameboard *g); extern void level_mouse_motion(Gameboard *g, int x, int y); extern void level_mouse_press(Gameboard *g, int x, int y); extern void local_reset (Gameboard *g); #endif /* DIALOG_LEVEL_H */ gplanarity-master/dialog_level_icons.c000066400000000000000000000251771510662254600205310ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include #include "graph.h" #include "timer.h" #include "gameboard.h" #include "gameboard_draw_button.h" #include "dialog_level.h" #include "levelstate.h" #include "main.h" static void draw_forward_arrow(graph *g,dialog_level_oneicon *l, cairo_t *c,int fill){ int w = l->w; int h = l->h; int cx = w/2; int cy = h/2; cairo_save(c); cairo_translate(c,l->x+g->width/2+.5,l->y+g->height/2+.5); cairo_set_line_width(c,B_LINE); cairo_move_to(c,w-10,cy); cairo_line_to(c,cx,h-10); cairo_line_to(c,cx,(int)h*.75); cairo_line_to(c,10,(int)h*.75); cairo_line_to(c,10,(int)h*.25); cairo_line_to(c,cx,(int)h*.25); cairo_line_to(c,cx,10); cairo_close_path(c); if(fill){ cairo_set_source_rgba (c, B_COLOR); cairo_fill_preserve (c); } cairo_set_source_rgba (c, B_LINE_COLOR); cairo_stroke (c); cairo_restore(c); } static void draw_backward_arrow(graph *g,dialog_level_oneicon *l, cairo_t *c,int fill){ int w = l->w; int h = l->h; int cx = w/2; int cy = h/2; cairo_save(c); cairo_translate(c,l->x+g->width/2-.5,l->y+g->height/2+.5); cairo_set_line_width(c,B_LINE); cairo_move_to(c,10,cy); cairo_line_to(c,cx,h-10); cairo_line_to(c,cx,(int)h*.75); cairo_line_to(c,w-10,(int)h*.75); cairo_line_to(c,w-10,(int)h*.25); cairo_line_to(c,cx,(int)h*.25); cairo_line_to(c,cx,10); cairo_close_path(c); if(fill){ cairo_set_source_rgba (c, B_COLOR); cairo_fill_preserve (c); } cairo_set_source_rgba (c, B_LINE_COLOR); cairo_stroke (c); cairo_restore(c); } static void invalidate_icon(Gameboard *g,dialog_level_oneicon *l){ int cx = g->g.width/2; int cy = g->g.height/2; GdkRectangle r; r.x=l->x+cx+g->d.center_x; r.y=l->y+cy; r.width=l->w; r.height=l->h; gdk_window_invalidate_rect (gtk_widget_get_window (GTK_WIDGET(g)), &r, FALSE); } static void dialog_level_oneicon_init(Gameboard *g, int num, dialog_level_oneicon *l){ int current = get_level_num(); l->num = num+current; if(l->icon)cairo_surface_destroy(l->icon); l->icon = levelstate_get_icon(num + current); l->alpha = 0.; l->w = ICON_WIDTH; l->h = ICON_HEIGHT; l->x = num*ICON_WIDTH*1.2 - (l->w*.5); l->y = 120 - (LEVELBOX_HEIGHT) / 2; } static void deploy_reset_button(Gameboard *g){ buttonstate *states=g->b.states; if(!g->d.reset_deployed){ states[10].sweepdeploy += SWEEP_DELTA; states[2].position = 2; //activate it states[2].y_target = states[2].y_active; g->d.reset_deployed=1; if(g->b.buttons_ready){ if(g->button_timer!=0) g_source_remove(g->button_timer); g->button_callback=0; g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g); } } } static void undeploy_reset_button(Gameboard *g){ buttonstate *states=g->b.states; if(g->d.reset_deployed){ states[10].sweepdeploy -= SWEEP_DELTA; states[2].y_target = states[2].y_inactive; g->d.reset_deployed=0; if(g->b.buttons_ready){ if(g->button_timer!=0) g_source_remove(g->button_timer); g->button_callback = 0; g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g); } } } static void alpha_update(Gameboard *g,dialog_level_oneicon *l){ int distance = labs(l->x - g->d.level_icons[2].x + g->d.center_x); double alpha = 1. - (distance/300.); if(alpha<0.)alpha=0.; //if(alpha>1.)alpha=1.; l->alpha = alpha; } void level_icons_init(Gameboard *g){ int i; for(i=0;i<5;i++) dialog_level_oneicon_init(g,i-2,g->d.level_icons+i); g->d.center_x = 0; g->d.center_done=1; g->d.level_lit = 2; g->d.reset_deployed = 0; if(levelstate_in_progress()) deploy_reset_button(g); memset(&g->d.text1,0,sizeof(g->d.text1)); memset(&g->d.text2,0,sizeof(g->d.text2)); memset(&g->d.text3,0,sizeof(g->d.text3)); memset(&g->d.text4,0,sizeof(g->d.text4)); } void render_level_icons(Gameboard *g, cairo_t *c, int ex,int ey, int ew, int eh){ if(g->level_dialog_active){ int w= g->g.width; int h= g->g.height; int y = h/2-LEVELBOX_HEIGHT/2+SCOREHEIGHT/2; int i; int ex2 = ex+ew; int ey2 = ey+eh; for(i=0;i<5;i++){ dialog_level_oneicon *l=g->d.level_icons+i; alpha_update(g,l); if(l->num >= 0 && l->num < levelstate_limit() && c){ int iw = l->w; int ih = l->h; int ix = l->x+g->d.center_x+w/2; int iy = l->y+h/2; if( l->alpha == 0.) continue; if( ix+iw < ex ) continue; if( ix > ex2 ) continue; if( iy+ih < ey ) continue; if( iy > ey2 ) continue; if(l->icon && cairo_surface_status(l->icon)==CAIRO_STATUS_SUCCESS){ cairo_set_source_surface(c,l->icon,ix,iy); cairo_paint_with_alpha(c,l->alpha); } if(g->d.center_x==0 && g->d.center_done){ if(i==2){ cairo_set_source_rgba (c, B_COLOR); borderbox_path(c,ix+1.5,iy+1.5,iw-3,ih-3); cairo_fill (c); } if(i==1) draw_backward_arrow(&g->g,l,c,i==g->d.level_lit); if(i==3) draw_forward_arrow(&g->g,l,c,i==g->d.level_lit); } } } // render level related text if(g->d.center_x == 0 && g->d.center_done && c){ char buffer[160]; // above text if(g->d.text1.width==0 || (eyd.text1.y+g->d.text1.height && ey2>g->d.text1.y)){ snprintf(buffer,160,_("Level %d:"),get_level_num()+1); set_font(c,20,20,0,1); cairo_set_source_rgba (c, TEXT_COLOR); g->d.text1=render_bordertext_centered(c, buffer,w/2,y+45); } if(g->d.text2.width==0 || (eyd.text2.y+g->d.text2.height && ey2>g->d.text2.y)){ set_font(c,18,18,0,0); cairo_set_source_rgba (c, TEXT_COLOR); g->d.text2=render_bordertext_centered(c, get_level_desc(),w/2,y+70); } if(g->d.text3.width==0 || (eyd.text3.y+g->d.text3.height && ey2>g->d.text3.y)){ if(levelstate_get_hiscore()==0){ set_font(c,18,18,1,0); snprintf(buffer,160,_("[not yet completed]")); }else{ set_font(c,18,18,0,0); snprintf(buffer,160,_("level high score: %ld"),levelstate_get_hiscore()); } cairo_set_source_rgba (c, TEXT_COLOR); g->d.text3=render_bordertext_centered(c, buffer,w/2,y+245); } if(g->d.text4.width==0 || (eyd.text4.y+g->d.text4.height && ey2>g->d.text4.y)){ snprintf(buffer,160,_("total score all levels: %ld"),levelstate_total_hiscore()); set_font(c,18,18,0,0); cairo_set_source_rgba (c, TEXT_COLOR); g->d.text4=render_bordertext_centered(c, buffer,w/2,y+265); } }else{ memset(&g->d.text1,0,sizeof(g->d.text1)); memset(&g->d.text2,0,sizeof(g->d.text2)); memset(&g->d.text3,0,sizeof(g->d.text3)); memset(&g->d.text4,0,sizeof(g->d.text4)); } } } static gboolean animate_level_frame(gpointer ptr){ Gameboard *g = GAMEBOARD (ptr); int i; if(g->d.center_x == 0){ g->d.center_done=1; g_source_remove(g->d.icon_timer); g->d.icon_timer=0; if(levelstate_in_progress()) deploy_reset_button(g); expose_full(g); return 0; } g->d.center_done=0; for(i=0;i<5;i++) if(g->d.level_icons[i].alpha) invalidate_icon(g, g->d.level_icons+i); if(g->d.center_x < 0){ g->d.center_x += ICON_DELTA; if(g->d.center_x > 0) g->d.center_x = 0; }else{ g->d.center_x -= ICON_DELTA; if(g->d.center_x < 0) g->d.center_x = 0; } // trick 'expose'; run it with a region that does nothing in order // to update the visibility flags render_level_icons(g, 0, 0, 0, 0, 0); for(i=0;i<5;i++) if(g->d.level_icons[i].alpha) invalidate_icon(g, g->d.level_icons+i); return 1; } static int find_icon(Gameboard *b,graph *g, int x, int y){ int i; int w= g->width; int h= g->height; x-=w/2; y-=h/2; for(i=1;i<4;i++){ dialog_level_oneicon *l=b->d.level_icons+i; if(l->num>=0 && l->num= l->x && x <= l->x + l->w && y >= l->y && y <= l->y + l->h) return i; } } return 2; } void local_reset (Gameboard *g){ levelstate_reset(); dialog_level_oneicon_init(g,0,g->d.level_icons+2); invalidate_icon(g, g->d.level_icons+2); undeploy_reset_button(g); } void level_mouse_motion(Gameboard *g, int x, int y){ int icon = find_icon(g,&g->g,x,y); if(icon != g->d.level_lit){ invalidate_icon(g, g->d.level_icons+g->d.level_lit); g->d.level_lit = icon; invalidate_icon(g, g->d.level_icons+g->d.level_lit); } } void level_mouse_press(Gameboard *g, int x, int y){ int i; level_mouse_motion(g, x, y); if(g->d.level_lit == 1){ if(levelstate_prev()){ if(!levelstate_in_progress()) undeploy_reset_button(g); if(g->d.level_icons[4].icon) cairo_surface_destroy(g->d.level_icons[4].icon); for(i=4;i>=1;i--){ g->d.level_icons[i].num = g->d.level_icons[i-1].num; g->d.level_icons[i].icon = g->d.level_icons[i-1].icon; } g->d.level_icons[0].icon=0; dialog_level_oneicon_init(g,-2,g->d.level_icons); if(g->d.center_x==0 && g->d.center_done)expose_full(g); // only needed to 'undraw' the text g->d.center_x = g->d.level_icons[1].x - g->d.level_icons[2].x; } } if(g->d.level_lit == 3){ if(levelstate_next()){ if(!levelstate_in_progress()) undeploy_reset_button(g); if(g->d.level_icons[0].icon) cairo_surface_destroy(g->d.level_icons[0].icon); for(i=0;i<4;i++){ g->d.level_icons[i].num = g->d.level_icons[i+1].num; g->d.level_icons[i].icon = g->d.level_icons[i+1].icon; } g->d.level_icons[4].icon=0; dialog_level_oneicon_init(g,2,g->d.level_icons+4); if(g->d.center_x==0 && g->d.center_done)expose_full(g); // only needed to 'undraw' the text g->d.center_x = g->d.level_icons[3].x - g->d.level_icons[2].x; } } if(g->d.center_x){ if(g->d.icon_timer) g_source_remove(g->d.icon_timer); g->d.icon_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_level_frame, (gpointer)g); } } gplanarity-master/dialog_pause.c000066400000000000000000000142211510662254600173300ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include #include "graph.h" #include "timer.h" #include "gameboard.h" #include "gameboard_draw_button.h" #include "dialog_pause.h" #include "main.h" static void unpause_post (Gameboard *g){ // back to buttonbar activity! pop_curtain(g); deploy_buttonbar(g); unpause_timer(); g->about_dialog_active=0; g->pause_dialog_active=0; } static void unpause_quit (Gameboard *g){ gtk_main_quit(); } static void local_unpause (Gameboard *g){ undeploy_buttons(g,unpause_post); } static void local_quit (Gameboard *g){ undeploy_buttons(g,unpause_quit); } /* initialize the rather weird little animation engine */ static void setup_pause_buttons(Gameboard *g,int bw, int bh){ int i; int w=g->g.width; int h=g->g.height; buttonstate *states=g->b.states; states[0].rollovertext=_("exit gPlanarity"); states[10].rollovertext=_("resume game!"); states[0].callback = local_quit; states[10].callback = local_unpause; for(i=0;ix = b->x_target = w/2 - bw/2 + PAUSE_BUTTON_BORDER; b->y_active = h/2 + bh/2 - PAUSE_BUTTON_Y; b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE; b->sweepdeploy = 0; } { buttonstate *b=states+10; b->x = b->x_target = w/2 + bw/2 - PAUSE_BUTTON_BORDER; b->y_active = h/2 + bh/2 - PAUSE_BUTTON_Y; b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE; b->sweepdeploy = SWEEP_DELTA; } for(i=0;ig.width; int h= g->g.height; cairo_t *c = cairo_create(g->background); borderbox_path(c, w/2 - PAUSEBOX_WIDTH/2, h/2 - PAUSEBOX_HEIGHT/2, PAUSEBOX_WIDTH, PAUSEBOX_HEIGHT); cairo_set_source_rgb(c,1,1,1); cairo_fill(c); centerbox(c, w/2 - PAUSEBOX_WIDTH/2, h/2 - PAUSEBOX_HEIGHT/2, PAUSEBOX_WIDTH, SCOREHEIGHT); centerbox(c, w/2 - PAUSEBOX_WIDTH/2 , h/2 + PAUSEBOX_HEIGHT/2 - SCOREHEIGHT, PAUSEBOX_WIDTH, SCOREHEIGHT); { char *time = get_timer_string(); set_font(c,18,18,0,1); cairo_set_source_rgba (c, TEXT_COLOR); render_text_centered(c,_("Game Paused"), w/2,h/2-PAUSEBOX_HEIGHT/2+SCOREHEIGHT/2); set_font(c,18,18,0,0); render_bordertext_centered(c,_("Time Elapsed:"), w/2,h/2-30); render_bordertext_centered(c,time, w/2,h/2); } cairo_destroy(c); } void pause_dialog(Gameboard *g){ g->pause_dialog_active=1; // set up new buttons setup_pause_buttons(g,PAUSEBOX_WIDTH, PAUSEBOX_HEIGHT); // draw pausebox push_curtain(g,draw_pausebox); // deploy new buttons deploy_buttons(g,0); } // the 'about' box is nearly identical, including the fact it pauses the game. // we just piggyback it here static void draw_aboutbox(Gameboard *g){ int w= g->g.width; int h= g->g.height; cairo_t *c = cairo_create(g->background); borderbox_path(c, w/2 - ABOUTBOX_WIDTH/2, h/2 - ABOUTBOX_HEIGHT/2, ABOUTBOX_WIDTH, ABOUTBOX_HEIGHT); cairo_set_source_rgb(c,1,1,1); cairo_fill(c); centerbox(c, w/2 - ABOUTBOX_WIDTH/2, h/2 - ABOUTBOX_HEIGHT/2, ABOUTBOX_WIDTH, SCOREHEIGHT); centerbox(c, w/2 - ABOUTBOX_WIDTH/2 , h/2 + ABOUTBOX_HEIGHT/2 - SCOREHEIGHT, ABOUTBOX_WIDTH, SCOREHEIGHT); { int y = h/2-ABOUTBOX_HEIGHT/2+SCOREHEIGHT/2; set_font(c,18,18,0,1); cairo_set_source_rgba (c, TEXT_COLOR); render_text_centered(c,_("gPlanarity"), w/2,y); set_font(c,18,18,0,0); y+=45; render_bordertext_centered(c,_("Untangle the mess!"), w/2,y); y+=30; set_font(c,13,13,0,0); render_bordertext_centered(c,_("Drag vertices to eliminate crossed lines."), w/2,y); y+=16; render_bordertext_centered(c,_("The objective may be a complete solution or"), w/2,y); y+=16; render_bordertext_centered(c,_("getting as close as possible to solving an"), w/2,y); y+=16; render_bordertext_centered(c,_("unsolvable puzzle. Work quickly and"), w/2,y); y+=16; render_bordertext_centered(c,_("exceed the objective for bonus points!"), w/2,y); y+=16; y+=16; cairo_move_to (c, w/2-100,y); cairo_line_to (c, w/2+100,y); cairo_stroke(c); y+=32; set_font(c,12,13,0,0); render_bordertext_centered(c,_("gPlanarity written by Monty "),w/2,y);y+=17; render_bordertext_centered(c,_("as a demonstration of Gtk+/Cairo"),w/2,y);y+=32; render_bordertext_centered(c,_("Original Flash version of Planarity by"),w/2,y);y+=17; render_bordertext_centered(c,_("John Tantalo "),w/2,y);y+=32; render_bordertext_centered(c,_("Original game concept by Mary Radcliffe"),w/2,y);y+=17; y = h/2+ABOUTBOX_HEIGHT/2-SCOREHEIGHT/2; set_font(c,10,11,0,1); render_text_centered(c,version, w/2,y); } cairo_destroy(c); } void about_dialog(Gameboard *g){ g->about_dialog_active=1; // set up new buttons setup_pause_buttons(g,ABOUTBOX_WIDTH,ABOUTBOX_HEIGHT); // draw about box push_curtain(g,draw_aboutbox); // deploy new buttons deploy_buttons(g,0); } gplanarity-master/dialog_pause.h000066400000000000000000000024561510662254600173440ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef DIALOG_PAUSE_H #define DIALOG_PAUSE_H #include "gameboard.h" #define PAUSE_BUTTON_BORDER 35 #define PAUSE_BUTTON_Y 25 #define PAUSEBOX_WIDTH 180 #define PAUSEBOX_HEIGHT 250 #define ABOUTBOX_WIDTH 350 #define ABOUTBOX_HEIGHT 400 extern void pause_dialog(Gameboard *g); extern void about_dialog(Gameboard *g); #endif /* DIALOG_PAUSE_H */ gplanarity-master/gPicon.png000066400000000000000000000044721510662254600164640ustar00rootroot00000000000000PNG  IHDR szz pHYs+tIME 3iIDATXíWiPS~IHB6A"Ec$pE-5 ZN* N[Go:Z;V2Rr]([P\((ZC$$INNF;Bw;ϻa45'x[w~k_{AiiyP8gs@LuWZ-]V׷pDI{ L&SNkn?_vIP6x_Dap8rJ57^ ց72of7}۷$XhHB67n^p8A娮ޟ|X.7tNuVXt: jzBxxx00apP@0 sW###d/<KƏ?O?} 'OR(ru@,>Ru v{bZZڃc,[LTfZEN-&g/)pՇ%VCMkȚ5[ȶm{ 0;v hjIH9s4%z;n'σO<"#m$88fc50f~X|<R n "mZmѠdKM6A {.jlHSPiEERkEcl&6( Nq%'''3 `uJJJP"Qn7sbޏF}ӆ#(j$|>&ܹ1okHH}kjuFcLFrsg]"{8Z[[sZ^ddhaXu+bqbcYO]po"!A ݎ}B'fyQF3g e/\ɘ7oFdzD~%$=}'8BH}}=hF#imm%}$*!V2i'dڴ#:$&~L<>I^^^V]e0(::z֪?uvgGM AQ|G]SX?6a7a ; :|?b 9 ;qA~wwg툏  mtRPap|>palL)++ǭP83/[8 o v( ρ f`N3L ܹsWD@ BdjrB||SUTeC( 5k6fG֤Ssl" :M".. P]] '9s&rr04qp``M\~y'˲bfB |2%&ܺude周(;IMimmmիOm,BNg##hql8cDym@,Yr >˕/ g!""bTd kc,h M?qℝSL1㳚G 8{|i~~4o#44tԽ";;== V͝5|C~a1PT2^Ѩju=`r0aF\\[Ӹq^ |S!>ҿ<--MhJLvvىO/CV֊QwGwGq$'`^0`0nܸ15!!뱇SSSCCBuaE/ * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "nls.h" #include "graph.h" #include "gameboard.h" #include "levelstate.h" static GtkWidgetClass *parent_class = NULL; static void gameboard_init (Gameboard *g){ // instance initialization g->g.width=g->g.orig_width=800; g->g.height=g->g.orig_height=600; g->resize_w = g->g.width; g->resize_h = g->g.height; g->resize_timeout = 0; } static void gameboard_destroy (GtkWidget *object){ if (GTK_WIDGET_CLASS (parent_class)->destroy) (*GTK_WIDGET_CLASS (parent_class)->destroy) (object); // free local resources } static gint gameboard_expose (GtkWidget *widget, GdkEventExpose *event){ if (gtk_widget_get_realized (widget)){ Gameboard *g = GAMEBOARD (widget); GtkAllocation allocation; gameboard_draw(g,event->area.x,event->area.y, event->area.width,event->area.height); if(g->resize_h>0 && g->resize_w>0){ gtk_widget_get_allocation(widget, &allocation); if(allocation.width != g->resize_w || allocation.height != g->resize_h){ if(time(NULL) > g->resize_timeout){ fprintf(stderr,_("\n\nERROR: The windowmanager appears to be ignoring resize requests.\n" "This stands a pretty good chance of scrambling any saved board larger\n" "than the default window size.\n\n")); fprintf(stderr,_("Clipping and/or expanding this board to the current window size...\n\n")); g->resize_w = 0; g->resize_h = 0; resize_buttons(g,g->g.width, g->g.height, allocation.width, allocation.height); graph_resize(&g->g, allocation.width, allocation.height); update_score(g); draw_buttonbar_box(g); update_full(g); } }else{ g->resize_h=0; g->resize_w=0; } } } return FALSE; } static gboolean gameboard_draw3 (GtkWidget *widget, cairo_t *cr) { Gameboard *g = GAMEBOARD (widget); GdkEventExpose event; event.area.x=event.area.y=0; event.area.width=g->g.width; event.area.height=g->g.height; return gameboard_expose (widget, &event); } static void gameboard_size_request (GtkWidget *widget, GtkRequisition *requisition){ Gameboard *g = GAMEBOARD (widget); requisition->width = g->g.orig_width; requisition->height = g->g.orig_height; } static void gameboard_get_preferred_width(GtkWidget *widget, gint *minimal_width, gint *natural_width) { GtkRequisition requisition; gameboard_size_request (widget, &requisition); *minimal_width = *natural_width = requisition.width; } static void gameboard_get_preferred_height(GtkWidget *widget, gint *minimal_height, gint *natural_height) { GtkRequisition requisition; gameboard_size_request (widget, &requisition); *minimal_height = *natural_height = requisition.height; } static void gameboard_realize (GtkWidget *widget){ Gameboard *g = GAMEBOARD (widget); GdkWindowAttr attributes; gint attributes_mask; cairo_t *wc; GtkAllocation allocation; gtk_widget_set_realized (widget, TRUE); gtk_widget_get_allocation(widget, &allocation); attributes.x = allocation.x; attributes.y = allocation.y; attributes.width = allocation.width; attributes.height = allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.window_type = GDK_WINDOW_CHILD; attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK| GDK_POINTER_MOTION_MASK| GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK| GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK; attributes.visual = gtk_widget_get_visual (widget); attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; gtk_widget_set_window (widget, gdk_window_new (gtk_widget_get_window (gtk_widget_get_parent (widget)), &attributes, attributes_mask)); gtk_widget_style_attach (widget); gtk_style_set_background (gtk_widget_get_style (widget), gtk_widget_get_window (widget), GTK_STATE_NORMAL); gdk_window_set_user_data (gtk_widget_get_window (widget), widget); gtk_widget_set_double_buffered (widget, FALSE); wc = gdk_cairo_create(gtk_widget_get_window (widget)); g->forescore = cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, allocation.width, SCOREHEIGHT); g->forebutton = cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, allocation.width, SCOREHEIGHT); g->background = cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR, allocation.width, allocation.height); g->foreground = cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR, allocation.width, allocation.height); cairo_destroy(wc); g->vertex = cache_vertex(g); g->vertex_lit = cache_vertex_lit(g); g->vertex_attached = cache_vertex_attached(g); g->vertex_grabbed = cache_vertex_grabbed(g); g->vertex_sel = cache_vertex_sel(g); g->vertex_ghost = cache_vertex_ghost(g); update_full(g); update_score(g); draw_buttonbar_box(g); init_buttons(g); cache_curtain(g); } void gameboard_size_allocate (GtkWidget *widget, GtkAllocation *allocation){ Gameboard *g = GAMEBOARD (widget); cairo_t *wc; GtkAllocation wa; if (gtk_widget_get_realized (widget)){ if(allocation->width != g->resize_w && allocation->height != g->resize_h && g->resize_timeout == 0 ){ fprintf(stderr,_("\n\nERROR: The window size granted by the windowmanager is not the\n" "window size gPlanarity requested. If the windowmanager is\n" "configured to ignore application sizing requests, this stands\n" "a pretty good chance of scrambling saved boards later (and\n" "making everything look funny now).\n\n")); fprintf(stderr,_("Clipping and/or expanding this board to the current window size...\n\n")); g->resize_h=0; g->resize_w=0; } g->resize_timeout=1; gtk_widget_get_allocation(widget, &wa); if(wa.width == allocation->width && wa.height == allocation->height) return; if (g->forescore) cairo_surface_destroy(g->forescore); if (g->forebutton) cairo_surface_destroy(g->forebutton); if (g->background) cairo_surface_destroy(g->background); if (g->foreground) cairo_surface_destroy(g->foreground); if (g->curtainp) cairo_pattern_destroy(g->curtainp); if (g->curtains) cairo_surface_destroy(g->curtains); gdk_window_move_resize (gtk_widget_get_window (widget), allocation->x, allocation->y, allocation->width, allocation->height); wc = gdk_cairo_create(gtk_widget_get_window (widget)); g->background = cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR, // don't need alpha allocation->width, allocation->height); g->forescore = cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, allocation->width, SCOREHEIGHT); g->forebutton = cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, allocation->width, SCOREHEIGHT); g->foreground = cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR, // don't need alpha allocation->width, allocation->height); cairo_destroy(wc); cache_curtain(g); resize_buttons(g,g->g.width, g->g.height, allocation->width, allocation->height); graph_resize(&g->g, allocation->width, allocation->height); draw_buttonbar_box(g); update_score(g); update_full(g); } gtk_widget_set_allocation(widget, allocation); } static void gameboard_class_init (GameboardClass * class) { GtkWidgetClass *widget_class = (GtkWidgetClass *) class; parent_class = g_type_class_peek (GTK_TYPE_WIDGET); widget_class->destroy = gameboard_destroy; widget_class->realize = gameboard_realize; widget_class->draw = gameboard_draw3; widget_class->get_preferred_width = gameboard_get_preferred_width; widget_class->get_preferred_height = gameboard_get_preferred_height; widget_class->size_allocate = gameboard_size_allocate; widget_class->button_press_event = mouse_press; widget_class->button_release_event = mouse_release; widget_class->motion_notify_event = mouse_motion; } GType gameboard_get_type (void){ static GType gameboard_type = 0; if (!gameboard_type) { static const GTypeInfo gameboard_info = { sizeof (GameboardClass), NULL, NULL, (GClassInitFunc) gameboard_class_init, NULL, NULL, sizeof (Gameboard), 0, (GInstanceInitFunc) gameboard_init, 0 }; gameboard_type = g_type_register_static (GTK_TYPE_WIDGET, "Gameboard", &gameboard_info, 0); } return gameboard_type; } Gameboard *gameboard_new (void) { GtkWidget *g = GTK_WIDGET (g_object_new (GAMEBOARD_TYPE, NULL)); Gameboard *gb = GAMEBOARD (g); return gb; } gplanarity-master/gameboard.h000066400000000000000000000242601510662254600166260ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef GAMEBOARD_H #define GAMEBOARD_H #include #include #include #include #include #include "graph.h" #include "nls.h" #define V_RADIUS 8 #define V_LINE 2 #define V_LINE_COLOR 0, 0, 0 #define V_FILL_IDLE_COLOR .2,.2, 1 #define V_FILL_LIT_COLOR 1, 1, 1 #define V_FILL_ADJ_COLOR 1,.2,.2 #define E_LINE 1.5 #define E_LINE_F_COLOR 0, 0, 0, 1 #define E_LINE_B_COLOR .5,.5,.5, 1 #define SELECTBOX_COLOR .2,.8,.8,.3 #define INTERSECTION_COLOR 1,.1,.1,.8 #define INTERSECTION_RADIUS 10 #define INTERSECTION_LINE_WIDTH 2 #define RESET_DELTA 2 #define SCALE_DELTA 8 #define B_LINE 1 #define B_BORDER 6.5 #define B_RADIUS 20 #define B_HUMP 130 #define B_COLOR .1,.1,.7,.1 #define B_LINE_COLOR 0, 0,.7,.3 #define TEXT_COLOR .0,.0,.7,.6 #define HIGH_COLOR .7,.0,.0,.6 #define SCOREHEIGHT 50 #define ICON_WIDTH 160 #define ICON_HEIGHT 120 #define FADE_FRAMES 50 #define FADE_ANIM_INTERVAL 100 G_BEGIN_DECLS #define GAMEBOARD_TYPE (gameboard_get_type ()) #define GAMEBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAMEBOARD_TYPE, Gameboard)) #define GAMEBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAMEBOARD_TYPE, GameboardClass)) #define IS_GAMEBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAMEBOARD_TYPE)) #define IS_GAMEBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAMEBOARD_TYPE)) typedef struct _Gameboard Gameboard; typedef struct _GameboardClass GameboardClass; typedef struct fade_list{ vertex *v; struct fade_list *next; } fade_list; typedef struct { fade_list *head; int count; gint fade_timer; } fade_state; #define NUMBUTTONS 11 typedef struct { int position; // 0 inactive // 1 left // 2 center // 3 right // negative indicates active but undeployed int x_target; int x; int y_target; int y_inactive; int y_active; int y; int sweepdeploy; int alphad; double alpha; cairo_surface_t *idle; cairo_surface_t *lit; char *rollovertext; cairo_text_extents_t ex; int rollover; int press; void (*callback)(Gameboard *); } buttonstate; typedef struct { buttonstate states[NUMBUTTONS]; int buttons_ready; int allclear; // short-circuit hint int sweeper; int sweeperd; buttonstate *grabbed; } buttongroup; typedef struct { int num; double alpha; cairo_surface_t *icon; int x; int y; int w; int h; } dialog_level_oneicon; typedef struct { dialog_level_oneicon level_icons[5]; int center_x; int center_done; int level_lit; int reset_deployed; GdkRectangle text1; GdkRectangle text2; GdkRectangle text3; GdkRectangle text4; gint icon_timer; // used for buttons and icons } dialog_level_state; struct _Gameboard{ GtkWidget w; graph g; int pushed_curtain; void (*redraw_callback)(Gameboard *g); cairo_surface_t *vertex; cairo_surface_t *vertex_lit; cairo_surface_t *vertex_grabbed; cairo_surface_t *vertex_attached; cairo_surface_t *vertex_sel; cairo_surface_t *vertex_ghost; cairo_surface_t *forescore; cairo_surface_t *forebutton; cairo_surface_t *background; cairo_surface_t *foreground; cairo_pattern_t *curtainp; cairo_surface_t *curtains; int delayed_background; int first_expose; int hide_lines; int realtime_background; int show_intersections; int finish_dialog_active; int about_dialog_active; int pause_dialog_active; int level_dialog_active; buttongroup b; dialog_level_state d; fade_state fade; vertex *grabbed_vertex; vertex *lit_vertex; int group_drag; int button_grabbed; int grabx; int graby; int dragx; int dragy; int graboffx; int graboffy; int selection_grab; int selection_active; int selectionx; int selectiony; int selectionw; int selectionh; int checkbutton_deployed; int buttonbar_sweeper; gint button_timer; // used for buttons and icons void (*button_callback)(Gameboard *); time_t resize_timeout; // watch for ignored resize events int resize_w; // watch for ignored resize events int resize_h; // watch for ignored resize events }; struct _GameboardClass{ GtkWidgetClass parent_class; void (* gameboard) (Gameboard *m); }; GType gameboard_get_type (void); Gameboard* gameboard_new (void); G_END_DECLS extern void init_buttons(Gameboard *g); extern buttonstate *find_button(Gameboard *g,int x,int y); extern void button_set_state(Gameboard *g, buttonstate *b, int rollover, int press); extern void rollover_extents(Gameboard *g, buttonstate *b); extern gboolean animate_button_frame(gpointer ptr); extern void expose_buttons(Gameboard *g,cairo_t *c, int x,int y,int w,int h); extern void resize_buttons(Gameboard *g,int oldw,int oldh,int w,int h); extern void button_clear_state(Gameboard *g); extern void update_push(Gameboard *g, cairo_t *c); extern void push_curtain(Gameboard *g,void(*redraw_callback)(Gameboard *g)); extern void pop_curtain(Gameboard *g); extern void prepare_reenter_game(Gameboard *g); extern void reenter_game(Gameboard *g); extern void enter_game(Gameboard *g); extern void quit_action(Gameboard *g); extern void finish_action(Gameboard *g); extern void expand_action(Gameboard *g); extern void shrink_action(Gameboard *g); extern void pause_action(Gameboard *g); extern void about_action(Gameboard *g); extern void level_action(Gameboard *g); extern void set_hide_lines(Gameboard *g, int state); extern void toggle_hide_lines(Gameboard *g); extern void set_show_intersections(Gameboard *g, int state); extern void toggle_show_intersections(Gameboard *g); extern void reset_action(Gameboard *g); extern int gameboard_write(char *basename, Gameboard *g); extern int gameboard_read(char *basename, Gameboard *g); extern void topbox (Gameboard *g,cairo_t *c, double w, double h); extern void bottombox (Gameboard *g,cairo_t *c, double w, double h); extern void centerbox (cairo_t *c, int x, int y, double w, double h); extern void borderbox_path (cairo_t *c, double x, double y, double w, double h); extern void setup_buttonbar(Gameboard *g); extern void deploy_buttonbar(Gameboard *g); extern void deploy_check(Gameboard *g); extern void undeploy_check(Gameboard *g); extern void update_draw(Gameboard *g); extern void update_full(Gameboard *g); extern void expose_full(Gameboard *g); extern void update_full_delayed(Gameboard *g); extern void update_add_vertex(Gameboard *g, vertex *v); extern void update_add_selgroup(Gameboard *g); extern void gameboard_draw(Gameboard *g, int x, int y, int w, int h); extern void draw_foreground(Gameboard *g,cairo_t *c, int x,int y,int width,int height); extern void draw_intersections(Gameboard *b,graph *g,cairo_t *c, int x,int y,int w,int h); extern void draw_score(Gameboard *g); extern void update_score(Gameboard *g); extern void draw_vertex(cairo_t *c,vertex *v,cairo_surface_t *s); extern void draw_vertex_with_alpha(cairo_t *c,vertex *v,cairo_surface_t *s,float alpha); extern cairo_surface_t *cache_vertex(Gameboard *g); extern cairo_surface_t *cache_vertex_sel(Gameboard *g); extern cairo_surface_t *cache_vertex_grabbed(Gameboard *g); extern cairo_surface_t *cache_vertex_lit(Gameboard *g); extern cairo_surface_t *cache_vertex_attached(Gameboard *g); extern cairo_surface_t *cache_vertex_ghost(Gameboard *g); extern void invalidate_vertex_off(GtkWidget *widget, vertex *v, int dx, int dy); extern void invalidate_vertex(Gameboard *g, vertex *v); extern void invalidate_attached(GtkWidget *widget, vertex *v); extern void invalidate_edges(GtkWidget *widget, vertex *v, int offx, int offy); extern void draw_selection_rectangle(Gameboard *g,cairo_t *c); extern void invalidate_selection(GtkWidget *widget); extern void invalidate_verticies_selection(GtkWidget *widget); extern void cache_curtain(Gameboard *g); extern void draw_curtain(Gameboard *g); extern void draw_buttonbar_box (Gameboard *g); extern gint mouse_motion(GtkWidget *widget,GdkEventMotion *event); extern gboolean mouse_press (GtkWidget *widget,GdkEventButton *event); extern gboolean mouse_release (GtkWidget *widget,GdkEventButton *event); extern void setup_background_edge(cairo_t *c); extern void setup_foreground_edge(cairo_t *c); extern void draw_edge(cairo_t *c,edge *e); extern void draw_edges(cairo_t *c, vertex *v, int offx, int offy); extern void finish_edge(cairo_t *c); extern cairo_surface_t *gameboard_read_icon(char *filename, char *ext,Gameboard *b); extern int gameboard_write_icon(char *filename, char *ext,Gameboard *b, graph *g, int lines, int intersections); extern int gameboard_icon_exists(char *filename, char *ext); extern void deploy_buttons(Gameboard *g, void (*callback)(Gameboard *)); extern void undeploy_buttons(Gameboard *g, void (*callback)(Gameboard *)); extern GdkRectangle render_text_centered(cairo_t *c, char *s, int x, int y); extern GdkRectangle render_border_centered(cairo_t *c, char *s, int x, int y); extern GdkRectangle render_bordertext_centered(cairo_t *c, char *s, int x, int y); extern void gameboard_size_allocate (GtkWidget *widget, GtkAllocation *allocation); extern void fade_cancel(Gameboard *g); extern void fade_attached(Gameboard *g,vertex *v); extern void fade_grabbed(Gameboard *g); extern void fade_marked(Gameboard *g); #endif /* GAMEBOARD_H */ gplanarity-master/gameboard_draw_box.c000066400000000000000000000153301510662254600205040ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include "graph.h" #include "gameboard.h" #include "gameboard_draw_button.h" void topbox (Gameboard *g,cairo_t *c, double w, double h){ double x0 = B_BORDER+B_RADIUS; double y0 = B_BORDER; double x1 = B_BORDER; double y1 = B_BORDER+B_RADIUS; double x2 = B_BORDER; double y2 = h-B_BORDER-B_RADIUS; double x3 = B_BORDER+B_RADIUS; double y3 = h-B_BORDER; double x4 = w/2 - B_HUMP - B_RADIUS; double y4 = h-B_BORDER; double x5 = x4+B_RADIUS; double y5 = y4; double x7 = w/2 + B_HUMP + B_RADIUS; double y7 = h-B_BORDER; double x8 = w - B_BORDER -B_RADIUS; double y8 = h-B_BORDER; double x9 = w - B_BORDER; double y9 = h-B_BORDER-B_RADIUS; double x10 = w - B_BORDER; double y10 = B_BORDER+B_RADIUS; double x11 = w - B_BORDER-B_RADIUS; double y11 = B_BORDER; cairo_set_line_width(c,B_LINE); cairo_move_to (c, x0, y0); cairo_curve_to (c, x1,y0, x1,y0, x1,y1); cairo_line_to (c, x2,y2); cairo_curve_to (c, x2,y3, x2,y3, x3,y3); cairo_line_to (c, x4,y4); { double hh = g->g.orig_height*.5+50; double radius = sqrt( (w*.5-x5) * (w*.5-x5) + (hh-y5) * (hh-y5)); double siderad = atan( (x5-w*.5)/(hh-y5)); double xx = sin(siderad+.05)*radius+w*.5; double yy = -cos(siderad+.05)*radius+hh; double x = sin(siderad+.1)*radius+w*.5; double y = -cos(siderad+.1)*radius+hh; cairo_curve_to (c, x4+B_RADIUS,y4, xx,yy, x,y); cairo_arc(c,w*.5,hh,radius,-M_PI*.5+siderad+.1,-M_PI*.5-siderad-.1); xx = -sin(siderad+.05)*radius+w*.5; yy = -cos(siderad+.05)*radius+hh; xx = -sin(siderad+.1)*radius+w*.5; yy = -cos(siderad+.1)*radius+hh; cairo_curve_to (c, xx,yy, x7-B_RADIUS,y7, x7,y7); } cairo_line_to (c, x8,y8); cairo_curve_to (c, x9,y8, x9,y8, x9,y9); cairo_line_to (c, x10,y10); cairo_curve_to (c, x10,y11, x10,y11, x11,y11); cairo_close_path (c); cairo_set_source_rgba (c, B_COLOR); cairo_fill_preserve (c); cairo_set_source_rgba (c, B_LINE_COLOR); cairo_stroke (c); } void bottombox (Gameboard *g, cairo_t *c, double w, double h){ double x0 = B_BORDER+B_RADIUS; double y0 = h-B_BORDER; double x1 = B_BORDER; double y1 = h-B_BORDER-B_RADIUS; double x2 = B_BORDER; double y2 = B_BORDER+B_RADIUS; double x3 = B_BORDER+B_RADIUS; double y3 = B_BORDER; double x4 = w/2 - B_HUMP - B_RADIUS; double y4 = B_BORDER; double x5 = x4+B_RADIUS; double y5 = y4; double x7 = w/2 + B_HUMP + B_RADIUS; double y7 = B_BORDER; double x8 = w - B_BORDER -B_RADIUS; double y8 = B_BORDER; double x9 = w - B_BORDER; double y9 = B_BORDER+B_RADIUS; double x10 = w - B_BORDER; double y10 = h- B_BORDER -B_RADIUS; double x11 = w - B_BORDER-B_RADIUS; double y11 = h-B_BORDER; cairo_set_line_width(c,B_LINE); cairo_move_to (c, x0, y0); cairo_curve_to (c, x1,y0, x1,y0, x1,y1); cairo_line_to (c, x2,y2); cairo_curve_to (c, x2,y3, x2,y3, x3,y3); cairo_line_to (c, x4,y4); { double hh = g->g.orig_height*.5+50; double radius = sqrt( (w*.5-x5) * (w*.5-x5) + (y5+hh-h) * (y5+hh-h)); double siderad = atan( (x5-w*.5)/(y5+hh-h)); double xx = sin(siderad+.05)*radius+w*.5; double yy = cos(siderad+.05)*radius-hh+h; double x = sin(siderad+.1)*radius+w*.5; double y = cos(siderad+.1)*radius-hh+h; cairo_curve_to (c, x4+B_RADIUS,y4, xx,yy, x,y); cairo_arc_negative(c,w*.5,h-hh,radius,M_PI*.5-siderad-.1,M_PI*.5+siderad+.1); xx = -sin(siderad+.05)*radius+w*.5; yy = cos(siderad+.05)*radius-hh+h; xx = -sin(siderad+.1)*radius+w*.5; yy = cos(siderad+.1)*radius-hh+h; cairo_curve_to (c, xx,yy, x7-B_RADIUS,y7, x7,y7); } cairo_line_to (c, x8,y8); cairo_curve_to (c, x9,y8, x9,y8, x9,y9); cairo_line_to (c, x10,y10); cairo_curve_to (c, x10,y11, x10,y11, x11,y11); cairo_close_path (c); cairo_set_source_rgba (c, B_COLOR); cairo_fill_preserve (c); cairo_set_source_rgba (c, B_LINE_COLOR); cairo_stroke (c); } void centerbox (cairo_t *c, int x, int y, double w, double h){ double x0 = B_BORDER+B_RADIUS; double y0 = h-B_BORDER; double x1 = B_BORDER; double y1 = h-B_BORDER-B_RADIUS; double x2 = B_BORDER; double y2 = B_BORDER+B_RADIUS; double x3 = B_BORDER+B_RADIUS; double y3 = B_BORDER; double x8 = w - B_BORDER -B_RADIUS; double y8 = B_BORDER; double x9 = w - B_BORDER; double y9 = B_BORDER+B_RADIUS; double x10 = w - B_BORDER; double y10 = h- B_BORDER -B_RADIUS; double x11 = w - B_BORDER-B_RADIUS; double y11 = h-B_BORDER; cairo_save(c); cairo_translate(c,x,y); cairo_set_line_width(c,B_LINE); cairo_move_to (c, x0, y0); cairo_curve_to (c, x1,y0, x1,y0, x1,y1); cairo_line_to (c, x2,y2); cairo_curve_to (c, x2,y3, x2,y3, x3,y3); cairo_line_to (c, x8,y8); cairo_curve_to (c, x9,y8, x9,y8, x9,y9); cairo_line_to (c, x10,y10); cairo_curve_to (c, x10,y11, x10,y11, x11,y11); cairo_close_path (c); cairo_set_source_rgba (c, B_COLOR); cairo_fill_preserve (c); cairo_set_source_rgba (c, B_LINE_COLOR); cairo_stroke (c); cairo_restore(c); } void borderbox_path (cairo_t *c, double x, double y, double w, double h){ double x0 = x+ B_RADIUS; double y0 = y+ h; double x1 = x; double y1 = y+ h-B_RADIUS; double x2 = x; double y2 = y+ B_RADIUS; double x3 = x+ B_RADIUS; double y3 = y; double x8 = x+ w -B_RADIUS; double y8 = y; double x9 = x+ w; double y9 = y+ B_RADIUS; double x10 = x+ w; double y10 = y+ h -B_RADIUS; double x11 = x+ w -B_RADIUS; double y11 = y+h; cairo_move_to (c, x0, y0); cairo_curve_to (c, x1,y0, x1,y0, x1,y1); cairo_line_to (c, x2,y2); cairo_curve_to (c, x2,y3, x2,y3, x3,y3); cairo_line_to (c, x8,y8); cairo_curve_to (c, x9,y8, x9,y8, x9,y9); cairo_line_to (c, x10,y10); cairo_curve_to (c, x10,y11, x10,y11, x11,y11); cairo_close_path (c); } gplanarity-master/gameboard_draw_button.c000066400000000000000000000150211510662254600212240ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include "graph.h" #include "gameboard.h" #include "gameboard_draw_button.h" /************************* simple round icon drawing *********************/ void path_button_help(cairo_t *c, double x, double y){ cairo_save(c); cairo_translate(c,x,y); cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD); cairo_set_line_width(c,1); cairo_arc(c,0,0,14,0,2*M_PI); cairo_move_to(c,-9,-2); cairo_curve_to(c,-8,-7, -4.5,-12, 0,-12); cairo_curve_to(c, 7,-12, 9,-6, 9,-4); cairo_curve_to(c, 9,0 ,6,2, 5,2); cairo_curve_to(c, 4,2, 2.5,3, 2.5,6); cairo_line_to(c,-2.5,6); cairo_curve_to(c,-2.5,3, -3,1, 0,-1); cairo_curve_to(c, 11,-4, -3,-12, -4,-2); cairo_close_path(c); cairo_move_to(c,-2.5,8); cairo_line_to(c,2.5,8); cairo_line_to(c,2.5,12); cairo_line_to(c,-2.5,12); cairo_close_path(c); cairo_fill_preserve(c); cairo_restore(c); } void path_button_pause(cairo_t *c, double x, double y){ cairo_save(c); cairo_translate(c,x,y); cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD); cairo_set_line_width(c,1); cairo_arc(c,0,0,14,0,2*M_PI); cairo_rectangle(c,-7,-9,5,18); cairo_rectangle(c,2,-9,5,18); cairo_fill_preserve(c); cairo_restore(c); } void path_button_exit(cairo_t *c, double x, double y){ cairo_save(c); cairo_translate(c,x,y); cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD); cairo_set_line_width(c,1); cairo_arc(c,0,0,14,0,2*M_PI); cairo_move_to(c,-6,-9.5); cairo_line_to(c,0,-3.5); cairo_line_to(c,6,-9.5); cairo_line_to(c,9.5,-6); cairo_line_to(c,3.5,0); cairo_line_to(c,9.5,6); cairo_line_to(c,6,9.5); cairo_line_to(c,0,3.5); cairo_line_to(c,-6,9.5); cairo_line_to(c,-9.5,6); cairo_line_to(c,-3.5,0); cairo_line_to(c,-9.5,-6); cairo_close_path(c); cairo_fill_preserve(c); cairo_restore(c); } void path_button_back(cairo_t *c, double x, double y){ cairo_save(c); cairo_translate(c,x,y); cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD); cairo_set_line_width(c,1); cairo_arc(c,0,0,14,0,2*M_PI); cairo_move_to(c,0,-11); cairo_line_to(c,-9,0); cairo_line_to(c,-3,0); cairo_line_to(c,-3,10); cairo_line_to(c,3,10); cairo_line_to(c,3,0); cairo_line_to(c,9,0); cairo_close_path(c); cairo_fill_preserve(c); cairo_restore(c); } void path_button_reset(cairo_t *c, double x, double y){ cairo_save(c); cairo_translate(c,x,y); cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD); cairo_set_line_width(c,1); cairo_arc(c,0,0,14,0,2*M_PI); cairo_move_to(c,-11,-5); cairo_line_to(c,-12,1); cairo_line_to(c,-6,1); cairo_line_to(c,0, 11); cairo_line_to(c,6,1); cairo_line_to(c,12,1); cairo_line_to(c,11,-5); cairo_line_to(c,4,-5); cairo_line_to(c,0,2); cairo_line_to(c,-4,-5); cairo_close_path(c); cairo_fill_preserve(c); cairo_restore(c); } void path_button_expand(cairo_t *c, double x, double y){ cairo_save(c); cairo_translate(c,x,y); cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD); cairo_set_line_width(c,1); cairo_arc(c,0,0,14,0,2*M_PI); cairo_move_to(c,-8.5,-3); cairo_line_to(c,-2.5,-3); cairo_line_to(c,-3,-8.5); cairo_line_to(c,3, -8.5); cairo_line_to(c,3,-3); cairo_line_to(c,8.5,-3); cairo_line_to(c,8.5,3); cairo_line_to(c,3,3); cairo_line_to(c,3,8.5); cairo_line_to(c,-3,8.5); cairo_line_to(c,-3,3); cairo_line_to(c,-8.5,3); cairo_close_path(c); cairo_fill_preserve(c); cairo_restore(c); } void path_button_shrink(cairo_t *c, double x, double y){ cairo_save(c); cairo_translate(c,x,y); cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD); cairo_set_line_width(c,1); cairo_arc(c,0,0,14,0,2*M_PI); cairo_move_to(c,-10,-3); cairo_line_to(c,10,-3); cairo_line_to(c,10,3); cairo_line_to(c,-10,3); cairo_close_path(c); cairo_fill_preserve(c); cairo_restore(c); } void path_button_lines(cairo_t *c, double x, double y){ cairo_save(c); cairo_translate(c,x,y); cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD); cairo_set_line_width(c,1); cairo_arc(c,0,0,14,0,2*M_PI); cairo_move_to(c,6,-4); cairo_arc(c,0,-4,6,0,2*M_PI); cairo_move_to(c,0,2); cairo_line_to(c,0,10); cairo_close_path(c); cairo_move_to(c,2.68328,5.36656-4); cairo_rel_line_to(c,4,8); cairo_close_path(c); cairo_move_to(c,-2.68328,5.36656-4); cairo_rel_line_to(c,-4,8); cairo_close_path(c); cairo_fill_preserve(c); cairo_restore(c); } void path_button_int(cairo_t *c, double x, double y){ cairo_save(c); cairo_translate(c,x,y); cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD); cairo_set_line_width(c,1); cairo_arc(c,0,0,14,0,2*M_PI); cairo_move_to(c,8,0); cairo_line_to(c,0,8); cairo_line_to(c,-8,0); cairo_line_to(c,0,-8); cairo_close_path(c); cairo_fill_preserve(c); cairo_restore(c); } void path_button_check(cairo_t *c, double x, double y){ cairo_save(c); cairo_translate(c,x,y); cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD); cairo_set_line_width(c,1); cairo_arc(c,0,0,14,0,2*M_PI); cairo_move_to(c,8,-8); cairo_curve_to(c, 7,-7, 11,-7.3, 10,-6); cairo_line_to(c,0,9); cairo_curve_to(c, -1,9.1, -2,11, -3,10); cairo_line_to(c,-11,4); cairo_curve_to(c, -12,3, -10,.5, -9,1); cairo_line_to(c,-3,3); cairo_close_path(c); cairo_fill_preserve(c); cairo_restore(c); } void path_button_play(cairo_t *c, double x, double y){ cairo_save(c); cairo_translate(c,x,y); cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD); cairo_set_line_width(c,1); cairo_arc(c,0,0,14,0,2*M_PI); cairo_move_to(c,-8,-8); cairo_line_to(c,10,0); cairo_line_to(c,-8,8); cairo_close_path(c); cairo_fill_preserve(c); cairo_restore(c); } gplanarity-master/gameboard_draw_button.h000066400000000000000000000052121510662254600212320ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef GAMEBOARD_DRAW_BUTTON_H #define GAMEBOARD_DRAW_BUTTON_H extern void path_button_help(cairo_t *c, double x, double y); extern void path_button_back(cairo_t *c, double x, double y); extern void path_button_reset(cairo_t *c, double x, double y); extern void path_button_pause(cairo_t *c, double x, double y); extern void path_button_exit(cairo_t *c, double x, double y); extern void path_button_expand(cairo_t *c, double x, double y); extern void path_button_shrink(cairo_t *c, double x, double y); extern void path_button_lines(cairo_t *c, double x, double y); extern void path_button_int(cairo_t *c, double x, double y); extern void path_button_check(cairo_t *c, double x, double y); extern void path_button_play(cairo_t *c, double x, double y); #define BUTTON_QUIT_IDLE_FILL .7,.1,.1,.3 #define BUTTON_QUIT_IDLE_PATH .7,.1,.1,.6 #define BUTTON_QUIT_LIT_FILL .7,.1,.1,.5 #define BUTTON_QUIT_LIT_PATH .7,.1,.1,.6 #define BUTTON_IDLE_FILL .1,.1,.7,.3 #define BUTTON_IDLE_PATH .1,.1,.7,.6 #define BUTTON_LIT_FILL .1,.1,.7,.6 #define BUTTON_LIT_PATH .1,.1,.7,.6 #define BUTTON_CHECK_IDLE_FILL .1,.5,.1,.3 #define BUTTON_CHECK_IDLE_PATH .1,.5,.1,.6 #define BUTTON_CHECK_LIT_FILL .1,.5,.1,.6 #define BUTTON_CHECK_LIT_PATH .1,.5,.1,.6 #define BUTTON_RADIUS 14 #define BUTTON_Y_FROM_BOTTOM 25 #define BUTTON_LINE_WIDTH 1 #define BUTTON_TEXT_BORDER 15 #define BUTTON_TEXT_COLOR .1,.1,.7,.8 #define BUTTON_TEXT_SIZE 15.,18. #define BUTTON_ANIM_INTERVAL 15 #define BUTTON_LEFT 5 #define BUTTON_RIGHT 5 #define BUTTON_BORDER 35 #define BUTTON_SPACING 35 #define BUTTON_EXPOSE 50 #define DEPLOY_DELTA 6 #define SWEEP_DELTA 3 #endif /* GAMEBOARD_DRAW_BUTTON_H */ gplanarity-master/gameboard_draw_buttonbar.c000066400000000000000000000025561510662254600217220ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include #include "graph.h" #include "gameboard.h" void draw_buttonbar_box (Gameboard *g){ cairo_t *c = cairo_create(g->forebutton); cairo_save(c); cairo_set_operator(c,CAIRO_OPERATOR_CLEAR); cairo_set_source_rgba (c, 1,1,1,1); cairo_paint(c); cairo_restore(c); bottombox(g,c,g->g.width,SCOREHEIGHT); cairo_destroy(c); } gplanarity-master/gameboard_draw_curtain.c000066400000000000000000000042571510662254600213670ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "graph.h" #include "gameboard.h" /* cache the curtain surface/pattern ******************************/ #define CW 4 void cache_curtain(Gameboard *g){ int x,y; cairo_t *wc = gdk_cairo_create(gtk_widget_get_window (&g->w)); cairo_t *c; g->curtains= cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, CW,CW); cairo_destroy(wc); c = cairo_create(g->curtains); cairo_save(c); cairo_set_operator(c,CAIRO_OPERATOR_CLEAR); cairo_set_source_rgba (c, 1,1,1,1); cairo_paint(c); cairo_restore(c); cairo_set_line_width(c,1); cairo_set_source_rgba (c, 0,0,0,.5); for(y=0;ycurtainp=cairo_pattern_create_for_surface (g->curtains); cairo_pattern_set_extend (g->curtainp, CAIRO_EXTEND_REPEAT); } void draw_curtain(Gameboard *g){ cairo_t *c = cairo_create(g->background); cairo_set_source (c, g->curtainp); cairo_paint(c); cairo_destroy(c); } gplanarity-master/gameboard_draw_edge.c000066400000000000000000000054351510662254600206250ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "graph.h" #include "gameboard.h" /******** draw edges ********************************************/ void setup_background_edge(cairo_t *c){ cairo_set_line_width(c,E_LINE); cairo_set_source_rgba(c,E_LINE_B_COLOR); } void setup_foreground_edge(cairo_t *c){ cairo_set_line_width(c,E_LINE); cairo_set_source_rgba(c,E_LINE_F_COLOR); } void draw_edge(cairo_t *c,edge *e){ cairo_move_to(c,e->A->x,e->A->y); cairo_line_to(c,e->B->x,e->B->y); } void finish_edge(cairo_t *c){ cairo_stroke(c); } void draw_edges(cairo_t *c, vertex *v, int offx, int offy){ if(v){ edge_list *el=v->edges; while (el){ edge *e=el->edge; if(e->A->grabbed==0 || e->B->grabbed==0 || v==e->A){ if(e->A->grabbed) cairo_move_to(c,e->A->x+offx,e->A->y+offy); else cairo_move_to(c,e->A->x,e->A->y); if(e->B->grabbed) cairo_line_to(c,e->B->x+offx,e->B->y+offy); else cairo_line_to(c,e->B->x,e->B->y); } el=el->next; } } } /* invalidate edge region for efficient expose *******************/ void invalidate_edges(GtkWidget *widget, vertex *v, int offx, int offy){ GdkRectangle r; if(v){ edge_list *el=v->edges; while (el){ edge *e=el->edge; if(e->A->grabbed==0 || e->B->grabbed==0 || v==e->A){ int Ax = e->A->x + (e->A->grabbed?offx:0); int Ay = e->A->y + (e->A->grabbed?offy:0); int Bx = e->B->x + (e->B->grabbed?offx:0); int By = e->B->y + (e->B->grabbed?offy:0); r.x = min(Ax,Bx) - E_LINE; r.y = min(Ay,By) - E_LINE; r.width = labs(Bx - Ax) + 1 + E_LINE*2; r.height = labs(By - Ay) + 1 + E_LINE*2; gdk_window_invalidate_rect (gtk_widget_get_window (widget), &r, FALSE); } el=el->next; } } } gplanarity-master/gameboard_draw_intersection.c000066400000000000000000000060701510662254600224230ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "graph.h" #include "gameboard.h" #include "main.h" static void draw_intersection(cairo_t *c,double x, double y){ cairo_move_to(c,x-INTERSECTION_RADIUS,y); cairo_rel_line_to(c,INTERSECTION_RADIUS,-INTERSECTION_RADIUS); cairo_rel_line_to(c,INTERSECTION_RADIUS,INTERSECTION_RADIUS); cairo_rel_line_to(c,-INTERSECTION_RADIUS,INTERSECTION_RADIUS); cairo_close_path(c); } static void draw_many_intersection(Gameboard *g,cairo_t *c){ int x2 = g->g.width/2; int y2 = g->g.height/2; int r = INTERSECTION_RADIUS*10; cairo_set_source_rgba (c, INTERSECTION_COLOR); cairo_set_line_width(c, INTERSECTION_LINE_WIDTH*10); cairo_move_to(c,x2-r,y2-r/4); cairo_rel_line_to(c,r,-r); cairo_rel_line_to(c,r,r); cairo_rel_line_to(c,-r,r); cairo_close_path(c); cairo_stroke(c); set_font(c, 30., 34., 0,1); render_bordertext_centered(c,_("rather many, really"),x2,y2+r/4); } void draw_intersections(Gameboard *b, graph *g, cairo_t *c, int x,int y,int w,int h){ double xx=x-(INTERSECTION_LINE_WIDTH*.5 + INTERSECTION_RADIUS); double x2=w+x+(INTERSECTION_LINE_WIDTH + INTERSECTION_RADIUS*2); double yy=y-(INTERSECTION_LINE_WIDTH*.5 + INTERSECTION_RADIUS); double y2=h+y+(INTERSECTION_LINE_WIDTH + INTERSECTION_RADIUS*2); if(g->active_intersections > 1000){ // don't draw them all; potential for accidental CPU sink. draw_many_intersection(b,c); }else{ cairo_set_source_rgba (c, INTERSECTION_COLOR); cairo_set_line_width(c, INTERSECTION_LINE_WIDTH); // walk the intersection list of all edges; draw if paired is a higher pointer edge *e=g->edges; while(e){ intersection *i = e->i.next; while(i){ if(i->paired > i){ double ix=i->x, iy=i->y; if(ix >= xx && ix <= x2 && iy >= yy && iy <= y2) draw_intersection(c,ix,iy); } cairo_stroke(c); /* incremental stroke! It's easy to run the path longer than the X server allows. */ i=i->next; } e=e->next; } } } gplanarity-master/gameboard_draw_main.c000066400000000000000000000271551510662254600206500ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "graph.h" #include "gameboard.h" #include "dialog_level.h" #include "main.h" /* The gPlanarity gameboard consists of a background and a foreground. The background is a predrawn backdrop of anything not currently being animated. The foreground is 'active' elements of the UI and anything that floats above them. There are also two translucent bars, top and bottom, that hold the score and buttonbar respectively. These are prerendered surfaces that are blitted onto the foreground during exposes */ void draw_foreground(Gameboard *g,cairo_t *c,int x,int y,int w,int h){ /* Edges attached to the grabbed vertex are drawn here */ if(g->grabbed_vertex && !g->hide_lines){ edge_list *el=g->grabbed_vertex->edges; setup_foreground_edge(c); while(el){ edge *e=el->edge; /* no need to check rectangle; if they're to be drawn, they'll always be in the rect due to expose combining */ draw_edge(c,e); el=el->next; } finish_edge(c); } if(g->group_drag){ vertex *v = g->g.verticies; setup_foreground_edge(c); while(v){ if(v->grabbed){ /* no need to check rectangle; if they're to be drawn, they'll always be in the rect due to expose combining */ draw_edges(c,v,g->dragx,g->dragy); } v=v->next; } finish_edge(c); } /* verticies drawn over the edges */ { vertex *v = g->g.verticies; float alpha = 1.*g->fade.count/FADE_FRAMES; int clipx = x-V_RADIUS; int clipw = x+w+V_RADIUS; int clipy = y-V_RADIUS; int cliph = y+h+V_RADIUS; while(v){ if(v->grabbed && g->group_drag){ vertex tv; tv.x=v->x+g->dragx; tv.y=v->y+g->dragy; /* is the vertex in the expose rectangle? */ if(tv.x>=clipx && tv.x<=clipw && tv.y>=clipy && tv.y<=cliph){ draw_vertex(c,&tv,g->vertex_ghost); } }else{ /* is the vertex in the expose rectangle? */ if(v->x>=clipx && v->x<=clipw && v->y>=clipy && v->y<=cliph){ if(v == g->grabbed_vertex && !g->group_drag) { draw_vertex(c,v,g->vertex_grabbed); } else if( v->selected ){ draw_vertex(c,v,g->vertex_sel); if(v->fading) draw_vertex_with_alpha(c,v,g->vertex_ghost,alpha); } else if ( v == g->lit_vertex){ draw_vertex(c,v,g->vertex_lit); } else if (v->attached_to_grabbed){ draw_vertex(c,v,g->vertex_attached); }else{ draw_vertex(c,v,g->vertex); if(v->fading) draw_vertex_with_alpha(c,v,g->vertex_attached,alpha); } } } v=v->next; } } if(g->selection_grab) draw_selection_rectangle(g,c); } static void draw_background(Gameboard *g,cairo_t *c){ edge *e=g->g.edges; cairo_set_source_rgb(c,1,1,1); cairo_paint(c); if(!g->hide_lines){ setup_background_edge(c); while(e){ if(e->active) draw_edge(c,e); e=e->next; } finish_edge(c); } } static void draw_background_realpart(Gameboard *g,cairo_t *c, int x, int y, int w, int h){ edge *e=g->g.edges; int x2 = x+w-1+E_LINE; int y2 = y+h-1+E_LINE; x-=E_LINE; y-=E_LINE; cairo_set_source_rgb(c,1,1,1); cairo_paint(c); if(!g->hide_lines){ setup_background_edge(c); while(e){ int ex1 = e->A->x; int ex2 = e->B->x; int ey1 = e->A->y; int ey2 = e->B->y; if(ex1ex2 || x2next;continue;} }else{ if(x>ex1 || x2next;continue;} } if(ey1ey2 || y2next;continue;} }else{ if(y>ey1 || y2next;continue;} } draw_edge(c,e); e=e->next; } finish_edge(c); } } /* Several very-high-level drawing sequences triggered by various actions in the game *********************************************/ /* request that the background plane be redrawn from scratch to match current game state and the full window invalidated to request an expose. As other layers are always drawn on the fly, this is effectively a full refresh of the screen. This is done as sparingly as possible and only within large state changes as it's not fast enough for animation. */ void update_full(Gameboard *g){ cairo_t *c = cairo_create(g->background); g->delayed_background=0; // render the far background plane draw_background(g,c); update_push(g,c); cairo_destroy(c); expose_full(g); } void expose_full(Gameboard *g){ GtkWidget *widget = GTK_WIDGET(g); GdkRectangle r; r.x=0; r.y=0; r.width=g->g.width; r.height=g->g.height; gdk_window_invalidate_rect (gtk_widget_get_window (widget), &r, FALSE); } void update_draw(Gameboard *g){ cairo_t *c = cairo_create(g->background); g->delayed_background=0; // render the far background plane draw_background(g,c); update_push(g,c); cairo_destroy(c); gameboard_draw(g,0,0,g->g.width,g->g.height); } /* request a full redraw update to be processed immediately *after* the next expose. This is used to increase apparent interactivity of a vertex 'grab' where the background must be redrawn, but the vertex itself should react immediately */ void update_full_delayed(Gameboard *g){ g->delayed_background=1; } /* specialized update request for when re-adding a grabbed vertex's edges to the background. Doesn't require a full redraw. */ void update_add_vertex(Gameboard *g, vertex *v){ GtkWidget *widget = GTK_WIDGET(g); edge_list *el=v->edges; cairo_t *c = cairo_create(g->background); if(!g->hide_lines){ setup_background_edge(c); while(el){ edge *e=el->edge; draw_edge(c,e); el=el->next; } finish_edge(c); } cairo_destroy(c); invalidate_attached(widget,v); } /* as above for re-inserting group drag edges to the background. Doesn't require a full redraw. */ void update_add_selgroup(Gameboard *g){ if(!g->hide_lines){ GtkWidget *widget = GTK_WIDGET(g); cairo_t *c = cairo_create(g->background); vertex *v = g->g.verticies; setup_background_edge(c); while(v){ if(v->grabbed){ edge_list *el=v->edges; while(el){ edge *e=el->edge; // draw the edge only once if it spans two grabbed verticies if(e->A->grabbed==0 || e->B->grabbed==0 || v==e->A) draw_edge(c,e); el=el->next; } } invalidate_attached(widget,v); v=v->next; } finish_edge(c); cairo_destroy(c); } } /* top level draw function called by expose. May also be called directly to immediately render a region of the board without going through the expose mechanism (necessary for some button draw operations where expose combining causes huge, slow in-server alpha blends that are undesirable) */ void gameboard_draw(Gameboard *g, int x, int y, int w, int h){ cairo_t *c = cairo_create(g->foreground); if (w==0 || h==0) return; if(g->realtime_background){ draw_background_realpart(g,c,x,y,w,h); }else{ // copy background to foreground draw buffer cairo_set_source_surface(c,g->background,0,0); cairo_rectangle(c,x,y,w,h); cairo_fill(c); } if(!g->pushed_curtain){ GtkAllocation allocation; gtk_widget_get_allocation(&g->w, &allocation); draw_foreground(g,c,x,y,w,h); // copy in any of the score or button surfaces? if(yforescore,0,0); cairo_rectangle(c, x,y,w, min(SCOREHEIGHT-y,h)); cairo_fill(c); } if(y+h>allocation.height-SCOREHEIGHT){ cairo_set_source_surface(c,g->forebutton,0, allocation.height-SCOREHEIGHT); cairo_rectangle(c, x,y,w,h); cairo_fill(c); } if(g->show_intersections) draw_intersections(g,&g->g,c,x,y,w,h); } render_level_icons(g,c,x,y,w,h); expose_buttons(g,c,x,y,w,h); cairo_destroy(c); // blit to window { cairo_t *wc = gdk_cairo_create(gtk_widget_get_window (&g->w)); cairo_set_source_surface(wc,g->foreground,0,0); cairo_rectangle(wc,x,y,w,h); cairo_fill(wc); cairo_destroy(wc); } if(g->delayed_background)update_full(g); g->first_expose=1; } cairo_surface_t *gameboard_read_icon(char *filename, char *ext, Gameboard *b){ char *name=alloca(strlen(boarddir)+strlen(filename)+strlen(ext)+2); name[0]=0; strcat(name,boarddir); strcat(name,filename); strcat(name,"."); strcat(name,ext); cairo_surface_t *s = cairo_image_surface_create_from_png(name); if(s==NULL || cairo_surface_status(s)!=CAIRO_STATUS_SUCCESS) fprintf(stderr,_("ERROR: Could not load board icon \"%s\"\n"), name); cairo_t *c = cairo_create(s); borderbox_path(c,1.5,1.5,ICON_WIDTH-3,ICON_HEIGHT-3); cairo_set_operator (c, CAIRO_OPERATOR_DEST_OVER); cairo_set_line_width(c,B_LINE); //cairo_set_source_rgba (c, B_COLOR); //cairo_fill_preserve (c); cairo_set_source_rgba (c, B_LINE_COLOR); cairo_stroke (c); cairo_destroy(c); return s; } int gameboard_write_icon(char *filename, char *ext, Gameboard *b, graph *g, int lines, int intersections){ char *name=alloca(strlen(boarddir)+strlen(filename)+strlen(ext)+2); name[0]=0; strcat(name,boarddir); strcat(name,filename); strcat(name,"."); strcat(name,ext); { cairo_surface_t *s = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ICON_WIDTH, ICON_HEIGHT); cairo_t *c = cairo_create(s); edge *e=g->edges; vertex *v = g->verticies; cairo_save(c); cairo_set_operator(c,CAIRO_OPERATOR_CLEAR); cairo_set_source_rgba (c, 1,1,1,1); cairo_paint(c); cairo_restore(c); cairo_scale(c,(float)ICON_WIDTH/g->width,(float)ICON_HEIGHT/g->height); if(lines){ setup_background_edge(c); while(e){ draw_edge(c,e); e=e->next; } finish_edge(c); } cairo_set_line_width(c,V_LINE); while(v){ // dirty, but we may not have the cached vertex surface yet. cairo_arc(c,v->x,v->y,V_RADIUS,0,2*M_PI); cairo_set_source_rgb(c,V_FILL_IDLE_COLOR); cairo_fill_preserve(c); cairo_set_source_rgb(c,V_LINE_COLOR); cairo_stroke(c); v=v->next; } if(intersections) draw_intersections(b,g,c,0,0,g->width,g->height); if(cairo_surface_write_to_png(s,name) != CAIRO_STATUS_SUCCESS){ fprintf(stderr,_("ERROR: Could not save board icon \"%s\"\n"), name); return -1; } cairo_destroy(c); cairo_surface_destroy(s); } return 0; } int gameboard_icon_exists(char *filename, char *ext){ struct stat s; char *name=alloca(strlen(boarddir)+strlen(filename)+strlen(ext)+2); name[0]=0; strcat(name,boarddir); strcat(name,filename); strcat(name,"."); strcat(name,ext); if(stat(name,&s))return 0; return 1; } gplanarity-master/gameboard_draw_score.c000066400000000000000000000066131510662254600210330ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "graph.h" #include "gameboard.h" #include "levelstate.h" #include "main.h" void draw_score(Gameboard *g){ char level_string[160]; char score_string[160]; char mult_string[160]; char int_string[160]; char obj_string[160]; cairo_text_extents_t extentsL; cairo_text_extents_t extentsS; cairo_text_extents_t extentsM; cairo_text_extents_t extentsO; cairo_text_extents_t extentsI; cairo_t *c = cairo_create(g->forescore); int xpx = 12; int ty1 = 23; int ty2 = 38; // clear the pane cairo_save(c); cairo_set_operator(c,CAIRO_OPERATOR_CLEAR); cairo_set_source_rgba (c, 1,1,1,1); cairo_paint(c); cairo_restore(c); topbox(g,c,g->g.width,SCOREHEIGHT); snprintf(level_string,160,_("Level %d: %s"),get_level_num()+1,get_level_desc()); snprintf(score_string,160,_("Score: %d"),graphscore_get_raw_score(&g->g)); snprintf(mult_string,160,_("%d%%"),graphscore_get_multiplier_percent(&g->g)); snprintf(int_string,160,_("Intersections: %ld"),g->g.active_intersections); snprintf(obj_string,160,_("Objective: %s"),graphscore_objective_string(&g->g)); set_font(c,xpx,15,0,1); cairo_set_source_rgba (c, TEXT_COLOR); cairo_text_extents (c, obj_string, &extentsO); cairo_text_extents (c, int_string, &extentsI); cairo_text_extents (c, score_string, &extentsS); cairo_text_extents (c, mult_string, &extentsM); cairo_move_to (c, 15, ty1); cairo_show_text (c, int_string); cairo_move_to (c, 15, ty2); cairo_show_text (c, score_string); if(graphscore_get_multiplier_percent(&g->g)>100){ cairo_save(c); cairo_set_source_rgba (c, HIGH_COLOR); cairo_move_to (c, 15 + extentsS.width+10, ty2); cairo_show_text (c, mult_string); cairo_restore(c); } cairo_move_to (c, g->g.width-extentsO.width-15, ty2); cairo_show_text (c, obj_string); while(xpx){ cairo_text_extents (c, level_string, &extentsL); if(extentsL.width > 300){ xpx--; set_font(c,xpx,15,0,1); }else break; } cairo_move_to (c, g->g.width-extentsL.width-15, ty1); cairo_show_text (c, level_string); cairo_destroy(c); } void update_score(Gameboard *g){ GdkRectangle r; draw_score(g); r.x=0; r.y=0; r.width=g->g.width; r.height = SCOREHEIGHT; gdk_window_invalidate_rect (gtk_widget_get_window (&g->w), &r, FALSE); } gplanarity-master/gameboard_draw_selection.c000066400000000000000000000042731510662254600217050ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "graph.h" #include "gameboard.h" // draw selection box void draw_selection_rectangle(Gameboard *g,cairo_t *c){ cairo_set_source_rgba(c,SELECTBOX_COLOR); cairo_rectangle(c,g->selectionx, g->selectiony, g->selectionw, g->selectionh); cairo_fill(c); } // invalidate the selection box plus enough area to catch any verticies void invalidate_selection(GtkWidget *widget){ Gameboard *g = GAMEBOARD (widget); GdkRectangle r; r.x = g->selectionx - (V_RADIUS + V_LINE)*2; r.y = g->selectiony - (V_RADIUS + V_LINE)*2; r.width = g->selectionw + (V_RADIUS + V_LINE)*4; r.height = g->selectionh + (V_RADIUS + V_LINE)*4; gdk_window_invalidate_rect (gtk_widget_get_window (widget), &r, FALSE); } // invalidate the selection box plus enough area to catch any verticies void invalidate_verticies_selection(GtkWidget *widget){ Gameboard *g = GAMEBOARD (widget); vertex *v=g->g.verticies; while(v){ if(v->selected){ invalidate_vertex_off(widget,v,g->dragx,g->dragy); invalidate_edges(widget,v,g->dragx,g->dragy); } v=v->next; } } gplanarity-master/gameboard_draw_text.c000066400000000000000000000040601510662254600206760ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include #include "graph.h" #include "gameboard.h" GdkRectangle render_text_centered(cairo_t *c, char *s, int x, int y){ cairo_text_extents_t ex; GdkRectangle r; cairo_text_extents (c, s, &ex); r.x=x-(ex.width/2); r.y=y+(ex.y_bearing/2); r.width=ex.width; r.height=ex.height; cairo_move_to (c, r.x-ex.x_bearing, r.y-ex.y_bearing); cairo_show_text (c, s); return r; } GdkRectangle render_border_centered(cairo_t *c, char *s, int x, int y){ cairo_text_extents_t ex; GdkRectangle r; cairo_text_extents (c, s, &ex); r.x=x-(ex.width/2)-2; r.y=y+(ex.y_bearing/2)-2; r.width=ex.width+5; r.height=ex.height+5; cairo_save(c); cairo_move_to (c, r.x-ex.x_bearing+2, r.y-ex.y_bearing+2 ); cairo_set_line_width(c,3); cairo_set_source_rgba(c,1,1,1,.9); cairo_text_path (c, s); cairo_stroke(c); cairo_restore(c); return r; } GdkRectangle render_bordertext_centered(cairo_t *c, char *s, int x, int y){ GdkRectangle r = render_border_centered(c,s,x,y); render_text_centered(c,s,x,y); return r; } gplanarity-master/gameboard_draw_vertex.c000066400000000000000000000153531510662254600212360ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "graph.h" #include "gameboard.h" /* draw/cache vertex surfaces; direct surface copies are faster than always redrawing lots of circles */ void draw_vertex(cairo_t *c,vertex *v,cairo_surface_t *s){ cairo_set_source_surface(c, s, v->x-V_LINE-V_RADIUS, v->y-V_LINE-V_RADIUS); cairo_paint(c); } void draw_vertex_with_alpha(cairo_t *c,vertex *v,cairo_surface_t *s,float alpha){ cairo_set_source_surface(c, s, v->x-V_LINE-V_RADIUS, v->y-V_LINE-V_RADIUS); cairo_paint_with_alpha(c,alpha); } // normal unlit vertex cairo_surface_t *cache_vertex(Gameboard *g){ cairo_t *wc = gdk_cairo_create(gtk_widget_get_window (&g->w)); cairo_surface_t *ret= cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, (V_RADIUS+V_LINE)*2, (V_RADIUS+V_LINE)*2); cairo_t *c = cairo_create(ret); cairo_destroy(wc); cairo_set_line_width(c,V_LINE); cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI); cairo_set_source_rgb(c,V_FILL_IDLE_COLOR); cairo_fill_preserve(c); cairo_set_source_rgb(c,V_LINE_COLOR); cairo_stroke(c); cairo_destroy(c); return ret; } // selected vertex cairo_surface_t *cache_vertex_sel(Gameboard *g){ cairo_t *wc = gdk_cairo_create(gtk_widget_get_window (&g->w)); cairo_surface_t *ret= cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, (V_RADIUS+V_LINE)*2, (V_RADIUS+V_LINE)*2); cairo_t *c = cairo_create(ret); cairo_destroy(wc); cairo_set_line_width(c,V_LINE); cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI); cairo_set_source_rgb(c,V_FILL_LIT_COLOR); cairo_fill_preserve(c); cairo_set_source_rgb(c,V_LINE_COLOR); cairo_stroke(c); cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS*.5,0,2*M_PI); cairo_set_source_rgb(c,V_FILL_IDLE_COLOR); cairo_fill(c); cairo_destroy(c); return ret; } // grabbed vertex cairo_surface_t *cache_vertex_grabbed(Gameboard *g){ cairo_t *wc = gdk_cairo_create(gtk_widget_get_window (&g->w)); cairo_surface_t *ret= cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, (V_RADIUS+V_LINE)*2, (V_RADIUS+V_LINE)*2); cairo_t *c = cairo_create(ret); cairo_destroy(wc); cairo_set_line_width(c,V_LINE); cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI); cairo_set_source_rgb(c,V_FILL_LIT_COLOR); cairo_fill_preserve(c); cairo_set_source_rgb(c,V_LINE_COLOR); cairo_stroke(c); cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS*.5,0,2*M_PI); cairo_set_source_rgb(c,V_FILL_ADJ_COLOR); cairo_fill(c); cairo_destroy(c); return ret; } // vertex under mouse rollover cairo_surface_t *cache_vertex_lit(Gameboard *g){ cairo_t *wc = gdk_cairo_create(gtk_widget_get_window (&g->w)); cairo_surface_t *ret= cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, (V_RADIUS+V_LINE)*2, (V_RADIUS+V_LINE)*2); cairo_t *c = cairo_create(ret); cairo_destroy(wc); cairo_set_line_width(c,V_LINE); cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI); cairo_set_source_rgb(c,V_FILL_LIT_COLOR); cairo_fill_preserve(c); cairo_set_source_rgb(c,V_LINE_COLOR); cairo_stroke(c); cairo_destroy(c); return ret; } // verticies attached to grabbed vertex cairo_surface_t *cache_vertex_attached(Gameboard *g){ cairo_t *wc = gdk_cairo_create(gtk_widget_get_window (&g->w)); cairo_surface_t *ret= cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, (V_RADIUS+V_LINE)*2, (V_RADIUS+V_LINE)*2); cairo_t *c = cairo_create(ret); cairo_destroy(wc); cairo_set_line_width(c,V_LINE); cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI); cairo_set_source_rgb(c,V_FILL_ADJ_COLOR); cairo_fill_preserve(c); cairo_set_source_rgb(c,V_LINE_COLOR); cairo_stroke(c); cairo_destroy(c); return ret; } // vertex being dragged in a group cairo_surface_t *cache_vertex_ghost(Gameboard *g){ cairo_t *wc = gdk_cairo_create(gtk_widget_get_window (&g->w)); cairo_surface_t *ret= cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, (V_RADIUS+V_LINE)*2, (V_RADIUS+V_LINE)*2); cairo_t *c = cairo_create(ret); cairo_destroy (wc); cairo_set_line_width(c,V_LINE); cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI); cairo_set_source_rgb(c,V_FILL_LIT_COLOR); cairo_fill_preserve(c); cairo_set_source_rgb(c,V_LINE_COLOR); cairo_stroke(c); cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS*.5,0,2*M_PI); cairo_set_source_rgb(c,V_FILL_ADJ_COLOR); cairo_fill(c); cairo_destroy(c); return ret; } /* region invalidation operations; do exposes efficiently! **********/ // invalidate the box around a single offset vertex void invalidate_vertex_off(GtkWidget *widget, vertex *v, int dx, int dy){ if(v){ GdkRectangle r; r.x = v->x - V_RADIUS - V_LINE + dx; r.y = v->y - V_RADIUS - V_LINE + dy; r.width = (V_RADIUS + V_LINE)*2; r.height = (V_RADIUS + V_LINE)*2; gdk_window_invalidate_rect (gtk_widget_get_window (widget), &r, FALSE); } } // invalidate the box around a single vertex void invalidate_vertex(Gameboard *g, vertex *v){ invalidate_vertex_off(&g->w,v,0,0); } // invalidate a vertex and any other attached verticies void invalidate_attached(GtkWidget *widget, vertex *v){ if(v){ edge_list *el=v->edges; while (el){ edge *e=el->edge; if(e->A != v)invalidate_vertex(GAMEBOARD(widget),e->A); if(e->B != v)invalidate_vertex(GAMEBOARD(widget),e->B); el=el->next; } invalidate_vertex(GAMEBOARD(widget),v); } } gplanarity-master/gameboard_logic.c000066400000000000000000000221211510662254600177700ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "graph.h" #include "timer.h" #include "gameboard.h" #include "levelstate.h" #include "dialog_finish.h" #include "dialog_pause.h" #include "dialog_level.h" #include "main.h" /* game state helpers ************************************************************************************/ void prepare_reenter_game(Gameboard *g){ g->lit_vertex=0; g->grabbed_vertex=0; g->delayed_background=0; g->group_drag=0; g->button_grabbed=0; g->selection_grab=0; g->selection_active=num_selected_verticies(&g->g); update_full(g); update_score(g); } void reenter_game(Gameboard *g){ deploy_buttonbar(g); unpause_timer(); set_in_progress(); } void enter_game(Gameboard *g){ set_timer(0); prepare_reenter_game(g); reenter_game(g); } static void animate_verticies(Gameboard *g, int *x_target, int *y_target, float *delta){ int flag=1,count=0; vertex *v=g->g.verticies; float *tx=alloca(g->g.vertex_num * sizeof(*tx)); float *ty=alloca(g->g.vertex_num * sizeof(*ty)); // hide intersections now; deactivating the verticies below will hide them anyway g->show_intersections = 0; g->realtime_background = 1; update_full(g); // deactivate all the verticies so they can be moved en-masse // without graph metadata updates at each move v=g->g.verticies; while(v){ deactivate_vertex(&g->g,v); tx[count]=v->x; ty[count++]=v->y; v=v->next; } // animate while(flag){ count=0; flag=0; v=g->g.verticies; while(v){ if(v->x!=x_target[count] || v->y!=y_target[count]){ float xd = x_target[count] - tx[count]; float yd = y_target[count] - ty[count]; float m = hypot(xd,yd); tx[count]+= xd/m*delta[count]; ty[count]+= yd/m*delta[count]; invalidate_vertex(g,v); invalidate_edges(GTK_WIDGET(g),v,0,0); v->x = rint(tx[count]); v->y = rint(ty[count]); if( (v->x > x_target[count] && xd > 0) || (v->x < x_target[count] && xd < 0) || (v->y > y_target[count] && yd > 0) || (v->y < y_target[count] && yd < 0) ){ v->x = x_target[count]; v->y = y_target[count]; }else flag=1; invalidate_vertex(g,v); invalidate_edges(GTK_WIDGET(g),v,0,0); } count++; v=v->next; } gdk_window_process_all_updates(); gdk_flush(); } // reactivate all the verticies activate_verticies(&g->g); // update the score update_score(g); // it's a reset; show lines is default. This also has the side // effect of forcing a full board redraw and expose g->realtime_background=0; update_full(g); // possible if(g->g.active_intersections <= g->g.objective){ deploy_check(g); }else{ undeploy_check(g); } } static void scale(Gameboard *g,double scale){ int x=g->g.width/2; int y=g->g.height/2; int sel = num_selected_verticies(&g->g); vertex *v; int *tx=alloca(g->g.vertex_num * sizeof(*tx)); int *ty=alloca(g->g.vertex_num * sizeof(*ty)); float *tm=alloca(g->g.vertex_num * sizeof(*ty)); int i=0; int minx=0; int maxx=g->g.width-1; int miny=0; int maxy=g->g.height-1; int okflag=0; // if selected, expand from center of selected mass if(sel){ double xac=0; double yac=0; v=g->g.verticies; while(v){ if(v->selected){ xac+=v->x; yac+=v->y; } v=v->next; } x = xac / sel; y = yac / sel; } while(!okflag){ okflag=1; i=0; v=g->g.verticies; while(v){ if(!sel || v->selected){ float nx = rint((v->x - x)*scale+x); float ny = rint((v->y - y)*scale+y); float m = hypot(nx - v->x,ny-v->y)/5; if(nxx-x); okflag=0; } if(nx>maxx){ scale = (float)(maxx-x) / (v->x - x); okflag=0; } if(nyy-y); okflag=0; } if(ny>maxy){ scale = (float)(maxy-y) / (v->y - y); okflag=0; } if(m<1)m=1; tx[i] = rint(nx); ty[i] = rint(ny); tm[i++] = m; }else{ tx[i] = v->x; ty[i] = v->y; tm[i++] = 0; } v=v->next; } } if(scale>=.99999 && scale<=1.00001){ ungrab_verticies(&g->g); v=g->g.verticies; while(v){ if(v->x<2 || v->x>=g->g.width-3)v->grabbed=1; if(v->y<2 || v->y>=g->g.height-3)v->grabbed=1; v=v->next; } fade_marked(g); ungrab_verticies(&g->g); }else{ animate_verticies(g,tx,ty,tm); } } static void gtk_main_quit_wrapper(Gameboard *g){ fade_cancel(g); gtk_main_quit(); } static void level_wrapper(Gameboard *g){ fade_cancel(g); level_dialog(g,0); } static void finish_wrapper(Gameboard *g){ fade_cancel(g); finish_level_dialog(g); } /* toplevel main gameboard action entry points; when a button is clicked and decoded to a specific action or a game state change triggers an action, one of the below functions is the entry point **************************************************************************************************************/ void quit_action(Gameboard *g){ pause_timer(); undeploy_buttons(g,gtk_main_quit_wrapper); } void level_action(Gameboard *g){ pause_timer(); undeploy_buttons(g,level_wrapper); } void finish_action(Gameboard *g){ if(g->g.active_intersections<=g->g.original_intersections){ pause_timer(); levelstate_finish(); undeploy_buttons(g,finish_wrapper); } } void pause_action(Gameboard *g){ pause_timer(); undeploy_buttons(g,pause_dialog); } void about_action(Gameboard *g){ pause_timer(); undeploy_buttons(g,about_dialog); } void expand_action(Gameboard *g){ scale(g,1.2); } void shrink_action(Gameboard *g){ scale(g,.8); } void set_hide_lines(Gameboard *g, int state){ g->hide_lines=state; update_full(g); } void toggle_hide_lines(Gameboard *g){ g->hide_lines= !g->hide_lines; update_full(g); } void set_show_intersections(Gameboard *g, int state){ if(g->show_intersections != state){ g->show_intersections=state; expose_full(g); } } void toggle_show_intersections(Gameboard *g){ g->show_intersections=!g->show_intersections; expose_full(g); } void reset_action(Gameboard *g){ vertex *v=g->g.verticies; int *target_x = alloca(g->g.vertex_num * sizeof(*target_x)); int *target_y = alloca(g->g.vertex_num * sizeof(*target_y)); float *target_m = alloca(g->g.vertex_num * sizeof(*target_m)); int i=0; int xd = (g->g.width-g->g.orig_width)>>1; int yd = (g->g.height-g->g.orig_height)>>1; while(v){ target_x[i]=v->orig_x+xd; target_y[i]=v->orig_y+yd; target_m[i++]=RESET_DELTA; v=v->next; } animate_verticies(g,target_x,target_y,target_m); // reset timer set_timer(0); unpause_timer(); } /***************** save/load gameboard the widget state we want to be persistent **************/ // there are only a few things; lines, intersections int gameboard_write(char *basename, Gameboard *g){ char *name; FILE *f; name=alloca(strlen(boarddir)+strlen(basename)+1); name[0]=0; strcat(name,boarddir); strcat(name,basename); f = fopen(name,"wb"); if(f==NULL){ fprintf(stderr,_("ERROR: Could not save board state for \"%s\":\n\t%s\n"), get_level_desc(),strerror(errno)); return errno; } graph_write(&g->g,f); if(g->hide_lines) fprintf(f,"hide_lines 1\n"); if(g->show_intersections) fprintf(f,"show_intersections 1\n"); fclose(f); return 0; } int gameboard_read(char *basename, Gameboard *g){ FILE *f; char *name; char *line=NULL; size_t n=0; name=alloca(strlen(boarddir)+strlen(basename)+3); name[0]=0; strcat(name,boarddir); strcat(name,basename); f = fopen(name,"rb"); if(f==NULL){ fprintf(stderr,_("ERROR: Could not read saved board state for \"%s\":\n\t%s\n"), get_level_desc(),strerror(errno)); return errno; } graph_read(&g->g,f); // get local game state while(getline(&line,&n,f)>0){ int i; if (sscanf(line,"hide_lines %d",&i)==1) if(i) g->hide_lines = 1; if (sscanf(line,"show_intersections %d",&i)==1) if(i) g->show_intersections = 1; } fclose (f); free(line); request_resize(g->g.width,g->g.height); activate_verticies(&g->g); return 0; } gplanarity-master/gameboard_logic_button.c000066400000000000000000000367231510662254600214000ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include #include #include "graph.h" #include "gameboard.h" #include "gameboard_draw_button.h" #include "main.h" /************************ manage the buttons for buttonbar and dialogs *********************/ /* determine the x/y/w/h box around the rollover text */ static GdkRectangle rollover_box(Gameboard *g, buttonstate *b){ GdkRectangle r; int width = g->g.width; int height = g->g.height; int x = b->x - b->ex.width/2 + b->ex.x_bearing -2; int y = b->y - BUTTON_RADIUS - BUTTON_TEXT_BORDER + b->ex.y_bearing -2; if(xex.width >= width - BUTTON_TEXT_BORDER) x = width - BUTTON_TEXT_BORDER - b->ex.width; if(y+b->ex.height >= height - BUTTON_TEXT_BORDER) y = height - BUTTON_TEXT_BORDER - b->ex.height; r.x=x; r.y=y; r.width=b->ex.width+5; r.height=b->ex.height+5; return r; } /* draw the actual rollover */ static void stroke_rollover(Gameboard *g, buttonstate *b, cairo_t *c){ set_font(c, BUTTON_TEXT_SIZE, 0, 1); { GdkRectangle r=rollover_box(g,b); cairo_move_to (c, r.x - b->ex.x_bearing +2, r.y -b->ex.y_bearing+2 ); cairo_set_line_width(c,3); cairo_set_source_rgba(c,1,1,1,.9); cairo_text_path (c, b->rollovertext); cairo_stroke(c); cairo_set_source_rgba(c,BUTTON_TEXT_COLOR); cairo_move_to (c, r.x - b->ex.x_bearing +2, r.y -b->ex.y_bearing+2 ); cairo_show_text (c, b->rollovertext); } } /* request an expose for a button region*/ static void invalidate_button(Gameboard *g,buttonstate *b){ GdkRectangle r; r.x=b->x-BUTTON_RADIUS-1; r.y=b->y-BUTTON_RADIUS-1; r.width=BUTTON_RADIUS*2+2; r.height=BUTTON_RADIUS*2+2; gdk_window_invalidate_rect(gtk_widget_get_window (&g->w),&r,FALSE); } /* request an expose for a rollover region*/ static void invalidate_rollover(Gameboard *g,buttonstate *b){ GdkRectangle r = rollover_box(g,b); invalidate_button(g,b); gdk_window_invalidate_rect(gtk_widget_get_window (&g->w),&r,FALSE); } /* like invalidation, but just expands a rectangular region */ static void expand_rectangle_button(buttonstate *b,GdkRectangle *r){ int x=b->x-BUTTON_RADIUS-1; int y=b->y-BUTTON_RADIUS-1; int x2=x+BUTTON_RADIUS*2+2; int y2=y+BUTTON_RADIUS*2+2; int rx2=r->x+r->width; int ry2=r->y+r->height; if(r->width==0 || r->height==0){ r->x=x; r->y=y; r->width=x2-x; r->height=y2-y; } if(xx) r->x=x; if(yy) r->y=y; if(rx2width=rx2-r->x; if(ry2height=ry2-r->y; } /* like invalidation, but just expands a rectangular region */ static void expand_rectangle_rollover(Gameboard *g,buttonstate *b,GdkRectangle *r){ GdkRectangle rr = rollover_box(g,b); int x=rr.x; int y=rr.y; int x2=x+rr.width; int y2=y+rr.height; int rx2=r->x+r->width; int ry2=r->y+r->height; if(r->width==0 || r->height==0){ r->x=x; r->y=y; r->width=x2-x; r->height=y2-y; } if(xx) r->x=x; if(yy) r->y=y; if(rx2width=rx2-r->x; if(ry2height=ry2-r->y; } /* cache buttons as small surfaces */ static cairo_surface_t *cache_button(Gameboard *g, void (*draw)(cairo_t *c, double x, double y), double pR,double pG,double pB,double pA, double fR,double fG,double fB,double fA){ cairo_t *wc = gdk_cairo_create(gtk_widget_get_window (&g->w)); cairo_surface_t *ret = cairo_surface_create_similar (cairo_get_target (wc), CAIRO_CONTENT_COLOR_ALPHA, BUTTON_RADIUS*2+1, BUTTON_RADIUS*2+1); cairo_t *c = cairo_create(ret); cairo_destroy (wc); cairo_save(c); cairo_set_operator(c,CAIRO_OPERATOR_CLEAR); cairo_set_source_rgba (c, 1,1,1,1); cairo_paint(c); cairo_restore(c); cairo_set_source_rgba(c,fR,fG,fB,fA); cairo_set_line_width(c,BUTTON_LINE_WIDTH); draw(c,BUTTON_RADIUS+.5,BUTTON_RADIUS+.5); cairo_set_source_rgba(c,pR,pG,pB,pA); cairo_stroke(c); cairo_destroy(c); return ret; } /* determine the x/y/w/h box around a button */ static GdkRectangle button_box(buttonstate *b){ GdkRectangle r; int x = b->x - BUTTON_RADIUS-1; int y = b->y - BUTTON_RADIUS-1; r.x=x; r.y=y; r.width = BUTTON_RADIUS*2+2; r.height= BUTTON_RADIUS*2+2; return r; } static int animate_x_axis(Gameboard *g, buttonstate *b, GdkRectangle *r){ int ret=0; if(b->x_target != b->x){ ret=1; expand_rectangle_button(b,r); if(b->rollover) expand_rectangle_rollover(g,b,r); if(b->x_target > b->x){ b->x+=DEPLOY_DELTA; if(b->x>b->x_target)b->x=b->x_target; }else{ b->x-=DEPLOY_DELTA; if(b->xx_target)b->x=b->x_target; } expand_rectangle_button(b,r); if(b->rollover) expand_rectangle_rollover(g,b,r); } return ret; } static int animate_y_axis(Gameboard *g, buttonstate *b, GdkRectangle *r){ int ret=0; if(b->y_target != b->y){ ret=1; expand_rectangle_button(b,r); if(b->rollover) expand_rectangle_rollover(g,b,r); if(b->y_target > b->y){ b->y+=DEPLOY_DELTA; if(b->y>b->y_target)b->y=b->y_target; }else{ b->y-=DEPLOY_DELTA; if(b->yy_target)b->y=b->y_target; } expand_rectangle_button(b,r); if(b->rollover) expand_rectangle_rollover(g,b,r); } if(b->alphad != b->y_active - b->y){ double alpha=0; if(b->y_inactive>b->y_active){ if(b->y<=b->y_active) alpha=1.; else if (b->y>=b->y_inactive) alpha=0.; else alpha = (double)(b->y_inactive-b->y)/(b->y_inactive-b->y_active); }else if (b->y_inactivey_active){ if(b->y>=b->y_active) alpha=1.; else if (b->y<=b->y_inactive) alpha=0.; else alpha = (double)(b->y_inactive-b->y)/(b->y_inactive-b->y_active); } if(alpha != b->alpha){ ret=1; expand_rectangle_button(b,r); b->alpha=alpha; } b->alphad = b->y_active - b->y; } return ret; } /* do the animation math for one button for one frame */ static int animate_one(Gameboard *g,buttonstate *b, GdkRectangle *r){ int ret=0; /* does this button need to be deployed? */ if(g->b.sweeperd>0){ if(b->y_target != b->y_active){ if(g->b.sweeper >= b->sweepdeploy){ b->y_target=b->y_active; ret=1; } } } /* does this button need to be undeployed? */ if(g->b.sweeperd<0){ if(b->y_target != b->y_inactive){ if(-g->b.sweeper >= b->sweepdeploy){ b->y_target=b->y_inactive; ret=1; } } } ret |= animate_x_axis(g,b,r); ret |= animate_y_axis(g,b,r); return ret; } /******************** toplevel abstraction calls *********************/ /* initialize the persistent caches; called once when gameboard is first created */ void init_buttons(Gameboard *g){ buttonstate *states=g->b.states; memset(g->b.states,0,sizeof(g->b.states)); states[0].idle = cache_button(g, path_button_exit, BUTTON_QUIT_IDLE_PATH, BUTTON_QUIT_IDLE_FILL); states[0].lit = cache_button(g, path_button_exit, BUTTON_QUIT_LIT_PATH, BUTTON_QUIT_LIT_FILL); states[1].idle = cache_button(g, path_button_back, BUTTON_IDLE_PATH, BUTTON_IDLE_FILL); states[1].lit = cache_button(g, path_button_back, BUTTON_LIT_PATH, BUTTON_LIT_FILL); states[2].idle = cache_button(g, path_button_reset, BUTTON_IDLE_PATH, BUTTON_IDLE_FILL); states[2].lit = cache_button(g, path_button_reset, BUTTON_LIT_PATH, BUTTON_LIT_FILL); states[3].idle = cache_button(g, path_button_pause, BUTTON_IDLE_PATH, BUTTON_IDLE_FILL); states[3].lit = cache_button(g, path_button_pause, BUTTON_LIT_PATH, BUTTON_LIT_FILL); states[4].idle = cache_button(g, path_button_help, BUTTON_IDLE_PATH, BUTTON_IDLE_FILL); states[4].lit = cache_button(g, path_button_help, BUTTON_LIT_PATH, BUTTON_LIT_FILL); states[5].idle = cache_button(g, path_button_expand, BUTTON_IDLE_PATH, BUTTON_IDLE_FILL); states[5].lit = cache_button(g, path_button_expand, BUTTON_LIT_PATH, BUTTON_LIT_FILL); states[6].idle = cache_button(g, path_button_shrink, BUTTON_IDLE_PATH, BUTTON_IDLE_FILL); states[6].lit = cache_button(g, path_button_shrink, BUTTON_LIT_PATH, BUTTON_LIT_FILL); states[7].idle = cache_button(g, path_button_lines, BUTTON_IDLE_PATH, BUTTON_IDLE_FILL); states[7].lit = cache_button(g, path_button_lines, BUTTON_LIT_PATH, BUTTON_LIT_FILL); states[8].idle = cache_button(g, path_button_int, BUTTON_IDLE_PATH, BUTTON_IDLE_FILL); states[8].lit = cache_button(g, path_button_int, BUTTON_LIT_PATH, BUTTON_LIT_FILL); states[9].idle = cache_button(g, path_button_check, BUTTON_CHECK_IDLE_PATH, BUTTON_CHECK_IDLE_FILL); states[9].lit = cache_button(g, path_button_check, BUTTON_CHECK_LIT_PATH, BUTTON_CHECK_LIT_FILL); states[10].idle= cache_button(g, path_button_play, BUTTON_CHECK_IDLE_PATH, BUTTON_CHECK_IDLE_FILL); states[10].lit = cache_button(g, path_button_play, BUTTON_CHECK_LIT_PATH, BUTTON_CHECK_LIT_FILL); } /* match x/y to a button if any */ buttonstate *find_button(Gameboard *g, int x,int y){ int i; buttonstate *states=g->b.states; for(i=0;iposition>0) if( (b->x-x)*(b->x-x) + (b->y-y)*(b->y-y) <= BUTTON_RADIUS*BUTTON_RADIUS+4) if(b->y != b->y_inactive) return b; } return 0; } /* set a button to pressed or lit */ void button_set_state(Gameboard *g, buttonstate *b, int rollover, int press){ int i; buttonstate *states=g->b.states; if(b->rollover == rollover && b->press == press)return; for(i=0;iposition>0){ if(bb!=b){ if(bb->rollover) invalidate_rollover(g,bb); if(bb->press) invalidate_button(g,bb); bb->rollover=0; bb->press=0; }else{ if(bb->rollover != rollover) invalidate_rollover(g,bb); if(bb->press != press) invalidate_button(g,bb); bb->rollover=rollover; bb->press=press; } } } g->b.allclear=0; } /* cache the text extents of a rollover */ void rollover_extents(Gameboard *g, buttonstate *b){ cairo_t *c = cairo_create(g->foreground); set_font(c, BUTTON_TEXT_SIZE, 0, 1); cairo_text_extents (c, b->rollovertext, &b->ex); cairo_destroy(c); } /* perform a single frame of animation for all buttons/rollovers */ gboolean animate_button_frame(gpointer ptr){ Gameboard *g=(Gameboard *)ptr; GdkRectangle expose; buttonstate *states=g->b.states; int ret=0,i,pos; if(!g->first_expose)return 1; g->b.sweeper += g->b.sweeperd; /* avoid the normal expose event mechanism during the button animations. This direct method is much faster as it won't accidentally combine exposes over long stretches of alpha-blended surfaces. */ for(pos=1;pos<=3;pos++){ memset(&expose,0,sizeof(expose)); for(i=0;ib.sweeperd = 0; if(!ret && g->button_timer!=0){ g_source_remove(g->button_timer); g->button_timer=0; } if(!ret && g->button_callback) // undeploy finished... call the undeploy callback g->button_callback(g); return ret; } /* the normal expose method for all buttons; called from the master widget's expose */ void expose_buttons(Gameboard *g,cairo_t *c, int x,int y,int w,int h){ int i; buttonstate *states=g->b.states; for(i=0;iposition>0){ GdkRectangle r = rollover_box(g,b); GdkRectangle br = button_box(b); if(x < br.x+br.width && y < br.y+br.height && x+w > br.x && y+h > br.y) { cairo_set_source_surface(c, (b->rollover || b->press ? b->lit : b->idle), br.x, br.y); if(b->press) cairo_paint_with_alpha(c,b->alpha); cairo_paint_with_alpha(c,b->alpha); } if((b->rollover || b->press) && b->y_target!=b->y_inactive) if(x < r.x+r.width && y < r.y+r.height && x+w > r.x && y+h > r.y) stroke_rollover(g,b,c); } } } /* resize the button bar; called from master resize in gameboard */ void resize_buttons(Gameboard *g,int oldw,int oldh,int w,int h){ int i; int dx=w/2-oldw/2; int dy=h/2-oldh/2; buttonstate *states=g->b.states; for(i=0;ib.states; if(!g->b.allclear){ for(i=0;iposition){ if(bb->rollover) invalidate_rollover(g,bb); if(bb->press) invalidate_button(g,bb); bb->rollover=0; bb->press=0; } } } g->b.allclear=1; g->b.grabbed=0; } void deploy_buttons(Gameboard *g, void (*callback)(Gameboard *g)){ if(!g->b.buttons_ready){ // sweep across the buttons inward from the horizontal edges; when // the sweep passes a button it is set to deploy by making the // target y equal to the active y target. g->b.sweeper = 0; g->b.sweeperd = 1; g->button_callback = callback; if(g->button_timer!=0) g_source_remove(g->button_timer); g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g); g->b.buttons_ready=1; } } void undeploy_buttons(Gameboard *g, void (*callback)(Gameboard *ptr)){ if(g->b.buttons_ready){ button_clear_state(g); g->b.buttons_ready=0; // sweep across the buttons outward from the center; when // the sweep passes a button it is set to undeploy by making the // target y equal to the inactive y target. g->b.sweeper = 0; g->b.sweeperd = -1; g->button_callback = callback; if(g->button_timer!=0) g_source_remove(g->button_timer); g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g); }else callback(g); } gplanarity-master/gameboard_logic_buttonbar.c000066400000000000000000000123111510662254600220500ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include #include "nls.h" #include "graph.h" #include "timer.h" #include "gameboard.h" #include "gameboard_draw_button.h" #include "gameboard_logic_buttonbar.h" #include "dialog_finish.h" #include "dialog_pause.h" #include "dialog_level.h" /************************ the lower button bar *********************/ /* initialize the rather weird little animation engine */ void setup_buttonbar(Gameboard *g){ buttonstate *states=g->b.states; int xcount=BUTTONBAR_BORDER; int dcount=0; int i; int w=g->g.width; int h=g->g.height; states[0].rollovertext=_("exit gPlanarity"); states[1].rollovertext=_("level selection menu"); states[2].rollovertext=_("reset board"); states[3].rollovertext=_("pause"); states[4].rollovertext=_("help / about"); states[5].rollovertext=_("expand"); states[6].rollovertext=_("shrink"); states[7].rollovertext=_("hide/show lines"); states[8].rollovertext=_("mark intersections"); states[9].rollovertext=_("click when finished!"); states[0].callback = quit_action; states[1].callback = level_action; states[2].callback = reset_action; states[3].callback = pause_action; states[4].callback = about_action; states[5].callback = expand_action; states[6].callback = shrink_action; states[7].callback = toggle_hide_lines; states[8].callback = toggle_show_intersections; states[9].callback = finish_action; for(i=0;iposition == 1){ b->x = b->x_target = xcount; b->y_active = h - BUTTONBAR_Y_FROM_BOTTOM; b->y = b->y_target = b->y_inactive = h - BUTTONBAR_Y_FROM_BOTTOM + BUTTON_EXPOSE; b->sweepdeploy = dcount; xcount += BUTTONBAR_SPACING; dcount += SWEEP_DELTA; rollover_extents(g,states+i); } } xcount = w-BUTTONBAR_BORDER; dcount = 0; for(i=NUMBUTTONS-1;i>=0;i--){ buttonstate *b=states+i; if(b->position == 3){ b->x = b->x_target = xcount; b->y_active = h - BUTTONBAR_Y_FROM_BOTTOM; b->y = b->y_target = b->y_inactive = h - BUTTONBAR_Y_FROM_BOTTOM + BUTTON_EXPOSE; b->sweepdeploy = dcount; if(i!=9 || g->checkbutton_deployed){ // special-case the checkbutton xcount -= BUTTONBAR_SPACING; dcount += SWEEP_DELTA; }else{ states[9].position = -3; //deactivate it for the deploy } rollover_extents(g,states+i); } } } /* effects animated 'rollout' of buttons when level begins */ void deploy_buttonbar(Gameboard *g){ if(!g->b.buttons_ready ){ if(g->g.active_intersections <= g->g.objective) g->checkbutton_deployed=1; else g->checkbutton_deployed=0; setup_buttonbar(g); deploy_buttons(g,0); } } /* effects animated rollout of 'check' button */ void deploy_check(Gameboard *g){ buttonstate *states=g->b.states; if(g->b.buttons_ready && !g->checkbutton_deployed){ int i; for(i=5;i<9;i++){ states[i].x_target-=BUTTONBAR_SPACING; states[i].sweepdeploy += SWEEP_DELTA; } states[9].position = 3; //activate it states[9].y_target = states[9].y_active; states[i].sweepdeploy = 0; if(g->button_timer!=0) g_source_remove(g->button_timer); g->button_callback=0; g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g); g->checkbutton_deployed=1; } } /* effects animated rollback of 'check' button */ void undeploy_check(Gameboard *g){ buttonstate *states=g->b.states; if(g->checkbutton_deployed){ int i; for(i=5;i<9;i++){ states[i].x_target+=BUTTONBAR_SPACING; states[i].sweepdeploy -= SWEEP_DELTA; } states[9].y_target=states[9].y_inactive; if(g->button_timer!=0) g_source_remove(g->button_timer); g->button_callback=0; g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g); g->checkbutton_deployed=0; } } gplanarity-master/gameboard_logic_buttonbar.h000066400000000000000000000027371510662254600220700ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef GAMEBOARD_LOGIC_BUTTONBAR_H #define GAMEBOARD_LOGIC_BUTTONBAR_H #define BUTTONBAR_Y_FROM_BOTTOM 25 #define BUTTONBAR_LINE_WIDTH 1 #define BUTTONBAR_TEXT_BORDER 15 #define BUTTONBAR_TEXT_COLOR .1,.1,.7,.8 #define BUTTONBAR_TEXT_SIZE 15.,18. #define BUTTONBAR_ANIM_INTERVAL 15 #define BUTTONBAR_EXPOSE 50 #define BUTTONBAR_DELTA 3 #define BUTTONBAR_LEFT 5 #define BUTTONBAR_RIGHT 5 #define BUTTONBAR_BUTTONS 5 #define BUTTONBAR_BORDER 35 #define BUTTONBAR_SPACING 35 #endif /* GAMEBOARD_LOGIC_BUTTONBAR_H */ gplanarity-master/gameboard_logic_fade.c000066400000000000000000000065711510662254600207620ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include "graph.h" #include "gameboard.h" static fade_list *pool=0; #define CHUNK 32 static void fade_add_vertex(fade_state *f,vertex *v){ fade_list *ret; if(pool==0){ int i; pool = calloc(CHUNK,sizeof(*pool)); for(i=0;inext; ret->v=v; v->fading=1; ret->next = f->head; f->head = ret; } static gint animate_fade(gpointer ptr){ Gameboard *g = (Gameboard *)ptr; fade_state *f = &g->fade; f->count--; if(f->count>0){ fade_list *l = f->head; while(l){ invalidate_vertex(g,l->v); l=l->next; } return 1; } fade_cancel(g); return 0; } void fade_cancel(Gameboard *g){ fade_state *f = &g->fade; fade_list *l = f->head; while(l){ fade_list *n = l->next; /* unflag vertex */ l->v->fading=0; /* invalidate the vertex */ invalidate_vertex(g,l->v); l->next=pool; pool=l; l=n; } f->head = 0; f->count = 0; if(f->fade_timer) g_source_remove(f->fade_timer); f->fade_timer=0; } void fade_attached(Gameboard *g,vertex *v){ fade_state *f = &g->fade; edge_list *el=v->edges; /* If a fade is already in progress, cancel it */ fade_cancel(g); while(el){ edge *e=el->edge; if(v == e->A){ fade_add_vertex(f,e->B); }else{ fade_add_vertex(f,e->A); } el=el->next; } f->count = FADE_FRAMES; f->fade_timer = g_timeout_add(FADE_ANIM_INTERVAL, animate_fade, (gpointer)g); } void fade_grabbed(Gameboard *g){ fade_state *f = &g->fade; vertex *v = g->g.verticies; /* If a fade is already in progress, cancel it */ fade_cancel(g); while(v){ if(v->grabbed){ edge_list *el=v->edges; while(el){ edge *e=el->edge; if(v == e->A){ if(!e->B->grabbed) fade_add_vertex(f,e->B); }else{ if(!e->A->grabbed) fade_add_vertex(f,e->A); } el=el->next; } } v=v->next; } f->count = FADE_FRAMES; f->fade_timer = g_timeout_add(FADE_ANIM_INTERVAL, animate_fade, (gpointer)g); } void fade_marked(Gameboard *g){ fade_state *f = &g->fade; vertex *v = g->g.verticies; /* If a fade is already in progress, cancel it */ fade_cancel(g); while(v){ if(v->grabbed) fade_add_vertex(f,v); v=v->next; } f->count = FADE_FRAMES; f->fade_timer = g_timeout_add(FADE_ANIM_INTERVAL, animate_fade, (gpointer)g); } gplanarity-master/gameboard_logic_mouse.c000066400000000000000000000234721510662254600212120ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "graph.h" #include "gameboard.h" #include "dialog_level.h" /* does the given x/y fall inside an on-screen vertex? */ static void check_lit(Gameboard *g,int x, int y){ vertex *v = find_vertex(&g->g,x,y); if(v!=g->lit_vertex){ invalidate_vertex(g,v); invalidate_vertex(g,g->lit_vertex); g->lit_vertex = v; } } /* toplevel mouse motion handler */ gint mouse_motion(GtkWidget *widget, GdkEventMotion *event){ Gameboard *g = GAMEBOARD (widget); /* the level selection dialog implements its own icon mouse management */ if(g->level_dialog_active) level_mouse_motion(g,(int)event->x,(int)event->y); /* similarly, if a vertex is grabbed, the only thing that can happen is that we're dragging that vertex */ if(g->grabbed_vertex){ int x = (int)event->x; int y = (int)event->y; g->dragx = x-g->grabx; g->dragy = y-g->graby; invalidate_vertex(g,g->grabbed_vertex); invalidate_edges(widget,g->grabbed_vertex,0,0); move_vertex(&g->g,g->grabbed_vertex,x+g->graboffx,y+g->graboffy); invalidate_vertex(g,g->grabbed_vertex); invalidate_edges(widget,g->grabbed_vertex,0,0); return TRUE; } /* if the selection is grabbed, we can only be dragging a selection box */ if (g->selection_grab){ invalidate_selection(widget); g->selectionx = min(g->grabx, event->x); g->selectionw = labs(g->grabx - event->x); g->selectiony = min(g->graby, event->y); g->selectionh = labs(g->graby - event->y); select_verticies(&g->g, g->selectionx,g->selectiony, g->selectionx+g->selectionw-1, g->selectiony+g->selectionh-1); invalidate_selection(widget); return TRUE; } /* if a selected vertex is grabbed (group drag) we're dragging the whole selection and its lines */ if(g->group_drag){ invalidate_verticies_selection(widget); g->dragx = event->x - g->grabx; g->dragy = event->y - g->graby; /* don't allow the drag to put a vertex offscreen; bound the drag at the edge */ { vertex *v=g->g.verticies; int w=g->g.width; int h=g->g.height; while(v){ if(v->selected){ if(v->x + g->dragx >= w) g->dragx=w - v->x -1; if(v->x + g->dragx < 0 ) g->dragx= -v->x; if(v->y + g->dragy >= h) g->dragy=h - v->y -1; if(v->y + g->dragy < 0 ) g->dragy= -v->y; } v=v->next; } } invalidate_verticies_selection(widget); return TRUE; } /* A vertex rollover has priority over a button rollover. However, a button grab disallows a rollover, as does the curtain. */ if(!g->pushed_curtain && !g->button_grabbed) check_lit(g, (int)event->x,(int)event->y); /* handle button rollovers and ongoing grabs; other grabs are already disallowed, but also verify a vertex rollover isn't already active (and that buttons are currently hot) */ if(!g->lit_vertex && g->b.buttons_ready){ buttonstate *b = find_button(g,(int)event->x,(int)event->y); if(g->b.grabbed){ /* a button is grabbed; a rollover sees only the grabbed button */ if(g->b.grabbed==b) button_set_state(g,b,1,1); else button_set_state(g,g->b.grabbed,0,0); }else{ /* no button is grabbed; any button may see a rollover */ if(b) button_set_state(g,b,1,0); else button_clear_state(g); } } return TRUE; } /* toplevel mouse button press handler */ gboolean mouse_press (GtkWidget *widget, GdkEventButton *event){ if(event->type == GDK_BUTTON_PRESS){ // filter out doubleclicks Gameboard *g = GAMEBOARD (widget); vertex *v = find_vertex(&g->g,(int)event->x,(int)event->y); buttonstate *b = find_button(g,(int)event->x,(int)event->y); int old_intersections = g->show_intersections; /* the level selection dialog implements its own icon mouse management */ if(g->level_dialog_active) level_mouse_press(g,(int)event->x,(int)event->y); button_clear_state(g); g->button_grabbed=0; set_show_intersections(g,0); /* presses that affect board elements other than buttons can only happen when the curtain isn't pushed. */ if(!g->pushed_curtain){ /* case: shift-click addition of a single new vertex to selection */ if(v && event->state&GDK_SHIFT_MASK){ if(v->selected){ v->selected=0; g->selection_active--; }else{ v->selected=1; g->selection_active++; } invalidate_vertex(g,g->lit_vertex); return TRUE; } /* case: shift-click drag of an additional region to add to selection */ if(event->state&GDK_SHIFT_MASK){ g->selection_grab=1; g->grabx = (int)event->x; g->graby = (int)event->y; g->selectionx = g->grabx; g->selectionw = 0; g->selectiony = g->graby; g->selectionh = 0; return TRUE; } /* case: drag the selected group of verticies to new location */ if(g->selection_active && v && v->selected){ g->group_drag=1; g->grabx = (int)event->x; g->graby = (int)event->y; g->dragx = 0; g->dragy = 0; // highlight vertex immediately; update the background after the // vertex change grab_selected(&g->g); invalidate_verticies_selection(widget); fade_cancel(g); update_full_delayed(g); return TRUE; } /* if selection is active, we got this far, and we're not about to take action based on pointing at a button, selection should be inactivated */ if(g->selection_active && (g->lit_vertex || !b)){ deselect_verticies(&g->g); g->selection_active=0; g->group_drag=0; // potentially pull verticies out of background (can happen if // mouse went offscreen during a grab) update_full(g); } /* case: grab/drag a single unselected vertex */ if(g->lit_vertex){ g->grabbed_vertex = g->lit_vertex; g->grabx = (int)event->x; g->graby = (int)event->y; g->graboffx = g->grabbed_vertex->x-g->grabx; g->graboffy = g->grabbed_vertex->y-g->graby; grab_vertex(&g->g,g->grabbed_vertex); invalidate_attached(widget,g->grabbed_vertex); invalidate_edges(widget,g->grabbed_vertex,0,0); fade_cancel(g); // highlight vertex immediately; update the background after the // vertex change update_full_delayed(g); return TRUE; } } /* case: button click */ if(b){ // if intersections were visible, a button press is the only // click that wouldn't auto-hide them, so restore the flag to // its state before entry. g->show_intersections=old_intersections; button_set_state(g,b,1,1); g->b.grabbed = b; return TRUE; } /* clicking anywhere else wtith no modifiers initiates a new selection drag (assuming curtain isn't pushed) */ if(!g->pushed_curtain){ g->selection_grab=1; g->grabx = (int)event->x; g->graby = (int)event->y; g->selectionx = g->grabx; g->selectionw = 0; g->selectiony = g->graby; g->selectionh = 0; return TRUE; } } return TRUE; } /* toplevel mouse button release handler */ gboolean mouse_release (GtkWidget *widget, GdkEventButton *event){ Gameboard *g = GAMEBOARD (widget); /* case: button grabbed */ if(g->b.grabbed){ buttonstate *b = find_button(g,(int)event->x,(int)event->y); if(b && g->b.grabbed==b){ button_set_state(g,b,1,0); if(b->callback) b->callback(g); } g->b.grabbed=0; } /* if the curtain is pushed, no sense checking for other grabs */ if(!g->pushed_curtain){ /* case: release a grabbed vertex */ if(g->grabbed_vertex){ ungrab_vertex(&g->g,g->grabbed_vertex); update_add_vertex(g,g->grabbed_vertex); fade_attached(g,g->grabbed_vertex); update_score(g); g->grabbed_vertex = 0; if(g->g.active_intersections<=g->g.objective) deploy_check(g); else undeploy_check(g); } /* case: release a selection grab */ if(g->selection_grab){ invalidate_selection(widget); g->selection_grab=0; /* are there selected verticies? If only one was selected, that's usually due to an accidental drag while clicking. Treat a single-vertex drag select as a nil selection */ if(num_selected_verticies(&g->g)<=1){ g->selection_active=0; deselect_verticies(&g->g); // could have grabbed just one }else{ commit_volatile_selection(&g->g); g->selection_active=num_selected_verticies(&g->g); } } /* case: release a group drag */ if(g->group_drag){ move_selected_verticies(&g->g,g->dragx,g->dragy); fade_grabbed(g); update_add_selgroup(g); ungrab_verticies(&g->g); update_score(g); g->group_drag=0; if(g->g.active_intersections<=g->g.objective) deploy_check(g); else undeploy_check(g); } } /* a release may result in a new mouse-over; look for it */ mouse_motion(widget,(GdkEventMotion *)event); // the cast is safe in this case return TRUE; } gplanarity-master/gameboard_logic_push.c000066400000000000000000000043051510662254600210330ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "graph.h" #include "gameboard.h" void update_push(Gameboard *g, cairo_t *c){ if(g->pushed_curtain){ int w = g->g.width; int h = g->g.height; draw_foreground(g,c,0,0,w,h); // copy in the score and button surfaces cairo_set_source_surface(c,g->forescore,0,0); cairo_rectangle(c, 0,0,w, min(SCOREHEIGHT,h)); cairo_fill(c); cairo_set_source_surface(c,g->forebutton,0,h-SCOREHEIGHT); cairo_rectangle(c, 0,0,w,h); cairo_fill(c); if(g->show_intersections) draw_intersections(g,&g->g,c,0,0,w,h); cairo_set_source (c, g->curtainp); cairo_paint(c); if(g->redraw_callback)g->redraw_callback(g); } } void push_curtain(Gameboard *g,void(*redraw_callback)(Gameboard *g)){ if(!g->pushed_curtain){ cairo_t *c = cairo_create(g->background); g->pushed_curtain=1; g->redraw_callback=redraw_callback; update_push(g,c); cairo_destroy(c); expose_full(g); //gameboard_draw(g,0,0,w,h); } } void pop_curtain(Gameboard *g){ if(g->pushed_curtain){ g->pushed_curtain=0; update_full(g); } } gplanarity-master/graph.c000066400000000000000000000453411510662254600160040ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include "nls.h" #include "graph.h" #include "random.h" #include "timer.h" #include "gameboard.h" #define CHUNK 64 static vertex *vertex_pool=0; static edge *edge_pool=0; static edge_list *edge_list_pool=0; static intersection *intersection_pool=0; /* mesh/board state */ /************************ edge list maint operations ********************/ edge_list *add_edge_to_list(edge_list *l, edge *e){ edge_list *ret; if(edge_list_pool==0){ int i; edge_list_pool = calloc(CHUNK,sizeof(*edge_list_pool)); for(i=0;inext; ret->edge=e; ret->next=l; return ret; } /* releases the edge list but not the edges */ void release_edge_list(edge_list *el){ if(el){ edge_list *end=el; while(end->next)end=end->next; end->next = edge_list_pool; edge_list_pool = el; } } /* releases the edge list but not the edges */ static void release_vertex_edge_list(vertex *v){ edge_list *el = v->edges; release_edge_list(el); v->edges=0; } /************************ intersection maint operations ********************/ static intersection *new_intersection(){ intersection *ret; if(intersection_pool==0){ int i; intersection_pool = calloc(CHUNK,sizeof(*intersection_pool)); for(i=0;inext; return ret; } static void add_paired_intersection(edge *a, edge *b, double x, double y){ intersection *A=new_intersection(); intersection *B=new_intersection(); A->paired=B; B->paired=A; A->next=a->i.next; if(A->next) A->next->prev=A; A->prev=&(a->i); a->i.next=A; B->next=b->i.next; if(B->next) B->next->prev=B; B->prev=&(b->i); b->i.next=B; A->x=B->x=x; A->y=B->y=y; } static void release_intersection(intersection *i){ memset(i,0,sizeof(*i)); i->next=intersection_pool; intersection_pool=i; } static void release_intersection_list(edge *e){ intersection *i=e->i.next; while(i!=0){ intersection *next=i->next; release_intersection(i); i=next; } e->i.next=0; } static int release_paired_intersection_list(edge *e){ intersection *i=e->i.next; int count=0; while(i){ intersection *next=i->next; intersection *j=i->paired; j->prev->next=j->next; if(j->next) j->next->prev=j->prev; release_intersection(i); release_intersection(j); i=next; count++; } e->i.next=0; return count; } /************************ edge maint operations ******************************/ edge *new_edge(vertex *A, vertex *B){ edge *ret; if(edge_pool==0){ int i; edge_pool = calloc(CHUNK,sizeof(*edge_pool)); for(i=0;inext; ret->A=A; ret->B=B; ret->active=0; ret->i.next=0; return ret; } /* makes a new egde and adds it to the vertex and graph edge lists */ edge *add_edge(graph *g, vertex *A, vertex *B){ edge *ret = new_edge(A,B); ret->next=g->edges; g->edges=ret; A->edges=add_edge_to_list(A->edges,ret); B->edges=add_edge_to_list(B->edges,ret); g->num_edges++; return ret; } /* adds existing edge to the vertex and graph edge lists, but only if it's not already there */ void insert_edge(graph *g, edge *e){ vertex *A = e->A; vertex *B = e->B; if(exists_edge(A,B)){ // already a matching edge; release this one release_intersection_list(e); e->next=edge_pool; edge_pool=e; }else{ e->next=g->edges; g->edges=e; A->edges=add_edge_to_list(A->edges,e); B->edges=add_edge_to_list(B->edges,e); g->num_edges++; } } static void release_edges(graph *g){ edge *e = g->edges; while(e){ edge *next=e->next; release_intersection_list(e); e->next=edge_pool; edge_pool=e; e=next; } g->edges=0; g->num_edges=0; g->num_edges_active=0; } int intersectsV(vertex *L1, vertex *L2, vertex *M1, vertex *M2, double *xo, double *yo){ // edges that share a vertex don't intersect by definition if(L1==M1) return 0; if(L1==M2) return 0; if(L2==M1) return 0; if(L2==M2) return 0; return intersects(L1->x,L1->y,L2->x,L2->y,M1->x,M1->y,M2->x,M2->y,xo,yo); } int intersects(int L1x, int L1y, int L2x, int L2y, int M1x, int M1y, int M2x, int M2y, double *xo, double *yo){ /* y = ax + b */ float La=0; float Lb=0; float Ma=0; float Mb=0; if(L1x != L2x){ La = (float)(L2y - L1y) / (L2x - L1x); Lb = (L1y - L1x * La); } if(M1x != M2x){ Ma = (float)(M2y - M1y) / (M2x - M1x); Mb = (M1y - M1x * Ma); } if(L1x == L2x){ // L is vertical line if(M1x == M2x){ // M is also a vertical line if(L1x == M1x){ // L and M vertical on same x, overlap? if(M1y > L1y && M1y > L2y && M2y > L1y && M2y > L2y) return 0; if(M1y < L1y && M1y < L2y && M2y < L1y && M2y < L2y) return 0; { double y1=max( min(M1y,M2y), min(L1y, L2y)); double y2=min( max(M1y,M2y), max(L1y, L2y)); *xo = M1x; *yo = (y1+y2)*.5; } }else // L and M vertical, different x return 0; }else{ // L vertical, M not vertical // needed if L is vertical and M is horizontal if(L1x < M1x && L1x < M2x) return 0; if(L1x > M1x && L1x > M2x) return 0; { float y = Ma*L1x + Mb; if(y < L1y && y < L2y) return 0; if(y > L1y && y > L2y) return 0; if(y < M1y && y < M2y) return 0; if(y > M1y && y > M2y) return 0; *xo = L1x; *yo=y; } } }else{ if(M1x == M2x){ // M vertical, L not vertical // needed if L is vertical and M is horizontal if(M1x < L1x && M1x < L2x) return 0; if(M1x > L1x && M1x > L2x) return 0; { float y = La*M1x + Lb; if(y < L1y && y < L2y) return 0; if(y > L1y && y > L2y) return 0; if(y < M1y && y < M2y) return 0; if(y > M1y && y > M2y) return 0; *xo = M1x; *yo=y; } }else{ // L and M both have non-infinite slope if(La == Ma){ //L and M have the same slope if(Mb != Lb) return 0; // two segments on same line... if(M1x > L1x && M1x > L2x && M2x > L1x && M2x > L2x) return 0; if(M1x < L1x && M1x < L2x && M2x < L1x && M2x < L2x) return 0; { double x1=max( min(M1x,M2x), min(L1x, L2x)); double x2=min( max(M1x,M2x), max(L1x, L2x)); double y1=max( min(M1y,M2y), min(L1y, L2y)); double y2=min( max(M1y,M2y), max(L1y, L2y)); *xo = (x1+x2)*.5; *yo = (y1+y2)*.5; } }else{ // finally typical case: L and M have different non-infinite slopes float x = (Mb-Lb) / (La - Ma); if(x < L1x && x < L2x) return 0; if(x > L1x && x > L2x) return 0; if(x < M1x && x < M2x) return 0; if(x > M1x && x > M2x) return 0; *xo = x; *yo = La*x + Lb; } } } return 1; } static void activate_edge(graph *g, edge *e){ /* computes all intersections */ if(!e->active && e->A->active && e->B->active){ edge *test=g->edges; while(test){ if(test != e && test->active){ double x,y; if(intersectsV(e->A,e->B,test->A,test->B,&x,&y)){ add_paired_intersection(e,test,x,y); g->active_intersections++; } } test=test->next; } e->active=1; g->num_edges_active++; if(g->num_edges_active == g->num_edges && g->original_intersections==0) g->original_intersections = g->active_intersections; } } static void deactivate_edge(graph *g, edge *e){ /* releases all associated intersections */ if(e->active){ g->active_intersections -= release_paired_intersection_list(e); g->num_edges_active--; e->active=0; } } int exists_edge(vertex *a, vertex *b){ edge_list *el=a->edges; while(el){ if(el->edge->A == b) return 1; if(el->edge->B == b) return 1; el=el->next; } return 0; } /*********************** vertex maint operations *************************/ static vertex *get_vertex(graph *g){ vertex *ret; if(vertex_pool==0){ int i; vertex_pool = calloc(CHUNK,sizeof(*vertex_pool)); for(i=0;inext; ret->x=0; ret->y=0; ret->active=0; ret->selected=0; ret->selected_volatile=0; ret->grabbed=0; ret->attached_to_grabbed=0; ret->fading=0; ret->edges=0; ret->num=g->vertex_num++; ret->next=g->verticies; g->verticies=ret; return ret; } static void release_vertex(vertex *v){ release_vertex_edge_list(v); v->next=vertex_pool; vertex_pool=v; } static void set_num_verticies(graph *g, int num){ /* do it the simple way; release all, link anew */ vertex *v=g->verticies; while(v){ vertex *next=v->next; release_vertex(v); v=next; } g->verticies=0; g->vertex_num=0; release_edges(g); while(num--) get_vertex(g); g->original_intersections = 0; g->active_intersections = 0; g->num_edges=0; // hopefully redundant g->num_edges_active=0; // hopefully redundant } void graph_release(graph *g){ set_num_verticies(g,0); } void activate_vertex(graph *g,vertex *v){ edge_list *el=v->edges; v->active=1; while(el){ activate_edge(g,el->edge); el=el->next; } } void deactivate_vertex(graph *g, vertex *v){ edge_list *el=v->edges; while(el){ edge_list *next=el->next; deactivate_edge(g,el->edge); el=next; } v->active=0; } void activate_verticies(graph *g){ vertex *v=g->verticies; while(v){ activate_vertex(g,v); v=v->next; } } void grab_vertex(graph *g, vertex *v){ edge_list *el=v->edges; deactivate_vertex(g,v); while(el){ edge_list *next=el->next; edge *e=el->edge; vertex *other=(e->A==v?e->B:e->A); other->attached_to_grabbed=1; el=next; } v->grabbed=1; } void grab_selected(graph *g){ vertex *v = g->verticies; while(v){ if(v->selected){ edge_list *el=v->edges; deactivate_vertex(g,v); while(el){ edge_list *next=el->next; edge *e=el->edge; vertex *other=(e->A==v?e->B:e->A); other->attached_to_grabbed=1; el=next; } v->grabbed=1; } v=v->next; } } void ungrab_vertex(graph *g,vertex *v){ edge_list *el=v->edges; activate_vertex(g,v); while(el){ edge_list *next=el->next; edge *e=el->edge; vertex *other=(e->A==v?e->B:e->A); other->attached_to_grabbed=0; el=next; } v->grabbed=0; } void ungrab_verticies(graph *g){ vertex *v = g->verticies; while(v){ if(v->grabbed){ edge_list *el=v->edges; activate_vertex(g,v); while(el){ edge_list *next=el->next; edge *e=el->edge; vertex *other=(e->A==v?e->B:e->A); other->attached_to_grabbed=0; el=next; } v->grabbed=0; } v=v->next; } } vertex *find_vertex(graph *g, int x, int y){ vertex *v = g->verticies; vertex *match = 0; while(v){ vertex *next=v->next; int xd=x-v->x; int yd=y-v->y; if(xd*xd + yd*yd <= V_RADIUS_SQ) match=v; v=next; } return match; } // tenative selection; must be confirmed if next call should not clear void select_verticies(graph *g,int x1, int y1, int x2, int y2){ vertex *v = g->verticies; if(x1>x2){ int temp=x1; x1=x2; x2=temp; } if(y1>y2){ int temp=y1; y1=y2; y2=temp; } x1-=V_RADIUS; x2+=V_RADIUS; y1-=V_RADIUS; y2+=V_RADIUS; while(v){ if(v->selected_volatile)v->selected=0; if(!v->selected){ if(v->x>=x1 && v->x<=x2 && v->y>=y1 && v->y<=y2){ v->selected=1; v->selected_volatile=1; } } v=v->next; } } int num_selected_verticies(graph *g){ vertex *v = g->verticies; int count=0; while(v){ if(v->selected)count++; v=v->next; } return count; } void deselect_verticies(graph *g){ vertex *v = g->verticies; while(v){ v->selected=0; v->selected_volatile=0; v=v->next; } } void commit_volatile_selection(graph *g){ vertex *v = g->verticies; while(v){ v->selected_volatile=0; v=v->next; } } static vertex *split_vertex_list(vertex *v){ vertex *half=v; vertex *prevhalf=v; while(v){ v=v->next; if(v)v=v->next; prevhalf=half; half=half->next; } prevhalf->next=0; return half; } static vertex *randomize_helper(vertex *v){ vertex *w=split_vertex_list(v); if(w){ vertex *a = randomize_helper(v); vertex *b = randomize_helper(w); v=0; w=0; while(a && b){ if(random_yes(64)&1){ // pull off head of a if(w) w=w->next=a; else v=w=a; a=a->next; }else{ // pull off head of b if(w) w=w->next=b; else v=w=b; b=b->next; } } if(a) w->next=a; if(b) w->next=b; } return v; } void randomize_verticies(graph *g){ g->verticies=randomize_helper(g->verticies); } static void check_vertex_helper(graph *g, vertex *v, int reactivate){ int flag=0; if(v->x>=g->width){ v->x=g->width-1; flag=1; } if(v->x<0){ v->x=0; flag=1; } if(v->y>=g->height){ v->y=g->height-1; flag=0; } if(v->y<0){ v->y=0; flag=1; } if(flag){ if(v->edges){ deactivate_vertex(g,v); if(reactivate)activate_vertex(g,v); } } } static void check_vertex(graph *g, vertex *v){ check_vertex_helper(g,v,1); } void check_verticies(graph *g){ vertex *v=g->verticies; while(v){ vertex *next=v->next; check_vertex_helper(g,v,0); v=next; } v=g->verticies; while(v){ vertex *next=v->next; activate_vertex(g,v); v=next; } } void move_vertex(graph *g, vertex *v, int x, int y){ if(!v->grabbed) deactivate_vertex(g,v); v->x=x; v->y=y; check_vertex_helper(g,v,0); if(!v->grabbed) activate_vertex(g,v); } void move_selected_verticies(graph *g,int dx, int dy){ vertex *v = g->verticies; /* move selected verticies; do not reactivate, done during ungrab */ v=g->verticies; while(v){ vertex *next=v->next; if(v->selected){ v->x+=dx; v->y+=dy; check_vertex(g,v); //activate_vertex(g,v); } v=next; } } void scale_verticies(graph *g,float amount){ vertex *v=g->verticies; int x=g->width/2; int y=g->height/2; while(v){ vertex *next=v->next; deactivate_vertex(g,v); v->x=rint((v->x-x)*amount)+x; v->y=rint((v->y-y)*amount)+y; v=next; } v=g->verticies; while(v){ vertex *next=v->next; check_vertex(g,v); activate_vertex(g,v); v=next; } } vertex *new_board(graph *g, int num_v){ set_num_verticies(g,num_v); return g->verticies; } // take the mesh, which is always generated for a 'normal sized' board // (right now, 800x600), set the original vertex coordinates to the // 'nominal' board, and move the 'live' vertex positions to be // centered on what the current board size is. void impress_location(graph *g){ int xd = (g->width-g->orig_width)>>1; int yd = (g->height-g->orig_height)>>1; vertex *v=g->verticies; while(v){ v->orig_x=v->x; v->orig_y=v->y; v->x+=xd; v->y+=yd; v=v->next; } } /******** read/write board **********/ int graph_write(graph *g, FILE *f){ int i; vertex *v=g->verticies; edge *e=g->edges; vertex **flat = alloca(g->vertex_num*sizeof(*flat)); int *iflat = alloca(g->vertex_num*sizeof(*iflat)); i=0; while(v){ flat[v->num]=v; iflat[v->num]=i++; v=v->next; } fprintf(f,"scoring %ld %f %f %ld %c %d\n", g->original_intersections, g->intersection_mult, g->objective_mult, (long)get_timer(), (g->objective_lessthan?'*':'='),g->objective); fprintf(f,"board %d %d %d %d\n", g->width,g->height,g->orig_width,g->orig_height); v=g->verticies; while(v){ fprintf(f,"vertex %d %d %d %d %d\n", v->orig_x,v->orig_y,v->x,v->y,v->selected); v=v->next; } while(e){ fprintf(f,"edge %d %d\n",iflat[e->A->num],iflat[e->B->num]); e=e->next; } return 0; } int graph_read(graph *g,FILE *f){ char *line=NULL,c; int x,y,ox,oy,sel,A,B; size_t n=0; vertex **flat,*v; long l; new_board(g,0); // get all verticies / scoring first while(getline(&line,&n,f)>0){ if(sscanf(line,"vertex %d %d %d %d %d", &ox,&oy,&x,&y,&sel)==5){ v=get_vertex(g); v->orig_x=ox; v->orig_y=oy; v->x=x; v->y=y; v->selected=sel; } if(sscanf(line,"scoring %ld %f %f %ld %c %d\n", &g->original_intersections, &g->intersection_mult, &g->objective_mult, &l, &c,&g->objective)==6){ pause_timer(); set_timer(l); if(c == '*') g->objective_lessthan = 1; else g->objective_lessthan = 0; } sscanf(line,"board %d %d %d %d",&g->width,&g->height,&g->orig_width,&g->orig_height); } rewind(f); flat=alloca(g->vertex_num*sizeof(*flat)); v=g->verticies; while(v){ flat[v->num]=v; v=v->next; } // get edges next while(getline(&line,&n,f)>0){ if(sscanf(line,"edge %d %d",&A,&B)==2){ if(A>=0 && Avertex_num && B>=0 && Bvertex_num) add_edge(g,flat[A],flat[B]); else fprintf(stderr,_("WARNING: edge references out of range vertex in save file\n")); } sscanf(line,"int %ld",&g->original_intersections); } rewind(f); free(line); return 0; } void graph_resize(graph *g, int width, int height){ vertex *v=g->verticies; edge *e=g->edges; int xd=(width-g->width)*.5; int yd=(height-g->height)*.5; // recenter all the verticies; doesn't require recomputation while(v){ v->x+=xd; v->y+=yd; v=v->next; } // recenter associated intersections as well; they all have // cached location (used only for drawing) while(e){ intersection *i = e->i.next; while(i){ if(i->paired > i){ i->x+=xd; i->y+=yd; } i=i->next; } e=e->next; } g->width=width; g->height=height; // verify all verticies are onscreen check_verticies(g); } gplanarity-master/graph.h000066400000000000000000000102411510662254600160000ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef GRAPH_H #define GRAPH_H #define V_RADIUS_SQ (V_RADIUS*V_RADIUS) #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) typedef struct vertex { int num; int x; int y; int orig_x; int orig_y; int active; int selected_volatile; int selected; int grabbed; int attached_to_grabbed; int fading; struct edge_list *edges; struct vertex *next; } vertex; typedef struct intersection { struct intersection *prev; struct intersection *next; struct intersection *paired; double x; double y; } intersection; typedef struct edge{ vertex *A; vertex *B; int active; intersection i; // correct, not a pointer struct edge *next; } edge; typedef struct edge_list{ edge *edge; struct edge_list *next; } edge_list; typedef struct graph { vertex *verticies; int vertex_num; edge *edges; long active_intersections; int num_edges; int num_edges_active; int width; int height; int orig_width; int orig_height; // scoring related metadata long original_intersections; float intersection_mult; int objective; int objective_lessthan; float objective_mult; } graph; typedef struct graphmeta{ int num; char *id; char *desc; void (*gen)(graph *,int arg); int gen_arg; int unlock_plus; } graphmeta; #include extern vertex *new_board(graph *g, int num_v); extern vertex *find_vertex(graph *g, int x, int y); extern edge_list *add_edge_to_list(edge_list *l, edge *e); extern void release_edge_list(edge_list *el); extern edge *new_edge(vertex *A, vertex *B); extern void release_edge_list(edge_list *el); extern void insert_edge(graph *g, edge *e); extern int intersectsV(vertex *L1, vertex *L2, vertex *M1, vertex *M2, double *xo, double *yo); extern int intersects(int L1x, int L1y, int L2x, int L2y, int M1x, int M1y, int M2x, int M2y, double *xo, double *yo); extern void move_vertex(graph *g, vertex *v, int x, int y); extern void grab_vertex(graph *g, vertex *v); extern void grab_selected(graph *g); extern void ungrab_vertex(graph *g,vertex *v); extern void ungrab_verticies(graph *g); extern void activate_vertex(graph *g, vertex *v); extern void deactivate_vertex(graph *g, vertex *v); extern void select_verticies(graph *g, int x1, int y1, int x2, int y2); extern void deselect_verticies(graph *g); extern void move_selected_verticies(graph *g, int dx, int dy); extern void scale_verticies(graph *g, float amount); extern void randomize_verticies(graph *g); extern edge *add_edge(graph *g,vertex *A, vertex *B); extern int exists_edge(vertex *a, vertex *b); extern int num_selected_verticies(graph *g); extern void check_verticies(graph *g); extern void impress_location(graph *g); extern void commit_volatile_selection(graph *g); extern void activate_verticies(graph *g); extern int graph_write(graph *g, FILE *f); extern int graph_read(graph *g, FILE *f); extern void graph_release(graph *g); extern int graphscore_get_score(graph *g); extern int graphscore_get_raw_score(graph *g); extern int graphscore_get_multiplier_percent(graph *g); extern int graphscore_get_bonus(graph *g); extern char *graphscore_objective_string(graph *g); extern void graph_resize(graph *g, int width, int height); #endif /* GRAPH_H */ gplanarity-master/graph_arrange.c000066400000000000000000000234051510662254600175000ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include "graph.h" #include "random.h" #include "gameboard.h" #include "graph_arrange.h" #include "graph_region.h" void arrange_verticies_circle(graph *g, float off1, float off2){ vertex *v = g->verticies; int n = g->vertex_num; int bw=g->orig_width; int bh=g->orig_height; int radius=min(bw,bh)*.45; int i; for(i=0;ix = rint( radius * sin( i*M_PI*2./n +off1) + (bw>>1)); v->y = rint( radius * -cos( i*M_PI*2./n +off2) + (bh>>1)); v=v->next; } } void arrange_verticies_polygon(graph *g, int sides, float angle, float rad, int xoff, int yoff, float xstretch, float ystretch){ vertex *v = g->verticies; int n = g->vertex_num; int bw=g->orig_width; int bh=g->orig_height; int radius=min(bw,bh)*rad*.45; float perleg=0,del=0,acc=0; int i; for(i=0;ix = rint(((xA + xD*acc) - bw/2) * xstretch + bw/2); v->y = rint(((yA + yD*acc) - bh/2) * ystretch + bh/2); v=v->next; acc+=del; } acc-=perleg; } } void arrange_verticies_polycircle(graph *g, int sides, float angle, float split, int radplus,int xoff,int yoff){ vertex *v = g->verticies; int n = g->vertex_num; int bw=g->orig_width; int bh=g->orig_height; int radius=min(bw,bh)*.45+radplus; float perleg=0,perarc=0,del,acc=0; int i; for(i=0;ix = rint( sin(ang0 + aD*acc)*radius+bw/2)+xoff; v->y = rint(-cos(ang0 + aD*acc)*radius+bh/2)+yoff; v=v->next; acc+=del; } acc-=perarc/2; // populate the line segment xD = (xB-xA) / perleg; yD = (yB-yA) / perleg; while(v && acc<=perleg){ v->x = rint(xA + xD*acc)+xoff; v->y = rint(yA + yD*acc)+yoff; v=v->next; acc+=del; } acc-=perleg; // populate the second arc segment while(v && acc<=perarc/2){ v->x = rint( sin(ang2 + aD*acc)*radius+bw/2)+xoff; v->y = rint(-cos(ang2 + aD*acc)*radius+bh/2)+yoff; v=v->next; acc+=del; } acc-=perarc/2; } } void arrange_verticies_mesh(graph *g, int width, int height){ vertex *v = g->verticies; int bw=g->orig_width; int bh=g->orig_height; int spacing=min((float)bw/width,(float)bh/height)*.9; int x,y; int xpad=(bw - (width-1)*spacing)/2; int ypad=(bh - (height-1)*spacing)/2; for(y=0;yx=x*spacing+xpad; v->y=y*spacing+ypad; v=v->next; } } } void arrange_verticies_nastymesh(graph *g, int w, int h, vertex **flat){ int A = 0; int B = w-1; int i; arrange_verticies_mesh(g,w,h); while(Ay-=10; flat[B+i]->y-=10; flat[i+(h-1)*w]->y+=10; flat[B+i+(h-1)*w]->y+=10; } A++; B--; } A = 0; B = (h-1)*w; while(Ax-=10; flat[B+i]->x-=10; flat[i +(w-1)]->x+=10; flat[B+i+(w-1)]->x+=10; } A+=w; B-=w; } } void arrange_region_star(graph *g){ region_init(); region_new_area(400,45,1); region_line_to(340,232); region_line_to(143,232); region_line_to(303,347); region_line_to(241,533); region_line_to(400,417); region_line_to(559,533); region_line_to(497,347); region_line_to(657,232); region_line_to(460,232); region_close_line(); } void arrange_region_rainbow(graph *g){ region_init(); region_new_area(40,500,2); region_arc_to(760,500,-M_PI); region_line_to(660,500); region_arc_to(200,500,M_PI); region_close_line(); } void arrange_region_dashed_circle(graph *g){ int bw=g->orig_width; int bh=g->orig_height; int radius=min(bw,bh)*.45; int i; region_init(); for(i=0;i<20;i+=2){ float phi0=(M_PI*2.f/20*(i-.5)); float phi1=(M_PI*2.f/20*(i+.5)); int x1= cos(phi0)*radius+bw/2; int y1= -sin(phi0)*radius+bh/2; int x2= cos(phi1)*radius+bw/2; int y2= -sin(phi1)*radius+bh/2; region_new_area(x1,y1,3); region_arc_to(x2,y2,M_PI/10); } } void arrange_region_bifur(graph *g){ int bw=g->orig_width; int bh=g->orig_height; region_init(); region_new_area(21,60,2); region_line_to(bw/2-130,60); region_arc_to(bw/2+130,60,-M_PI*.25); region_line_to(bw-21,60); region_new_area(21,bh-60,1); region_line_to(bw/2-130,bh-60); region_arc_to(bw/2+130,bh-60,M_PI*.25); region_line_to(bw-21,bh-60); } void arrange_region_dairyqueen(graph *g){ int bw=g->orig_width; int bh=g->orig_height; int radius=min(bw,bh)*.45; float phi0=(M_PI/2 + M_PI*2.f/8); float phi1=(M_PI/2 - M_PI*2.f/8); int x1= cos(phi0)*radius+bw/2; int x2= cos(phi1)*radius+bw/2; int y1= -sin(phi0)*radius+bh/2; int y2= sin(phi0)*radius+bh/2; region_init(); region_new_area(x1,y1,2); region_arc_to(x2,y1,-M_PI/2); region_line_to(750,bh/2); region_line_to(x2,y2); region_arc_to(x1,y2,-M_PI/2); region_line_to(50,bh/2); region_close_line(); } void arrange_region_cloud(graph *g){ int bw=g->orig_width; int bh=g->orig_height; int radius=min(bw,bh)*.45-20; int i=0; float phi0=(M_PI*2.f/20*(i-.5)),phi1; int x1= cos(phi0)*radius+bw/2,x2; int y1= -sin(phi0)*radius+bh/2,y2; region_init(); region_new_area(x1,y1,1); for(i=0;i<19;i++){ phi1=(M_PI*2.f/20*(i+.5)); x2= cos(phi1)*radius+bw/2; y2= -sin(phi1)*radius+bh/2; region_arc_to(x2,y2,M_PI*.7); } region_close_arc(M_PI*.7); } void arrange_region_ring(graph *g){ int bw=g->orig_width; int bh=g->orig_height; int radius=min(bw,bh)*.45; region_init(); region_circle(bw/2,bh/2,radius,3); region_circle(bw/2,bh/2,radius*.4,1); } void arrange_region_storm(graph *g){ int bw=g->orig_width; int bh=g->orig_height; int radius=min(bw,bh)*.45; int i=0; region_init(); for(i=0;i<10;i++){ float phi0=(M_PI*2.f/10*(i-.5)); float phi1=(M_PI*2.f/10*(i+.5)); int x1= cos(phi0)*radius+bw/2; int y1= -sin(phi0)*radius+bh/2; int x2= cos(phi1)*radius*.8+bw/2; int y2= -sin(phi1)*radius*.8+bh/2; region_new_area(x1,y1,1); region_arc_to(x2,y2,M_PI*.2); } region_circle(bw/2,bh/2,radius*.2,0); } void arrange_region_target(graph *g){ int bw=g->orig_width; int bh=g->orig_height; int radius=min(bw,bh)*.45; region_init(); region_circle(bw/2,bh/2,radius,3); region_circle(bw/2,bh/2,radius*.5,1); region_split_here(); region_circle(bw/2,bh/2,radius*.35,3); } void arrange_region_plus(graph *g){ region_init(); region_new_area(316,43,2); region_arc_to(483,43,-M_PI*2/10); region_line_to(483,216); region_line_to(656,216); region_arc_to(656,384,-M_PI*2/10); region_line_to(483,384); region_line_to(483,556); region_arc_to(316,556,-M_PI*2/10); region_line_to(316,384); region_line_to(143,384); region_arc_to(143,216,-M_PI*2/10); region_line_to(316,216); region_close_line(); } void arrange_region_hole3(graph *g){ int bw=g->orig_width; int bh=g->orig_height; int radius=min(bw,bh)*.45; region_init(); region_circle(bw/2,bh/2,radius,3); region_new_area(400,200,2); region_line_to(313,349); region_line_to(487,349); region_close_line(); } void arrange_region_hole4(graph *g){ int bw=g->orig_width; int bh=g->orig_height; int radius=min(bw,bh)*.45; region_init(); region_circle(bw/2,bh/2,radius,3); region_new_area(325,225,1); region_line_to(475,225); region_line_to(475,375); region_line_to(325,375); region_close_line(); } void arrange_region_ovals(graph *g){ region_init(); region_new_area(270,163,2); region_arc_to(530,163,-M_PI*.99); region_line_to(530,437); region_arc_to(270,437,-M_PI*.99); region_close_line(); region_split_here(); region_new_area(80,263,2); region_arc_to(230,263,-M_PI*.99); region_line_to(230,337); region_arc_to(80,337,-M_PI*.99); region_close_line(); region_split_here(); region_new_area(570,263,2); region_arc_to(720,263,-M_PI*.99); region_line_to(720,337); region_arc_to(570,337,-M_PI*.99); region_close_line(); region_split_here(); } gplanarity-master/graph_arrange.h000066400000000000000000000041151510662254600175020ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef GRAPH_ARRANGE_H #define GRAPH_ARRANGE_H extern void arrange_verticies_circle(graph *g, float off1, float off2); extern void arrange_verticies_polygon(graph *g, int sides, float angle, float rad, int xoff, int yoff, float xa, float ya); extern void arrange_verticies_polycircle(graph *g, int sides, float angle, float split, int radplus,int xoff,int yoff); extern void arrange_verticies_mesh(graph *g, int width, int height); extern void arrange_verticies_nastymesh(graph *g, int w, int h, vertex **flat); extern void arrange_region_star(graph *g); extern void arrange_region_rainbow(graph *g); extern void arrange_region_dashed_circle(graph *g); extern void arrange_region_bifur(graph *g); extern void arrange_region_dairyqueen(graph *g); extern void arrange_region_cloud(graph *g); extern void arrange_region_ring(graph *g); extern void arrange_region_storm(graph *g); extern void arrange_region_target(graph *g); extern void arrange_region_plus(graph *g); extern void arrange_region_hole3(graph *g); extern void arrange_region_hole4(graph *g); extern void arrange_region_ovals(graph *g); #endif /* GRAPH_ARRANGE_H */ gplanarity-master/graph_generate.c000066400000000000000000000300001510662254600176400ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include "graph.h" #include "graph_generate.h" #include "nls.h" typedef struct { char *class; int instancenum; char *desc; void (*gen)(graph *g, int num); float intersection_mult; float objective_mult; int unlock; } gen_instance; #define FINITE_LEVELS 79 static gen_instance i_list[FINITE_LEVELS]={ {"simple", 1, "A Small Beginning", generate_simple, 1.,4., 1 }, // 1 {"simple", 2, "My First Real Level(tm)", generate_simple, 1.,4., 2 }, // 2 {"data", 0, "My First Mission Impossible(tm)", generate_data, 20.,4., 3 }, // 3 {"simple", 3, "Larger But Not Harder", generate_simple, 1.,4., 2 }, // 4 {"crest", 5, "The Trick Is It's Easy", generate_crest, 1.,4., 2 }, // 5 {"simple", 4, "Practice Before the Handbasket: One of Three", generate_simple, 1.,4., 2 }, // 6 {"simple", 5, "Practice Before the Handbasket: Two of Three", generate_simple, 1.,4., 2 }, // 7 {"simple", 6, "Practice Before the Handbasket: Three of Three", generate_simple, 1.,4., 2 }, // 8 {"sparse", 4, "Tough and Stringy", generate_sparse, 1.2,4., 2 }, // 9 {"sparse", 5, "Threadbare", generate_sparse, 1.2,4., 2 }, // 10 {"nasty", 4, "The Bumpy Circles Are Slightly More Difficult", generate_nasty, 1.5,4., 3 }, // 11 {"nasty", 5, "Three is a Magic Number", generate_nasty, 1.5,4., 3 }, // 12 {"nasty", 6, "Last Call For (Sort of) Triangles (For Now)", generate_nasty, 1.5,4., 3 }, // 13 {"free", 4, "Something Only Subtly Different", generate_freeform, 1.5,4., 3 }, // 14 {"free", 5, "It Can Roll! Granted, Not Very Well", generate_freeform, 1.5,4., 3 }, // 15 {"free", 6, "If You Squint, It's a Round Brick", generate_freeform, 1.5,4., 3 }, // 16 {"rogue", 5, "A New Objective", generate_rogue, 1.6,4., 3 }, // 17 {"rogue", 6, "How Low Can You Go?", generate_rogue, 1.6,4., 3 }, // 18 {"rogue", 7, "Military Industrial Complex", generate_rogue, 1.6,4., 4 }, // 19 {"embed", 4, "The Hexagon is a Subtle and Wily Beast", generate_embed, 2.,4., 4 }, // 20 {"embed", 5, "No, Really, The Hexagon Puzzles Are Harder", generate_embed, 3.,4., 5 }, // 21 {"embed", 6, "Cursed? Call 1-800-HEX-A-GON Today!", generate_embed, 4.,4., 6 }, // 22 {"simple", 7, "Round but Straightforward", generate_simple, 1.,4., 4 }, // 23 {"shape", 0, "A Star Is Born... Then Solved", generate_shape, 1.,2., 6 }, // 24 {"shape", 1, "Oh, Rain*bows*...", generate_shape, 1.,2., 6 }, // 25 {"shape", 2, "Solve Along the Dotted Line", generate_shape, 1.,2., 6 }, // 26 {"shape", 3, "Using All Available Space", generate_shape, 1.,2., 6 }, // 27 {"shape", 4, "Brainfreeze", generate_shape, 1.,2., 6 }, // 28 {"shape", 6, "Tropical Storm Invest", generate_shape, 1.,2., 6 }, // 30 {"dense", 8, "Algorithm: Original/Dense (Order: 8)", generate_dense, .8,1., 5 }, // 31 {"simple", 8, "Algorithm: Original (Order: 8)", generate_simple, 1.,1., 6 }, // 32 {"sparse", 8, "Algorithm: Original/Sparse (Order: 8)",generate_sparse, 1.2,1., 7 }, // 33 {"nasty", 8, "Algorithm: Nasty (Order: 8)", generate_nasty, 1.5,1., 8 }, // 34 {"free", 8, "Algorithm: Freeform/4 (Order: 8)", generate_freeform, 1.5,1., 9 }, // 35 {"rogue", 8, "Algorithm: Rogue (Order: 8)", generate_rogue, 1.6,1.,10 }, // 36 {"embed", 8, "Algorithm: Embed (Order: 8)", generate_embed, 4.,1.,10 }, // 37 {"shape", 7, "Operator", generate_shape, 1.,2.,10 }, // 38 {"dense", 9, "Algorithm: Original/Dense (Order: 9)", generate_dense, .8,1., 5 }, // 39 {"simple", 9, "Algorithm: Original (Order: 9)", generate_simple, 1.,1., 6 }, // 40 {"sparse", 9, "Algorithm: Original/Sparse (Order: 9)",generate_sparse, 1.2,1., 7 }, // 41 {"nasty", 9, "Algorithm: Nasty (Order: 9)", generate_nasty, 1.5,1., 8 }, // 42 {"free", 9, "Algorithm: Freeform/4 (Order: 9)", generate_freeform, 1.5,1., 9 }, // 43 {"rogue", 9, "Algorithm: Rogue (Order: 9)", generate_rogue, 1.6,1.,10 }, // 44 {"embed", 9, "Algorithm: Embed (Order: 9)", generate_embed, 4.,1.,10 }, // 45 {"shape", 8, "The Inside Is Pointy", generate_shape, 1.,2.,10 }, // 46 {"dense", 10, "Algorithm: Original/Dense (Order: 10)", generate_dense, .8,1., 5 }, // 47 {"simple",10, "Algorithm: Original (Order: 10)", generate_simple, 1.,1., 6 }, // 48 {"sparse",10, "Algorithm: Original/Sparse (Order: 10)",generate_sparse, 1.2,1., 7 }, // 49 {"nasty", 10, "Algorithm: Nasty (Order: 10)", generate_nasty, 1.5,1., 8 }, // 50 {"free", 10, "Algorithm: Freeform/4 (Order: 10)", generate_freeform, 1.5,1., 9 }, // 51 {"rogue", 10, "Algorithm: Rogue (Order: 10)", generate_rogue, 1.6,1.,10 }, // 52 {"embed", 10, "Algorithm: Embed (Order: 10)", generate_embed, 4.,1.,10 }, // 53 {"shape", 9, "Riches and Good Luck", generate_shape, 1.,2.,10 }, // 54 {"dense", 11, "Algorithm: Original/Dense (Order: 11)", generate_dense, .8,1., 5 }, // 55 {"simple",11, "Algorithm: Original (Order: 11)", generate_simple, 1.,1., 6 }, // 56 {"sparse",11, "Algorithm: Original/Sparse (Order: 11)",generate_sparse, 1.2,1., 7 }, // 57 {"nasty", 11, "Algorithm: Nasty (Order: 11)", generate_nasty, 1.5,1., 8 }, // 58 {"free", 11, "Algorithm: Freeform/4 (Order: 11)", generate_freeform, 1.5,1., 9 }, // 59 {"rogue", 11, "Algorithm: Rogue (Order: 11)", generate_rogue, 1.6,1.,10 }, // 60 {"embed", 11, "Algorithm: Embed (Order: 11)", generate_embed, 4.,1.,10 }, // 61 {"shape", 10, "Mmmm... Doughnut", generate_shape, 1.,2.,10 }, // 62 {"dense", 12, "Algorithm: Original/Dense (Order: 12)", generate_dense, .8,1., 5 }, // 63 {"simple",12, "Algorithm: Original (Order: 12)", generate_simple, 1.,1., 6 }, // 64 {"sparse",12, "Algorithm: Original/Sparse (Order: 12)",generate_sparse, 1.2,1., 7 }, // 65 {"nasty", 12, "Algorithm: Nasty (Order: 12)", generate_nasty, 1.5,1., 8 }, // 66 {"free", 12, "Algorithm: Freeform/4 (Order: 12)", generate_freeform, 1.5,1., 9 }, // 67 {"rogue", 12, "Algorithm: Rogue (Order: 12)", generate_rogue, 1.6,1.,10 }, // 68 {"embed", 12, "Algorithm: Embed (Order: 12)", generate_embed, 4.,1.,10 }, // 69 {"shape", 11, "Quick and Dirty, or Slow and Steady", generate_shape, 1.,1.,10 }, // 70 {"shape", 5, "Little Fluffy Clouds", generate_shape, 1.,2., 6 }, // 29 {"dense", 13, "Algorithm: Original/Dense (Order: 13)", generate_dense, .8,1., 5 }, // 71 {"simple",13, "Algorithm: Original (Order: 13)", generate_simple, 1.,1., 6 }, // 72 {"sparse",13, "Algorithm: Original/Sparse (Order: 13)",generate_sparse, 1.2,1., 7 }, // 73 {"nasty", 13, "Algorithm: Nasty (Order: 13)", generate_nasty, 1.5,1., 8 }, // 74 {"free", 13, "Algorithm: Freeform/4 (Order: 13)", generate_freeform, 1.5,1., 9 }, // 75 {"rogue", 13, "Algorithm: Rogue (Order: 13)", generate_rogue, 1.6,1.,10 }, // 76 {"embed", 13, "Algorithm: Embed (Order: 13)", generate_embed, 4.,1.,10 }, // 77 {"shape", 12, "A Sudden Urge To Go Shopping", generate_shape, 1.,1.,10 }, // 78 {"shape", 13, "Sweet Reward", generate_shape, 1.,1.,10 }, // 79 }; #define LOOP_LEVELS 8 static gen_instance i_list_loop[LOOP_LEVELS]={ {"dense", 14, "Algorithm: Original/Dense (Order: %d)", generate_dense, .8,1., 5 }, // n {"simple",14, "Algorithm: Original (Order: %d)", generate_simple, 1.,1., 6 }, // n {"sparse",14, "Algorithm: Original/Sparse (Order: %d)",generate_sparse, 1.2,1., 7 }, // n {"nasty", 14, "Algorithm: Nasty (Order: %d)", generate_nasty, 1.5,1., 8 }, // n {"free", 14, "Algorithm: Freeform/4 (Order: %d)", generate_freeform, 1.5,1., 9 }, // n {"rogue", 14, "Algorithm: Rogue (Order: %d)", generate_rogue, 1.6,1.,10 }, // n {"embed", 14, "Algorithm: Embed (Order: %d)", generate_embed, 4.,1.,10 }, // n {"shape", 14, "Algorithm: Region (Order: %d)", generate_shape, 1.,2.,10 }, }; int generate_find_number(char *id){ int i; char buffer[160]; for(i=0;inum = num; gm->desc = _(i_list[num].desc); gm->unlock_plus = i_list[num].unlock+1; if(asprintf(&gm->id,"%s %d",i_list[num].class,i_list[num].instancenum)==-1){ fprintf(stderr,_("Couldn't allocate memory for level name.\n")); return -1; } return 0; }else{ /* past the finite list; one of the loop levels */ int classnum = (num - FINITE_LEVELS) % LOOP_LEVELS; int ordernum = (num - FINITE_LEVELS) / LOOP_LEVELS + i_list_loop[classnum].instancenum; gm->num = num; gm->unlock_plus = i_list_loop[classnum].unlock+1; if(asprintf(&gm->desc,i_list_loop[classnum].desc,ordernum)==-1){ fprintf(stderr,_("Couldn't allocate memory for level description.\n")); return -1; } if(asprintf(&gm->id,"%s %d",i_list_loop[classnum].class,ordernum)==-1){ fprintf(stderr,_("Couldn't allocate memory for level name.\n")); return -1; } return 0; } } void generate_board(graph *g,int num){ gen_instance *gi; if(numgen(g,gi->instancenum); }else{ int classnum = (num - FINITE_LEVELS) % LOOP_LEVELS; int ordernum = (num - FINITE_LEVELS) / LOOP_LEVELS + i_list_loop[classnum].instancenum; gi = i_list_loop+classnum; gi->gen(g,ordernum); } // clear out overloaded flags { vertex *v = g->verticies; while(v){ v->active=0; v->selected=0; v->grabbed=0; v=v->next; } } g->objective_mult = gi->objective_mult; g->intersection_mult = gi->intersection_mult; } gplanarity-master/graph_generate.h000066400000000000000000000033101510662254600176510ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef GRAPH_GENERATE_H #define GRAPH_GENERATE_H #include "graph.h" #include "nls.h" extern int generate_find_number(char *id); extern int generate_get_meta(int num, graphmeta *gm); extern void generate_board(graph *g,int num); extern void generate_simple(graph *g, int order); extern void generate_nasty(graph *g, int order); extern void generate_sparse(graph *g, int order); extern void generate_dense(graph *g, int order); extern void generate_rogue(graph *g, int order); extern void generate_embed(graph *g, int order); extern void generate_crest(graph *g, int order); extern void generate_data(graph *g, int order); extern void generate_freeform(graph *g, int order); extern void generate_shape(graph *g, int order); #endif /* GRAPH_GENERATE_H */ gplanarity-master/graph_generate_data.c000066400000000000000000000043571510662254600206510ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include "graph.h" #include "graph_generate.h" typedef struct d_vertex{ int x; int y; } d_vertex; typedef struct d_edge{ int a; int b; } d_edge; typedef struct d_level{ int obj; int less; d_vertex *v; d_edge *e; } d_level; static d_vertex v_level1[] = { {400,30}, {143,216}, {241,518}, {559,518}, {657,216}, {282,138}, {210,362}, {400,500}, {590,362}, {518,138}, {-1,-1}, }; static d_edge e_level1[] = { {0,5}, {5,1}, {0,2}, {0,3}, {0,9}, {9,4}, {1,6}, {6,2}, {1,3}, {1,4}, {2,7}, {7,3}, {2,4}, {3,8}, {8,4},{-1,-1}, }; static d_level leveldata[] = { {1,0,v_level1,e_level1} }; void generate_data(graph *g, int order){ int i; d_level *l = leveldata+order; vertex *vlist; vertex **flat; // scan for number of verticies i=0; while(l->v[i].x != -1)i++; vlist=new_board(g, i); flat = alloca(i*sizeof(*flat)); // build graph from data // add verticies { vertex *v=vlist; i=0; while(v){ v->x = l->v[i].x; v->y = l->v[i].y; flat[i++]=v; v=v->next; } } // add edges { int i=0; while(l->e[i].a != -1){ add_edge(g,flat[l->e[i].a],flat[l->e[i].b]); i++; } } g->objective = l->obj; g->objective_lessthan = l->less; } gplanarity-master/graph_generate_mesh1.c000066400000000000000000000521321510662254600207470ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include "graph.h" #include "random.h" #include "gameboard.h" #include "graph_generate.h" #include "graph_arrange.h" typedef struct { vertex **v; edge_list *embed_list; int width; int height; } mesh; typedef struct { int vnum[8]; vertex *center; mesh *m; } neighbors_grid; typedef struct { int vnum[8]; int num; } neighbors_list; /* The 'embed_list' is a set of edges that don't obey or neighboring intersection calculation mode and are thus tracked seperately/explicitly. They're added to the main graph after the rest of the graph is generated. */ /* add edge to the embed_list */ static void embedlist_add_edge(mesh *m, vertex *A, vertex *B){ edge *e = new_edge(A,B); m->embed_list = add_edge_to_list(m->embed_list,e); } /* move embed_list edges into the real graph */ static void embedlist_add_to_mesh(graph *g, mesh *m){ edge_list *el = m->embed_list; /* move the edges out of the embed_list and add them to the main graph */ while(el){ edge *e = el->edge; el->edge = 0; insert_edge(g,e); el=el->next; } release_edge_list(m->embed_list); m->embed_list=0; /* be pedantic */ } static int embedlist_intersects(mesh *m, vertex *A, vertex *B){ edge_list *el = m->embed_list; double dummy_x,dummy_y; while(el){ edge *e = el->edge; if(intersectsV(A,B,e->A,e->B,&dummy_x,&dummy_y)) return 1; el=el->next; } return 0; } static void embedlist_filter_intersections(neighbors_grid *ng){ int i; vertex *A = ng->center; for(i=0;i<8;i++){ if(ng->vnum[i] != -1){ vertex *B = ng->m->v[ng->vnum[i]]; if(embedlist_intersects(ng->m,A,B)) ng->vnum[i]=-1; } } } static int embedlist_contains_vertex(mesh *m,vertex *v){ edge_list *el = m->embed_list; while(el){ edge *e = el->edge; if(e->A == v) return 1; if(e->B == v) return 1; el=el->next; } return 0; } static int embedlist_vertex_poisoned(mesh *m, vertex *v){ return v->selected; } static void poison_vertex(mesh *m, vertex *v){ v->selected=1; } /* neighboring intersection model */ static void populate_neighbors(int vnum, mesh *m, neighbors_grid *ng){ int width = m->width; int y = vnum/width; int x = vnum - (y*width); int i; for(i=0;i<8;i++)ng->vnum[i]=-1; ng->center = m->v[vnum]; ng->m = m; if(y-1 >= 0){ if(x-1 >= 0) ng->vnum[0]= (y-1)*width+(x-1); ng->vnum[1]= (y-1)*width+x; if(x+1 < m->width) ng->vnum[2]= (y-1)*width+(x+1); } if(x-1 >= 0) ng->vnum[3]= y*width+(x-1); if(x+1 < m->width) ng->vnum[4]= y*width+(x+1); if(y+1 < m->height){ if(x-1 >= 0) ng->vnum[5]= (y+1)*width+(x-1); ng->vnum[6]= (y+1)*width+x; if(x+1 < m->width) ng->vnum[7]= (y+1)*width+(x+1); } } // eliminate from neighbor structs the verticies that already have at // least one edge static void filter_spanned_neighbors(neighbors_grid *ng, neighbors_list *nl){ int i; int count=0; for(i=0;i<8;i++) if(ng->vnum[i]==-1 || ng->m->v[ng->vnum[i]]->edges){ ng->vnum[i]=-1; }else{ nl->vnum[count++]=ng->vnum[i]; } nl->num=count; } // eliminate from neighbor struct any verticies to which we can't make // an edge without crossing another edge. Only 0,2,5,7 possible. static void filter_intersections(neighbors_grid *ng){ int i; for(i=0;i<8;i++){ switch(i){ case 0: if(ng->vnum[1] != -1 && ng->vnum[3] != -1 && exists_edge(ng->m->v[ng->vnum[1]], ng->m->v[ng->vnum[3]])) ng->vnum[i]=-1; break; case 2: if(ng->vnum[1] != -1 && ng->vnum[4] != -1 && exists_edge(ng->m->v[ng->vnum[1]], ng->m->v[ng->vnum[4]])) ng->vnum[i]=-1; break; case 5: if(ng->vnum[3] != -1 && ng->vnum[6] != -1 && exists_edge(ng->m->v[ng->vnum[3]], ng->m->v[ng->vnum[6]])) ng->vnum[i]=-1; break; case 7: if(ng->vnum[4] != -1 && ng->vnum[6] != -1 && exists_edge(ng->m->v[ng->vnum[4]], ng->m->v[ng->vnum[6]])) ng->vnum[i]=-1; break; } } embedlist_filter_intersections(ng); } /* eliminate verticies we've already connected to */ static void filter_edges(neighbors_grid *ng, neighbors_list *nl){ vertex *v=ng->center; int count=0,i; for(i=0;i<8;i++){ if(ng->vnum[i]!=-1){ if(!exists_edge(v,ng->m->v[ng->vnum[i]])) nl->vnum[count++]=ng->vnum[i]; else ng->vnum[i]=-1; } } nl->num=count; } static void random_populate(graph *g, int current, mesh *m, int min_connect, int prob_128){ int num_edges=0,i; neighbors_grid ng; neighbors_list nl; populate_neighbors(current, m, &ng); filter_intersections(&ng); filter_edges(&ng,&nl); { edge_list *el=m->v[current]->edges; while(el){ num_edges++; el=el->next; } } while(num_edgesv[current], m->v[nl.vnum[choice]]); num_edges++; filter_intersections(&ng); filter_edges(&ng,&nl); } for(i=0;iv[current], m->v[nl.vnum[i]]); } } static void span_depth_first(graph *g,int current, mesh *m){ neighbors_grid ng; neighbors_list nl; while(1){ populate_neighbors(current, m, &ng); // don't reverse the order of the next two filter_intersections(&ng); filter_spanned_neighbors(&ng,&nl); if(nl.num == 0) break; { int choice = random_number() % nl.num; add_edge(g,m->v[current], m->v[nl.vnum[choice]]); span_depth_first(g,nl.vnum[choice], m); } } } /* nastiness adds long edges along the outer perimeter to make it harder to rely on verticies always being near each other; mesh 2 takes this further, but we can add some of the same flavor to mesh1. */ static void nasty_horizontal(graph *g, mesh *m, int A, int B, int limit){ if(limit == 0) return; if(A+2 > B)return; /* adjacent is too close */ add_edge(g,m->v[A],m->v[B]); A++; B--; nasty_horizontal(g,m,A,B,limit-1); } static void nasty_vertical(graph *g, mesh *m, int A, int B, int limit){ if(limit == 0) return; if(A+(m->width*2) > B)return; /* adjacent is too close */ add_edge(g,m->v[A],m->v[B]); A+=m->width; B-=m->width; nasty_vertical(g,m,A,B,limit-1); } /* Don't use this along with k5 embedding; the assumptions the nastiness algorithm makes about solvable conditions won't always coexist with the assumptions the k5 embedding makes about solvable conditions. */ static void mesh_nastiness(graph *g, mesh *m, int limit){ nasty_horizontal(g,m,0,m->width-1, limit); nasty_horizontal(g,m,(m->height-1)*m->width,m->width*m->height-1, limit); nasty_vertical(g,m,0,(m->height-1)*m->width,limit); nasty_vertical(g,m,m->width-1,m->width*m->height-1, limit); } /* Embed one k5 in the solved graph */ /* Don't use this along with 'nastiness'; the assumptions the nastiness algorithm makes about solvable conditions won't always coexist with the assumptions that non-planar embedding makes about solvable conditions. */ static void mesh_embed_k5(graph *g, mesh *m,int x, int y){ /* Add the k5s up front in their own special edge list; This list will also be checked explicitly by the various neighboring algorithms as the k5's edges don't all conceptually work within the implicit neighboring algorithm we're using. Also, by using a special edge list and not adding the k5 edges to the vertex edge lists up front, we can still use the unmodified initial spanning walk algorithm. */ int w = m->width; vertex *A = m->v[y*w+x+1]; vertex *B = m->v[(y+1)*w+x+1]; vertex *C = m->v[(y+1)*w+x+2]; vertex *D = m->v[(y+1)*w+x+3]; vertex *E = m->v[(y+2)*w+x]; // poisoned verticies are already inside another kernel (the regular // mesh is deflectable and thus not really regular) if(embedlist_vertex_poisoned(m,A))return; if(embedlist_vertex_poisoned(m,B))return; if(embedlist_vertex_poisoned(m,C))return; if(embedlist_vertex_poisoned(m,D))return; if(embedlist_vertex_poisoned(m,E))return; // the way k5 works we don't need to poison the internal verticies embedlist_add_edge(m, A,B); embedlist_add_edge(m, A,C); embedlist_add_edge(m, A,D); embedlist_add_edge(m, A,E); embedlist_add_edge(m, B,C); embedlist_add_edge(m, B,D); embedlist_add_edge(m, B,E); embedlist_add_edge(m, C,D); embedlist_add_edge(m, C,E); embedlist_add_edge(m, D,E); g->objective++; } /* Embed one k3,3 in the solved graph */ /* Don't use this along with 'nastiness'; the assumptions the nastiness algorithm makes about solvable conditions won't always coexist with the assumptions that k5 embedding makes about solvable conditions. */ static void mesh_embed_k33(graph *g, mesh *m, int x, int y){ /* same disclaimers as k5 */ /* the k3,3 embedding works with the standard walk algorithm only because an edge with an endpoint exactly on another edge is considered an intersection. */ /* the way it is added, the walk/population can add additional edges inside the embedded kernel; this is fine, the population will be certain not to introduce intersections. */ int w = m->width; vertex *A = m->v[y*w+x]; vertex *B = m->v[y*w+x+1]; vertex *C = m->v[y*w+x+2]; vertex *D = m->v[(y+1)*w+x]; vertex *E = m->v[(y+1)*w+x+1]; vertex *F = m->v[(y+1)*w+x+2]; // poisoned verticies are already inside another kernel (the regular // mesh is deflectable and thus not really regular) if(embedlist_vertex_poisoned(m,A))return; if(embedlist_vertex_poisoned(m,B))return; if(embedlist_vertex_poisoned(m,C))return; if(embedlist_vertex_poisoned(m,D))return; if(embedlist_vertex_poisoned(m,E))return; if(embedlist_vertex_poisoned(m,F))return; // check that verticies we want to poison ourselves are not already in use if(embedlist_contains_vertex(m,B))return; if(embedlist_contains_vertex(m,E))return; /* B and E are internal according to x/y, but according to the position in the mesh, they're on the outside. Poison them so that they're explicitly marked inside. */ poison_vertex(m,B); poison_vertex(m,E); /* need to mode two of the intersections to avoid unwanted intersections (not spurious; they are in fact intersections until moved) */ B->y+=2; E->y-=2; embedlist_add_edge(m, A,C); embedlist_add_edge(m, A,D); embedlist_add_edge(m, A,E); embedlist_add_edge(m, B,C); embedlist_add_edge(m, B,D); embedlist_add_edge(m, B,E); embedlist_add_edge(m, C,F); embedlist_add_edge(m, D,F); embedlist_add_edge(m, E,F); g->objective++; } /* Embed one non-miminal k3,3 in the solved graph */ /* Don't use this along with 'nastiness'; the assumptions the nastiness algorithm makes about solvable conditions won't always coexist with the assumptions that k5 embedding makes about solvable conditions. */ static void mesh_embed_bigk33(graph *g, mesh *m, int x, int y){ /* as above */ int w = m->width; vertex *A = m->v[(y+2)*w+x]; vertex *B = m->v[(y+1)*w+x+2]; vertex *C = m->v[y*w+x+4]; vertex *D = m->v[(y+4)*w+x+1]; vertex *E = m->v[(y+3)*w+x+3]; vertex *F = m->v[(y+2)*w+x+5]; // poisoned verticies are already inside another kernel (the regular // mesh is deflectable and thus not really regular) if(embedlist_vertex_poisoned(m,A))return; if(embedlist_vertex_poisoned(m,B))return; if(embedlist_vertex_poisoned(m,C))return; if(embedlist_vertex_poisoned(m,D))return; if(embedlist_vertex_poisoned(m,E))return; if(embedlist_vertex_poisoned(m,F))return; // check that verticies we want to poison ourselves are not already in use if(embedlist_contains_vertex(m,B))return; if(embedlist_contains_vertex(m,E))return; /* B and E are internal according to x/y, but according to the position in the mesh, they're on the outside. Poison them so that they're explicitly marked inside. */ poison_vertex(m,B); poison_vertex(m,E); /* need to move two of the intersections to avoid unwanted intersections (not spurious; they are in fact intersections until moved) */ B->y+=2; E->y-=2; embedlist_add_edge(m, A,C); embedlist_add_edge(m, A,D); embedlist_add_edge(m, A,E); embedlist_add_edge(m, B,C); embedlist_add_edge(m, B,D); embedlist_add_edge(m, B,E); embedlist_add_edge(m, C,F); embedlist_add_edge(m, D,F); embedlist_add_edge(m, E,F); g->objective++; } static void mesh_embed_recurse(graph *g,mesh *m,int x, int y, int w, int h, int k5, int k33, int bigk33){ int xd,yd,wd,hd; // not minimal spacing; the k33 needs vertical offset, but the others are larger just to space them out. if( bigk33 && w>=6 && h>=5 ){ wd = 5; hd = 4; xd = random_number() % (w-wd); yd = random_number() % (h-hd); mesh_embed_bigk33(g,m,x+xd,y+yd); }else if(k5 && w>=4 && h>=3){ wd = 3; hd = 2; xd = random_number() % (w-wd); yd = random_number() % (h-hd); mesh_embed_k5(g,m,x+xd,y+yd); }else if(k33 && w>=3 && h>=2 ){ wd = 2; hd = 1; xd = random_number() % (w-wd); yd = random_number() % (h-hd); mesh_embed_k33(g,m,x+xd,y+yd); }else return; mesh_embed_recurse(g,m, x, y, w, yd+1, k5,k33,bigk33); mesh_embed_recurse(g,m, x, y+yd+hd, w, h-yd-hd, k5,k33,bigk33); mesh_embed_recurse(g,m, x, y+yd, xd+1, hd+1, k5,k33,bigk33); mesh_embed_recurse(g,m, x+xd+wd,y+yd, w-xd-wd, hd+1, k5,k33,bigk33); } /* Embed k5s and k3,3s in the solved graph in such a way that we know each added non-planar kernel adds exactly one and only one certain intersection. */ /* Don't use this along with 'nastiness'; the assumptions the nastiness algorithm makes about solvable conditions won't always coexist with the assumptions that non-planar embedding makes about solvable conditions. */ static void mesh_embed_nonplanar(graph *g, mesh *m,int k5, int k33, int bigk33){ // selection is used as a poison flag during embedding deselect_verticies(g); mesh_embed_recurse(g, m, 0,0,m->width,m->height, k5,k33,bigk33); deselect_verticies(g); } /* Rogues are added lines inserted between verticies on neighboring rows/columns; the idea is to choose the longest ones that cross the smallest number of lines. */ /* Right now, the rogue insertion doesn't take embedded kernel poisoning or niceness constraints into account, so don't mix them */ static int count_intersections(graph *g, vertex *A, vertex *B){ edge *e=g->edges; double dummy_x,dummy_y; int count=0; while(e){ if(intersectsV(A,B,e->A,e->B,&dummy_x,&dummy_y)) count++; e=e->next; } return count; } static void scan_rogue(graph *g, mesh *m, int aoff,int boff, int step, int end, float *metric, edge *best, int *cross){ int a,b; for(a=0;a+1v[a*step+aoff]; vertex *vb = m->v[b*step+boff]; if(!va->selected && !vb->selected){ if(!exists_edge(va,vb)){ int count = count_intersections(g,va,vb); if(count){ float test = (b-a)/count; if(test>=*metric){ *metric=test; best->A=va; best->B=vb; *cross=count; } } } } } } } /* scan the entire mesh looking for the candidate edge with the highest rogue objective value */ static void mesh_add_rogues(graph *g, mesh *m){ int w = m->width; int h = m->height; deselect_verticies(g); while(1){ int i; edge best; float metric=2.1; int cross = 0; best.A=0; best.B=0; for(i=0;i+1selected=1; best.B->selected=1; g->objective+=cross; g->objective_lessthan = 1; }else{ break; } } deselect_verticies(g); } /* Initial generation setup */ static void mesh_setup(graph *g, mesh *m, int order, int divis){ int flag=0; int wiggle=0; int n; m->width=3; m->height=2; { while(--order){ if(flag){ flag=0; m->height+=1; }else{ flag=1; m->width+=2; } } } n=m->width*m->height; // is this divisible by our requested divisor if any? if(divis>0 && n%divis){ while(1){ wiggle++; if(!((n+wiggle)%divis)) break; if(n-wiggle>6 && !((n-wiggle)%divis)){ wiggle = -wiggle; break; } } // refactor the rectangular mesh's dimensions. { int h = (int)sqrt(n+wiggle),w; while( (n+wiggle)%h )h--; if(h==1){ // double it and be content with a working result h=2; w=(n+wiggle); }else{ // good factoring w = (n+wiggle)/h; } m->width=w; m->height=h; } } new_board(g, m->width * m->height); m->embed_list=0; // used for rogue calcs { int x,y; vertex *v = g->verticies; for(y=0;yheight;y++) for(x=0;xwidth;x++){ v->x=x*50; // not a random number; other things depend on this v->y=y*50; // not a random number; other things depend on this v=v->next; } } g->objective = 0; g->objective_lessthan = 0; } static void mesh_flatten(graph *g,mesh *m){ /* a flat vector is easier to address while building the mesh */ int i; vertex *v=g->verticies; for(i=0;iwidth*m->height;i++){ m->v[i]=v; v=v->next; } } static void generate_mesh(graph *g, mesh *m, int density_128){ /* first walk a random spanning tree */ span_depth_first(g, 0, m); /* now iterate the whole mesh adding random edges */ { int i; for(i=0;iwidth*m->height;i++) random_populate(g, i, m, 2, density_128); } } void generate_simple(graph *g, int order){ mesh m; random_seed(order); mesh_setup(g,&m, order, 0); m.v=alloca(m.width*m.height * sizeof(*m.v)); mesh_flatten(g,&m); generate_mesh(g,&m,40); randomize_verticies(g); if((m.width*m.height)&1) arrange_verticies_circle(g,0,0); else arrange_verticies_circle(g,M_PI/2,M_PI/2); } void generate_sparse(graph *g, int order){ mesh m; random_seed(order); mesh_setup(g,&m, order, 3); m.v=alloca(m.width*m.height * sizeof(*m.v)); mesh_flatten(g,&m); generate_mesh(g,&m,2); mesh_nastiness(g,&m,-1); randomize_verticies(g); if((m.width*m.height)&1) arrange_verticies_circle(g,0,0); else arrange_verticies_circle(g,M_PI/2,M_PI/2); } void generate_dense(graph *g, int order){ mesh m; random_seed(order); mesh_setup(g,&m, order, 3); m.v=alloca(m.width*m.height * sizeof(*m.v)); mesh_flatten(g,&m); generate_mesh(g,&m,96); mesh_nastiness(g,&m,-1); randomize_verticies(g); if((m.width*m.height)&1) arrange_verticies_circle(g,0,0); else arrange_verticies_circle(g,M_PI/2,M_PI/2); } void generate_nasty(graph *g, int order){ mesh m; random_seed(order+8236); mesh_setup(g,&m, order,4); m.v=alloca(m.width*m.height * sizeof(*m.v)); mesh_flatten(g,&m); generate_mesh(g,&m,32); mesh_nastiness(g,&m,-1); randomize_verticies(g); arrange_verticies_polycircle(g,3,0,.3,25,0,25); } void generate_rogue(graph *g, int order){ mesh m; random_seed(order+3005); mesh_setup(g,&m, order,5); m.v=alloca(m.width*m.height * sizeof(*m.v)); mesh_flatten(g,&m); generate_mesh(g,&m,24); mesh_add_rogues(g,&m); randomize_verticies(g); if(order*.03<.3) arrange_verticies_polycircle(g,5,0,order*.03,0,0,0); else arrange_verticies_polycircle(g,5,0,.3,0,0,0); } void generate_embed(graph *g, int order){ mesh m; random_seed(order+347); mesh_setup(g,&m, order, 6); m.v=alloca(m.width*m.height * sizeof(*m.v)); mesh_flatten(g,&m); mesh_embed_nonplanar(g,&m,1,1,1); generate_mesh(g,&m,48); embedlist_add_to_mesh(g,&m); randomize_verticies(g); if(order*.03<.3) arrange_verticies_polycircle(g,6,0,order*.03,0,0,0); else arrange_verticies_polycircle(g,6,0,.3,0,0,0); } void generate_crest(graph *g, int order){ int n; mesh m; random_seed(order); mesh_setup(g,&m, order,0); m.v=alloca(m.width*m.height * sizeof(*m.v)); mesh_flatten(g,&m); generate_mesh(g,&m,128); n=m.width*m.height; arrange_verticies_circle(g,M_PI/n,M_PI/n); } gplanarity-master/graph_generate_mesh2.c000066400000000000000000000305001510662254600207430ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include "graph.h" #include "random.h" #include "gameboard.h" #include "graph_generate.h" #include "graph_arrange.h" #include "graph_region.h" /* Mesh1 has three primary considerations in mind: 1) By default, act like the algorithm in the original planarity 2) Conform to a population contraint that is easy to work with/modify 3) Playability; short edges result in graphs that are easier to solve. Mesh2 is intended to be a freeform populator with two different uses; harder levels that disrupt the easy solution algorithms that mesh1 allows, as well as being able to densely populate arbitrary regions. */ typedef struct { graph *g; int width; int height; int active_current; int active_max; } mesh; // check for intersections with other edges static int check_intersects_edge(mesh *m, edge *e, int intersections){ edge *ge = m->g->edges; int count=0; while(ge){ double xo,yo; // edges that aren't in this region don't exist (for // now) by definition if(ge->A->active == m->active_current || ge->B->active == m->active_current){ // edges that share a vertex don't intersect by definition if(ge->A!=e->A && ge->A!=e->B && ge->B!=e->A && ge->B!=e->B) if(intersects(ge->A->orig_x,ge->A->orig_y, ge->B->orig_x,ge->B->orig_y, e->A->orig_x,e->A->orig_y, e->B->orig_x,e->B->orig_y, &xo,&yo)){ count++; if(count>intersections)return 1; } } ge=ge->next; } return 0; } static float dot(vertex *A, vertex *B, vertex *C){ return (float)(B->orig_x-A->orig_x)*(float)(C->orig_x-B->orig_x) + (float)(B->orig_y-A->orig_y)*(float)(C->orig_y-B->orig_y); } static float cross(vertex *A, vertex *B, vertex *C){ return (float)(B->orig_x-A->orig_x)*(float)(C->orig_y-A->orig_y) - (float)(B->orig_y-A->orig_y)*(float)(C->orig_x-A->orig_x); } static float sq_point_distance(vertex *A, vertex *B){ float xd = A->orig_x-B->orig_x; float yd = A->orig_y-B->orig_y; return xd*xd+yd*yd; } static float sq_line_distance(edge *e, vertex *v){ if(dot(e->A,e->B,v) > 0) return sq_point_distance(e->B,v); if(dot(e->B,e->A,v) > 0) return sq_point_distance(e->A,v); { float c = cross(e->A,e->B,v); return c*c/sq_point_distance(e->A,e->B); } } // Does this edge pass within ten pixels of another vertex static int check_intersects_vertex(mesh *m, edge *e){ vertex *v = m->g->verticies; while(v){ if(v->active == m->active_current) if(v!=e->A && v!=e->B && sq_line_distance(e,v)<16)return 1; v=v->next; } return 0; } static int select_available(mesh *m,vertex *current,float length_limit,int intersections){ int count=0; vertex *v = m->g->verticies; // mark all possible choices while(v){ v->selected = 0; if(v!=current && current->active == m->active_current){ if(length_limit==0 || sq_point_distance(v,current)<=length_limit){ if(!exists_edge(v,current)){ edge e; e.A = v; e.B = current; if(!region_intersects(&e)){ if(!check_intersects_edge(m,&e,intersections)){ if(!check_intersects_vertex(m,&e)){ v->selected=1; count++; } } } } } } v=v->next; } return count; } // Although very inefficient, it is simple and correct. Even // impossibly large boards generate in a fraction of a second on old // boxen. There's likely no need to bother optimizing this step of // board creation. */ typedef struct insort{ int metric; vertex *v; } insort; static int insort_c(const void *a, const void *b){ insort *A=(insort *)a; insort *B=(insort *)b; return(A->metric-B->metric); } static vertex *vertex_num_sel(graph *g,int num){ vertex *v=g->verticies; if(num<0)return 0; while(v){ if(v->selected){ if(!num) break; else num--; } v=v->next; } return v; } static void prepopulate(mesh *m,int length_limit){ // sort all verticies in ascending order by their number of potential edges int i=0; int num=0; insort index[m->g->vertex_num]; vertex *v=m->g->verticies; while(v){ if(v->active == m->active_current){ index[num].v=v; index[num].metric = select_available(m,v,0,0); num++; } v=v->next; } qsort(index,num,sizeof(*index),insort_c); // populate in ascending order for(i=0;iedges; while(el){ edges++; el=el->next; if(edges>=2)break; } } if(edges>=2)continue; // it's possible some intersections will be necessary, but go for // fewest possible while(edges<2 && intersections<10){ int count = select_available(m,v,length_limit,intersections); if(count){ vertex *short0=0; vertex *short1=0; vertex *w=m->g->verticies; long d0=0; long d1=0; if(length_limit){ // choose two at random int a=random_number()%count; int b=-1; if(count>1) while(b==-1){ b=random_number()%count; if(b==a)b=-1; } short0=vertex_num_sel(m->g,a); short1=vertex_num_sel(m->g,b); }else{ // used with region-constrined meshes // of the possible edges, choose the shortest two while(w){ if(w!=v && w->selected){ int xd=w->orig_x-v->orig_x; int yd=w->orig_y-v->orig_y; long d=xd*xd+yd*yd; if(!short0){ short0=w; d0=d; }else if(!short1 || dnext; } } if(short0){ add_edge(m->g,v,short0); edges++; m->g->objective +=intersections; if(intersections)m->g->objective_lessthan=1; } if(edges<2 && short1){ add_edge(m->g,v,short1); edges++; m->g->objective +=intersections; if(intersections)m->g->objective_lessthan=1; } } intersections++; } } } // the spanning walk is to make an attempt at a single, connected graph. static void span_depth_first2(mesh *m,vertex *current, float length_limit){ current->grabbed=1; // overloaded; "we walked this already" while(1){ // prefer walking along edges that already exist { edge_list *el=current->edges; while(el){ edge *e=el->edge; vertex *v; if(e->A==current) v=e->B; else v=e->A; if(!v->grabbed){ span_depth_first2(m, v, length_limit); } el=el->next; } } // now walk any possible edges that have not been walked { int count=select_available(m,current,length_limit,0); int count2=0; int choice; vertex *v = m->g->verticies; // filter out already-walked edges while(v){ if(v->grabbed && v->selected){ // grabbed is also overloaded to mean walked v->selected = 0; count--; } v=v->next; } if(count == 0) return; choice = random_number()%count; v = m->g->verticies; while(v){ if(v->selected){ if(count2++ == choice){ add_edge(m->g,v,current); span_depth_first2(m,v, length_limit); break; } } v=v->next; } if(count == 1) return; // because we just took care of it } } } static void random_populate(mesh *m,vertex *current,int dense_128, float length_limit){ if(current->active == m->active_current){ int count=select_available(m,current,length_limit,0); if(count){ vertex *v = m->g->verticies; while(v){ if(v->selected && random_yes(dense_128)){ add_edge(m->g,v,current); v->selected=0; } v=v->next; } } } } /* Initial generation setup */ static void mesh_setup(graph *g, mesh *m, int order, int divis){ int flag=0; int wiggle=0; int n; m->g = g; m->width=3; m->height=2; { while(--order){ if(flag){ flag=0; m->height+=1; }else{ flag=1; m->width+=2; } } } n=m->width*m->height; // is this divisible by our requested divisor if any? if(divis>0 && n%divis){ while(1){ wiggle++; if(!((n+wiggle)%divis)) break; if(n-wiggle>6 && !((n-wiggle)%divis)){ wiggle = -wiggle; break; } } // refactor the rectangular mesh's dimensions. { int h = (int)sqrt(n+wiggle),w; while( (n+wiggle)%h )h--; if(h==1){ // double it and be content with a working result h=2; w=(n+wiggle); }else{ // good factoring w = (n+wiggle)/h; } m->width=w; m->height=h; } } new_board(g, m->width * m->height); region_init(); // clear it // used for intersection calcs { int x,y; vertex *v = g->verticies; for(y=0;yheight;y++) for(x=0;xwidth;x++){ v->orig_x=x*50; // not a random number v->orig_y=y*50; // not a random number v=v->next; } } g->objective = 0; g->objective_lessthan = 0; m->active_max=0; } static void generate_mesh2(mesh *m, int density_128, float length_limit){ vertex *v; int i; length_limit*=50; length_limit*=length_limit; for(i=0;i<=m->active_max;i++){ m->active_current=i; if(have_region()) prepopulate(m,0); /* connect the graph into as few discrete sections as possible */ v = m->g->verticies; while(v){ v->grabbed = 0; v=v->next; } v = m->g->verticies; // make sure we walk all verticies while(v){ if(v->active == m->active_current && !v->grabbed) span_depth_first2(m, m->g->verticies, length_limit); v=v->next; } if(!have_region()) prepopulate(m,length_limit); /* now iterate the whole mesh adding random edges */ v=m->g->verticies; while(v){ random_populate(m, v, density_128, length_limit); v=v->next; } } } void generate_freeform(graph *g, int order){ mesh m; random_seed(order+1); mesh_setup(g, &m, order, 0); generate_mesh2(&m,48,4); randomize_verticies(g); if(order*.03<.3) arrange_verticies_polycircle(g,4,0,order*.03,0,0,0); else arrange_verticies_polycircle(g,4,0,.3,0,0,0); } void generate_shape(graph *g, int order){ int mod=0; int dens=64; int min=8; mesh m; random_seed(order+1); switch(order%13){ case 0: // star mod=10; break; case 1: break; case 2: // dashed circle dens=48; break; case 3: // bifur dens=80; break; case 4: break; case 5: min = 12; dens = 10; break; case 6: min = 10; break; case 7: min = 10; break; case 8: min = 10; break; case 9: min = 10; break; case 10: // ring dens=128; min = 11; break; case 11: min = 12; break; case 12: // target min = 14; break; } mesh_setup(g, &m, (order>min?order:min), mod); randomize_verticies(g); switch(order % 13){ case 0: // star arrange_region_star(g); break; //4 case 1: // rainbow arrange_region_rainbow(g); break; //9 case 2: // dashed circle arrange_region_dashed_circle(g); break; //0 case 3: // bifur arrange_region_bifur(g); break; //0 case 4: // dairyqueen arrange_region_dairyqueen(g); break; //0 case 5: // cloud arrange_region_cloud(g); break; //0 case 6: // storm arrange_region_storm(g); break; //11 case 7: // plus; arrange_region_plus(g); break; //2 case 8: arrange_region_hole3(g); break; //4 case 9: arrange_region_hole4(g); break; //15 case 10: // ring arrange_region_ring(g); break; //29 case 11: arrange_region_ovals(g); break; //95 case 12: // target arrange_region_target(g); break; //108 } m.active_max=region_layout(g); generate_mesh2(&m,dens,0); } gplanarity-master/graph_region.c000066400000000000000000000441471510662254600173520ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include #include "graph.h" #include "graph_region.h" #include "nls.h" /* Regions are 'electric fences' for mesh building; used in mesh2 to make non-convex shapes */ typedef struct region_segment { int layout; /* 0 no layout, 1 left, 2 right, 3 layout-only */ int cont; /* is this continuous from last line? */ int split; /* are we splitting the graph into interntionally seperate regions here? */ float x1; float y1; float x2; float y2; // arc computation cache (if arc) float cx; float cy; float radius; float phi0; float phi1; float phi; float length; struct region_segment *next; } region_segment; typedef struct region{ int num; region_segment *l; int ox,oy,x,y; int layout; int cont; int split_next; } region; static region r; static region layout_adj; static region_segment *segpool=0; #define CHUNK 64 static region_segment *new_segment(region *r, int x1,int y1,int x2, int y2){ region_segment *ret; if(!segpool){ int i; segpool = calloc(CHUNK,sizeof(*segpool)); for(i=0;inext; memset(ret,0,sizeof(*ret)); ret->next = r->l; ret->layout=r->layout; ret->x1=x1; ret->y1=y1; ret->x2=x2; ret->y2=y2; ret->cont = r->cont; ret->split = r->split_next; r->l=ret; r->split_next=0; return ret; } /* angle convention: reversed y (1,-1 is first quadrant, ala X windows), range -PI to PI */ static int intersects_arc(edge *e, region_segment *r){ float Ax = e->A->x - r->cx; float Ay = e->A->y - r->cy; float Bx = e->B->x - r->cx; float By = e->B->y - r->cy; float dx = Bx - Ax; float dy = By - Ay; float dr2 = dx*dx + dy*dy; float D = Ax*By - Bx*Ay; float discriminant =(r->radius*r->radius)*dr2 - D*D; // does it even intersect the full circle? if(discriminant<=0)return 0; { float x1,y1,x2,y2; float sqrtd = sqrt(discriminant); float sign = (dy>0?1.f:-1.f); // finite precision required here else 0/inf slope lines will be // slighly off the secant x1 = rint((D*dy + sign*dx*sqrtd) / dr2); x2 = rint((D*dy - sign*dx*sqrtd) / dr2); y1 = rint((-D*dx + fabs(dy)*sqrtd) / dr2); y2 = rint((-D*dx - fabs(dy)*sqrtd) / dr2); Ax = rint(Ax); Ay = rint(Ay); Bx = rint(Bx); By = rint(By); // is x1,y1 actually on the segment? if( !(x1Ax && x1>Bx) && !(y1Ay && y1>By)){ // yes. it is in the angle range we care about? float ang = acos(x1 / r->radius); if(y1>0) ang = -ang; if(r->phi<0){ if(r->phi0 < r->phi1){ if(ang <= r->phi0 || ang >= r->phi1)return 1; }else{ if(ang <= r->phi0 && ang >= r->phi1)return 1; } }else{ if(r->phi0 < r->phi1){ if(ang >= r->phi0 && ang <= r->phi1)return 1; }else{ if(ang >= r->phi0 || ang <= r->phi1)return 1; } } } // is x2,y2 actually on the segment? // if so, it is in the arc range we care about? if( !(x2Ax && x2>Bx) && !(y2Ay && y2>By)){ // yes. it is in the angle range we care about? float ang = acos(x2 / r->radius); if(y2>0) ang = -ang; if(r->phi<0){ if(r->phi0 < r->phi1){ if(ang <= r->phi0 || ang >= r->phi1)return 1; }else{ if(ang <= r->phi0 && ang >= r->phi1)return 1; } }else{ if(r->phi0 < r->phi1){ if(ang >= r->phi0 && ang <= r->phi1)return 1; }else{ if(ang >= r->phi0 || ang <= r->phi1)return 1; } } } } return 0; } static float line_angle(float x1, float y1, float x2, float y2){ float xd = x2-x1; float yd = y2-y1; if(xd == 0){ if(yd>0) return -M_PI/2; else return M_PI/2; }else if(xd<0){ if(yd<0) return atan(-yd/xd)+M_PI; else return atan(-yd/xd)-M_PI; }else{ return atan(-yd/xd); } } static float line_mag(float x1, float y1, float x2, float y2){ float xd = x2-x1; float yd = y2-y1; return hypot(xd,yd); } static void compute_arc(region_segment *r,float phi){ float x1=r->x1; float y1=r->y1; float x2=r->x2; float y2=r->y2; float ar,br,cr; float cx,cy,a,c,d; float xd = x2-x1; float yd = y2-y1; if(phi<-M_PI){ ar = phi + M_PI*2; }else if (phi<0){ ar = -phi; }else if (phi0 && phicx=cx; r->cy=cy; r->radius=d; // have the center of the circle, have radius. Determine the // portion of the arc we want. r->phi0 = acos( (x1-cx) / d); r->phi1 = acos( (x2-cx) / d); if(y1>cy) r->phi0= -r->phi0; if(y2>cy) r->phi1= -r->phi1; r->phi=phi; } static region_segment *region_arc(region *re, int x1, int y1, int x2, int y2, float rad){ region_segment *n= new_segment(re,x1,y1,x2,y2); compute_arc(n,rad); return n; } static region_segment *region_line(region *re,int x1, int y1, int x2, int y2){ return new_segment(re,x1,y1,x2,y2); } /* The overall idea here is to massage the region segments and arcs slightly so that when we layout points based on a region, the layout is slightly inside or outside (as requested) the actual region. This also reverses the path when rebuilding into the new region, putting it in the order we actually need to evaluate it in. */ #define ADJ 2.f static void point_adj(float x1, float y1, float x2, float y2, float *Px, float *Py, int left){ float xd = x2-x1; float yd = y2-y1; float M = hypot(xd,yd); if(left){ *Px += yd/M*ADJ; *Py += -xd/M*ADJ; }else{ *Px += -yd/M*ADJ; *Py += xd/M*ADJ; } } static void line_adj(float *x1, float *y1, float *x2, float *y2, int left){ float xd = *x2-*x1; float yd = *y2-*y1; float M = hypot(xd,yd); if(left){ *x1 += yd/M*ADJ; *x2 += yd/M*ADJ; *y1 += -xd/M*ADJ; *y2 += -xd/M*ADJ; }else{ *x1 += -yd/M*ADJ; *x2 += -yd/M*ADJ; *y1 += xd/M*ADJ; *y2 += xd/M*ADJ; } // make sure there's an overlap! *x1-=xd/M*4.; *x2+=xd/M*4.; *y1-=yd/M*4.; *y2+=yd/M*4.; } static float tangent_distance_from_center(float x1, float y1, float x2, float y2, float cx, float cy){ float xd = x2 - x1; float yd = y2 - y1; return ((x2-x1)*(cy-y1) - (y2-y1)*(cx-x1)) / hypot(xd,yd); } static float radius_adjust(float r, float arc_phi, int left){ if(arc_phi<0){ if(left){ r+=ADJ; }else{ r-=ADJ; } }else{ if(left){ r-=ADJ; }else{ r+=ADJ; } } return r; } static void line_line_adj(region_segment *A, region_segment *B, float *new_x, float *new_y, int left){ double newd_x; double newd_y; float Ax1=A->x1; float Ay1=A->y1; float Ax2=A->x2; float Ay2=A->y2; float Bx1=B->x1; float By1=B->y1; float Bx2=B->x2; float By2=B->y2; line_adj(&Ax1, &Ay1, &Ax2, &Ay2, left); line_adj(&Bx1, &By1, &Bx2, &By2, left); // compute new intersection if(!intersects(Ax1,Ay1,Ax2,Ay2, Bx1,By1,Bx2,By2, &newd_x, &newd_y)){ // odd; do nothing rather than fail unpredictably *new_x=Ax2; *new_y=Ay2; }else{ *new_x=newd_x; *new_y=newd_y; } } static void line_arc_adj(float x1, float y1, float x2, float y2, float cx, float cy, float r, float arc_phi, float *new_x2, float *new_y2, int lleft, int aleft){ float xd = x2 - x1; float yd = y2 - y1; float c = tangent_distance_from_center(x1,y1,x2,y2,cx,cy); float a = sqrt(r*r - c*c),a2; float M = hypot(xd,yd); float ax = x2 + xd/M*a; float ay = y2 + yd/M*a; float ax1 = x2 - xd/M*a; float ay1 = y2 - yd/M*a; if(hypot(ax1-cx,ay1-cy) < hypot(ax-cx,ay-cy)){ ax=ax1; ay=ay1; } xd = ax-x2; yd = ay-y2; point_adj(x1, y1, x2, y2, &ax, &ay, lleft); r = radius_adjust(r,arc_phi,aleft); c = hypot(cx-ax,cy-ay); a2 = sqrt(r*r-c*c); *new_x2 = ax - xd/a*a2; *new_y2 = ay - yd/a*a2; } static void arc_arc_adj(region_segment *arc, region_segment *next, float *new_x2, float *new_y2, int left){ float x2 =arc->x2; float y2 =arc->y2; float cx1=arc->cx; float cy1=arc->cy; float r1 =arc->radius; float cx2=next->cx; float cy2=next->cy; float r2 =next->radius; float c; float xd = cx2-cx1; float yd = cy2-cy1; float d = hypot(xd,yd); float x = (d*d - r1*r1 + r2*r2) / (2*d); // is the old x2/y2 to the left or right of the line connecting the // circle centers? float angle_x2y2 = line_angle(cx1,cy1,x2,y2); float angle_c1c2 = line_angle(cx1,cy1,cx2,cy2); float angle = angle_x2y2 - angle_c1c2; if(angle < -M_PI)angle += M_PI*2.f; if(angle > M_PI)angle -= M_PI*2.f; r1=radius_adjust(r1,arc->phi,left); r2=radius_adjust(r2,arc->phi,left); if(r1+r2>=d){ // still have a valid solution x = (d*d - r1*r1 + r2*r2) / (2*d); c = sqrt(r2*r2 - x*x); if(angle>0){ // left of c1,c2 segment *new_x2 = cx1+xd/d*x + yd/d*c; *new_y2 = cy1+yd/d*x - xd/d*c; }else{ // right *new_x2 = cx1+xd/d*x - yd/d*c; *new_y2 = cy1+yd/d*x + xd/d*c; } }else{ // circles shrunk and no longer overlap. fprintf(stderr,_("region overlap adjustment failed in arc_arc_adj; \n" " This is an internal error that should never happen.\n")); } } static float phisub(float phi0, float phi1, float arcphi){ float phid = phi1-phi0; if(arcphi<0){ if(phid>0) phid -= M_PI*2.f; }else{ if(phid<0) phid += M_PI*2.f; } return phid; } static void radius_adj_xy(region_segment *s,float *x1,float *y1, int left){ float xd = *x1 - s->cx; float yd = *y1 - s->cy; float r = s->radius; float new_r = radius_adjust(r,s->phi,left); float delta = new_r/r; *x1 = s->cx + xd*delta; *y1 = s->cy + yd*delta; } static void adjust_layout(){ /* build adjustments from intersection region into layout region */ region_segment *s = r.l; region_segment *endpath = 0; region_segment *endpath_adj = 0; float x2=-1,y2=-1; // first, release previous layout region_segment *l=layout_adj.l; region_segment *le=l; while(le && le->next)le=le->next; if(le){ le->next=segpool; segpool=l; } memset(&layout_adj,0,sizeof(layout_adj)); while(s){ float x1=0,y1=0,phi=0,radius=0; if(s->cont){ if(!endpath){ endpath=s; endpath_adj=0; } } if(s->layout){ if(s->layout<3){ // the flags mark beginning and end of the path, but don't say // if it's closed. if(!s->cont && endpath_adj) if(endpath->x2 != s->x1 || endpath->y2 != s->y1) endpath_adj=0; /* first handle the lone-circle special case */ if(s->x1==s->x2 && s->y1==s->y2){ if(s->radius>0){ if(s->layout == 1) radius= s->radius+2; if(s->layout == 2) radius= s->radius-2; x1=x2=s->x1;y1=y2=s->y1; phi=s->phi; } }else{ region_segment *p = 0; if(s->cont) p = s->next; else if(endpath_adj) p = endpath; if(p){ if(s->radius){ if(x2==-1){ x2=s->x2; y2=s->y2; radius_adj_xy(s,&x2,&y2,s->layout==1); } if(p->radius){ // arc - arc case float phi0,phi1; arc_arc_adj(p,s,&x1,&y1,s->layout==1); phi0=line_angle(s->cx,s->cy,x1,y1); phi1=line_angle(s->cx,s->cy,x2,y2); phi=phisub(phi0,phi1,s->phi); }else{ // arc-line case float phi0,phi1; line_arc_adj(p->x1, p->y1, p->x2, p->y2, s->cx, s->cy, s->radius, s->phi, &x1, &y1, s->layout==1, s->layout==1); phi0=line_angle(s->cx,s->cy,x1,y1); phi1=line_angle(s->cx,s->cy,x2,y2); phi=phisub(phi0,phi1,s->phi); } }else{ if(x2==-1){ x2=s->x2; y2=s->y2; point_adj(s->x1, s->y1, s->x2, s->y2, &x2, &y2, s->layout==1); } if(p->radius){ // line-arc case line_arc_adj(s->x2, s->y2, s->x1, s->y1, p->cx, p->cy, p->radius, p->phi, &x1, &y1, s->layout==2, s->layout==1); }else{ // line-line case line_line_adj(p, s, &x1, &y1, s->layout==1); } } }else{ x1=s->x1; y1=s->y1; x2=s->x2; y2=s->y2; if(s->radius){ // lone arc case; alter radius radius_adj_xy(s,&x1,&y1,s->layout==1); radius_adj_xy(s,&x2,&y2,s->layout==1); phi=s->phi; }else{ // lone line segment case; offset point_adj(s->x1, s->y1, s->x2, s->y2, &x1, &y1, s->layout==1); point_adj(s->x1, s->y1, s->x2, s->y2, &x2, &y2, s->layout==1); } } } }else{ x1=s->x1; x2=s->x2; y1=s->y1; y2=s->y2; phi=s->phi; if(x1==x2 && y1==y2) radius = s->radius; } // push the region segment { region_segment *n=new_segment(&layout_adj,rint(x1),rint(y1),rint(x2),rint(y2)); n->layout=3; n->cont=(s->cont || endpath_adj); n->split = s->split; if(radius){ // circle; radius variable is treated as a flag n->cx=x1; n->cy=y1; n->radius=radius; n->phi0=-M_PI; n->phi1= M_PI; n->cont=1; }else if(s->radius){ // arc compute_arc(n,phi); } if(s->cont && !endpath_adj)endpath_adj=n; } if(endpath_adj && !s->cont){ // go back and clean up the endpath path member endpath_adj->x2 = rint(x1); endpath_adj->y2 = rint(y1); if(endpath->radius>0){ endpath_adj->phi1=line_angle(endpath->cx,endpath->cy,endpath_adj->x2,endpath_adj->y2); endpath_adj->phi=phisub(endpath_adj->phi0,endpath_adj->phi1,endpath_adj->phi); } } } if(!s->cont){ endpath_adj=0; endpath=0; x2=-1; y2=-1; }else{ x2=x1; y2=y1; } s=s->next; } } void region_init(){ // release any lines and arcs region_segment *l=r.l; region_segment *le=r.l; region_segment *a=layout_adj.l; region_segment *ae=layout_adj.l; while(le && le->next)le=le->next; while(ae && ae->next)ae=ae->next; if(le){ le->next=segpool; segpool=l; } if(ae){ ae->next=segpool; segpool=a; } memset(&r,0,sizeof(r)); memset(&layout_adj,0,sizeof(layout_adj)); } int region_layout(graph *g){ // count up the total length of the region segments used in layout float length=0,acc=0,ldel; int num_adj=g->vertex_num; int activenum=0; region_segment *l; vertex *v = g->verticies; adjust_layout(); l = layout_adj.l; while(l){ if(l->radius==0){ float xd=l->x2 - l->x1; float yd=l->y2 - l->y1; length += l->length = hypot(xd,yd); }else{ float diam = l->radius*2.f*M_PI; float del=phisub(l->phi0,l->phi1,l->phi); if(l->phi<0) del = -del; length += l->length = diam*del*(1.f/(M_PI*2.f)); } l=l->next; } // non-contiguous beginnings sink a single point segment per l = layout_adj.l; while(l){ if(!l->cont) num_adj--; l=l->next; } /* perform layout segment by segment */ l = layout_adj.l; ldel = (float)length/num_adj; while(l && v){ int i; int num_placed = l->cont ? rint((l->length-acc)/ldel) : rint((l->length-acc)/ldel)+1; float snap_del = l->cont ? l->length/num_placed : l->length/(num_placed-1); float snap_acc=l->cont?snap_del:0; if(l->split)activenum++; if(l->radius==0){ float x1 = l->x1; float y1 = l->y1; float x2 = l->x2; float y2 = l->y2; float xd=(x2-x1)/l->length; float yd=(y2-y1)/l->length; for(i=0;v && ix = rint(x1+xd*snap_acc); v->y = rint(y1+yd*snap_acc); if(snap_acc) acc+=ldel; snap_acc+=snap_del; v->active=activenum; v=v->next; } }else{ /* next is an arc */ float x = l->cx; float y = l->cy; float phid = phisub(l->phi0,l->phi1,l->phi); phid /= l->length; for(i=0;v && ix = rint( cos(l->phi0+phid*snap_acc)*(l->radius)+x); v->y = rint( -sin(l->phi0+phid*snap_acc)*(l->radius)+y); if(snap_acc) acc+=ldel; snap_acc+=snap_del; v->active=activenum; v=v->next; } } acc-=l->length; l=l->next; } return activenum; } void region_circle(int x,int y, float rad, int layout){ region_segment *a=new_segment(&r,0,0,0,0); a->cx=a->x1=a->x2=x; a->cy=a->y1=a->y2=y; a->radius=rad; a->phi0=-M_PI; a->phi1=M_PI; a->phi=M_PI*2.f; a->layout=layout; a->cont=0; // not really necessary, just consistent r.cont=0; } void region_new_area(int x, int y, int layout){ r.x=r.ox=x; r.y=r.oy=y; r.layout=layout; r.cont=0; } void region_line_to(int x,int y){ region_line(&r,r.x,r.y,x,y); r.x=x; r.y=y; r.cont=1; } void region_arc_to(int x,int y, float rad){ region_arc(&r,r.x,r.y,x,y,rad); r.x=x; r.y=y; r.cont=1; } void region_close_line(){ region_line(&r,r.x,r.y,r.ox,r.oy); r.x=r.ox; r.y=r.oy; r.cont=0; } void region_close_arc(float rad){ region_arc(&r,r.x,r.y,r.ox,r.oy,rad); r.x=r.ox; r.y=r.oy; r.cont=0; } void region_split_here(){ r.split_next=1; } int region_intersects(edge *e){ region_segment *s=r.l; while(s){ if(s->layout<3){ if(s->radius!=0){ if(intersects_arc(e,s))return 1; }else{ double xdummy,ydummy; if(intersects(e->A->x,e->A->y,e->B->x,e->B->y, s->x1,s->y1,s->x2,s->y2, &xdummy,&ydummy))return 1; } } s=s->next; } return 0; } int have_region(){ if(r.l)return 1; return 0; } gplanarity-master/graph_region.h000066400000000000000000000027471510662254600173570ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef GRAPH_REGION #define GRAPH_REGION #include "nls.h" extern void region_init(); extern int region_intersects(edge *e); extern int region_layout(graph *g); extern void region_circle(int x,int y, float rad, int layout); extern void region_new_area(int x, int y, int layout); extern void region_line_to(int x,int y); extern void region_arc_to(int x,int y, float rad); extern void region_close_line(); extern void region_close_arc(float rad); extern int have_region(); extern void region_split_here(); #endif /* GRAPH_REGION */ gplanarity-master/graph_score.c000066400000000000000000000045371510662254600172010ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include #include #include "graph.h" #include "timer.h" #include "nls.h" static char objective_string[160]; int graphscore_get_raw_score(graph *g){ return (int)ceil((g->original_intersections- g->active_intersections)* g->intersection_mult); } int graphscore_get_multiplier_percent(graph *g){ float obj_multiplier = 100; if(g->objective_lessthan) if(g->objective > g->active_intersections) obj_multiplier += 100.f * g->objective_mult / g->objective * (g->objective - g->active_intersections); return ceil(obj_multiplier); } int graphscore_get_score(graph *g){ return graphscore_get_raw_score(g)*graphscore_get_multiplier_percent(g)/100; } int graphscore_get_bonus(graph *g){ int obj_multiplier = graphscore_get_multiplier_percent(g); if(get_timer()< g->original_intersections*g->intersection_mult) return ceil ((g->original_intersections*g->intersection_mult-get_timer()) * obj_multiplier / 100); return 0; } char *graphscore_objective_string(graph *g){ if(g->objective == 0) return _("zero intersections"); if(g->objective == 1){ if(g->objective_lessthan){ return _("1 intersection or fewer"); }else{ return _("1 intersection"); } }else{ snprintf(objective_string,160,_("%d intersections%s"), g->objective,(g->objective_lessthan? _(" or fewer"):"")); return objective_string; } } gplanarity-master/icon.h000066400000000000000000002374161510662254600156460ustar00rootroot00000000000000#ifndef ICON_H #define ICON_H static unsigned char icon32[]={ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7a, 0x7a, 0xf4, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc4, 0x00, 0x00, 0x0e, 0xc4, 0x01, 0x95, 0x2b, 0x0e, 0x1b, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5, 0x0a, 0x11, 0x00, 0x19, 0x33, 0x08, 0xe2, 0xc7, 0x69, 0x00, 0x00, 0x08, 0xd9, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xad, 0x57, 0x69, 0x50, 0x53, 0xe7, 0x1a, 0x7e, 0xce, 0x49, 0x48, 0x42, 0x36, 0x41, 0x83, 0x08, 0x22, 0x45, 0x63, 0x24, 0x01, 0x83, 0x90, 0x70, 0x91, 0x45, 0x14, 0xbd, 0x2d, 0x35, 0xa1, 0xbd, 0x08, 0x83, 0x0b, 0x5a, 0x9d, 0x4e, 0xad, 0xf6, 0x2a, 0x0c, 0x9d, 0xab, 0xd3, 0x4e, 0x5b, 0x47, 0x6f, 0xa5, 0xd8, 0x3a, 0x5a, 0x1d, 0x3b, 0x56, 0xc7, 0x32, 0xad, 0x52, 0xac, 0xb6, 0xa2, 0xdc, 0x72, 0x5d, 0x28, 0x88, 0xc5, 0x5b, 0x50, 0x5c, 0x28, 0x28, 0xa6, 0x5a, 0x14, 0x17, 0x16, 0xd9, 0x43, 0x24, 0x24, 0x07, 0xc2, 0x49, 0x4e, 0xbe, 0xfb, 0x83, 0x4e, 0x46, 0x3b, 0xe3, 0x42, 0xf5, 0xf9, 0x77, 0xe6, 0xbc, 0xdf, 0x3b, 0xcf, 0xf7, 0xbd, 0xcf, 0xbb, 0xf1, 0xf0, 0x17, 0x61, 0x34, 0x1a, 0x35, 0x1c, 0xa7, 0xda, 0x27, 0x97, 0xcf, 0x78, 0x5b, 0xa3, 0x19, 0xdb, 0x77, 0xff, 0x7e, 0x6b, 0xd3, 0x5f, 0xf1, 0xc3, 0x7b, 0x9a, 0x41, 0x69, 0x69, 0xa9, 0xa4, 0xb6, 0xb6, 0x79, 0xb3, 0x50, 0x38, 0x67, 0x73, 0x40, 0x80, 0x4c, 0x75, 0xf0, 0xe0, 0x57, 0x17, 0xb5, 0x5a, 0x2d, 0x5d, 0x56, 0xe6, 0xfc, 0xd9, 0xd7, 0xb7, 0x70, 0x8e, 0x44, 0x92, 0xa9, 0xec, 0xee, 0xee, 0x49, 0x7b, 0xed, 0xb5, 0x09, 0xc7, 0x4c, 0x26, 0x53, 0x9f, 0x4e, 0x97, 0xb0, 0xd2, 0xcb, 0x6b, 0xf6, 0x6e, 0x3f, 0xbf, 0xc0, 0xbf, 0xa7, 0xa4, 0xc4, 0x5f, 0xba, 0x76, 0xed, 0x9a, 0xed, 0x49, 0xfe, 0xa9, 0xa7, 0x11, 0x50, 0xab, 0xe3, 0x36, 0xf2, 0x78, 0x5f, 0xe7, 0x8a, 0x44, 0x61, 0x70, 0x38, 0x1a, 0xe1, 0x72, 0xbd, 0xf5, 0xb1, 0x4a, 0x35, 0xee, 0xab, 0x1b, 0x37, 0x5e, 0xed, 0xf4, 0xf5, 0xcd, 0x06, 0x00, 0x0c, 0x0e, 0xd6, 0x81, 0x90, 0x37, 0x32, 0x03, 0x03, 0x03, 0xcd, 0xcd, 0xcd, 0x6f, 0x97, 0xfb, 0xfa, 0x66, 0xd2, 0x1c, 0x37, 0x00, 0xbb, 0x7d, 0xe5, 0x99, 0xdb, 0xb7, 0x8f, 0xbd, 0xf2, 0x24, 0xff, 0xf4, 0xd3, 0x08, 0x58, 0xad, 0x8a, 0x68, 0x91, 0x48, 0x03, 0x00, 0x10, 0x89, 0x42, 0x11, 0x16, 0x36, 0x37, 0xa7, 0xa4, 0xa4, 0xa4, 0x6e, 0xfa, 0xf4, 0x5e, 0x70, 0x9c, 0x15, 0x84, 0x38, 0x41, 0xd3, 0xe5, 0xa8, 0xae, 0xae, 0xde, 0x9f, 0x9c, 0x9c, 0x7c, 0x58, 0x2e, 0x37, 0xd0, 0x00, 0xc0, 0xe3, 0xc9, 0xe1, 0x74, 0x4e, 0x8b, 0x1e, 0x75, 0x08, 0x56, 0xac, 0x58, 0xe1, 0xed, 0x74, 0x3a, 0x0d, 0x6a, 0xb5, 0x7a, 0x42, 0x78, 0x78, 0x78, 0x1b, 0x30, 0x30, 0x61, 0x70, 0x50, 0xf5, 0xaa, 0x40, 0x30, 0x09, 0x0c, 0x73, 0x01, 0xab, 0x57, 0x8b, 0xbc, 0x23, 0x23, 0x23, 0x64, 0x2f, 0xbf, 0x3c, 0x1d, 0x16, 0x4b, 0x01, 0xc6, 0x8f, 0x3f, 0x87, 0x4f, 0x3f, 0x7d, 0x0d, 0x93, 0x27, 0x4f, 0xf6, 0x52, 0x28, 0x14, 0x92, 0xc2, 0xc2, 0x13, 0x10, 0x08, 0xa2, 0xe0, 0x72, 0x75, 0x40, 0x2c, 0x3e, 0x52, 0xd9, 0xd5, 0x75, 0xfd, 0xf0, 0x82, 0x05, 0x0b, 0xc2, 0xed, 0x76, 0x7b, 0x62, 0x5a, 0x5a, 0xda, 0x83, 0x86, 0x86, 0x06, 0xfb, 0x63, 0xd9, 0x2c, 0x5b, 0xb6, 0x4c, 0xac, 0x54, 0x66, 0xfe, 0x1a, 0x1a, 0x5a, 0x45, 0xa6, 0x4e, 0x2d, 0x26, 0xb3, 0x67, 0x2f, 0x29, 0x70, 0xbb, 0xdd, 0xd5, 0x87, 0x0f, 0x1f, 0x25, 0xab, 0x56, 0xe5, 0x91, 0x43, 0x87, 0x8e, 0x12, 0xb7, 0xdb, 0x4d, 0x9e, 0x84, 0xf3, 0xe7, 0x6b, 0xc8, 0x9a, 0x35, 0x5b, 0xc8, 0xb6, 0x6d, 0x7b, 0x09, 0xc3, 0x30, 0xb6, 0x1d, 0x3b, 0x76, 0x1f, 0x08, 0x09, 0xd9, 0xe5, 0xd0, 0x68, 0x6a, 0x49, 0x48, 0xc8, 0xfa, 0xde, 0x39, 0x73, 0x92, 0x34, 0x8f, 0x25, 0x10, 0x1e, 0x1e, 0x9e, 0x1a, 0x1a, 0x7a, 0x9e, 0xe8, 0xf5, 0x84, 0xe8, 0xf5, 0x84, 0xa8, 0xd5, 0x3b, 0x88, 0xdd, 0x6e, 0x27, 0xcf, 0x83, 0xd4, 0xd4, 0x4f, 0x3c, 0xfe, 0x22, 0x23, 0x6d, 0x24, 0x38, 0x38, 0x66, 0xe7, 0x63, 0x35, 0x30, 0x66, 0xcc, 0x18, 0xc6, 0xed, 0x7e, 0xe0, 0xf9, 0x16, 0x89, 0x58, 0xf0, 0xf9, 0x7c, 0x3c, 0x0f, 0xa4, 0x52, 0x0a, 0x84, 0xb8, 0x00, 0x00, 0x6e, 0xb7, 0x0d, 0x22, 0x11, 0x6d, 0x7f, 0xac, 0x06, 0xb4, 0x5a, 0x6d, 0x8b, 0xc3, 0xd1, 0xa0, 0x64, 0x18, 0x4b, 0x04, 0x4d, 0xff, 0x0f, 0x9b, 0x36, 0x85, 0x41, 0xab, 0x0d, 0x7b, 0x2e, 0x02, 0x6a, 0xb5, 0x1f, 0xca, 0xca, 0xf6, 0xc1, 0x6c, 0xbe, 0x05, 0xb9, 0xfc, 0x48, 0x53, 0x50, 0x10, 0xbb, 0xba, 0xa9, 0xa9, 0x69, 0xf0, 0xcf, 0x45, 0x45, 0xaa, 0x52, 0xa9, 0x96, 0x6b, 0xb5, 0xda, 0x45, 0x0e, 0x87, 0x63, 0x9f, 0xd9, 0x6c, 0x26, 0x36, 0x9b, 0x8d, 0xbc, 0x28, 0x0c, 0x0f, 0x0f, 0x93, 0xce, 0xce, 0x4e, 0xc2, 0x71, 0x9c, 0x25, 0x27, 0x27, 0x27, 0x33, 0x20, 0x20, 0x60, 0x75, 0x4a, 0x4a, 0x4a, 0x10, 0x00, 0x50, 0x05, 0x05, 0x05, 0x82, 0xdc, 0xdc, 0xf2, 0x8b, 0x22, 0xd1, 0x07, 0x51, 0x6e, 0x37, 0x83, 0xb9, 0x73, 0xcf, 0x62, 0xef, 0xde, 0x8f, 0x46, 0x7d, 0xd3, 0x86, 0x86, 0x06, 0xec, 0xdc, 0xf9, 0x23, 0x28, 0x6a, 0x24, 0xaa, 0x7c, 0x3e, 0x1f, 0x13, 0x26, 0x8c, 0xc7, 0xdc, 0xb9, 0x93, 0x31, 0x6f, 0xde, 0x3c, 0x50, 0x14, 0x85, 0x82, 0x82, 0x1f, 0xf0, 0xd9, 0x67, 0x7c, 0x08, 0x04, 0x3a, 0x30, 0xcc, 0x3e, 0x6b, 0x48, 0x48, 0x9d, 0x8e, 0xd7, 0xdc, 0xdc, 0x3c, 0xdb, 0xe5, 0x5a, 0xff, 0x81, 0x54, 0x9a, 0x00, 0x81, 0x60, 0x12, 0x7e, 0xff, 0xfd, 0x26, 0x32, 0x32, 0x02, 0x20, 0x93, 0xc9, 0x46, 0x45, 0xa0, 0xb0, 0xf0, 0x04, 0x2a, 0x2b, 0xb3, 0x70, 0xff, 0x7e, 0x30, 0x1a, 0x1b, 0xdb, 0xd1, 0xd3, 0xf3, 0x2a, 0x5a, 0x5a, 0xe6, 0xe3, 0xd4, 0xa9, 0x21, 0x10, 0x72, 0x1a, 0x31, 0x31, 0x11, 0x78, 0xf7, 0xdd, 0x12, 0x50, 0xd4, 0x3f, 0xc1, 0xe7, 0xfb, 0x42, 0x20, 0x98, 0x29, 0x6a, 0x6d, 0xdd, 0xfa, 0x80, 0x56, 0x2a, 0x95, 0x7d, 0x1c, 0xd7, 0xf1, 0x90, 0xf0, 0xac, 0x90, 0x4a, 0xa5, 0x7f, 0x2a, 0x46, 0x56, 0x1c, 0x39, 0x72, 0x04, 0xbb, 0x77, 0xef, 0x46, 0x65, 0x65, 0x25, 0x5a, 0x5a, 0x5a, 0x50, 0x57, 0x57, 0x87, 0xdb, 0xb7, 0x6f, 0x7b, 0x6c, 0x7e, 0xfd, 0xd5, 0x01, 0x9a, 0x16, 0x21, 0x28, 0xe8, 0x14, 0xae, 0x5d, 0x5b, 0x8e, 0x82, 0x82, 0x61, 0x10, 0x52, 0x0a, 0xa1, 0x30, 0x1c, 0x45, 0x45, 0x3d, 0x00, 0x00, 0x85, 0x82, 0x80, 0x10, 0x0e, 0x00, 0xe0, 0x74, 0xde, 0xc7, 0xd8, 0xb1, 0x3e, 0x7d, 0xfc, 0xe2, 0xe2, 0xe2, 0x6b, 0x6a, 0x75, 0xf7, 0x46, 0xab, 0xb5, 0x63, 0x83, 0x4c, 0x46, 0x89, 0x72, 0x73, 0x67, 0x3c, 0x72, 0xfb, 0xaa, 0xaa, 0x2a, 0xac, 0x5b, 0xd7, 0x08, 0x96, 0x35, 0x82, 0xcf, 0xf7, 0x01, 0xcb, 0xde, 0x03, 0xd0, 0x84, 0xe1, 0xe1, 0x61, 0xa4, 0xa5, 0x55, 0x62, 0xdb, 0xb6, 0xf7, 0xc0, 0x30, 0x0c, 0x1a, 0x1b, 0x25, 0x10, 0x08, 0x00, 0xbd, 0x9e, 0x82, 0x8f, 0x8f, 0x0f, 0xf4, 0x7a, 0x1d, 0x14, 0x8a, 0x72, 0xf4, 0xf5, 0x01, 0x2e, 0x17, 0x01, 0x00, 0xe4, 0xe5, 0x65, 0x20, 0x2b, 0x2b, 0x17, 0x2d, 0x2d, 0x62, 0xf0, 0xf9, 0xe7, 0xff, 0x13, 0x16, 0xf6, 0x52, 0x3e, 0x1f, 0x00, 0x1a, 0x1b, 0xcf, 0xe5, 0xf5, 0xf7, 0x9f, 0xfc, 0x5d, 0x22, 0x91, 0x1c, 0x7b, 0x38, 0xed, 0x5a, 0x5b, 0x5b, 0x91, 0x93, 0x73, 0x17, 0x14, 0xb5, 0x04, 0x5a, 0xed, 0x5e, 0x64, 0x64, 0x68, 0x61, 0xb1, 0x58, 0xb0, 0x75, 0x2b, 0x1f, 0x62, 0x71, 0x12, 0x62, 0x63, 0x59, 0x4f, 0xfc, 0x5d, 0xae, 0x19, 0x70, 0xbb, 0x6f, 0x22, 0x21, 0x41, 0x0d, 0xbb, 0xdd, 0x8e, 0x83, 0x07, 0x8f, 0xa3, 0xbd, 0x7d, 0x06, 0x84, 0x42, 0x27, 0x66, 0xce, 0x1c, 0x79, 0x51, 0x8d, 0x46, 0x83, 0x33, 0x67, 0xfe, 0x0d, 0x96, 0x65, 0xeb, 0x2f, 0x5c, 0x88, 0xc9, 0x98, 0x37, 0x6f, 0xde, 0x08, 0xb3, 0xd8, 0xd8, 0xd8, 0xf9, 0x46, 0xa3, 0xf1, 0xb0, 0xc9, 0x64, 0x7a, 0x44, 0xbd, 0x1f, 0x7e, 0xf8, 0x25, 0xd1, 0xe9, 0x9c, 0x24, 0x3d, 0x7d, 0x27, 0xe1, 0x38, 0x8e, 0x10, 0x42, 0x48, 0x7d, 0x7d, 0x3d, 0xd1, 0x68, 0xea, 0x88, 0x46, 0xf3, 0x23, 0x69, 0x6d, 0x6d, 0x25, 0x84, 0x10, 0xb2, 0x7d, 0xfb, 0xd7, 0x24, 0x2a, 0x8a, 0x21, 0x91, 0x91, 0x56, 0x32, 0x69, 0xd2, 0x27, 0x64, 0xda, 0xb4, 0x12, 0xa2, 0xd5, 0xde, 0x23, 0x3a, 0x9d, 0x93, 0x24, 0x26, 0x7e, 0x4c, 0xba, 0xba, 0xba, 0x3c, 0x3e, 0xbb, 0xbb, 0xbb, 0x49, 0x5e, 0x5e, 0x5e, 0xbb, 0x56, 0xab, 0x5d, 0x65, 0x30, 0x18, 0x28, 0x3a, 0x3a, 0x7a, 0xd6, 0xaa, 0xde, 0xde, 0xf5, 0x3f, 0x75, 0x76, 0x16, 0x67, 0xa6, 0xa5, 0x9d, 0x47, 0x4d, 0xcd, 0x05, 0xcf, 0x0b, 0xd4, 0xd6, 0x0a, 0x41, 0x51, 0x7c, 0xa4, 0xa7, 0x07, 0x83, 0xa6, 0x47, 0xd4, 0x5d, 0x53, 0xd3, 0x00, 0xb1, 0x58, 0x07, 0x3f, 0xbf, 0x36, 0x04, 0x05, 0x05, 0xfd, 0x61, 0x37, 0x08, 0x9a, 0x16, 0x83, 0x61, 0xce, 0x01, 0x20, 0xa0, 0xe9, 0x3b, 0x08, 0x0a, 0x3a, 0x89, 0xcc, 0xcc, 0x7c, 0x94, 0x96, 0xae, 0x87, 0xbf, 0xbf, 0x3f, 0x00, 0xc0, 0x62, 0xb1, 0x20, 0x39, 0xf9, 0x0b, 0x1c, 0x3b, 0x96, 0x1d, 0xc8, 0x71, 0x07, 0xf3, 0xef, 0xdd, 0xc3, 0x41, 0x7e, 0x77, 0x77, 0xf0, 0x1b, 0xe3, 0xc7, 0x67, 0x00, 0x00, 0xe4, 0xf2, 0x95, 0xf8, 0xe1, 0x87, 0xed, 0x88, 0x8f, 0x8f, 0x03, 0x00, 0xf4, 0xf4, 0xf4, 0xc0, 0xcb, 0x0b, 0x10, 0x0a, 0x85, 0x0f, 0x89, 0x6d, 0xa4, 0xbd, 0xeb, 0x74, 0x52, 0x50, 0x14, 0x05, 0x86, 0x61, 0x70, 0xf3, 0xa6, 0x04, 0x7c, 0x3e, 0xb0, 0x70, 0x61, 0x13, 0xb6, 0x6c, 0xd9, 0xf8, 0xd8, 0x4c, 0x29, 0x2b, 0x2b, 0x03, 0xc7, 0xad, 0x84, 0x50, 0x38, 0x06, 0xde, 0xde, 0x33, 0xd0, 0xdf, 0x1f, 0xb7, 0x8c, 0x2f, 0x12, 0x99, 0x5b, 0x38, 0xce, 0x0a, 0x1e, 0x6f, 0x0c, 0x9c, 0xce, 0x76, 0x28, 0x95, 0x0a, 0xcf, 0x81, 0x80, 0x00, 0x09, 0xcc, 0x66, 0x60, 0xe7, 0x4e, 0x33, 0x4c, 0xa6, 0x0a, 0xdc, 0xb9, 0x73, 0x17, 0x57, 0xae, 0x44, 0x40, 0x20, 0xb0, 0x42, 0xaf, 0x1f, 0x11, 0xaa, 0xc9, 0x64, 0x02, 0xcb, 0x6a, 0xe1, 0x72, 0xdd, 0x42, 0x7c, 0x7c, 0xe8, 0x13, 0x53, 0x55, 0xa9, 0x54, 0x82, 0x65, 0xaf, 0x43, 0x28, 0x9c, 0x02, 0xc0, 0x0d, 0x1e, 0xaf, 0xbb, 0x85, 0x9e, 0x35, 0x6b, 0xe2, 0x07, 0x36, 0xdb, 0xca, 0xd3, 0x66, 0xf3, 0x47, 0xd6, 0xa4, 0xa4, 0xef, 0xdd, 0xef, 0xbc, 0xb3, 0xdc, 0x73, 0xe0, 0xfd, 0xf7, 0xa3, 0x01, 0x14, 0xc2, 0x6c, 0x1e, 0x87, 0xa2, 0x22, 0x0b, 0xfa, 0xfa, 0x3a, 0xc0, 0xe3, 0x4d, 0x06, 0xcb, 0xd6, 0x22, 0x2e, 0x2e, 0x0a, 0x00, 0x50, 0x5d, 0x5d, 0x0b, 0x87, 0xa3, 0x09, 0x03, 0x03, 0xfb, 0x11, 0x1b, 0xfb, 0xb7, 0x27, 0x12, 0x98, 0x39, 0x73, 0x26, 0x72, 0x72, 0xfa, 0x30, 0x34, 0xb4, 0x71, 0x70, 0x60, 0x60, 0x4d, 0xa3, 0x5c, 0x7e, 0x79, 0xb1, 0xe7, 0x27, 0xcb, 0xb2, 0x94, 0xc5, 0x62, 0xa9, 0x66, 0x18, 0x86, 0x10, 0x42, 0xc8, 0xe0, 0xe0, 0x20, 0xb9, 0x7c, 0xf9, 0x32, 0xe9, 0xed, 0xed, 0x25, 0x26, 0x93, 0x89, 0xdc, 0xba, 0x75, 0x8b, 0x64, 0x65, 0xe5, 0x91, 0xa8, 0x28, 0x3b, 0x49, 0x4d, 0xdd, 0xea, 0x69, 0xcb, 0x6d, 0x6d, 0x6d, 0xe4, 0xea, 0xd5, 0xab, 0xe4, 0xfa, 0xf5, 0xeb, 0x4f, 0x6d, 0xd5, 0x2c, 0xcb, 0x12, 0x8b, 0xc5, 0x42, 0x9c, 0x4e, 0x67, 0xe2, 0x23, 0x23, 0x99, 0xd1, 0x68, 0xa4, 0xee, 0xdc, 0x71, 0x6c, 0xe7, 0x38, 0x63, 0x8e, 0x44, 0xc2, 0x79, 0x6d, 0xd8, 0x10, 0x8a, 0x90, 0x90, 0x40, 0x2c, 0x59, 0x72, 0x17, 0x0a, 0x85, 0x00, 0xbe, 0xbe, 0x3e, 0xe8, 0xed, 0xed, 0x85, 0xcb, 0x95, 0x00, 0x8a, 0xfa, 0x2f, 0x0a, 0x0b, 0x67, 0x21, 0x22, 0x22, 0x62, 0x54, 0x95, 0xd2, 0x64, 0xfa, 0x0d, 0x6b, 0xd7, 0x16, 0xa3, 0xa3, 0x63, 0x2c, 0x68, 0xfa, 0x97, 0x0a, 0x8d, 0x86, 0x4d, 0x3f, 0x71, 0xe2, 0x84, 0x9d, 0x07, 0x00, 0x53, 0xa6, 0x4c, 0x89, 0x31, 0x9b, 0xdf, 0xda, 0xef, 0xe3, 0xb3, 0x9a, 0x47, 0xd3, 0x09, 0x38, 0x7b, 0xf6, 0x14, 0x92, 0x92, 0x7c, 0xd0, 0xd9, 0x69, 0x81, 0xdd, 0xde, 0x0e, 0x9b, 0xad, 0x19, 0x7e, 0x7e, 0x34, 0x12, 0x13, 0x6f, 0xe3, 0xf3, 0xcf, 0xe7, 0x23, 0x34, 0x34, 0x74, 0xd4, 0xbd, 0x22, 0x3b, 0x3b, 0x1f, 0x3d, 0x3d, 0x1b, 0xe0, 0xed, 0x1d, 0x0b, 0x8a, 0x8a, 0x56, 0x9a, 0xcd, 0xdf, 0xf4, 0x9b, 0xcd, 0x9d, 0x35, 0x7c, 0x00, 0xe8, 0xee, 0xee, 0x1e, 0x43, 0xd3, 0x7e, 0x1e, 0xe3, 0xe1, 0x61, 0x31, 0xa2, 0xa2, 0xa2, 0x50, 0x54, 0xf4, 0x32, 0x5e, 0x14, 0xfa, 0xfb, 0x01, 0x8a, 0xe2, 0xfd, 0xd1, 0xa8, 0xc6, 0xc1, 0x6a, 0x75, 0xc8, 0x3d, 0x03, 0x89, 0xc1, 0x60, 0xa8, 0x72, 0xbb, 0xbf, 0xb9, 0xcc, 0x30, 0x17, 0x61, 0xb3, 0x9d, 0x46, 0x5c, 0x5c, 0x5b, 0xd3, 0xb8, 0x71, 0xe3, 0x08, 0x5e, 0x20, 0xde, 0x7c, 0x53, 0xfd, 0xe0, 0xc1, 0x83, 0xfd, 0xae, 0xa1, 0x21, 0x13, 0xac, 0xd6, 0xdc, 0x3e, 0xa5, 0xd2, 0xbf, 0xe0, 0x91, 0xb1, 0x3c, 0x2d, 0x2d, 0x4d, 0xdc, 0xd8, 0xd8, 0x68, 0x90, 0x4a, 0xa5, 0x4c, 0x76, 0x76, 0xf6, 0xd9, 0x89, 0x13, 0x83, 0x8a, 0x4f, 0x9e, 0xbc, 0x9c, 0xe2, 0xef, 0x2f, 0x43, 0x56, 0xd6, 0x8a, 0x51, 0x77, 0x47, 0x8e, 0xe3, 0xf0, 0xdd, 0x77, 0x47, 0x71, 0xe9, 0xd2, 0x1d, 0x24, 0x27, 0xcf, 0x60, 0x5e, 0x7f, 0xdd, 0x30, 0xc7, 0x60, 0x30, 0xf0, 0x6e, 0xdc, 0xb8, 0x31, 0x35, 0x21, 0x21, 0xa1, 0xb2, 0xa8, 0xa8, 0xa8, 0xeb, 0xb1, 0x87, 0x53, 0x53, 0x53, 0x43, 0x43, 0x42, 0xb6, 0xd8, 0x75, 0xba, 0x61, 0x12, 0x11, 0xd1, 0x45, 0x96, 0x2f, 0xdf, 0x3c, 0xea, 0x21, 0xe4, 0xcb, 0x2f, 0xf7, 0x13, 0x8d, 0xa6, 0x96, 0xe8, 0x74, 0x2e, 0xa2, 0x52, 0x1d, 0x77, 0x47, 0x46, 0xc6, 0x2f, 0x7b, 0xe6, 0xbd, 0xa0, 0xa6, 0xa6, 0x26, 0x5e, 0x2a, 0x5d, 0x2c, 0xa1, 0x28, 0x01, 0xbc, 0xbc, 0xfc, 0x71, 0xee, 0x9c, 0x17, 0x38, 0x8e, 0xf3, 0x14, 0x9e, 0xfc, 0xfc, 0x7c, 0xdc, 0xbd, 0x7b, 0xf7, 0xa1, 0xf8, 0xf6, 0xe3, 0xdb, 0x6f, 0xbf, 0x45, 0x45, 0x45, 0x05, 0x08, 0x19, 0x89, 0x5c, 0x45, 0xc5, 0x7d, 0x88, 0xc5, 0xd1, 0xa0, 0x28, 0x1e, 0x64, 0x32, 0x03, 0xd5, 0xd9, 0xc9, 0x7f, 0xe5, 0x99, 0x09, 0xe8, 0xf5, 0xfa, 0xdf, 0x18, 0xe6, 0x67, 0x27, 0x00, 0x10, 0xe2, 0x00, 0x8f, 0x77, 0xf3, 0x2a, 0x45, 0x51, 0xef, 0x15, 0x17, 0x97, 0xb4, 0xa7, 0xa7, 0x5f, 0xc1, 0x9e, 0x3d, 0xff, 0x80, 0xd1, 0x78, 0x1c, 0xf5, 0xf5, 0x57, 0x30, 0x30, 0x30, 0x00, 0x83, 0x61, 0x1b, 0x76, 0xec, 0x48, 0x42, 0x4e, 0x8e, 0x08, 0x9b, 0x36, 0xed, 0x72, 0x02, 0xf8, 0x9e, 0x61, 0x6e, 0x1e, 0x65, 0xd9, 0x36, 0x00, 0xc0, 0xd0, 0x50, 0x3d, 0xfc, 0xfc, 0x5c, 0x75, 0xa3, 0x5a, 0xcd, 0xf4, 0xfa, 0x59, 0x4b, 0xcd, 0xe6, 0x90, 0xb5, 0x5e, 0x5e, 0x03, 0xe6, 0x69, 0xd3, 0xb8, 0xf7, 0x4a, 0x4b, 0x4f, 0x35, 0x05, 0x07, 0x2f, 0xfd, 0xc5, 0xcf, 0xef, 0xd0, 0xec, 0x11, 0x62, 0x2c, 0x22, 0x23, 0x3f, 0xe9, 0x8a, 0x8b, 0x7b, 0xc9, 0xb6, 0x6b, 0x57, 0xa2, 0x4a, 0x24, 0x0a, 0xfd, 0x63, 0x78, 0xc9, 0x23, 0x0a, 0xc5, 0x29, 0xfe, 0xe2, 0xc5, 0x8b, 0xe5, 0x7b, 0xf6, 0x1c, 0xcf, 0x1b, 0x1a, 0x0a, 0x8e, 0x96, 0xcb, 0xef, 0x95, 0x6d, 0xde, 0x9c, 0xbd, 0x75, 0xd1, 0xa2, 0x45, 0x8e, 0x51, 0xef, 0x86, 0x0f, 0x43, 0xa5, 0x4a, 0x29, 0x92, 0x4a, 0x8f, 0x2e, 0xa4, 0x69, 0x6f, 0x38, 0x9d, 0x1d, 0x60, 0xd9, 0xcc, 0x6d, 0xbe, 0xbe, 0xce, 0xaa, 0xbe, 0xbe, 0x4d, 0x27, 0x65, 0xb2, 0xf9, 0x00, 0x00, 0xbb, 0x7d, 0x5d, 0x57, 0x7c, 0x7c, 0x7f, 0xe0, 0x81, 0x03, 0x07, 0x9e, 0x29, 0x8b, 0x78, 0xa3, 0x21, 0x90, 0x94, 0xa4, 0xad, 0x6d, 0x6d, 0x2d, 0x4d, 0x60, 0x98, 0xeb, 0x13, 0xdd, 0xee, 0x03, 0xe5, 0x31, 0x31, 0x8a, 0x7f, 0x01, 0x30, 0xf5, 0xf7, 0x57, 0xc9, 0x06, 0x07, 0x9b, 0x63, 0x9c, 0xce, 0x92, 0x1e, 0x91, 0xa8, 0x6a, 0x69, 0x79, 0xf9, 0x4f, 0xf7, 0x9e, 0xd5, 0xe7, 0xff, 0x01, 0x15, 0x6f, 0x09, 0x08, 0x2b, 0xc2, 0x8e, 0x36, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; #if 0 static unsigned char icon134[]={ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x86, 0x08, 0x06, 0x00, 0x00, 0x00, 0x18, 0x79, 0xf2, 0x91, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc4, 0x00, 0x00, 0x0e, 0xc4, 0x01, 0x95, 0x2b, 0x0e, 0x1b, 0x00, 0x00, 0x13, 0xa2, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x5d, 0x7b, 0x50, 0x14, 0x57, 0xba, 0xff, 0xf5, 0x3c, 0x14, 0x1c, 0x40, 0x86, 0xc4, 0xc5, 0x2b, 0x83, 0xb2, 0x42, 0x56, 0x9d, 0x19, 0xbc, 0x0e, 0x23, 0xb8, 0x26, 0xa8, 0x51, 0x63, 0x14, 0xd0, 0x80, 0x2b, 0x56, 0xa2, 0xae, 0x31, 0x9b, 0x58, 0xc9, 0xdd, 0x1b, 0x22, 0xc6, 0xd4, 0x1a, 0xd7, 0x64, 0xeb, 0xd6, 0xee, 0xc6, 0x4d, 0xb2, 0xb5, 0x46, 0xc5, 0xca, 0x63, 0x2b, 0x31, 0x15, 0xad, 0x75, 0x89, 0xa5, 0xf8, 0x48, 0x0c, 0xe8, 0x4a, 0x15, 0x61, 0x56, 0x13, 0x79, 0x0c, 0xbe, 0x06, 0x88, 0x96, 0xc8, 0x43, 0x7c, 0x60, 0xa2, 0x83, 0x3c, 0xe5, 0x35, 0xe7, 0xfe, 0x81, 0x3d, 0x8b, 0x08, 0xd3, 0x67, 0x66, 0xba, 0x7b, 0x7a, 0xa0, 0x7f, 0x55, 0x5d, 0x25, 0xce, 0xe9, 0xaf, 0x4f, 0x7f, 0xdf, 0xaf, 0xcf, 0xf9, 0xce, 0x77, 0xbe, 0x73, 0x0e, 0x30, 0x8c, 0x41, 0x08, 0xb9, 0x40, 0x06, 0xc7, 0x85, 0xe1, 0xac, 0x1b, 0x66, 0x98, 0x12, 0x82, 0xb8, 0xa5, 0x24, 0x86, 0x19, 0x76, 0x7a, 0x52, 0x0c, 0x67, 0x52, 0x94, 0x94, 0x94, 0x60, 0xfd, 0xfa, 0xf5, 0x30, 0x1a, 0x8d, 0x08, 0x0a, 0x0a, 0x42, 0x50, 0x50, 0x10, 0x8c, 0x46, 0x23, 0xd6, 0xaf, 0x5f, 0x8f, 0x92, 0x92, 0x12, 0x8f, 0x89, 0x24, 0xc3, 0x0f, 0x49, 0x41, 0x08, 0x21, 0x97, 0x2f, 0x5f, 0x26, 0x49, 0x49, 0x49, 0x04, 0x80, 0xcb, 0x2b, 0x29, 0x29, 0x89, 0x5c, 0xbe, 0x7c, 0xd9, 0xd9, 0xb7, 0xc8, 0x1a, 0x1c, 0x82, 0x7e, 0x00, 0x7b, 0x43, 0x61, 0x61, 0x21, 0xd1, 0x6a, 0xb5, 0x04, 0x00, 0x51, 0xab, 0x23, 0x88, 0x4e, 0xb7, 0x95, 0xe8, 0xf5, 0x36, 0x62, 0x32, 0xb5, 0x10, 0x93, 0xa9, 0x85, 0xe8, 0xf5, 0x36, 0xa2, 0xd3, 0x6d, 0x25, 0x6a, 0x75, 0x04, 0x01, 0x40, 0xb4, 0x5a, 0x2d, 0x29, 0x2c, 0x2c, 0x74, 0x9b, 0x1c, 0xfe, 0xee, 0xbf, 0x30, 0x52, 0xfe, 0xba, 0xf9, 0xf2, 0x03, 0x58, 0x59, 0x55, 0x55, 0x55, 0x98, 0x3e, 0x7d, 0x3a, 0x1a, 0x1b, 0x1b, 0xa1, 0xd5, 0x2e, 0x43, 0x54, 0xd4, 0x6e, 0x28, 0x14, 0x9a, 0x01, 0xef, 0x71, 0x38, 0x5a, 0x51, 0x53, 0xb3, 0x06, 0x76, 0x7b, 0x0e, 0x42, 0x43, 0x43, 0x51, 0x5a, 0x5a, 0x8a, 0xe8, 0xe8, 0x68, 0xea, 0x67, 0xf9, 0xbb, 0xff, 0xa2, 0x90, 0x3a, 0x29, 0xf8, 0xf4, 0x03, 0xd6, 0xad, 0x5b, 0xe7, 0x24, 0xc5, 0xc4, 0x89, 0xfb, 0x07, 0x25, 0x05, 0x00, 0x28, 0x14, 0x1a, 0x4c, 0x9c, 0xb8, 0x1f, 0x5a, 0xed, 0x32, 0x34, 0x36, 0x36, 0x62, 0xdd, 0xba, 0x75, 0xb2, 0xff, 0x32, 0x94, 0xfc, 0x00, 0x42, 0x88, 0x95, 0x10, 0x42, 0x8a, 0x8a, 0x8a, 0xee, 0x77, 0x1f, 0x3a, 0x62, 0x32, 0xb5, 0x10, 0xb3, 0x99, 0x50, 0x5d, 0x26, 0x53, 0x0b, 0x51, 0xab, 0x75, 0x04, 0x00, 0x29, 0x2a, 0x2a, 0x62, 0x1f, 0x63, 0x1d, 0xea, 0xfe, 0x8b, 0x42, 0x8a, 0x2d, 0x85, 0xc5, 0x62, 0x41, 0x7c, 0x7c, 0x3c, 0xf2, 0xf2, 0xf2, 0xa0, 0x56, 0x47, 0x40, 0xa7, 0xdb, 0x0a, 0xbd, 0xde, 0x06, 0x93, 0xa9, 0x05, 0x26, 0x53, 0x0b, 0xf4, 0x7a, 0x1b, 0x74, 0xba, 0xad, 0x50, 0xab, 0x23, 0x90, 0x97, 0x97, 0x87, 0xf8, 0xf8, 0x78, 0x58, 0x2c, 0x96, 0xc1, 0xbe, 0xc0, 0x38, 0x00, 0xc8, 0xce, 0xce, 0x06, 0x00, 0x84, 0x87, 0xbf, 0xee, 0xb2, 0xa5, 0x18, 0xa8, 0xe5, 0x08, 0x0f, 0x7f, 0x1d, 0x7d, 0x65, 0xb0, 0x32, 0x05, 0xae, 0xb7, 0xec, 0x63, 0x08, 0xe9, 0x07, 0xb0, 0x72, 0x8d, 0x46, 0x23, 0xca, 0xcb, 0xcb, 0xa1, 0xd7, 0xdb, 0x10, 0x18, 0x68, 0x70, 0xab, 0x6e, 0xed, 0xed, 0xe5, 0xa8, 0xa8, 0x30, 0xc2, 0x60, 0x30, 0xc0, 0x66, 0xb3, 0x0d, 0x28, 0x5f, 0x0c, 0xff, 0x65, 0x58, 0xfb, 0x18, 0x42, 0xf9, 0x01, 0x75, 0x75, 0x75, 0x00, 0x80, 0x11, 0x23, 0xc6, 0xbb, 0x5d, 0x27, 0xf6, 0x1e, 0x56, 0x86, 0x2f, 0xfc, 0x97, 0x61, 0x49, 0x0c, 0xb6, 0xcf, 0x2e, 0x2e, 0x2e, 0x46, 0x6e, 0x6e, 0x2e, 0xd4, 0x6a, 0x1d, 0xa2, 0xa2, 0x76, 0x53, 0x36, 0x68, 0x0c, 0xa2, 0xa2, 0x76, 0x43, 0xad, 0xd6, 0x21, 0x37, 0x37, 0x17, 0xc5, 0xc5, 0xc5, 0xac, 0xcc, 0x4a, 0x42, 0x48, 0x86, 0x80, 0x75, 0xce, 0x20, 0x84, 0x54, 0x0a, 0x50, 0x6f, 0xab, 0x4c, 0x0c, 0x61, 0xfd, 0x80, 0xc9, 0x00, 0x76, 0xb2, 0x7f, 0x8c, 0x1f, 0xdf, 0xfb, 0xd5, 0x77, 0x76, 0xd6, 0xb9, 0x5d, 0x39, 0xf6, 0x1e, 0x56, 0xc6, 0x7d, 0xec, 0xbc, 0xff, 0x0c, 0x41, 0xfd, 0x17, 0xb9, 0x2b, 0x01, 0x70, 0xe2, 0xc4, 0x09, 0x00, 0x40, 0x48, 0xc8, 0x42, 0xb7, 0xef, 0x65, 0xef, 0x61, 0x65, 0xf4, 0xc7, 0x82, 0x05, 0x0b, 0x00, 0x00, 0x4d, 0x4d, 0xc7, 0xdd, 0x96, 0xcd, 0xde, 0xc3, 0xca, 0x10, 0xb3, 0xde, 0x32, 0x31, 0x04, 0xf6, 0x03, 0x56, 0xac, 0x58, 0x01, 0x00, 0x68, 0x68, 0xd8, 0x06, 0x87, 0xa3, 0x95, 0x5a, 0xae, 0xc3, 0xd1, 0x8a, 0x86, 0x86, 0x6d, 0x0f, 0xc8, 0x10, 0xdb, 0x7f, 0x91, 0x9d, 0x4f, 0x01, 0x91, 0x90, 0x90, 0x80, 0xe4, 0xe4, 0x64, 0x74, 0x75, 0xd5, 0xa3, 0xa6, 0x66, 0xcd, 0xfd, 0x70, 0x02, 0xa7, 0x27, 0x81, 0x9a, 0x9a, 0x35, 0xe8, 0xea, 0xaa, 0x47, 0x72, 0x72, 0x32, 0x12, 0x12, 0x12, 0x86, 0x4d, 0x3c, 0x49, 0x52, 0xc4, 0x10, 0xc0, 0x0f, 0x78, 0x00, 0x59, 0x59, 0x59, 0x08, 0x0d, 0x0d, 0x85, 0xdd, 0x9e, 0x83, 0x2b, 0x57, 0x96, 0xbb, 0x6c, 0x39, 0x1c, 0x8e, 0x56, 0x5c, 0xb9, 0xb2, 0xdc, 0x39, 0xa4, 0xcc, 0xca, 0xca, 0xf2, 0x59, 0xbd, 0x87, 0x3d, 0x31, 0x84, 0xf4, 0x03, 0x00, 0x20, 0x3a, 0x3a, 0x1a, 0x47, 0x8e, 0x1c, 0x81, 0x56, 0xab, 0x85, 0xdd, 0x9e, 0x03, 0x9b, 0x6d, 0x12, 0x1a, 0x1a, 0x3e, 0x40, 0x7b, 0x7b, 0x39, 0x1c, 0x8e, 0x56, 0x38, 0x1c, 0xad, 0x68, 0x6f, 0x2f, 0x47, 0x43, 0xc3, 0x07, 0xb0, 0xd9, 0x26, 0xc1, 0x6e, 0xcf, 0x81, 0x56, 0xab, 0xc5, 0x91, 0x23, 0x47, 0x9c, 0x71, 0x06, 0x5f, 0xd4, 0x7b, 0xc8, 0x04, 0xb8, 0xee, 0xcf, 0x1e, 0x1a, 0x07, 0xf9, 0xd9, 0xc6, 0x30, 0x4c, 0xec, 0x00, 0xc3, 0xd5, 0xb8, 0xe2, 0xe2, 0x62, 0xcc, 0x98, 0x31, 0x03, 0x6a, 0xb5, 0x0e, 0x46, 0xe3, 0x0f, 0xd4, 0x1e, 0xbe, 0xc3, 0xd1, 0x0a, 0x9b, 0x6d, 0x32, 0xba, 0xba, 0xea, 0x51, 0x54, 0x54, 0xc4, 0xd9, 0xe4, 0x57, 0x55, 0x55, 0xe1, 0xb5, 0xd7, 0x5e, 0x43, 0x5e, 0x5e, 0x9e, 0xcb, 0x72, 0x49, 0x49, 0x49, 0xd8, 0xb9, 0x73, 0xa7, 0x4b, 0x52, 0xb0, 0xc3, 0x55, 0x1e, 0xeb, 0x5d, 0xc6, 0x30, 0x8c, 0xb9, 0x9f, 0x7e, 0x5c, 0xf6, 0x7b, 0x42, 0x04, 0xc5, 0x18, 0x9e, 0x09, 0xe1, 0xf1, 0xcc, 0x22, 0x7b, 0x6f, 0x4a, 0x4a, 0x0a, 0x72, 0x73, 0x73, 0x9d, 0x81, 0x22, 0xee, 0x2a, 0x12, 0x67, 0x93, 0x9f, 0x9c, 0x9c, 0x8c, 0x6f, 0xbe, 0xf9, 0x86, 0xfa, 0xf9, 0x25, 0x25, 0x25, 0xd8, 0xbb, 0x77, 0x2f, 0xf2, 0xf3, 0xf3, 0x51, 0x53, 0x53, 0x03, 0x00, 0x88, 0x8a, 0x8a, 0xc2, 0x53, 0x4f, 0x3d, 0x85, 0x55, 0xab, 0x56, 0x21, 0x3e, 0x3e, 0x9e, 0x5a, 0x16, 0x5f, 0xf5, 0x1e, 0x48, 0x27, 0x9e, 0xe8, 0x53, 0x32, 0xc4, 0xe8, 0x3f, 0xb3, 0x48, 0xab, 0x70, 0xa1, 0x42, 0xcb, 0x62, 0x43, 0xa8, 0x50, 0xbe, 0xa7, 0xfa, 0x94, 0x04, 0xbc, 0x9d, 0x59, 0x24, 0x84, 0x6c, 0xee, 0xfb, 0x87, 0xb7, 0xc9, 0x34, 0xbe, 0x02, 0x4f, 0xf5, 0xde, 0x3c, 0x24, 0x66, 0x6a, 0x85, 0x32, 0xa6, 0x17, 0x24, 0xf3, 0x29, 0xf8, 0xaa, 0xb7, 0x58, 0x99, 0x66, 0x82, 0x74, 0x25, 0x62, 0x34, 0xff, 0x7c, 0xfa, 0x01, 0x62, 0xc2, 0x9b, 0x7a, 0x4b, 0x61, 0xa6, 0x96, 0x17, 0x62, 0x88, 0xe9, 0x30, 0x0e, 0x07, 0x08, 0xe1, 0xc8, 0x8a, 0x46, 0x0c, 0xb1, 0x87, 0x98, 0xc3, 0x05, 0x7c, 0xeb, 0xd3, 0x53, 0x72, 0x78, 0x13, 0xe0, 0x12, 0x62, 0x46, 0x74, 0xd8, 0x43, 0x2a, 0xfa, 0xf4, 0x3a, 0xf2, 0x39, 0x14, 0x67, 0x16, 0x7d, 0x09, 0xa9, 0xe8, 0xd3, 0x6b, 0x62, 0x0c, 0xc5, 0x99, 0x45, 0x5f, 0x42, 0x2a, 0xfa, 0x54, 0xc8, 0xa6, 0x90, 0x21, 0x08, 0x31, 0x86, 0xe2, 0xcc, 0xa2, 0x2f, 0x21, 0x15, 0x7d, 0x7a, 0x4d, 0x8c, 0xa1, 0x38, 0xb3, 0xe8, 0x4b, 0x48, 0x45, 0x9f, 0xde, 0x10, 0xa3, 0x0c, 0x10, 0x36, 0x33, 0x6a, 0x38, 0x42, 0x2a, 0xfa, 0xf4, 0x98, 0x18, 0xec, 0xd4, 0xb0, 0x9c, 0x19, 0xc5, 0x2f, 0xf8, 0xd4, 0xa7, 0xcf, 0x23, 0x9f, 0xfe, 0x3a, 0x23, 0x2a, 0x55, 0x0c, 0x89, 0xc5, 0x4b, 0xfe, 0x3e, 0x23, 0x2a, 0x55, 0xf8, 0x7a, 0x12, 0x8d, 0x57, 0x72, 0xf8, 0xeb, 0x8c, 0xa8, 0x54, 0xe1, 0xcb, 0x69, 0x77, 0x9f, 0x27, 0xea, 0xc8, 0xe0, 0x86, 0x2f, 0x12, 0x75, 0x18, 0x4a, 0xa3, 0xbb, 0xcc, 0xe1, 0x04, 0x30, 0x13, 0xc0, 0x0f, 0x00, 0x22, 0x64, 0x33, 0xfa, 0x14, 0xd7, 0xd0, 0xbb, 0x3a, 0xee, 0xaf, 0x00, 0x7e, 0x3b, 0x48, 0x99, 0x8f, 0x19, 0x86, 0xf9, 0x5f, 0xaf, 0x88, 0x21, 0x6f, 0xea, 0x31, 0xb4, 0xe1, 0xaa, 0x75, 0x51, 0xd0, 0x76, 0x0d, 0x34, 0xbb, 0xc3, 0xc8, 0x90, 0x4e, 0xd7, 0x23, 0xc8, 0x6e, 0x3e, 0xb2, 0x33, 0xe9, 0x1a, 0xc5, 0xc5, 0x35, 0x9c, 0x3a, 0x19, 0xfc, 0x52, 0x12, 0xa5, 0x32, 0x98, 0x8c, 0x18, 0x11, 0x4e, 0x46, 0x8d, 0x9a, 0x48, 0xc6, 0x8e, 0x9d, 0x43, 0x4c, 0xa6, 0x17, 0xc9, 0xd2, 0xa5, 0x5b, 0xc8, 0xdf, 0xff, 0xfe, 0x2d, 0x69, 0x6b, 0xeb, 0x94, 0xa6, 0xb3, 0x2a, 0x0f, 0x3f, 0xb9, 0xf1, 0xfa, 0xeb, 0xbb, 0xbd, 0x20, 0x86, 0xeb, 0x4b, 0xa9, 0x0c, 0x26, 0x53, 0xa6, 0x3c, 0x47, 0x8e, 0x1e, 0x3d, 0xef, 0xd3, 0xe1, 0x2d, 0x23, 0x07, 0xac, 0xdc, 0x87, 0xd9, 0xbc, 0x16, 0x65, 0x65, 0xbb, 0x60, 0x36, 0xf3, 0xef, 0x82, 0x59, 0xad, 0x8c, 0xd3, 0x34, 0x7a, 0xfd, 0x73, 0xf8, 0xd7, 0xbf, 0x3e, 0x46, 0x44, 0xc4, 0x68, 0xd1, 0x03, 0x62, 0x03, 0xfa, 0x18, 0x43, 0x6d, 0x77, 0x18, 0xbe, 0x71, 0xf1, 0x62, 0xa1, 0x80, 0xa4, 0x23, 0xf7, 0x09, 0x47, 0x50, 0x51, 0x91, 0x0d, 0xbd, 0x3e, 0x11, 0xa5, 0xa5, 0xae, 0x67, 0x5a, 0x85, 0xb0, 0x57, 0xdf, 0x55, 0x4f, 0x72, 0x0e, 0x27, 0x05, 0x6c, 0xb6, 0x1b, 0x88, 0x8d, 0x1d, 0xe7, 0x34, 0xa2, 0xd0, 0xb0, 0x5a, 0x19, 0x04, 0x05, 0xfd, 0x02, 0x75, 0x75, 0x67, 0xa1, 0xd5, 0x06, 0x3e, 0xf4, 0x3b, 0xcf, 0xf6, 0xda, 0xc1, 0x30, 0xcc, 0xfa, 0xfe, 0x2d, 0x86, 0x9c, 0xc3, 0x49, 0x81, 0xbd, 0x7b, 0x0b, 0x45, 0x23, 0x05, 0xfb, 0x9c, 0x96, 0x96, 0x4b, 0x48, 0x4b, 0x7b, 0x6b, 0xc0, 0xdf, 0x79, 0xb6, 0x57, 0xe6, 0xa0, 0x5d, 0x89, 0x9c, 0xc3, 0xe9, 0x1a, 0x05, 0x05, 0x16, 0xea, 0x2f, 0xbd, 0xff, 0xe5, 0x0d, 0x2c, 0x96, 0x2c, 0x58, 0xad, 0x57, 0x21, 0x96, 0xbd, 0x1e, 0x22, 0x86, 0x9c, 0xc3, 0xe9, 0x1a, 0x15, 0x15, 0x85, 0x54, 0xa4, 0xe0, 0x93, 0x2c, 0xbd, 0xad, 0x53, 0x0f, 0xde, 0x7f, 0xff, 0xe1, 0x96, 0x58, 0x28, 0x7b, 0xc9, 0x39, 0x9f, 0x6e, 0xa0, 0xaa, 0xea, 0x27, 0x34, 0x37, 0x57, 0x52, 0x95, 0x3d, 0x74, 0xe8, 0x0c, 0x08, 0x21, 0xce, 0xab, 0xab, 0xab, 0x07, 0x37, 0x6e, 0x34, 0xe1, 0xd8, 0xb1, 0x72, 0x6c, 0xd8, 0xb0, 0x07, 0xe3, 0xc7, 0x2f, 0x72, 0x49, 0xa2, 0x81, 0x50, 0x54, 0x54, 0x20, 0xda, 0xbb, 0x3e, 0x44, 0x0c, 0x29, 0xe6, 0x70, 0x1e, 0x3c, 0x78, 0x06, 0x4b, 0x97, 0x6e, 0x41, 0x54, 0x54, 0x0a, 0x34, 0x9a, 0x68, 0xa8, 0x54, 0x21, 0x60, 0x18, 0x15, 0xd4, 0xea, 0x30, 0x68, 0x34, 0x31, 0x88, 0x8a, 0x4a, 0x41, 0x7a, 0xfa, 0xbb, 0xc8, 0xc9, 0x29, 0x13, 0xd8, 0xbf, 0xf8, 0x37, 0x00, 0xe2, 0xd2, 0xbf, 0xb0, 0x5a, 0x19, 0x28, 0x95, 0xa1, 0x58, 0xbc, 0x78, 0xea, 0x03, 0xff, 0xaf, 0x52, 0x29, 0x30, 0x76, 0x6c, 0x30, 0x16, 0x2e, 0xd4, 0x63, 0xeb, 0xd6, 0xd5, 0xa8, 0xad, 0xcd, 0xc3, 0x9f, 0xff, 0x7c, 0x18, 0x0c, 0x33, 0x92, 0x9a, 0x1c, 0x3f, 0xfe, 0x78, 0x11, 0x62, 0xd9, 0xeb, 0x21, 0x62, 0x48, 0x25, 0xe7, 0xd0, 0xe1, 0x20, 0x78, 0xf3, 0xcd, 0x7f, 0x22, 0x2c, 0x2c, 0x0e, 0xcb, 0x96, 0xc5, 0xe1, 0xf0, 0xe1, 0xb7, 0x51, 0x5b, 0x9b, 0x8b, 0xb6, 0xb6, 0x2b, 0xe8, 0xe9, 0x69, 0x06, 0xd0, 0x83, 0xee, 0x6e, 0x3b, 0xda, 0xda, 0xaa, 0x50, 0x5b, 0x9b, 0x8b, 0x9c, 0x9c, 0xcd, 0x48, 0x4f, 0x37, 0x23, 0x2c, 0x2c, 0x0e, 0x9b, 0x36, 0x65, 0xa3, 0xb3, 0xb3, 0x07, 0xa3, 0x47, 0x1b, 0xc1, 0x30, 0x0c, 0xe7, 0xb5, 0x69, 0x13, 0x9d, 0xb3, 0x7c, 0xe2, 0x04, 0xdd, 0x30, 0x35, 0x32, 0xf2, 0x09, 0xa8, 0x54, 0xdc, 0x8d, 0xf1, 0xdb, 0x6f, 0xa7, 0x62, 0xf1, 0xe2, 0xcd, 0xd4, 0x3a, 0xe9, 0xe8, 0xb8, 0x05, 0xb1, 0xec, 0x25, 0xc9, 0xe1, 0xea, 0xf1, 0xe3, 0x15, 0x58, 0xb5, 0xea, 0x05, 0xdc, 0xbe, 0x5d, 0xd2, 0xaf, 0x9f, 0xa5, 0xef, 0xdb, 0x35, 0x9a, 0x18, 0xb4, 0xb6, 0x5e, 0xa6, 0x7a, 0x5e, 0x69, 0x69, 0x1d, 0xcc, 0xe6, 0x48, 0xce, 0x72, 0x61, 0x61, 0x71, 0xb0, 0xdb, 0xcf, 0x70, 0xb6, 0x18, 0xcf, 0x3e, 0xfb, 0x57, 0x7c, 0xf9, 0xe5, 0xef, 0xa8, 0x9e, 0x7d, 0xf2, 0x64, 0x15, 0x66, 0xcd, 0x8a, 0xe1, 0x7c, 0xbf, 0xde, 0x77, 0x53, 0x82, 0x90, 0x6e, 0x51, 0x86, 0xab, 0x2a, 0x27, 0x43, 0x18, 0xc6, 0x4c, 0x08, 0x21, 0x6c, 0xce, 0x61, 0x6e, 0x6e, 0x2e, 0x6a, 0x6a, 0xd6, 0x50, 0x2f, 0xaa, 0xe5, 0x2b, 0x87, 0x73, 0xc3, 0x86, 0x3d, 0xd8, 0xbe, 0xfd, 0x15, 0x10, 0x72, 0xcf, 0xed, 0x21, 0xa1, 0xbb, 0xe5, 0xad, 0x56, 0x06, 0x01, 0x01, 0xe3, 0xa9, 0x48, 0x71, 0xed, 0xda, 0x5d, 0xd8, 0xed, 0xe7, 0xa8, 0xe4, 0x3e, 0xf3, 0xcc, 0x6c, 0xea, 0x3a, 0x98, 0x4c, 0x91, 0xd4, 0x65, 0x95, 0xca, 0x51, 0x0f, 0xfd, 0x1f, 0x9f, 0xf6, 0x62, 0x49, 0x31, 0xa8, 0xf3, 0x29, 0xd4, 0xee, 0x76, 0x5c, 0x48, 0x4f, 0x7f, 0x17, 0xdb, 0xb6, 0xad, 0xf1, 0x88, 0x14, 0x9e, 0x22, 0x3a, 0x3a, 0x91, 0xd2, 0xbf, 0x38, 0x09, 0xc0, 0xc1, 0xd9, 0x5a, 0x28, 0x14, 0x1a, 0xfc, 0xea, 0x57, 0x66, 0xea, 0xe7, 0xd7, 0xd5, 0xd9, 0xa9, 0xcb, 0x8e, 0x1c, 0x39, 0x06, 0x62, 0xd9, 0xeb, 0x01, 0x62, 0xb0, 0xb1, 0x72, 0xa1, 0x76, 0xb7, 0x73, 0x85, 0xd5, 0xab, 0xb7, 0x23, 0x27, 0x67, 0xb3, 0xa8, 0xc1, 0x23, 0x00, 0x98, 0x39, 0x93, 0x8e, 0x18, 0xc7, 0x8f, 0xd3, 0xf9, 0x17, 0xe3, 0xc6, 0x3d, 0x8e, 0x80, 0x00, 0x95, 0x1b, 0xf1, 0x89, 0x4a, 0xea, 0xb2, 0x63, 0xc6, 0x4c, 0x1e, 0x84, 0xdc, 0xde, 0xdb, 0xab, 0x7f, 0x6e, 0xc6, 0x43, 0x6f, 0xc0, 0x30, 0x0c, 0x43, 0x08, 0x21, 0xb3, 0x67, 0xcf, 0x46, 0x49, 0x49, 0x89, 0x73, 0x77, 0xbb, 0xfa, 0xfa, 0x37, 0x00, 0xbc, 0x31, 0x60, 0xc5, 0x68, 0x77, 0xb7, 0x1b, 0x0c, 0xef, 0xbf, 0x7f, 0x14, 0xff, 0xf8, 0xc7, 0x06, 0x2a, 0x52, 0xb8, 0x37, 0xf6, 0xe7, 0x46, 0x5a, 0x1a, 0x1d, 0x31, 0xce, 0x9f, 0xb7, 0x50, 0x3e, 0x77, 0xb6, 0x5b, 0xef, 0xfe, 0xc5, 0x17, 0xfb, 0xa9, 0xcb, 0x4e, 0x9b, 0x36, 0x73, 0xd0, 0xdf, 0xbc, 0xb1, 0xd7, 0x40, 0x09, 0x3b, 0x54, 0x67, 0x7b, 0x09, 0x99, 0xc3, 0x69, 0xb5, 0x5e, 0xc5, 0x2f, 0x7f, 0xf9, 0xdf, 0xe8, 0xee, 0xb6, 0x53, 0x91, 0x82, 0x61, 0xd4, 0x88, 0x8e, 0x4e, 0xc1, 0xf2, 0xe5, 0xcf, 0x61, 0xfe, 0xfc, 0x69, 0x88, 0x8d, 0x8d, 0x80, 0x42, 0xc1, 0xe0, 0xfb, 0xef, 0xab, 0xf0, 0xf5, 0xd7, 0xdf, 0x21, 0x3f, 0xff, 0x1b, 0x54, 0x57, 0xe7, 0x01, 0xe8, 0xe1, 0x6c, 0xf6, 0x55, 0x2a, 0x2d, 0x3a, 0x3a, 0x6e, 0x43, 0xa1, 0x70, 0x4d, 0xb6, 0x9f, 0x7e, 0x6a, 0xc5, 0x98, 0x31, 0xa1, 0x00, 0xba, 0x39, 0x65, 0x7e, 0xfa, 0x69, 0x21, 0xd6, 0xae, 0xa5, 0x23, 0x47, 0x5e, 0x5e, 0x39, 0x52, 0x52, 0xe2, 0x40, 0x48, 0x27, 0xa7, 0x5c, 0x00, 0x38, 0x70, 0xc0, 0x8a, 0x65, 0xcb, 0xb8, 0xf7, 0xa0, 0xe7, 0x23, 0x47, 0xd4, 0xe7, 0xa9, 0x7d, 0x13, 0x27, 0x2e, 0x41, 0x75, 0xf5, 0x51, 0x2a, 0x52, 0x84, 0x85, 0x4d, 0xc7, 0x17, 0x5f, 0xec, 0xc2, 0x92, 0x25, 0x53, 0x5d, 0x96, 0x9d, 0x34, 0x69, 0x39, 0x2e, 0x5d, 0x3a, 0xc0, 0xa9, 0xec, 0xa8, 0xa8, 0x14, 0x54, 0x57, 0x1f, 0xe5, 0xac, 0x63, 0x56, 0xd6, 0x09, 0x64, 0x66, 0x3e, 0xcd, 0x29, 0x8f, 0x61, 0x02, 0x70, 0xf7, 0x6e, 0x23, 0x82, 0x83, 0x47, 0x72, 0xca, 0x3c, 0x75, 0xea, 0x0a, 0x9e, 0x7e, 0x7a, 0x01, 0xda, 0xda, 0xae, 0x50, 0xbd, 0xbb, 0x56, 0x1b, 0x87, 0x3b, 0x77, 0xf8, 0x3d, 0xb1, 0xc2, 0xa3, 0xd4, 0x3e, 0xf6, 0xc6, 0xfb, 0x37, 0xdb, 0x84, 0x20, 0xc5, 0xdf, 0xfe, 0x96, 0x47, 0x65, 0x18, 0xab, 0x95, 0xc1, 0x84, 0x09, 0xc9, 0xa8, 0xab, 0x3b, 0xc5, 0x49, 0x0a, 0x00, 0xa8, 0xad, 0xfd, 0x8e, 0xea, 0xf9, 0xd3, 0xa7, 0x27, 0x52, 0x7e, 0xd9, 0x74, 0xdd, 0x48, 0x78, 0x78, 0x02, 0x27, 0x29, 0x3a, 0x3b, 0x7b, 0xf0, 0xf2, 0xcb, 0x9f, 0xe0, 0xc9, 0x27, 0x13, 0xa8, 0x49, 0x01, 0x00, 0x19, 0x19, 0xbf, 0xe7, 0x4b, 0xed, 0x1f, 0xf7, 0xb1, 0xeb, 0xa0, 0x50, 0x51, 0x32, 0x2b, 0x96, 0x10, 0xf2, 0x22, 0x80, 0x5d, 0x7c, 0x12, 0xe3, 0xbd, 0xf7, 0xfe, 0x8f, 0xd3, 0x1f, 0xb0, 0x5a, 0x19, 0x8c, 0x19, 0x33, 0x13, 0xe7, 0xce, 0xe5, 0x40, 0xa3, 0x19, 0xc1, 0x29, 0xf3, 0xfb, 0xef, 0xab, 0xd1, 0xd1, 0x71, 0x9d, 0xea, 0xf9, 0xc9, 0xc9, 0x74, 0xc4, 0x38, 0x73, 0x86, 0xce, 0xf1, 0x9c, 0x36, 0xed, 0xc1, 0x2e, 0xa4, 0xbd, 0xbd, 0x0b, 0x37, 0x6e, 0x34, 0xa1, 0xaa, 0xea, 0x16, 0x0a, 0x0a, 0xce, 0xa3, 0xb0, 0xf0, 0x24, 0x4a, 0x4b, 0xf7, 0xa3, 0xb3, 0xb3, 0xc1, 0x2d, 0x3f, 0x68, 0xdc, 0xb8, 0xb9, 0xf8, 0xd3, 0x9f, 0xd2, 0xf9, 0x50, 0xf9, 0x4b, 0x0c, 0xc3, 0x7c, 0x4e, 0x53, 0x50, 0xe5, 0x86, 0xd0, 0x28, 0x3e, 0x49, 0xb1, 0x7b, 0xf7, 0x77, 0x0f, 0x04, 0xb0, 0x06, 0x6f, 0x9e, 0x47, 0x20, 0x3b, 0xfb, 0x73, 0x8c, 0x1e, 0x1d, 0x40, 0x25, 0xf7, 0xc0, 0x81, 0x93, 0x54, 0x64, 0x63, 0x98, 0x91, 0x48, 0x4f, 0xe7, 0xf6, 0x8d, 0xee, 0xde, 0xbd, 0x87, 0x5b, 0xb7, 0x8a, 0xa9, 0x9e, 0x7d, 0xec, 0xd8, 0x3b, 0x60, 0x98, 0x77, 0x78, 0x73, 0x8c, 0xad, 0x56, 0x06, 0x6a, 0xf5, 0xa3, 0x38, 0x7a, 0x74, 0x0f, 0x5f, 0x6a, 0xa7, 0xb6, 0xa1, 0x8a, 0xc3, 0xc7, 0x70, 0xb5, 0x9e, 0xc4, 0x2b, 0x64, 0x65, 0x7d, 0x4e, 0xa5, 0xa4, 0x79, 0xf3, 0xd6, 0x63, 0xfe, 0xfc, 0xc9, 0x6e, 0x0c, 0xff, 0x4e, 0x52, 0x0e, 0xfd, 0xa6, 0x53, 0xf9, 0x02, 0xfb, 0xf6, 0x15, 0x81, 0x90, 0x0e, 0xce, 0x7a, 0x9a, 0xcd, 0x64, 0xc0, 0x11, 0x93, 0xa7, 0x43, 0x6f, 0x36, 0x26, 0xf2, 0xe9, 0xa7, 0x47, 0x60, 0x32, 0xe9, 0xf8, 0x52, 0xfb, 0x1f, 0x08, 0x21, 0x7f, 0xa0, 0xf1, 0x31, 0x54, 0xbe, 0x70, 0x3a, 0xbb, 0xbb, 0x1d, 0xb8, 0x70, 0xe1, 0x08, 0x45, 0xdf, 0xaa, 0xc0, 0x96, 0x2d, 0xbf, 0x75, 0x4b, 0xf6, 0xa5, 0x4b, 0xa7, 0xa8, 0xca, 0x4d, 0x9d, 0x4a, 0xd7, 0x8d, 0xe4, 0xe6, 0x5a, 0xa8, 0x9f, 0xcd, 0x57, 0xfc, 0xa5, 0x77, 0xc4, 0x14, 0x86, 0x4f, 0x3e, 0x39, 0x8c, 0x35, 0x6b, 0x1e, 0x17, 0xcc, 0x0e, 0xac, 0x9d, 0x07, 0x22, 0x88, 0x82, 0x6b, 0x98, 0x2a, 0xc4, 0x7a, 0x92, 0xfd, 0xfb, 0x4b, 0xd1, 0xd5, 0xf5, 0x13, 0xa7, 0x22, 0x23, 0x22, 0xe6, 0x62, 0xc6, 0x0c, 0xfa, 0x1e, 0xac, 0xb6, 0xd6, 0x8e, 0xa6, 0xa6, 0x0a, 0xaa, 0xb2, 0x0b, 0x16, 0xcc, 0xa2, 0x2a, 0x57, 0x5a, 0x5a, 0x08, 0xb1, 0xc0, 0xe6, 0x68, 0x68, 0xb5, 0x26, 0xe4, 0xe7, 0x9f, 0xc6, 0x4b, 0x2f, 0xcd, 0xf2, 0x4a, 0x9e, 0x37, 0xeb, 0x4b, 0x54, 0x03, 0x91, 0xc2, 0xd5, 0xb1, 0x0d, 0xe5, 0xe5, 0xe5, 0x28, 0x2f, 0x2f, 0xc7, 0x8e, 0x1d, 0x3b, 0x3c, 0x0e, 0x6c, 0x1d, 0x3b, 0x76, 0x9a, 0x72, 0xd4, 0x30, 0xc7, 0x2d, 0xb9, 0xfb, 0xf6, 0x7d, 0x07, 0x9a, 0x69, 0x71, 0x80, 0xc1, 0x8a, 0x15, 0x4f, 0x70, 0xca, 0xeb, 0x75, 0x1e, 0x4f, 0x8b, 0x42, 0x08, 0xa0, 0x37, 0xdd, 0x2e, 0x25, 0x65, 0x23, 0xf6, 0xed, 0xfb, 0x3d, 0x02, 0x03, 0xd5, 0x1e, 0xcb, 0xf3, 0xc4, 0x7e, 0x84, 0x10, 0xd2, 0xb7, 0xe5, 0x50, 0xf5, 0x27, 0x85, 0xc5, 0x62, 0x41, 0x5a, 0x5a, 0x1a, 0xec, 0x76, 0x3b, 0xd4, 0xea, 0x08, 0x84, 0x87, 0x6f, 0x40, 0x48, 0xc8, 0x42, 0x8c, 0x1c, 0xd9, 0xfb, 0xe5, 0x76, 0x74, 0xd4, 0xa0, 0xa9, 0xe9, 0x38, 0x1a, 0x1a, 0x3e, 0x70, 0x9e, 0x36, 0x7c, 0xf8, 0xf0, 0x61, 0xcc, 0x9e, 0x4d, 0x1f, 0xf1, 0x3b, 0x77, 0xee, 0x0c, 0x55, 0xb9, 0xb9, 0x73, 0x67, 0xb8, 0xa5, 0x90, 0xfc, 0x7c, 0x3a, 0xff, 0x22, 0x24, 0xc4, 0x80, 0xc8, 0xc8, 0x50, 0xce, 0x72, 0x39, 0x39, 0x56, 0x38, 0x1c, 0xad, 0x02, 0x2f, 0x13, 0x00, 0x94, 0xca, 0x50, 0x3c, 0xf1, 0xc4, 0x6f, 0xf0, 0xd1, 0x47, 0x1b, 0x61, 0x30, 0x8c, 0xf5, 0x4a, 0xae, 0x37, 0xf6, 0xeb, 0x4b, 0x0e, 0x55, 0xff, 0x96, 0x22, 0x35, 0x35, 0xd5, 0xe5, 0xfa, 0x84, 0xc0, 0x40, 0x03, 0x02, 0x03, 0x0d, 0x18, 0x33, 0xe6, 0x15, 0xe7, 0xfa, 0x84, 0xd4, 0xd4, 0x54, 0xb7, 0xd6, 0x93, 0xdc, 0xbc, 0x49, 0x37, 0x1d, 0x6e, 0x36, 0xbb, 0xd7, 0x12, 0x9d, 0x3f, 0x4f, 0xe7, 0x5f, 0x4c, 0x9e, 0x4c, 0xe7, 0x5f, 0x1c, 0x39, 0x52, 0xe8, 0xb6, 0x91, 0x69, 0xa1, 0x54, 0x86, 0x20, 0x3a, 0x7a, 0x01, 0x52, 0x53, 0x97, 0x62, 0xd3, 0xa6, 0xa5, 0x08, 0x0b, 0x1b, 0xe5, 0x35, 0xd9, 0xf8, 0xb0, 0x1f, 0x4b, 0x8e, 0x07, 0xba, 0x92, 0xfe, 0xeb, 0x13, 0x5c, 0x05, 0x46, 0xd9, 0xf5, 0x09, 0xec, 0x4c, 0xdd, 0xba, 0x75, 0xeb, 0xa8, 0xf7, 0x04, 0x6f, 0x6a, 0xba, 0x46, 0x55, 0x4e, 0xa7, 0xd3, 0x52, 0x2b, 0xa5, 0xb5, 0xb5, 0x13, 0xb7, 0x6e, 0xd1, 0xf9, 0x3d, 0x73, 0xe6, 0xd0, 0x11, 0xa3, 0xa4, 0xc4, 0xe2, 0x21, 0x29, 0x7a, 0x87, 0xd9, 0x0a, 0xc5, 0x48, 0xa8, 0xd5, 0x21, 0x08, 0x0c, 0xfc, 0x19, 0x42, 0x43, 0xc7, 0x21, 0x32, 0xf2, 0x31, 0x18, 0x0c, 0x53, 0xb0, 0x68, 0x51, 0x02, 0x92, 0x93, 0x63, 0xa9, 0x92, 0x79, 0xdc, 0x01, 0x9f, 0xf6, 0x53, 0xf1, 0x71, 0x4a, 0x72, 0x4b, 0x4b, 0x91, 0xf3, 0xb4, 0x61, 0x9a, 0x5c, 0x8c, 0xce, 0xce, 0xdb, 0x54, 0x2f, 0x3a, 0x76, 0x6c, 0x08, 0xb5, 0x52, 0x0e, 0x1c, 0x28, 0xe5, 0x9c, 0xae, 0x67, 0x8d, 0xb8, 0x7c, 0x39, 0x37, 0x31, 0xba, 0xbb, 0x1d, 0xa8, 0xaf, 0xa7, 0xeb, 0x9a, 0xde, 0x7b, 0xef, 0x6b, 0xbc, 0xf9, 0xe6, 0x62, 0xf8, 0x12, 0x7c, 0xda, 0x8f, 0x10, 0x42, 0x14, 0xf0, 0xc1, 0x7a, 0x12, 0x87, 0xe3, 0x1e, 0x65, 0xcb, 0x72, 0x8f, 0xba, 0x1e, 0x79, 0x79, 0x74, 0xdd, 0x48, 0x40, 0x80, 0x0e, 0xf1, 0xf1, 0x13, 0x28, 0xba, 0x91, 0xb3, 0xe8, 0xe9, 0x69, 0xa2, 0x20, 0x9a, 0x02, 0x2b, 0x57, 0x26, 0xc2, 0xd7, 0xe0, 0xdb, 0x7e, 0xce, 0xb6, 0x4c, 0xdc, 0xf5, 0x24, 0x74, 0xce, 0x9c, 0xc5, 0x72, 0xd1, 0x8d, 0xa1, 0x19, 0xdd, 0xd7, 0x3d, 0x71, 0x22, 0xdd, 0x10, 0xf0, 0xd0, 0x21, 0x3a, 0xff, 0x22, 0x34, 0x34, 0x96, 0xca, 0x91, 0x15, 0x1a, 0x7c, 0xdb, 0xcf, 0x49, 0x0c, 0x31, 0xd7, 0x93, 0xa8, 0x54, 0x74, 0x8a, 0xfc, 0xec, 0xb3, 0x43, 0x94, 0x2d, 0x10, 0xc1, 0xd5, 0xab, 0x74, 0x13, 0x67, 0xb4, 0x89, 0x39, 0x45, 0x45, 0x74, 0x81, 0x2d, 0xbd, 0x7e, 0x36, 0xa4, 0x00, 0xbe, 0xed, 0xe7, 0x93, 0x75, 0x25, 0x01, 0x01, 0x8f, 0x50, 0x7e, 0x05, 0xdb, 0x71, 0xe2, 0x44, 0x25, 0x47, 0x13, 0x5a, 0x8c, 0x71, 0xe3, 0x66, 0x53, 0x05, 0xcc, 0x00, 0x20, 0x35, 0x35, 0x91, 0x8a, 0x68, 0x35, 0x35, 0xff, 0xa6, 0xaa, 0xe3, 0xfc, 0xf9, 0xd2, 0x20, 0x06, 0xdf, 0x70, 0x12, 0x43, 0xcc, 0xf5, 0x24, 0x91, 0x91, 0x26, 0x8a, 0xa1, 0x2a, 0x81, 0xc3, 0xd1, 0x8a, 0xe4, 0xe4, 0x27, 0x90, 0x9e, 0xfe, 0x2e, 0x72, 0x73, 0x6d, 0xb8, 0x75, 0xab, 0x05, 0xcd, 0xcd, 0x1d, 0x38, 0x75, 0xea, 0x0a, 0x32, 0x32, 0x76, 0x21, 0x22, 0x62, 0x1e, 0x56, 0xae, 0x9c, 0x81, 0x86, 0x86, 0x93, 0x54, 0xd3, 0xd7, 0x4a, 0x65, 0x28, 0x92, 0x92, 0xb8, 0xa7, 0x7e, 0x8e, 0x1d, 0x2b, 0x47, 0x77, 0xf7, 0x6d, 0x2a, 0x47, 0x76, 0xd5, 0x2a, 0x69, 0x10, 0x83, 0x6f, 0xfb, 0x39, 0x89, 0x21, 0xe6, 0x7a, 0x92, 0xc4, 0x44, 0xba, 0x88, 0xa6, 0xd9, 0x4c, 0xd0, 0xdd, 0x6d, 0x47, 0x4e, 0xce, 0x66, 0xa4, 0xa4, 0xc4, 0x22, 0x3c, 0x3c, 0x18, 0x21, 0x21, 0x01, 0x48, 0x4c, 0x8c, 0xc6, 0x87, 0x1f, 0xae, 0xc5, 0xf5, 0xeb, 0x05, 0xce, 0x72, 0x74, 0xc3, 0xdf, 0x99, 0x54, 0x43, 0xc4, 0x83, 0x07, 0xe9, 0xba, 0x91, 0xe0, 0xe0, 0xc9, 0x98, 0x34, 0xe9, 0x67, 0x92, 0x20, 0x06, 0xdf, 0xf6, 0x53, 0xc0, 0x07, 0x7b, 0x82, 0x6f, 0xdc, 0xb8, 0x0c, 0x0a, 0xc5, 0x28, 0xaa, 0xc0, 0x10, 0xbb, 0x5f, 0x84, 0xab, 0x8b, 0x16, 0x71, 0x71, 0x74, 0xfe, 0xc5, 0xa9, 0x53, 0x74, 0x8e, 0xe7, 0xa4, 0x49, 0xd2, 0xe9, 0x46, 0xf8, 0xb6, 0x9f, 0xc2, 0x17, 0x7b, 0x82, 0x47, 0x47, 0x3f, 0x8a, 0x59, 0xb3, 0xfe, 0x47, 0x74, 0xe5, 0xd1, 0x26, 0xe6, 0x5c, 0xb9, 0x42, 0xd7, 0x62, 0xcc, 0x9d, 0x2b, 0x1d, 0x62, 0xf0, 0xbd, 0x07, 0xb9, 0xcf, 0x4e, 0x49, 0xbe, 0x73, 0xa7, 0x0d, 0x31, 0x31, 0xb3, 0x60, 0xb7, 0x97, 0x79, 0x34, 0x17, 0xf1, 0x9f, 0xd6, 0x46, 0x09, 0xb3, 0xb9, 0x9b, 0xb3, 0xac, 0x42, 0x31, 0x0a, 0x8d, 0x8d, 0x77, 0x38, 0x73, 0x30, 0x0a, 0x0a, 0x2e, 0x61, 0xde, 0xbc, 0x49, 0x2e, 0xbb, 0x28, 0xf6, 0xd9, 0xb4, 0x2b, 0xd8, 0xc4, 0x02, 0x9f, 0x5b, 0x2e, 0x29, 0xd8, 0x7f, 0xf4, 0x7e, 0xc9, 0xe2, 0xad, 0x27, 0x09, 0x0b, 0x1b, 0x85, 0x82, 0x82, 0xaf, 0x10, 0x16, 0x36, 0xdd, 0xad, 0x2d, 0x01, 0xfe, 0x53, 0x56, 0x85, 0xf9, 0xf3, 0x37, 0x22, 0x2e, 0xee, 0x05, 0xaa, 0x7b, 0x23, 0x23, 0xe7, 0x50, 0x25, 0xe6, 0x1c, 0x38, 0x60, 0xa1, 0xf2, 0x5b, 0x02, 0x03, 0xa3, 0x24, 0x45, 0x0a, 0xbe, 0xec, 0x37, 0x60, 0xf2, 0x8e, 0x2f, 0xb6, 0x71, 0x6c, 0x69, 0xe9, 0x20, 0x0b, 0x17, 0xbe, 0x45, 0x94, 0xca, 0xd1, 0xd4, 0xdb, 0x21, 0x1a, 0x0c, 0xab, 0x48, 0x7e, 0x7e, 0x25, 0x21, 0x84, 0x10, 0x8d, 0xe6, 0x31, 0x02, 0x80, 0x98, 0xcd, 0x64, 0xd0, 0x0b, 0x00, 0x79, 0xf9, 0xe5, 0x4f, 0xa8, 0xea, 0x63, 0x34, 0xfe, 0x9a, 0xaa, 0x1e, 0x53, 0xa7, 0x3e, 0x3f, 0xbc, 0xf6, 0x20, 0x7f, 0x70, 0x3f, 0xcb, 0x62, 0x92, 0x99, 0x99, 0x49, 0x0c, 0x06, 0x03, 0xd1, 0x68, 0x34, 0x44, 0xa3, 0xd1, 0x10, 0x83, 0xc1, 0x40, 0x32, 0x33, 0x33, 0x49, 0x71, 0x71, 0x31, 0xaf, 0x2f, 0x73, 0xe3, 0x46, 0x13, 0xc9, 0xc8, 0xd8, 0x45, 0xa6, 0x4e, 0x7d, 0x9e, 0x04, 0x07, 0xeb, 0x89, 0x5a, 0x3d, 0x86, 0x30, 0x8c, 0x9a, 0x28, 0x95, 0x21, 0x44, 0xa3, 0x89, 0x21, 0x13, 0x26, 0x24, 0x93, 0xe7, 0x9f, 0xdf, 0x41, 0x8a, 0x8b, 0x6b, 0x9c, 0xf7, 0x7c, 0xf5, 0xd5, 0x39, 0xe7, 0x4b, 0xba, 0x22, 0x05, 0xc3, 0xa8, 0x49, 0x75, 0xf5, 0x6d, 0xaa, 0x7a, 0x04, 0x04, 0x8c, 0xa7, 0x22, 0xc6, 0xab, 0xaf, 0x7e, 0xe6, 0x07, 0xfb, 0x91, 0xd2, 0xdb, 0xaf, 0x3f, 0x0f, 0x98, 0xc1, 0xc8, 0xe1, 0x0f, 0x41, 0x18, 0xbd, 0x7e, 0x05, 0x2a, 0x2b, 0xbf, 0xe4, 0x8c, 0x37, 0x18, 0x0c, 0x2b, 0x61, 0xb3, 0xed, 0x85, 0x8c, 0x81, 0x41, 0x95, 0xda, 0xe7, 0xf4, 0x4a, 0x05, 0x5c, 0x4f, 0xc2, 0x07, 0x36, 0x6c, 0xd8, 0x83, 0xca, 0xca, 0x2f, 0x29, 0x1c, 0x54, 0x06, 0xef, 0xbc, 0xf3, 0x3b, 0xd9, 0xfa, 0xae, 0xed, 0x0c, 0x2a, 0x62, 0xf4, 0xb9, 0x31, 0x96, 0x19, 0x00, 0x00, 0x6e, 0x7b, 0x5a, 0x99, 0xb8, 0xb8, 0x97, 0xa0, 0x50, 0x8c, 0x40, 0x4c, 0x4c, 0x1a, 0xfe, 0xf8, 0xc7, 0x83, 0xb0, 0xdb, 0xdb, 0xdd, 0xba, 0xff, 0xe6, 0xcd, 0x66, 0x2c, 0x5a, 0xf4, 0x36, 0xb6, 0x6d, 0x7b, 0x81, 0xca, 0x49, 0x34, 0x1a, 0x57, 0x21, 0x2d, 0x6d, 0xda, 0x70, 0xb6, 0xff, 0x6d, 0x66, 0x10, 0xb8, 0xb4, 0xbd, 0x3b, 0x4f, 0xe0, 0xa3, 0x8b, 0xd1, 0x6a, 0x4d, 0x68, 0x6c, 0x3c, 0xdb, 0x87, 0x7c, 0x01, 0xd0, 0xe9, 0x66, 0x23, 0x21, 0xe1, 0x49, 0x3c, 0xfe, 0xb8, 0x09, 0xb3, 0x66, 0x4d, 0xc1, 0xcf, 0x7f, 0xfe, 0x28, 0x42, 0x42, 0x02, 0x70, 0xe7, 0x4e, 0x1b, 0x7e, 0xfc, 0xb1, 0x19, 0x65, 0x65, 0x35, 0xb0, 0x5a, 0x2f, 0xe2, 0xdb, 0x6f, 0x0b, 0x50, 0x59, 0x79, 0x14, 0xdd, 0xdd, 0x76, 0x4e, 0x52, 0xf4, 0x66, 0x5a, 0x3f, 0x82, 0x33, 0x67, 0x2e, 0xc0, 0x68, 0xfc, 0x2f, 0xb9, 0x79, 0x80, 0x7b, 0x67, 0x99, 0x30, 0x9e, 0x90, 0xc2, 0xd3, 0x45, 0xce, 0xad, 0xad, 0x9d, 0x08, 0x0e, 0x0e, 0x02, 0x21, 0x5d, 0x4e, 0xa3, 0x7a, 0x92, 0x16, 0x47, 0xb7, 0xac, 0x8f, 0xc1, 0x96, 0x2d, 0x87, 0xb1, 0x79, 0xf3, 0x33, 0x43, 0xde, 0xe0, 0x42, 0x1c, 0x74, 0xc3, 0xb8, 0x43, 0x0a, 0x57, 0xd9, 0xc7, 0x7d, 0x31, 0x58, 0xf6, 0x78, 0x4e, 0x4e, 0x19, 0xd2, 0xd3, 0xcd, 0x82, 0xee, 0x7f, 0xc1, 0x12, 0x6d, 0xf5, 0xea, 0xed, 0xd8, 0xb3, 0x27, 0x73, 0x48, 0x13, 0xc2, 0x53, 0x7b, 0xd0, 0x90, 0x83, 0xa1, 0x25, 0x85, 0x3b, 0xd9, 0xc7, 0x5d, 0x5d, 0xd7, 0xa0, 0xd5, 0x6a, 0x1f, 0xca, 0x1e, 0xcf, 0xc8, 0xd8, 0x85, 0x0f, 0x3f, 0x5c, 0x2b, 0x18, 0x31, 0xd8, 0x8c, 0xaa, 0x17, 0x5f, 0xcc, 0xc2, 0xae, 0x5d, 0xaf, 0x0e, 0x69, 0x52, 0x78, 0x6b, 0x0f, 0xaf, 0x7c, 0x0c, 0xbe, 0x43, 0xe5, 0x33, 0x67, 0xbe, 0x8a, 0xd3, 0xa7, 0x3f, 0xe2, 0x9d, 0x18, 0x6c, 0x2b, 0x11, 0x10, 0x10, 0x89, 0xed, 0xdb, 0xf7, 0xe0, 0x95, 0x57, 0x9e, 0x1c, 0xf2, 0x2d, 0x85, 0xd0, 0xc7, 0x6f, 0x52, 0x25, 0xea, 0xf0, 0xb5, 0xbb, 0x7d, 0x55, 0xd5, 0x19, 0x5e, 0xc9, 0xc0, 0x5e, 0x4a, 0x65, 0x30, 0x16, 0x2e, 0x7c, 0x0b, 0x57, 0xaf, 0x56, 0x0e, 0x79, 0x52, 0xf0, 0x69, 0x0f, 0x8f, 0x5a, 0x0c, 0x21, 0xb6, 0x77, 0xd4, 0xe9, 0x9e, 0xc2, 0xf5, 0xeb, 0x27, 0x41, 0x48, 0x07, 0x2f, 0x0a, 0xd2, 0x6a, 0x4d, 0x48, 0x4a, 0xfa, 0x35, 0xfe, 0xf2, 0x97, 0xdf, 0x60, 0xc2, 0x04, 0x2d, 0x86, 0x03, 0x78, 0xde, 0xbe, 0xb1, 0x8c, 0x9d, 0x5d, 0xef, 0x0f, 0x57, 0xab, 0xdd, 0x79, 0xc9, 0x1e, 0xaf, 0xaf, 0x7f, 0x03, 0xd9, 0xd9, 0xd9, 0x48, 0x48, 0x48, 0x40, 0x7d, 0x7d, 0x3e, 0x5a, 0x5b, 0x3b, 0x71, 0xfc, 0x78, 0x39, 0x4e, 0x9f, 0xae, 0xc0, 0x85, 0x0b, 0x3f, 0xe0, 0xea, 0xd5, 0x6a, 0xd8, 0xed, 0x37, 0xd0, 0xdc, 0x7c, 0x13, 0x1d, 0x1d, 0xb7, 0xd1, 0xd3, 0xd3, 0x0e, 0x87, 0xe3, 0x1e, 0x08, 0xe9, 0x82, 0x42, 0x11, 0x08, 0xa5, 0x32, 0x08, 0x6a, 0x75, 0x10, 0x02, 0x03, 0x1f, 0xc1, 0xd8, 0xb1, 0x8f, 0x21, 0x26, 0x66, 0x32, 0xa6, 0x4e, 0x9d, 0x82, 0x67, 0x9f, 0x4d, 0xf4, 0x7a, 0xd5, 0x96, 0x3f, 0x82, 0x4f, 0x7b, 0xb0, 0x36, 0x76, 0xb7, 0xc5, 0x20, 0xbd, 0x01, 0x22, 0x23, 0xca, 0xcb, 0xcb, 0xa1, 0xd7, 0xdb, 0x10, 0x18, 0x68, 0x70, 0xeb, 0x25, 0xda, 0xdb, 0xcb, 0x51, 0x51, 0x61, 0x84, 0xc1, 0x60, 0x80, 0xcd, 0x66, 0x83, 0x0c, 0xef, 0xc1, 0xb7, 0x3d, 0x3c, 0x8a, 0x7c, 0x02, 0xf2, 0x69, 0x04, 0x52, 0x83, 0x58, 0xf6, 0x90, 0x4f, 0x1f, 0x90, 0xe1, 0x19, 0x31, 0xa4, 0x78, 0x1a, 0xc1, 0x70, 0x86, 0x58, 0xf6, 0xe0, 0x24, 0x86, 0x54, 0x4e, 0x23, 0x90, 0x21, 0xae, 0x3d, 0x5c, 0x11, 0x43, 0xf4, 0xec, 0x71, 0x19, 0xdc, 0xe0, 0xd9, 0x1e, 0x65, 0x6e, 0x13, 0xc3, 0x17, 0xd9, 0xe3, 0x32, 0xb8, 0xc1, 0x73, 0x36, 0xb8, 0xd9, 0xed, 0xe1, 0x6a, 0xdf, 0x21, 0xab, 0x7c, 0x40, 0xaf, 0xb4, 0x20, 0x46, 0x48, 0x9c, 0x9b, 0x6b, 0xf2, 0x91, 0xde, 0x92, 0x04, 0xdf, 0x47, 0x76, 0x7b, 0x45, 0x0e, 0x31, 0xb3, 0xc7, 0x65, 0xf8, 0x28, 0x1b, 0xdc, 0x53, 0x72, 0x78, 0x90, 0x3d, 0xbe, 0x44, 0x36, 0x21, 0xef, 0x58, 0xc2, 0x57, 0x36, 0x38, 0xef, 0xe4, 0xa0, 0x41, 0x9f, 0xfb, 0xd6, 0xf8, 0x6a, 0x59, 0x82, 0x3f, 0xc0, 0x4d, 0x7d, 0xac, 0xf1, 0xd6, 0x1e, 0x82, 0x81, 0x10, 0x72, 0xc1, 0xc5, 0xf3, 0x2f, 0xc8, 0x5d, 0x91, 0xb8, 0x5d, 0x81, 0xbb, 0xf6, 0x90, 0x04, 0x64, 0xe7, 0x55, 0xc2, 0xce, 0xa3, 0x0b, 0x30, 0x42, 0x93, 0x42, 0x1e, 0xee, 0x4a, 0x74, 0xb8, 0x29, 0x85, 0x49, 0x34, 0x31, 0x32, 0x8e, 0xfc, 0x09, 0xfe, 0xa0, 0x0f, 0x46, 0xc0, 0xd6, 0x42, 0x32, 0x07, 0xfc, 0x4a, 0x09, 0x62, 0x65, 0x60, 0x49, 0xb9, 0xc5, 0x10, 0x7d, 0xff, 0x50, 0x7f, 0x00, 0xcf, 0xfa, 0x88, 0x13, 0xaa, 0x9e, 0x82, 0x77, 0x25, 0xe2, 0xee, 0x1f, 0x2a, 0x7d, 0xf8, 0x8b, 0x3e, 0x04, 0x27, 0x86, 0x9c, 0x01, 0xe6, 0x9f, 0xfa, 0x18, 0x72, 0x19, 0x5c, 0x42, 0x1d, 0xbe, 0x23, 0x94, 0x5c, 0xa9, 0x42, 0x48, 0xe7, 0x53, 0xd4, 0x64, 0x62, 0x6f, 0x97, 0x4f, 0x8a, 0x25, 0x57, 0xac, 0x64, 0x5e, 0xc9, 0xb7, 0x18, 0x62, 0x64, 0x1c, 0x59, 0x2c, 0x16, 0xc4, 0xc7, 0xc7, 0x23, 0x2f, 0x2f, 0x0f, 0x6a, 0x75, 0x04, 0x74, 0xba, 0xad, 0xd0, 0xeb, 0x6d, 0x30, 0x99, 0x5a, 0x60, 0x32, 0xb5, 0x40, 0xaf, 0xb7, 0x41, 0xa7, 0xdb, 0x0a, 0xb5, 0x3a, 0xc2, 0x79, 0x78, 0x8b, 0xc5, 0xc2, 0xbd, 0x33, 0x9f, 0x10, 0x72, 0xfd, 0x25, 0x23, 0xce, 0xef, 0x87, 0xab, 0x42, 0x05, 0xcf, 0x84, 0x92, 0x3b, 0xec, 0x87, 0xab, 0x02, 0x65, 0x80, 0x65, 0x01, 0x68, 0x11, 0x23, 0x58, 0xc4, 0xb3, 0xdc, 0x96, 0xfb, 0x75, 0x17, 0x2d, 0x03, 0x4b, 0xb2, 0x2d, 0x46, 0x5f, 0x3f, 0x83, 0xcf, 0x10, 0x30, 0x21, 0x64, 0x24, 0x80, 0x4b, 0x00, 0xc6, 0x0b, 0xd5, 0x1a, 0xf1, 0x2c, 0xb7, 0x0e, 0xc0, 0x2f, 0x18, 0x86, 0xe9, 0x10, 0x42, 0x1f, 0x7e, 0x39, 0x2a, 0xe1, 0x73, 0xff, 0x50, 0x56, 0x16, 0xc3, 0x30, 0x1d, 0x00, 0xc6, 0x0b, 0x19, 0x3c, 0xe3, 0x59, 0xee, 0xf8, 0xfb, 0x75, 0x16, 0x44, 0x1f, 0x7e, 0xd9, 0x62, 0x0c, 0xd4, 0x72, 0xf0, 0xb1, 0xd1, 0x87, 0xd0, 0x23, 0x1e, 0xa1, 0x47, 0x0e, 0x7c, 0xeb, 0xc3, 0x6f, 0x89, 0xd1, 0x57, 0x19, 0x6c, 0x4c, 0xc0, 0x9b, 0xad, 0x81, 0x58, 0x59, 0x21, 0x21, 0x21, 0x68, 0x6e, 0x6e, 0xc6, 0xb4, 0x69, 0x4d, 0x50, 0x2a, 0x83, 0xdd, 0xaa, 0x4f, 0x4f, 0x4f, 0x33, 0xce, 0x9e, 0x0d, 0x41, 0x70, 0x70, 0x30, 0x9a, 0x9a, 0x9a, 0xfa, 0x45, 0x18, 0xf9, 0x95, 0xeb, 0xea, 0x1d, 0xf8, 0xd0, 0x87, 0x10, 0x50, 0x89, 0x16, 0x30, 0xe9, 0xf5, 0x0f, 0x08, 0x00, 0xc4, 0xc7, 0xc7, 0x0f, 0xba, 0x4f, 0xd7, 0x40, 0x5d, 0xd1, 0x50, 0x84, 0xd4, 0xf5, 0xa1, 0x10, 0x5b, 0x19, 0x14, 0xfb, 0x87, 0xda, 0x68, 0xb6, 0x1b, 0x04, 0x84, 0x5b, 0xae, 0x27, 0xd6, 0x32, 0x40, 0xbe, 0xf5, 0xe1, 0xb7, 0xc4, 0xe8, 0xa3, 0x90, 0x58, 0x66, 0x70, 0xc4, 0xfa, 0x3a, 0x78, 0x26, 0x76, 0x10, 0x8a, 0x2f, 0x7d, 0xf8, 0x3d, 0x31, 0x78, 0x80, 0x10, 0xcb, 0x27, 0xcb, 0x04, 0x94, 0xeb, 0x77, 0xf0, 0x4b, 0x62, 0x08, 0x11, 0x3c, 0x63, 0x18, 0xc6, 0x2c, 0x94, 0x5c, 0xbf, 0xd4, 0xb1, 0xbf, 0x3a, 0x6f, 0x42, 0x05, 0x8b, 0xfc, 0x29, 0x08, 0x25, 0xc3, 0x05, 0x39, 0x84, 0xc8, 0xb8, 0xf6, 0x97, 0x4c, 0x6e, 0x19, 0x14, 0xe4, 0xe0, 0x7b, 0xb9, 0x9e, 0xa4, 0x96, 0x01, 0xca, 0xf0, 0x8e, 0x1c, 0x7c, 0x2f, 0xd7, 0x93, 0xd4, 0x32, 0x40, 0xd9, 0xc7, 0xf0, 0xce, 0xe7, 0x70, 0x27, 0xa6, 0xe2, 0x4b, 0xb9, 0xf2, 0xa8, 0xc4, 0x4f, 0x83, 0x67, 0xfe, 0x10, 0x84, 0x92, 0x21, 0x43, 0x74, 0xfc, 0x3f, 0xcb, 0x88, 0xe5, 0xa1, 0xe9, 0x09, 0x6b, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; #endif static unsigned char icon64[]={ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0xaa, 0x69, 0x71, 0xde, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc4, 0x00, 0x00, 0x0e, 0xc4, 0x01, 0x95, 0x2b, 0x0e, 0x1b, 0x00, 0x00, 0x16, 0x09, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xd5, 0x5b, 0x79, 0x58, 0x93, 0x67, 0xb6, 0xff, 0xe5, 0xcb, 0x42, 0x08, 0x49, 0xc8, 0x4a, 0x04, 0xd9, 0x14, 0x41, 0x50, 0x41, 0x09, 0xa2, 0x56, 0x1d, 0x50, 0xc1, 0xad, 0x96, 0xd2, 0x5a, 0x9d, 0x6e, 0x2e, 0xb5, 0x2d, 0xd5, 0xd6, 0x56, 0x3b, 0x4a, 0xed, 0xad, 0xd7, 0xf6, 0xd6, 0x8e, 0xda, 0x65, 0xdc, 0xed, 0xae, 0xd3, 0x5b, 0x47, 0x6b, 0xf5, 0x8e, 0x9d, 0x22, 0xde, 0x16, 0xab, 0x8c, 0x0f, 0x32, 0x3a, 0x4c, 0x0b, 0x95, 0xc7, 0x0a, 0xb8, 0xd4, 0x8e, 0xa8, 0x10, 0x84, 0x40, 0x08, 0x21, 0x0b, 0x49, 0xbe, 0x2f, 0xe7, 0xfe, 0x21, 0xc4, 0x04, 0x82, 0x56, 0xad, 0xcb, 0x7d, 0x9f, 0x87, 0x3f, 0x78, 0xbf, 0x37, 0xe7, 0x7b, 0xcf, 0x79, 0xcf, 0xf2, 0x3b, 0xe7, 0xbc, 0x1f, 0x0f, 0x77, 0x61, 0x10, 0x11, 0xb1, 0x2c, 0x0b, 0x97, 0xcb, 0x05, 0x00, 0x10, 0x89, 0x44, 0x10, 0x08, 0x04, 0xe0, 0xf1, 0x78, 0x3c, 0xfc, 0x7f, 0x1e, 0xd4, 0x6d, 0x04, 0x5a, 0xc3, 0xb2, 0x2c, 0x1d, 0x39, 0x72, 0x84, 0x72, 0x72, 0xa6, 0x93, 0x52, 0xd9, 0x8f, 0x94, 0xca, 0x7e, 0x94, 0x93, 0x33, 0x9d, 0x8e, 0x1c, 0x39, 0x42, 0x2c, 0xcb, 0xd2, 0xcd, 0xd2, 0xbd, 0x27, 0x98, 0x6f, 0x6f, 0x6f, 0xa7, 0x0b, 0x17, 0x2e, 0xd0, 0x85, 0x0b, 0x17, 0xc8, 0x62, 0xb1, 0xf4, 0xd8, 0x2c, 0x11, 0x51, 0x41, 0x41, 0x01, 0x69, 0xb5, 0xc3, 0x28, 0x2e, 0xee, 0x6b, 0x4a, 0x4d, 0x6d, 0xa7, 0xd4, 0xd4, 0x76, 0x8a, 0x8b, 0xfb, 0x9a, 0xb4, 0xda, 0x61, 0x54, 0x50, 0x50, 0x10, 0xf0, 0x37, 0x16, 0x8b, 0xc5, 0x4b, 0xb7, 0xbd, 0xbd, 0xfd, 0xde, 0x13, 0x82, 0xcb, 0xe5, 0xa2, 0x82, 0x82, 0x02, 0x1a, 0x37, 0x6e, 0x1a, 0xa9, 0xd5, 0x69, 0xa4, 0x52, 0xe9, 0x29, 0x23, 0x63, 0x2a, 0xed, 0xdd, 0xbb, 0x97, 0x9c, 0x4e, 0x27, 0x75, 0x31, 0x62, 0x32, 0x99, 0x28, 0x2d, 0x2d, 0x83, 0x06, 0x0e, 0xfc, 0x07, 0xa5, 0xa5, 0x91, 0xdf, 0xdf, 0x95, 0xb9, 0x0c, 0x32, 0x99, 0x4c, 0x5e, 0x06, 0x9d, 0x4e, 0x27, 0xed, 0xdd, 0xbb, 0x97, 0x32, 0x32, 0xa6, 0x92, 0x4a, 0xa5, 0x27, 0xb5, 0x3a, 0x8d, 0xc6, 0x8d, 0x9b, 0x46, 0x05, 0x05, 0x05, 0xe4, 0x72, 0xb9, 0x7e, 0x13, 0x21, 0x08, 0x7e, 0x8b, 0x93, 0xdf, 0xb5, 0x6b, 0x17, 0x5e, 0x7e, 0xf9, 0x7d, 0x28, 0x95, 0xab, 0x10, 0x1d, 0x3d, 0x0a, 0x00, 0x0f, 0x8d, 0x8d, 0xe5, 0x58, 0xb0, 0xe0, 0x35, 0x58, 0xad, 0x56, 0x74, 0x31, 0x54, 0x53, 0x53, 0x83, 0xfa, 0x7a, 0x05, 0xc2, 0xc3, 0x87, 0xf7, 0xa0, 0x23, 0x91, 0x0c, 0x47, 0x7d, 0xbd, 0x02, 0x35, 0x35, 0x35, 0x18, 0x33, 0x66, 0x0c, 0x88, 0x88, 0xb6, 0x6f, 0xdf, 0x8e, 0xfc, 0xfc, 0x4f, 0xa1, 0x56, 0xbf, 0x8d, 0x98, 0x98, 0x74, 0x00, 0x04, 0x83, 0xe1, 0x5f, 0xc8, 0xcb, 0x5b, 0x81, 0x8d, 0x1b, 0x6d, 0x20, 0x22, 0xba, 0x55, 0xbf, 0xc1, 0xdc, 0x2a, 0xf3, 0xcd, 0xcd, 0xcd, 0x58, 0xbb, 0xf6, 0x53, 0xa8, 0xd5, 0x1b, 0x21, 0x93, 0x4d, 0x00, 0xc3, 0x48, 0xc0, 0x30, 0xc1, 0x90, 0x4a, 0x33, 0x10, 0x16, 0xf6, 0x01, 0xd6, 0xae, 0xdd, 0x8a, 0xa6, 0xa6, 0x26, 0x00, 0x80, 0xcd, 0x66, 0x03, 0xcb, 0x8a, 0xc0, 0xe3, 0x09, 0x7b, 0xd0, 0xe2, 0xf1, 0x84, 0x60, 0x59, 0x11, 0x6c, 0x36, 0x1b, 0x00, 0xa0, 0xa9, 0xa9, 0x09, 0x6b, 0xd7, 0x6e, 0x45, 0x58, 0xd8, 0x07, 0x90, 0x4a, 0x33, 0xc0, 0x30, 0xc1, 0x60, 0x18, 0x09, 0x64, 0xb2, 0x09, 0x50, 0xab, 0x37, 0x62, 0xed, 0xda, 0x4f, 0xd1, 0xdc, 0xdc, 0x8c, 0x5b, 0x35, 0x07, 0xe6, 0x56, 0x35, 0xe0, 0xcc, 0x99, 0x33, 0x30, 0x18, 0xe4, 0x90, 0x48, 0x86, 0xf6, 0x78, 0x26, 0x16, 0x0f, 0x82, 0xd1, 0xa8, 0x43, 0x75, 0x75, 0x35, 0x00, 0x20, 0x26, 0x26, 0x06, 0x21, 0x21, 0xcd, 0xe0, 0xb8, 0xd6, 0x1e, 0x6b, 0x39, 0xae, 0x15, 0x21, 0x21, 0xcd, 0x88, 0x89, 0x89, 0x01, 0x00, 0x54, 0x57, 0x57, 0xc3, 0x68, 0xd4, 0x41, 0x2c, 0x1e, 0x14, 0x40, 0x5b, 0x86, 0xc2, 0x60, 0x90, 0xe3, 0xcc, 0x99, 0x33, 0xb7, 0x6c, 0x02, 0xb7, 0x2c, 0x00, 0xa7, 0xd3, 0x09, 0x8e, 0x13, 0x00, 0xe0, 0x07, 0x78, 0xca, 0x07, 0xc7, 0x09, 0xe1, 0x74, 0x3a, 0x01, 0x00, 0x03, 0x06, 0x0c, 0xc0, 0xa4, 0x49, 0x09, 0x68, 0x6c, 0x7c, 0x1b, 0x44, 0x4e, 0x1f, 0x4d, 0x72, 0xa2, 0xb1, 0xf1, 0x6d, 0x4c, 0x9a, 0x94, 0x80, 0x01, 0x03, 0x06, 0xf8, 0xd0, 0x15, 0x5e, 0x83, 0xae, 0xc0, 0x4b, 0xf7, 0x8e, 0xf8, 0x80, 0xee, 0xaa, 0xd6, 0x65, 0x7b, 0xfd, 0xfa, 0xf5, 0x83, 0x5c, 0xde, 0x0c, 0x96, 0x35, 0x42, 0x28, 0x0c, 0xef, 0x71, 0xaa, 0x12, 0x49, 0xbd, 0x97, 0x29, 0x3e, 0x9f, 0x8f, 0x55, 0xab, 0xfe, 0x08, 0xb3, 0x79, 0x31, 0x0e, 0x1e, 0xbc, 0x1f, 0x52, 0xe9, 0x64, 0x00, 0x80, 0xd5, 0xfa, 0x1d, 0x26, 0x4d, 0x0a, 0xc3, 0xaa, 0x55, 0x9b, 0xc0, 0xe7, 0xf3, 0xbd, 0xc2, 0x92, 0x48, 0xea, 0xc1, 0x71, 0xad, 0x10, 0x08, 0x34, 0xdd, 0x42, 0xa9, 0x11, 0x72, 0x79, 0x33, 0xfa, 0xf5, 0xeb, 0x77, 0xdd, 0xfd, 0xdd, 0xb2, 0x00, 0xba, 0x08, 0x57, 0x55, 0x55, 0xe1, 0xd8, 0xb1, 0x63, 0x10, 0x0a, 0x85, 0xc8, 0xc8, 0xc8, 0xf0, 0xce, 0xc7, 0xc6, 0xc6, 0xe2, 0xe1, 0x87, 0x47, 0x62, 0xfb, 0xf6, 0xd7, 0x10, 0x15, 0xf5, 0x21, 0x18, 0x46, 0x02, 0x00, 0xf0, 0x78, 0x3a, 0x60, 0x30, 0xbc, 0x86, 0x47, 0x1f, 0x1d, 0x86, 0xb8, 0xb8, 0x38, 0x2f, 0xbd, 0xb0, 0xb0, 0x30, 0xec, 0xd8, 0xf1, 0x39, 0xca, 0xcb, 0xcb, 0x71, 0xf8, 0xf0, 0x61, 0x00, 0xc0, 0x84, 0x09, 0x2b, 0x91, 0x9e, 0x9e, 0x8e, 0xa0, 0xa0, 0x20, 0xef, 0xba, 0xb8, 0xb8, 0x38, 0x3c, 0xf8, 0xe0, 0x30, 0xec, 0xd9, 0xf3, 0x1a, 0x22, 0x23, 0xb7, 0x80, 0x61, 0xc4, 0x9d, 0x74, 0xed, 0x30, 0x18, 0x5e, 0xc3, 0xdc, 0xb9, 0x23, 0x11, 0x1b, 0x1b, 0xeb, 0xdd, 0xe3, 0xb9, 0x73, 0xe7, 0x50, 0x5a, 0x5a, 0x0a, 0xb7, 0xdb, 0xed, 0x75, 0xa2, 0x37, 0x22, 0x88, 0x5e, 0x99, 0x37, 0x9b, 0xcd, 0x34, 0x7b, 0xf6, 0x1c, 0x92, 0xcb, 0x53, 0x49, 0xa7, 0x5b, 0x42, 0x3a, 0xdd, 0x4b, 0xa4, 0x54, 0x26, 0xd3, 0xd2, 0xa5, 0x4b, 0xc9, 0x6a, 0xb5, 0x52, 0x57, 0x9c, 0x9e, 0x3f, 0x7f, 0x01, 0xc9, 0xe5, 0x43, 0x3b, 0xd7, 0xe4, 0x93, 0x5c, 0x3e, 0x8c, 0x9e, 0x7e, 0xfa, 0x19, 0x6a, 0x6b, 0x6b, 0xa3, 0x9b, 0x1d, 0x6d, 0x6d, 0x6d, 0xf4, 0xf4, 0xd3, 0xcf, 0x90, 0x5c, 0x3e, 0x8c, 0x74, 0xba, 0x7c, 0xd2, 0xe9, 0x96, 0x90, 0x5c, 0x3e, 0x94, 0xe6, 0xcf, 0x5f, 0xe0, 0xc5, 0x19, 0x56, 0xab, 0x95, 0x96, 0x2e, 0x5d, 0x4a, 0x4a, 0x65, 0x32, 0xe9, 0x74, 0x2f, 0x75, 0xae, 0x49, 0xa5, 0xd9, 0xb3, 0xe7, 0x90, 0xd9, 0x6c, 0xbe, 0x2e, 0x66, 0xb8, 0xa6, 0x74, 0x3c, 0x1e, 0x0f, 0xe5, 0xe5, 0xe5, 0x61, 0xff, 0x7e, 0x11, 0x22, 0x23, 0x37, 0x79, 0xbd, 0x37, 0xc7, 0x59, 0x70, 0xf1, 0xe2, 0xb3, 0x58, 0xb4, 0x68, 0x30, 0xde, 0x78, 0xe3, 0x0d, 0x74, 0x09, 0xf9, 0xf4, 0xe9, 0xd3, 0x38, 0x72, 0xe4, 0x08, 0x88, 0x08, 0x19, 0x19, 0x19, 0x18, 0x34, 0x68, 0xd0, 0x6f, 0x82, 0x33, 0x6a, 0x6a, 0x6a, 0x50, 0x5a, 0x5a, 0x0a, 0x1e, 0x8f, 0x87, 0xcc, 0xcc, 0x4c, 0x24, 0x26, 0x26, 0x76, 0x1d, 0x10, 0xde, 0x7a, 0xeb, 0x2d, 0x6c, 0xde, 0x5c, 0x8d, 0xe8, 0xe8, 0x6d, 0xe0, 0xf3, 0xe5, 0x9d, 0xf3, 0x6e, 0xd4, 0xd5, 0x2d, 0x46, 0x4e, 0x8e, 0x0b, 0x5b, 0xb7, 0x6e, 0x05, 0xc3, 0x30, 0xbc, 0x1b, 0x16, 0x00, 0x11, 0xd1, 0xa9, 0x53, 0xa7, 0x90, 0x95, 0xf5, 0x2c, 0x74, 0xba, 0x22, 0x2f, 0xf1, 0xab, 0xe0, 0xa7, 0x16, 0x6e, 0xf7, 0x53, 0x28, 0x2e, 0xfe, 0x02, 0x7d, 0xfb, 0xf6, 0xbd, 0x2b, 0x00, 0xac, 0xbe, 0xbe, 0x1e, 0xd9, 0xd9, 0x4f, 0x42, 0x28, 0xfc, 0x1c, 0x22, 0x51, 0x6c, 0x37, 0xff, 0x63, 0x41, 0x63, 0xe3, 0x54, 0x1c, 0x3e, 0xfc, 0x67, 0x24, 0x26, 0x26, 0xf6, 0x6a, 0x0a, 0xcc, 0xf5, 0x24, 0xcf, 0xb2, 0x09, 0xe0, 0xf3, 0xa5, 0x3d, 0x9e, 0x09, 0x85, 0x7d, 0x61, 0x34, 0x8a, 0x51, 0x57, 0x57, 0x77, 0xd7, 0x10, 0x68, 0x5d, 0x5d, 0x1d, 0x8c, 0x46, 0x31, 0x84, 0xc2, 0x9e, 0x07, 0xc0, 0xe7, 0x4b, 0xc1, 0xb2, 0x09, 0xde, 0x10, 0x7c, 0x53, 0x61, 0x50, 0x2c, 0x16, 0x83, 0xc7, 0x73, 0x82, 0xc8, 0x13, 0x40, 0x43, 0x58, 0x08, 0x04, 0x04, 0xa1, 0x50, 0x78, 0xd7, 0x04, 0x20, 0x14, 0x0a, 0x21, 0x10, 0x10, 0x88, 0xd8, 0x00, 0xfb, 0xf3, 0x80, 0xc7, 0x73, 0x42, 0x2c, 0x16, 0xdf, 0xbc, 0x00, 0xf4, 0x7a, 0x3d, 0x64, 0xb2, 0x9f, 0xe1, 0x72, 0x9d, 0xef, 0xf1, 0xcc, 0x6e, 0xaf, 0x40, 0xbf, 0x7e, 0x84, 0xfe, 0xfd, 0xfb, 0xdf, 0x35, 0x01, 0xf4, 0xef, 0xdf, 0x1f, 0xfd, 0xfa, 0x11, 0xec, 0xf6, 0x8a, 0x00, 0xf9, 0xc9, 0x79, 0xc8, 0x64, 0x3f, 0x43, 0xaf, 0xd7, 0xdf, 0x9c, 0x00, 0x78, 0x3c, 0x1e, 0x2f, 0x3c, 0x3c, 0x1c, 0x4b, 0x96, 0xcc, 0x83, 0xc1, 0xf0, 0x0c, 0x6c, 0xb6, 0x1f, 0x40, 0xe4, 0x84, 0xc7, 0x63, 0x83, 0xc5, 0x72, 0x08, 0x66, 0xf3, 0xab, 0xc8, 0xcf, 0x9f, 0x0f, 0x85, 0x42, 0x71, 0xd7, 0x04, 0xa0, 0x50, 0x28, 0x90, 0x9f, 0x3f, 0x1f, 0x66, 0xf3, 0xab, 0xb0, 0x58, 0x0e, 0xc1, 0xe3, 0xb1, 0x81, 0xc8, 0x09, 0x9b, 0xed, 0x07, 0x18, 0x0c, 0xcf, 0x60, 0xc9, 0x92, 0x79, 0x08, 0x0f, 0x0f, 0xbf, 0xb5, 0x50, 0xe8, 0x74, 0x3a, 0x69, 0xc7, 0x8e, 0x1d, 0x34, 0x6a, 0xd4, 0x44, 0x52, 0x2a, 0xd3, 0x49, 0xa3, 0x19, 0x41, 0xe3, 0xc7, 0x3f, 0x40, 0x85, 0x85, 0x85, 0xc4, 0xb2, 0x2c, 0xdd, 0xed, 0xc1, 0xb2, 0x2c, 0x15, 0x16, 0x16, 0xd2, 0xf8, 0xf1, 0x0f, 0x90, 0x46, 0x33, 0x82, 0x94, 0xca, 0x74, 0x1a, 0x35, 0x6a, 0x22, 0xed, 0xd8, 0xb1, 0xc3, 0x9b, 0x89, 0xfe, 0xea, 0x30, 0x78, 0xad, 0x98, 0xd9, 0xd6, 0xd6, 0x86, 0x96, 0x96, 0x16, 0xf0, 0x78, 0x3c, 0x68, 0xb5, 0x5a, 0x48, 0xa5, 0xd2, 0x7b, 0x2a, 0x25, 0xb7, 0x5a, 0xad, 0x30, 0x1a, 0x8d, 0x20, 0x22, 0xa8, 0xd5, 0x6a, 0x84, 0x86, 0x86, 0xe2, 0x5a, 0xda, 0xdd, 0x43, 0x00, 0x44, 0x44, 0x46, 0xa3, 0x11, 0x1f, 0x7f, 0xfc, 0x31, 0xf6, 0xed, 0xdb, 0x07, 0x8b, 0xc5, 0x82, 0xf4, 0xf4, 0x74, 0x2c, 0x5c, 0xb8, 0x10, 0xf7, 0xdd, 0x77, 0x1f, 0xee, 0x54, 0xb5, 0xca, 0xed, 0xe6, 0x50, 0x50, 0x50, 0x80, 0xa6, 0xa6, 0xcb, 0x01, 0xcf, 0x8b, 0xc7, 0x13, 0x40, 0x20, 0x90, 0x20, 0x34, 0xb4, 0x0f, 0x92, 0x93, 0x13, 0x91, 0x94, 0x14, 0x89, 0x40, 0x5b, 0x23, 0x22, 0x94, 0x95, 0x95, 0xe1, 0x83, 0x0f, 0x3e, 0x40, 0x79, 0x79, 0x39, 0xe4, 0x72, 0x39, 0x72, 0x73, 0x73, 0xb1, 0x60, 0xc1, 0x02, 0x68, 0xb5, 0x5a, 0xaf, 0x10, 0x78, 0x5d, 0xcc, 0xd7, 0xd7, 0xd7, 0xe3, 0xa1, 0x87, 0x66, 0xa2, 0xae, 0xee, 0x3e, 0xa8, 0xd5, 0x79, 0xe0, 0xf3, 0x43, 0x61, 0xb5, 0x1e, 0x45, 0x6b, 0xeb, 0x5b, 0xd8, 0xbc, 0xf9, 0x55, 0xcc, 0x9a, 0x35, 0xeb, 0x8e, 0x08, 0xe0, 0xe7, 0x9f, 0xeb, 0x91, 0x95, 0x35, 0x07, 0x6e, 0xf7, 0xf0, 0x6b, 0x28, 0x2d, 0x0f, 0x0c, 0x23, 0x00, 0xc3, 0x18, 0xa1, 0xd5, 0x9e, 0xc5, 0xeb, 0xaf, 0xaf, 0x40, 0x6e, 0xee, 0x78, 0xf8, 0xe2, 0x9d, 0x9d, 0x3b, 0x77, 0x62, 0xd1, 0xa2, 0x77, 0xa1, 0x54, 0xbe, 0x01, 0xa9, 0x74, 0x2c, 0x38, 0xae, 0x0d, 0x2d, 0x2d, 0x5b, 0x11, 0x19, 0x59, 0x86, 0x82, 0x82, 0xbf, 0xa2, 0x6f, 0xdf, 0xbe, 0xe0, 0x75, 0x49, 0xc1, 0xed, 0x76, 0xd3, 0xe2, 0xc5, 0x7f, 0x40, 0x41, 0x81, 0x16, 0xe1, 0xe1, 0xaf, 0xfb, 0x59, 0x86, 0xd3, 0x79, 0x16, 0x8d, 0x8d, 0x39, 0xa8, 0xae, 0x3e, 0x0a, 0xad, 0x56, 0x7b, 0xdb, 0x05, 0x50, 0x5c, 0x7c, 0x14, 0x33, 0x67, 0xbe, 0x87, 0xb8, 0xb8, 0xc2, 0x5f, 0x03, 0xd6, 0xd1, 0xd1, 0xf1, 0x33, 0x9a, 0x9a, 0xde, 0xc5, 0xf2, 0xe5, 0xbf, 0xc3, 0xe2, 0xc5, 0x73, 0xc1, 0xe3, 0xf1, 0x60, 0x34, 0x1a, 0x31, 0x78, 0xf0, 0x58, 0xe8, 0x74, 0xfb, 0x11, 0x14, 0x94, 0xe0, 0xb7, 0xbe, 0xa1, 0xe1, 0x8f, 0x78, 0xe8, 0x21, 0x23, 0x36, 0x6d, 0xda, 0x00, 0xa1, 0x50, 0xc8, 0x63, 0xba, 0xec, 0xa7, 0xa8, 0xe8, 0x5f, 0xd0, 0x68, 0xf2, 0x7a, 0x80, 0xc3, 0x2b, 0x04, 0xb2, 0xf1, 0xed, 0xb7, 0xdf, 0xde, 0x11, 0x0d, 0x38, 0x70, 0xe0, 0x9f, 0x08, 0x0b, 0xfb, 0x83, 0x0f, 0x1c, 0xef, 0x80, 0xc1, 0xb0, 0x02, 0x75, 0x75, 0x4b, 0xd1, 0xd6, 0xf6, 0x0d, 0x58, 0xb6, 0x05, 0x1c, 0x67, 0xf6, 0x6a, 0x83, 0x58, 0x9c, 0x80, 0xe8, 0xe8, 0x3f, 0x63, 0xf5, 0xea, 0x9d, 0x38, 0x7d, 0xfa, 0x02, 0x00, 0x74, 0xee, 0x35, 0xbb, 0x1b, 0xf3, 0x57, 0xd6, 0x6b, 0x34, 0x79, 0x28, 0x2a, 0xfa, 0x17, 0xac, 0x56, 0xeb, 0xd5, 0x30, 0xe8, 0x76, 0xbb, 0xd1, 0xdc, 0x6c, 0x81, 0x40, 0xa0, 0xee, 0x05, 0x70, 0xf4, 0x85, 0xc1, 0x60, 0xb8, 0xee, 0xe6, 0x59, 0xd6, 0x83, 0xc6, 0xc6, 0x56, 0x5c, 0xbc, 0x58, 0x87, 0x8b, 0x17, 0x2f, 0xa1, 0xbe, 0xbe, 0x11, 0x56, 0x6b, 0xc7, 0x0d, 0xd4, 0x16, 0x39, 0x54, 0x55, 0xfd, 0xe8, 0xcd, 0xfc, 0x00, 0xc0, 0x68, 0xdc, 0x82, 0x79, 0xf3, 0x82, 0xb0, 0x72, 0x65, 0x02, 0x5e, 0x7c, 0xb1, 0x16, 0xc3, 0x86, 0xad, 0x81, 0xd1, 0x98, 0x85, 0xf6, 0xf6, 0x12, 0xbf, 0xdf, 0x4a, 0xa5, 0xb3, 0xb1, 0x77, 0xef, 0x01, 0x00, 0x80, 0xc1, 0x60, 0x08, 0x88, 0x0e, 0x01, 0x40, 0x20, 0x50, 0xa3, 0xb9, 0xd9, 0x02, 0xb7, 0xdb, 0x7d, 0x35, 0x1d, 0x0e, 0x0a, 0x0a, 0x42, 0x74, 0xb4, 0x16, 0x4e, 0x67, 0x2d, 0xc4, 0xe2, 0x84, 0x00, 0x6a, 0x56, 0x8d, 0xc4, 0xc4, 0x19, 0xd7, 0x64, 0xbc, 0xac, 0xec, 0x04, 0x3e, 0xfa, 0xe8, 0x13, 0x1c, 0x3b, 0x76, 0x19, 0x2d, 0x2d, 0x97, 0xe0, 0xf1, 0xb0, 0x90, 0x48, 0xd4, 0x48, 0x4c, 0xd4, 0xe2, 0xd1, 0x47, 0x73, 0xd0, 0xd2, 0x52, 0x87, 0x73, 0xe7, 0xaa, 0xfc, 0x7e, 0xb7, 0x7c, 0xf9, 0x1a, 0x0c, 0x1a, 0x14, 0xed, 0xfd, 0xdf, 0x60, 0x30, 0xe2, 0xdc, 0x39, 0x31, 0x14, 0x8a, 0xfb, 0x7c, 0x00, 0xd7, 0xdf, 0x90, 0x9f, 0x7f, 0x00, 0x4a, 0xe5, 0x55, 0xaf, 0x5e, 0x59, 0xf9, 0x33, 0x1e, 0x79, 0xe4, 0x3f, 0x00, 0x8c, 0xf3, 0xa3, 0x67, 0x34, 0x9e, 0x03, 0x00, 0x24, 0x26, 0x26, 0xa2, 0xa3, 0x63, 0x2f, 0x00, 0xea, 0xa1, 0xd1, 0x4e, 0x67, 0x2d, 0xa2, 0xa3, 0xb5, 0xde, 0xd4, 0x5b, 0x70, 0x45, 0x7a, 0x52, 0x3c, 0xfe, 0xf8, 0xfd, 0xd8, 0xb4, 0xe9, 0x3d, 0x44, 0x46, 0x6e, 0x04, 0xc3, 0x48, 0xbd, 0xcc, 0xb7, 0xb5, 0x15, 0x41, 0xa7, 0x3b, 0x83, 0xec, 0xec, 0xec, 0x80, 0xcc, 0xdb, 0xed, 0x4e, 0xbc, 0xfb, 0xee, 0x47, 0xf8, 0xfc, 0xf3, 0x7f, 0x43, 0x28, 0x9c, 0x02, 0x8d, 0x66, 0x1a, 0xb4, 0xda, 0xab, 0xf0, 0xd8, 0x64, 0xfa, 0x11, 0x9b, 0x37, 0xd7, 0x03, 0x18, 0x0c, 0xa2, 0x44, 0x1f, 0x66, 0x17, 0x63, 0xf3, 0x66, 0x7f, 0x10, 0x75, 0xe1, 0xc2, 0x45, 0xb4, 0xb6, 0x3a, 0xd1, 0x85, 0xad, 0x58, 0xb6, 0x05, 0x69, 0x69, 0x29, 0x90, 0x48, 0x24, 0x7e, 0xeb, 0x86, 0x0c, 0xe9, 0x0f, 0xbd, 0x3e, 0x19, 0xb5, 0xb5, 0x3d, 0xe1, 0x2f, 0x00, 0x64, 0x67, 0x67, 0x43, 0xa7, 0x5b, 0x8d, 0xb6, 0xb6, 0x22, 0x84, 0x86, 0x4e, 0xf5, 0x0a, 0xc1, 0xe3, 0xb1, 0xa2, 0xa9, 0xe9, 0x3d, 0x2c, 0x5e, 0x7c, 0xbf, 0x37, 0x8c, 0x0b, 0x00, 0x80, 0x61, 0x18, 0x2c, 0x58, 0x30, 0x1f, 0x35, 0x35, 0x7f, 0xc0, 0xc1, 0x83, 0xb3, 0x21, 0x93, 0xcd, 0xec, 0x8c, 0x02, 0xc7, 0x10, 0x1a, 0x7a, 0x18, 0x1f, 0x7d, 0xb4, 0x0e, 0x32, 0x99, 0x2c, 0x00, 0x48, 0x72, 0xe3, 0xf5, 0xd7, 0xd7, 0xe2, 0x8b, 0x2f, 0xce, 0x23, 0x22, 0x62, 0xb3, 0xb7, 0x18, 0x72, 0x45, 0x3d, 0xc9, 0xcf, 0x84, 0x24, 0x92, 0x34, 0xbf, 0xdf, 0x86, 0x86, 0xee, 0x46, 0x48, 0x48, 0xb0, 0xdf, 0xdc, 0xa1, 0x43, 0x65, 0x50, 0xa9, 0xae, 0x46, 0x1b, 0x8b, 0xe5, 0x00, 0x26, 0x4f, 0xee, 0x87, 0xa0, 0x20, 0x61, 0xb7, 0x98, 0xdf, 0x01, 0x83, 0xc1, 0x14, 0x00, 0x19, 0x5e, 0xa9, 0x27, 0xca, 0x64, 0x32, 0x7c, 0xf4, 0xd1, 0x3a, 0xcc, 0x9f, 0xff, 0x2a, 0xea, 0xeb, 0x8f, 0x42, 0x2a, 0x1d, 0x03, 0x8e, 0x6b, 0x43, 0x7b, 0xfb, 0x5f, 0x31, 0x69, 0x92, 0x0c, 0x0b, 0x16, 0xcc, 0x07, 0xc3, 0x30, 0x57, 0x05, 0xc0, 0xe3, 0xf1, 0x78, 0x44, 0x44, 0x9f, 0x7c, 0xf2, 0x21, 0x8a, 0x8b, 0x8b, 0xf1, 0xed, 0xb7, 0xdf, 0xa2, 0xad, 0xad, 0x0d, 0xe9, 0xe9, 0xe9, 0x98, 0x31, 0x63, 0xb7, 0xb7, 0x50, 0xd9, 0x7d, 0x7c, 0xf9, 0xe5, 0x7e, 0xec, 0xde, 0x5d, 0x87, 0x88, 0x88, 0x4d, 0x5e, 0xe6, 0x1b, 0x1b, 0xdf, 0x46, 0x4a, 0x4a, 0x35, 0x72, 0x73, 0x73, 0x11, 0x1b, 0xab, 0x41, 0x79, 0xf9, 0x59, 0x6c, 0xdf, 0xbe, 0x13, 0x36, 0xdb, 0x7a, 0x84, 0x84, 0xa4, 0x77, 0x82, 0xaa, 0xfd, 0x98, 0x3a, 0x35, 0x01, 0x22, 0x91, 0xd0, 0xcf, 0xfe, 0x4f, 0x9e, 0x3c, 0x09, 0x81, 0x60, 0xb4, 0x8f, 0x80, 0xcf, 0x21, 0x33, 0x33, 0xbb, 0x5b, 0x8d, 0x82, 0xb0, 0x7f, 0x7f, 0x31, 0xce, 0x9d, 0xb3, 0x20, 0xfa, 0xaa, 0xf5, 0xa0, 0xb5, 0xf5, 0x4b, 0x64, 0x65, 0xad, 0xf1, 0xfe, 0x9f, 0x91, 0x91, 0x81, 0x03, 0x07, 0x76, 0x63, 0xef, 0xde, 0xbd, 0x28, 0x2f, 0xff, 0x0b, 0x42, 0x43, 0x43, 0x71, 0xff, 0xfd, 0x73, 0x91, 0x9d, 0x9d, 0x0d, 0xa9, 0x54, 0x1a, 0x18, 0x1e, 0xdf, 0x08, 0x04, 0xad, 0xaf, 0x37, 0x52, 0x52, 0xd2, 0x24, 0x1a, 0x3c, 0xf8, 0x94, 0xb7, 0xb9, 0x11, 0x19, 0xb9, 0x86, 0x36, 0x6c, 0xd8, 0x4e, 0x1d, 0x1d, 0x2e, 0x1f, 0xa8, 0xca, 0x51, 0x6e, 0xee, 0xe3, 0x14, 0x1f, 0x7f, 0xd0, 0xbb, 0x2e, 0x26, 0x66, 0x1b, 0x7d, 0xf6, 0xd9, 0xff, 0xfa, 0xd1, 0x33, 0x18, 0x9a, 0xa9, 0x5f, 0xbf, 0x99, 0x7e, 0xcd, 0x12, 0xad, 0x36, 0x9b, 0xea, 0xea, 0x1a, 0xc9, 0xe3, 0xf1, 0x50, 0x4b, 0x8b, 0x8d, 0x8e, 0x1e, 0xad, 0xa2, 0x65, 0xcb, 0xd6, 0x50, 0x54, 0xd4, 0x1c, 0x1a, 0x36, 0xcc, 0xec, 0x5d, 0x17, 0x1f, 0x7f, 0x90, 0x32, 0x32, 0x66, 0x90, 0xd5, 0xea, 0xf8, 0x55, 0x7b, 0xff, 0x4d, 0x1a, 0x23, 0x5f, 0x7d, 0x75, 0x10, 0x2d, 0x2d, 0x89, 0x88, 0x8a, 0xba, 0x62, 0xd7, 0x66, 0xf3, 0xdf, 0x30, 0x7e, 0x7c, 0x33, 0x16, 0x2e, 0x5c, 0x06, 0xa1, 0xf0, 0x6a, 0x25, 0xb7, 0xa9, 0xc9, 0x8c, 0xb3, 0x67, 0xf9, 0x90, 0x4a, 0xc7, 0xfa, 0x9c, 0xd6, 0x76, 0x4c, 0x98, 0xb0, 0xbb, 0x9b, 0xfd, 0xd7, 0xa3, 0xbd, 0x5d, 0x0a, 0x95, 0xca, 0x77, 0xb6, 0x2f, 0xc6, 0x8c, 0x19, 0x09, 0x3e, 0x9f, 0x81, 0x4c, 0x36, 0x0b, 0x66, 0xb3, 0x03, 0x7c, 0xfe, 0x08, 0xa8, 0xd5, 0x2f, 0x82, 0xcf, 0x97, 0x75, 0x6a, 0x4e, 0x1d, 0x5c, 0xae, 0x2d, 0xf8, 0xd3, 0x9f, 0xd6, 0x20, 0x24, 0x44, 0x7c, 0xf3, 0x55, 0x61, 0x22, 0xa2, 0xc6, 0xc6, 0x46, 0x1c, 0x39, 0x72, 0x04, 0x66, 0xb3, 0x19, 0x29, 0x29, 0x29, 0x18, 0x3e, 0x7c, 0x38, 0x04, 0x02, 0x41, 0x80, 0x70, 0xc5, 0xa2, 0xb8, 0xf8, 0x18, 0xb4, 0xda, 0x17, 0x7d, 0x3c, 0xf0, 0x06, 0xe4, 0xe7, 0x7f, 0xe6, 0xc7, 0xfc, 0x95, 0xf9, 0x26, 0xd4, 0xd7, 0x5f, 0x42, 0x7c, 0xfc, 0x55, 0x7b, 0x8f, 0x8a, 0x8a, 0x84, 0x52, 0xe9, 0xef, 0x00, 0x0f, 0x1e, 0xfc, 0x27, 0x64, 0xb2, 0x49, 0x7e, 0x73, 0x91, 0x91, 0x1f, 0x83, 0xe3, 0xda, 0x3a, 0xc3, 0x57, 0x18, 0x34, 0x1a, 0x7f, 0xad, 0x35, 0x9b, 0xf7, 0x81, 0x61, 0xbe, 0xc0, 0xd6, 0xad, 0xcb, 0x91, 0x9e, 0x3e, 0xb8, 0x97, 0x08, 0xc5, 0xa2, 0xa2, 0xa2, 0x02, 0x3f, 0xfd, 0xf4, 0x13, 0x14, 0x0a, 0x05, 0x32, 0x33, 0x33, 0xfd, 0x3a, 0x4a, 0x82, 0x2e, 0x24, 0xf8, 0xe9, 0xa7, 0x9f, 0xe2, 0xcd, 0x37, 0xd7, 0x83, 0x65, 0x47, 0x83, 0x61, 0x14, 0x70, 0xb9, 0x76, 0x61, 0xf8, 0xf0, 0x20, 0x6c, 0xdb, 0xb6, 0x15, 0xd1, 0xbe, 0xc6, 0x06, 0xc0, 0x68, 0x34, 0xa3, 0xaa, 0xca, 0x0c, 0xa5, 0x32, 0xc9, 0x27, 0x37, 0x8f, 0x43, 0x4c, 0x4c, 0x44, 0x8f, 0x0d, 0x1c, 0x3e, 0x7c, 0x1c, 0x1a, 0xcd, 0x42, 0x9f, 0xd3, 0xdf, 0x8b, 0xdf, 0xfd, 0x4e, 0x09, 0xa9, 0x34, 0xd8, 0x67, 0x93, 0x1c, 0xaa, 0xaa, 0xaa, 0x11, 0x1c, 0x9c, 0xe7, 0x9f, 0xab, 0x33, 0x62, 0x3f, 0x4c, 0x70, 0xa5, 0xd4, 0xd5, 0x0e, 0xa3, 0x71, 0x0b, 0xec, 0xf6, 0xbf, 0x23, 0x37, 0x77, 0x38, 0xde, 0x7c, 0x73, 0x0b, 0xa2, 0xa3, 0x75, 0x01, 0xf3, 0x81, 0x8b, 0x17, 0x2f, 0xe2, 0xd9, 0x67, 0xf3, 0x50, 0x51, 0xe1, 0x84, 0x48, 0xa4, 0x87, 0xc7, 0x63, 0x86, 0x40, 0xf0, 0x06, 0xde, 0x7c, 0x73, 0x09, 0xdc, 0x6e, 0x37, 0x09, 0x85, 0x42, 0x9e, 0x80, 0x88, 0xa8, 0xb0, 0xb0, 0x10, 0xf9, 0xf9, 0x9f, 0x22, 0x36, 0xf6, 0x3b, 0x88, 0x44, 0x5d, 0x0e, 0xcf, 0x83, 0xd3, 0xa7, 0x37, 0x62, 0xf6, 0xec, 0xa7, 0x51, 0x54, 0x54, 0xe8, 0x17, 0x8a, 0x1c, 0x0e, 0x1b, 0x5a, 0x5a, 0x0c, 0x50, 0x2a, 0xaf, 0xbe, 0x2c, 0x21, 0x21, 0x0a, 0x12, 0x89, 0xb8, 0x47, 0x42, 0x52, 0x59, 0xf9, 0x4f, 0x30, 0xcc, 0x14, 0x1f, 0x27, 0xe6, 0xc0, 0xd0, 0xa1, 0x63, 0xfc, 0x70, 0xbb, 0xc5, 0x62, 0x43, 0x59, 0xd9, 0x2f, 0xd0, 0xe9, 0x52, 0x7c, 0xea, 0x7d, 0x4b, 0xd1, 0xde, 0xfe, 0x89, 0x37, 0x01, 0x12, 0x0a, 0xe5, 0x50, 0xab, 0x23, 0x91, 0x9a, 0x9a, 0x8c, 0xe7, 0x9e, 0xcb, 0x44, 0x6e, 0xee, 0x5e, 0x44, 0x44, 0x28, 0x7b, 0x55, 0x6d, 0xbb, 0xdd, 0x8e, 0xd9, 0xb3, 0x9f, 0xc6, 0xf9, 0xf3, 0xf7, 0xa3, 0x7f, 0xff, 0x97, 0xbd, 0xa5, 0x0f, 0x97, 0xeb, 0x02, 0xf2, 0xf3, 0x1f, 0x41, 0x9f, 0x3e, 0x7d, 0x40, 0x44, 0x24, 0x70, 0xbb, 0xdd, 0xd8, 0xb0, 0xe1, 0x43, 0x84, 0x87, 0xaf, 0xf3, 0x61, 0xfe, 0x0a, 0x48, 0x0c, 0x0b, 0x7b, 0x19, 0x27, 0x4e, 0x94, 0xa0, 0xb4, 0xb4, 0x14, 0x53, 0xa6, 0xf8, 0x32, 0xe1, 0x02, 0xcb, 0xda, 0xfc, 0x5e, 0x18, 0x1c, 0x2c, 0x04, 0x9f, 0xcf, 0x74, 0x53, 0x51, 0x1b, 0x4e, 0x9e, 0xec, 0x40, 0x68, 0xe8, 0x03, 0xde, 0xb9, 0xe6, 0xe6, 0x2d, 0x98, 0x38, 0x71, 0x67, 0x37, 0xfb, 0x6f, 0x80, 0xd3, 0x79, 0xb5, 0xc9, 0xd1, 0xd1, 0x71, 0x06, 0x49, 0x49, 0x46, 0xec, 0xdf, 0xdf, 0x82, 0x90, 0x90, 0xa0, 0x9b, 0xf2, 0x51, 0xa5, 0xa5, 0xa5, 0x38, 0x71, 0x42, 0x82, 0x01, 0x03, 0x5e, 0xf6, 0xab, 0xfb, 0x88, 0x44, 0x31, 0x08, 0x0f, 0x5f, 0x87, 0x0d, 0x1b, 0xde, 0xc6, 0xd4, 0xa9, 0x53, 0xc1, 0xb8, 0xdd, 0x6e, 0x54, 0x56, 0x9e, 0xf6, 0x86, 0xa8, 0xee, 0x05, 0x23, 0x99, 0x2c, 0x13, 0x65, 0x65, 0x65, 0xdd, 0xf2, 0x69, 0xa6, 0x47, 0x31, 0xe9, 0xf8, 0xf1, 0x33, 0x68, 0x69, 0xb1, 0xf8, 0x9d, 0x7e, 0x6d, 0xed, 0x25, 0xd4, 0xd6, 0xd6, 0xfb, 0xad, 0xeb, 0xdb, 0x77, 0x20, 0xb4, 0xda, 0xb0, 0x6e, 0xf6, 0x7f, 0x14, 0x12, 0x89, 0xde, 0xc7, 0xc7, 0x5c, 0xc4, 0xc0, 0x81, 0x31, 0x37, 0xcd, 0x3c, 0x00, 0x94, 0x95, 0x95, 0x41, 0x26, 0xcb, 0x0c, 0x58, 0xf4, 0x0a, 0x09, 0x49, 0x47, 0x65, 0xe5, 0x69, 0xb8, 0xdd, 0x6e, 0x08, 0x78, 0x3c, 0x1e, 0xc4, 0xe2, 0x20, 0x78, 0x3c, 0x1d, 0xde, 0x58, 0xee, 0x1f, 0x77, 0x1d, 0x3d, 0x90, 0x98, 0x50, 0x18, 0x0c, 0x99, 0xcc, 0x9f, 0x09, 0x93, 0x29, 0x05, 0x2f, 0xbe, 0xf8, 0x9f, 0x98, 0x37, 0xef, 0xf7, 0x10, 0x8b, 0x85, 0xd8, 0xbf, 0xbf, 0x04, 0xfb, 0xf6, 0x7d, 0x8f, 0xc8, 0xc8, 0x8f, 0x7d, 0xd4, 0xf2, 0x38, 0x92, 0x93, 0x43, 0xa1, 0x56, 0xcb, 0x7d, 0x6c, 0xda, 0x83, 0xe3, 0xc7, 0x4f, 0x42, 0x26, 0x5b, 0xe4, 0x53, 0x7c, 0x29, 0x44, 0x76, 0xf6, 0x03, 0xb7, 0x94, 0x54, 0x49, 0x24, 0x12, 0x78, 0x3c, 0x8e, 0x5e, 0xfa, 0x1d, 0x1d, 0x10, 0x8b, 0x83, 0xc0, 0xe3, 0xf1, 0xc0, 0x08, 0x85, 0x42, 0x64, 0x65, 0x8d, 0x82, 0xd9, 0x5c, 0x10, 0xa0, 0x63, 0x6b, 0x86, 0xc3, 0x51, 0x84, 0x89, 0x13, 0x27, 0xfa, 0xcd, 0xeb, 0x74, 0x1a, 0xa4, 0xa6, 0xea, 0x60, 0xb7, 0xff, 0xe8, 0x9d, 0xeb, 0xd3, 0xe7, 0x55, 0x54, 0x56, 0x3e, 0x84, 0x97, 0x5e, 0xb2, 0x20, 0x2f, 0xaf, 0x05, 0x85, 0x85, 0xc9, 0x90, 0x48, 0x36, 0xf9, 0x99, 0x95, 0xdb, 0x6d, 0xc0, 0xe0, 0xc1, 0x83, 0x20, 0x10, 0x30, 0x3e, 0xa7, 0xed, 0xc6, 0xd1, 0xa3, 0x95, 0x08, 0x0a, 0xea, 0xef, 0xa3, 0xa6, 0xad, 0x48, 0x4a, 0x4a, 0xb8, 0x25, 0x01, 0x4c, 0x9c, 0x38, 0x11, 0x0e, 0x47, 0x91, 0x4f, 0xe6, 0xe8, 0x6b, 0x9a, 0x05, 0xc8, 0xca, 0x1a, 0x05, 0x91, 0x48, 0x04, 0x46, 0x20, 0x10, 0x60, 0xd9, 0xb2, 0x25, 0x20, 0x7a, 0x1f, 0x26, 0xd3, 0x97, 0xe0, 0xb8, 0x36, 0x10, 0xb9, 0xd1, 0xd1, 0x71, 0x16, 0x97, 0x2e, 0x2d, 0xc4, 0x13, 0x4f, 0xa4, 0x21, 0x39, 0x39, 0xb9, 0x9b, 0xbd, 0x8b, 0xb0, 0x6c, 0xd9, 0x7c, 0xb8, 0xdd, 0x9f, 0xc1, 0x6e, 0xaf, 0xf4, 0xce, 0xcb, 0xe5, 0xd9, 0x08, 0x0d, 0x7d, 0x00, 0x3c, 0x9e, 0x10, 0xed, 0xed, 0xff, 0x0d, 0xbb, 0xfd, 0xef, 0xdd, 0x5e, 0xbc, 0x17, 0x13, 0x27, 0x8e, 0xf2, 0x9b, 0x3b, 0x77, 0xce, 0x00, 0x8b, 0x85, 0xf5, 0x71, 0xb0, 0xd5, 0x88, 0x8a, 0xb2, 0x22, 0x3a, 0x3a, 0xfc, 0x96, 0x04, 0x90, 0x9c, 0x9c, 0x8c, 0x27, 0x9e, 0x48, 0xc3, 0xa5, 0x4b, 0x0b, 0xd1, 0xd1, 0x71, 0x16, 0x44, 0x6e, 0x70, 0x5c, 0x1b, 0x4c, 0xa6, 0x2f, 0x41, 0xf4, 0x3e, 0x96, 0x2d, 0x5b, 0xe2, 0x6d, 0xc4, 0x82, 0xe3, 0x38, 0x2a, 0x2b, 0x2b, 0xa3, 0x9c, 0x9c, 0x19, 0x14, 0x11, 0x31, 0x86, 0x14, 0x8a, 0x91, 0x34, 0x64, 0xc8, 0x38, 0x5a, 0xbd, 0x7a, 0x4d, 0xaf, 0xbd, 0x3d, 0x8e, 0xf3, 0x50, 0x49, 0x49, 0x05, 0x4d, 0x9b, 0xf6, 0x1c, 0x85, 0x87, 0x3f, 0x4c, 0x52, 0xe9, 0x18, 0x92, 0xc9, 0xc6, 0x52, 0x54, 0xd4, 0xef, 0x69, 0xc6, 0x8c, 0x67, 0x69, 0xcf, 0x9e, 0x83, 0x24, 0x95, 0xa6, 0x78, 0xd1, 0xda, 0xd0, 0xa1, 0x46, 0x4a, 0x4e, 0x7e, 0x8c, 0x2e, 0x5f, 0x36, 0xf9, 0xd1, 0xd9, 0xb8, 0x71, 0x07, 0x89, 0x44, 0xd1, 0x14, 0x12, 0x92, 0x4e, 0x21, 0x21, 0xe9, 0x24, 0x16, 0x27, 0xd1, 0x53, 0x4f, 0xe5, 0xff, 0x26, 0x05, 0xd3, 0xb6, 0xb6, 0x36, 0x5a, 0xbd, 0x7a, 0x0d, 0x0d, 0x19, 0x32, 0x8e, 0x14, 0x8a, 0x91, 0x14, 0x11, 0x31, 0x86, 0x72, 0x72, 0x66, 0x50, 0x59, 0x59, 0x19, 0x71, 0x1c, 0x47, 0x3d, 0x6a, 0x82, 0x76, 0xbb, 0x1d, 0x8d, 0x8d, 0x8d, 0x70, 0xb9, 0x5c, 0x50, 0xa9, 0x54, 0xd0, 0x68, 0x34, 0xd7, 0xad, 0x05, 0x3a, 0x1c, 0x2e, 0x34, 0x34, 0x18, 0xe1, 0x74, 0x5a, 0x01, 0xf0, 0x10, 0x1c, 0x2c, 0x43, 0x44, 0x84, 0x16, 0xcb, 0x97, 0xaf, 0xc3, 0x97, 0x5f, 0xb2, 0x08, 0x0f, 0xff, 0xcf, 0x4e, 0x44, 0xf8, 0x3e, 0x66, 0xce, 0x6c, 0xc3, 0xda, 0xb5, 0xcb, 0xfd, 0x68, 0x1a, 0x8d, 0xcd, 0x30, 0x1a, 0x9b, 0xfc, 0x68, 0x6a, 0x34, 0x7d, 0x10, 0x16, 0xa6, 0xfa, 0x4d, 0x0a, 0x2c, 0x44, 0x84, 0xe6, 0xe6, 0x66, 0x98, 0x4c, 0x26, 0x88, 0x44, 0x22, 0xe8, 0x74, 0x3a, 0x48, 0x24, 0x12, 0xff, 0x9a, 0xe0, 0xaf, 0xad, 0x0c, 0x77, 0x8d, 0xb7, 0xde, 0xda, 0x82, 0x7d, 0xfb, 0xbe, 0xc6, 0x8c, 0x19, 0xd3, 0x91, 0x9e, 0x3e, 0x06, 0x29, 0x29, 0x03, 0xa0, 0x50, 0x48, 0xd0, 0xdc, 0x6c, 0x45, 0x55, 0xd5, 0x2f, 0xf8, 0xea, 0xab, 0xff, 0xc1, 0x57, 0x5f, 0x55, 0x21, 0x3a, 0x7a, 0x37, 0x18, 0x46, 0x0a, 0x96, 0x35, 0xc2, 0x66, 0xcb, 0xc3, 0x37, 0xdf, 0x6c, 0x41, 0x42, 0x42, 0xd4, 0x5d, 0xaf, 0x20, 0x07, 0xac, 0x0a, 0xfb, 0x0a, 0xe0, 0xe2, 0xc5, 0x8b, 0xd8, 0xb4, 0x69, 0x13, 0xbe, 0xf9, 0xe6, 0x1b, 0x38, 0x1c, 0x0e, 0x8c, 0x19, 0x33, 0x06, 0x4b, 0x97, 0x2e, 0x45, 0x5a, 0x5a, 0x1a, 0x58, 0x96, 0xc3, 0xe3, 0x8f, 0x2f, 0xc2, 0xc9, 0x93, 0x4f, 0xc0, 0xe1, 0xf8, 0x09, 0x44, 0x06, 0x04, 0x07, 0x07, 0x81, 0xcf, 0x67, 0xc0, 0xb2, 0x1c, 0x3a, 0x3a, 0x5c, 0x10, 0x89, 0xd2, 0x21, 0x97, 0x4f, 0x04, 0xc3, 0x04, 0x83, 0x65, 0x5b, 0x50, 0x57, 0xf7, 0x28, 0xd6, 0xad, 0x5b, 0x84, 0x39, 0x73, 0x1e, 0xc4, 0x9d, 0x28, 0x2e, 0xff, 0xf8, 0xe3, 0x8f, 0x58, 0xb7, 0x6e, 0x1d, 0x8e, 0x1d, 0x3b, 0x86, 0xe0, 0xe0, 0x60, 0x4c, 0x9b, 0x36, 0x0d, 0x8b, 0x17, 0x2f, 0x46, 0x74, 0x74, 0x74, 0x8f, 0x2c, 0xb0, 0x47, 0x5f, 0xa0, 0xba, 0xba, 0x1a, 0x0f, 0x3f, 0xfc, 0x24, 0xec, 0xf6, 0x47, 0xa1, 0x52, 0xcd, 0x06, 0xc3, 0x04, 0xa3, 0xbd, 0xfd, 0xef, 0x68, 0x69, 0x59, 0x8e, 0xbf, 0xfc, 0x65, 0x3d, 0xc6, 0x8e, 0x1d, 0x8f, 0xd1, 0xa3, 0xf3, 0x20, 0x95, 0xee, 0xbe, 0x8e, 0xea, 0xb1, 0xb0, 0x58, 0x0e, 0xc0, 0x6e, 0xff, 0x18, 0xab, 0x57, 0xe7, 0x61, 0xee, 0xdc, 0x07, 0xef, 0x48, 0x69, 0xbd, 0xb0, 0xb0, 0x10, 0x73, 0xe6, 0x2c, 0x81, 0x5a, 0xbd, 0x06, 0x32, 0x59, 0x16, 0x3c, 0x1e, 0x07, 0x4c, 0xa6, 0x1d, 0x90, 0x48, 0xf6, 0xe0, 0xeb, 0xaf, 0xbf, 0xc0, 0xe0, 0xc1, 0x83, 0x7b, 0xd7, 0x00, 0x87, 0xc3, 0x41, 0xb3, 0x66, 0x3d, 0x85, 0x8a, 0x8a, 0x6c, 0x68, 0x34, 0xcf, 0x76, 0xb3, 0xf5, 0x2a, 0xd8, 0x6c, 0x33, 0x71, 0xe8, 0xd0, 0xb7, 0x18, 0x37, 0xee, 0x09, 0x08, 0x85, 0x53, 0xe0, 0x76, 0xb3, 0xf0, 0x78, 0x38, 0x00, 0x9e, 0xce, 0x02, 0x08, 0x03, 0x1e, 0x8f, 0x81, 0x40, 0xc0, 0xa0, 0xa3, 0x63, 0x07, 0xa6, 0x4f, 0x7f, 0x02, 0xaf, 0xbc, 0xb2, 0x08, 0x71, 0x71, 0x7d, 0xee, 0x88, 0x6a, 0x5b, 0x2c, 0x16, 0xa4, 0xa4, 0x8c, 0x44, 0x48, 0xc8, 0x5f, 0x11, 0x1c, 0x3c, 0xc4, 0xef, 0x59, 0x73, 0xf3, 0x36, 0x0c, 0x1f, 0x5e, 0x8c, 0x9d, 0x3b, 0x3f, 0x47, 0x70, 0x70, 0x30, 0x2f, 0x60, 0x36, 0x78, 0xfe, 0xfc, 0x79, 0xfc, 0xf0, 0x43, 0x03, 0x54, 0xaa, 0xe9, 0x3d, 0x88, 0x07, 0x07, 0x0f, 0x86, 0xd1, 0xa8, 0xc7, 0xa9, 0x53, 0x27, 0xf1, 0xef, 0x7f, 0xff, 0x03, 0x27, 0x4e, 0xd4, 0xe2, 0xfc, 0xf9, 0x0b, 0xb0, 0x58, 0x9a, 0xc0, 0xb2, 0x56, 0x10, 0x71, 0x60, 0x18, 0x31, 0x24, 0x12, 0x15, 0x62, 0x62, 0xe2, 0x30, 0x72, 0xe4, 0x7f, 0x41, 0x2c, 0x16, 0xdc, 0x51, 0xdb, 0x2e, 0x29, 0x29, 0x81, 0xdd, 0xae, 0x87, 0x46, 0x33, 0x38, 0x40, 0xb5, 0x68, 0x3a, 0x7e, 0xf8, 0x61, 0x07, 0x1a, 0x1a, 0x1a, 0x7a, 0x66, 0x83, 0xbe, 0x09, 0x44, 0x7b, 0x3b, 0x0b, 0xad, 0x56, 0x1e, 0xb0, 0x21, 0xc1, 0x30, 0x5a, 0x18, 0x8d, 0x46, 0x04, 0x05, 0x09, 0x30, 0x62, 0xc4, 0x00, 0x8c, 0x18, 0x31, 0xe0, 0x9e, 0x6a, 0x8f, 0x19, 0x8d, 0x46, 0x30, 0x8c, 0x36, 0x90, 0x6b, 0x03, 0x9f, 0x2f, 0x47, 0x7b, 0x3b, 0x0b, 0xbb, 0xdd, 0xde, 0x7b, 0x77, 0x58, 0xa1, 0x50, 0x20, 0x2c, 0x4c, 0x04, 0xb7, 0xdb, 0x10, 0xc0, 0xa6, 0x39, 0xb0, 0xec, 0x19, 0xc4, 0xc7, 0xc7, 0xe3, 0x5e, 0x1d, 0xf1, 0xf1, 0xf1, 0x60, 0xd9, 0x33, 0x20, 0xe2, 0x02, 0xb4, 0xdc, 0x0c, 0x08, 0x0b, 0x13, 0xf5, 0xe8, 0x66, 0x33, 0xbe, 0xa1, 0x41, 0xa7, 0xd3, 0x21, 0x27, 0x67, 0x38, 0x9a, 0x9a, 0x36, 0xc0, 0xe3, 0xb1, 0xfb, 0x95, 0xc6, 0x5b, 0x5b, 0x77, 0x21, 0x31, 0xd1, 0x8e, 0x51, 0xa3, 0x46, 0xdd, 0xb3, 0x02, 0x18, 0x35, 0x6a, 0x14, 0x12, 0x13, 0xed, 0x68, 0x6d, 0xdd, 0xe5, 0x57, 0x94, 0xf5, 0x78, 0xec, 0x68, 0x6a, 0xda, 0x80, 0x9c, 0x9c, 0xe1, 0xd0, 0xe9, 0x74, 0xbd, 0x3b, 0xc1, 0x2b, 0xb5, 0x39, 0x03, 0x16, 0x2d, 0x5a, 0x82, 0x23, 0x47, 0x58, 0x48, 0xa5, 0xb9, 0x9d, 0x51, 0xe0, 0x30, 0xfa, 0xf6, 0x3d, 0x81, 0x1d, 0x3b, 0x3e, 0xc1, 0x90, 0x21, 0x43, 0x70, 0x2f, 0x8f, 0xaa, 0xaa, 0x2a, 0xcc, 0x9e, 0x3d, 0x1f, 0xf5, 0xf5, 0x43, 0x21, 0x93, 0x4d, 0x80, 0xc7, 0xe3, 0x80, 0xd5, 0xba, 0x0f, 0x99, 0x99, 0x02, 0x6c, 0xde, 0xbc, 0x1e, 0x11, 0x11, 0x11, 0xd7, 0xc7, 0x01, 0x16, 0x8b, 0x05, 0x87, 0x0f, 0x1f, 0xc6, 0x77, 0xdf, 0x7d, 0xe7, 0xc5, 0x01, 0xb9, 0xb9, 0xb9, 0x08, 0x0b, 0x0b, 0xeb, 0x82, 0xce, 0x38, 0x73, 0xe6, 0x0c, 0x7e, 0xf9, 0xe5, 0x17, 0x84, 0x84, 0x84, 0x20, 0x35, 0x35, 0x15, 0x4a, 0xa5, 0xf2, 0x8e, 0x32, 0xda, 0xda, 0xda, 0x8a, 0xca, 0xca, 0x4a, 0xd8, 0x6c, 0x36, 0xc4, 0xc5, 0xc5, 0x61, 0xe0, 0xc0, 0x81, 0x5e, 0x6c, 0xdf, 0xd4, 0xd4, 0x84, 0x7d, 0xfb, 0xf6, 0x79, 0x71, 0xc0, 0xe4, 0xc9, 0x93, 0x31, 0x61, 0xc2, 0x04, 0xc8, 0xe5, 0xf2, 0x5f, 0x77, 0x59, 0xe2, 0x5a, 0xf8, 0xfa, 0xf2, 0xe5, 0xcb, 0x34, 0x77, 0xee, 0x3c, 0x8a, 0x8c, 0xcc, 0x24, 0xad, 0xf6, 0x49, 0xd2, 0xe9, 0x1e, 0xa1, 0x21, 0x43, 0xee, 0xa3, 0x3d, 0x7b, 0xf6, 0x10, 0xc7, 0x71, 0xb7, 0xfd, 0x42, 0x04, 0xc7, 0x71, 0xb4, 0x67, 0xcf, 0x1e, 0x1a, 0x32, 0xe4, 0x3e, 0xd2, 0xe9, 0x1e, 0x21, 0xad, 0xf6, 0x49, 0x8a, 0x8c, 0xcc, 0xa4, 0xb9, 0x73, 0xe7, 0xd1, 0xe5, 0xcb, 0x97, 0x7f, 0x75, 0x35, 0xf8, 0xa6, 0x86, 0xd3, 0xe9, 0xa4, 0xe9, 0xd3, 0x67, 0x52, 0x9f, 0x3e, 0xaf, 0xd0, 0xb0, 0x61, 0xad, 0x94, 0x96, 0xc6, 0x91, 0x5e, 0xef, 0xa4, 0xa4, 0xa4, 0x72, 0x52, 0xab, 0xf5, 0x74, 0xe8, 0xd0, 0xa1, 0xdb, 0x2e, 0x80, 0x43, 0x87, 0x0e, 0x91, 0x5a, 0xad, 0xa7, 0xa4, 0xa4, 0x72, 0xd2, 0xeb, 0x9d, 0x94, 0x96, 0xc6, 0xd1, 0xb0, 0x61, 0xad, 0xd4, 0xa7, 0xcf, 0x2b, 0x34, 0x7d, 0xfa, 0xcc, 0x5f, 0x75, 0x2b, 0xa4, 0xd7, 0x28, 0x70, 0x3d, 0xad, 0x28, 0x2f, 0x2f, 0x47, 0x71, 0xb1, 0x11, 0x11, 0x11, 0xab, 0xc0, 0xe7, 0x2b, 0x3a, 0x81, 0x8f, 0x08, 0x12, 0xc9, 0x70, 0x28, 0x95, 0xab, 0xb0, 0x6e, 0xdd, 0x16, 0x6f, 0xd3, 0xf1, 0xf6, 0x5c, 0x9e, 0x70, 0x63, 0xdd, 0xba, 0x2d, 0x50, 0x2a, 0x57, 0x41, 0x22, 0x19, 0x0e, 0x1e, 0x4f, 0x04, 0x80, 0x01, 0x9f, 0xaf, 0x40, 0x44, 0xc4, 0x2a, 0x14, 0x17, 0x1b, 0x51, 0x5e, 0x5e, 0x7e, 0x43, 0x57, 0xe8, 0x6f, 0xe8, 0xb6, 0x78, 0x49, 0x49, 0x09, 0x64, 0xb2, 0xc9, 0x9d, 0x2f, 0xf6, 0x1f, 0x32, 0x59, 0x06, 0xbe, 0xff, 0xbe, 0x06, 0x0e, 0x87, 0x23, 0x60, 0x69, 0xda, 0xe9, 0x74, 0xc2, 0xe5, 0x72, 0xc1, 0xe3, 0xf1, 0xf4, 0x4a, 0xdf, 0xe3, 0xf1, 0xc0, 0xe5, 0x72, 0xc1, 0xe9, 0x74, 0x82, 0x65, 0xd9, 0x00, 0x99, 0xa7, 0x03, 0xdf, 0x7f, 0x5f, 0x03, 0x99, 0x2c, 0x23, 0x40, 0x82, 0x23, 0x82, 0x4c, 0x36, 0x19, 0x25, 0x25, 0x25, 0xb8, 0x2d, 0x1a, 0x70, 0x05, 0x4c, 0xf0, 0x03, 0xc6, 0xd8, 0xae, 0xc6, 0x24, 0xc3, 0x30, 0x7e, 0x78, 0xdf, 0xe5, 0x72, 0x61, 0xd7, 0xae, 0x5d, 0xc8, 0xcc, 0x9c, 0x04, 0x8d, 0xa6, 0x3f, 0xe2, 0xe2, 0x86, 0x62, 0xe1, 0xc2, 0x97, 0x50, 0xdb, 0xbd, 0xab, 0x09, 0xa0, 0xb6, 0xb6, 0x16, 0x0b, 0x17, 0xbe, 0x84, 0xb8, 0xb8, 0xa1, 0xd0, 0x68, 0xfa, 0x23, 0x33, 0x73, 0x12, 0x76, 0xed, 0xda, 0xe5, 0xfd, 0xb2, 0xac, 0x33, 0x54, 0x83, 0x61, 0x98, 0x80, 0xf7, 0x16, 0xbb, 0xb0, 0x8a, 0xb7, 0xc8, 0x71, 0x3b, 0x04, 0x30, 0x7e, 0xfc, 0x78, 0xd8, 0x6c, 0xdf, 0x75, 0xc3, 0x08, 0xe8, 0x6c, 0x88, 0x16, 0x63, 0xf4, 0xe8, 0x64, 0xef, 0xc5, 0x44, 0x8e, 0xe3, 0xf0, 0xce, 0x3b, 0xef, 0xe2, 0x85, 0x17, 0xb6, 0xc1, 0x64, 0x5a, 0x83, 0xf8, 0xf8, 0x5f, 0xa0, 0x52, 0x95, 0x60, 0xff, 0xfe, 0x18, 0x4c, 0x99, 0x32, 0x03, 0xe7, 0xcf, 0x5f, 0xbd, 0x7b, 0x78, 0xfe, 0xfc, 0x79, 0x4c, 0x99, 0x32, 0x03, 0xfb, 0xf7, 0xc7, 0x40, 0xa5, 0x2a, 0x41, 0x7c, 0xfc, 0x2f, 0x30, 0x99, 0xd6, 0xe0, 0x85, 0x17, 0xb6, 0xe1, 0x9d, 0x77, 0xde, 0x05, 0xc7, 0x5d, 0x11, 0xba, 0x58, 0x2c, 0xc6, 0xe8, 0xd1, 0xc9, 0x68, 0x6f, 0x2f, 0x0e, 0xa0, 0x3d, 0x76, 0xd8, 0x6c, 0xdf, 0x61, 0xfc, 0xf8, 0xf1, 0xb7, 0x2f, 0xf4, 0xb8, 0x5c, 0x2e, 0x9a, 0x35, 0x6b, 0x2e, 0x85, 0x85, 0xbd, 0x40, 0x29, 0x29, 0x0d, 0xa4, 0xd7, 0xb3, 0x94, 0x9a, 0x6a, 0xa7, 0x84, 0x84, 0xc3, 0xa4, 0xd3, 0xe9, 0xa9, 0xb4, 0xb4, 0xd4, 0xeb, 0xac, 0x6a, 0x6a, 0x6a, 0x48, 0xad, 0x4e, 0xa3, 0x94, 0x94, 0x86, 0x1e, 0x1f, 0x48, 0x45, 0x46, 0xbe, 0x47, 0xcf, 0x3d, 0xf7, 0x3c, 0x71, 0x1c, 0x47, 0x1c, 0xc7, 0xd1, 0x73, 0xcf, 0x3d, 0x4f, 0x91, 0x91, 0xef, 0xf5, 0x58, 0x97, 0x92, 0xd2, 0x40, 0x6a, 0x75, 0x1a, 0xd5, 0xd4, 0xd4, 0x78, 0xe9, 0x96, 0x96, 0x96, 0x92, 0x4e, 0xa7, 0xa7, 0x84, 0x84, 0xc3, 0x94, 0x9a, 0x6a, 0x27, 0xbd, 0x9e, 0xa5, 0x94, 0x94, 0x06, 0x0a, 0x0b, 0x7b, 0x81, 0x66, 0xcd, 0x9a, 0x7b, 0xc3, 0x1f, 0x53, 0xdd, 0x90, 0x06, 0x08, 0x85, 0x42, 0xac, 0x5f, 0xff, 0x27, 0x3c, 0xf6, 0x98, 0x10, 0x56, 0xeb, 0x63, 0xb8, 0x70, 0x61, 0x3a, 0x1a, 0x1a, 0x66, 0x40, 0xa5, 0x5a, 0x85, 0x6d, 0xdb, 0x56, 0x62, 0xf4, 0xe8, 0xd1, 0xde, 0x38, 0x7b, 0xe0, 0xc0, 0x01, 0x88, 0x44, 0x53, 0x21, 0x14, 0xf6, 0xcc, 0x04, 0x55, 0xaa, 0x39, 0x28, 0x2a, 0x2a, 0x85, 0xd3, 0xe9, 0x84, 0xd3, 0xe9, 0x44, 0x51, 0x51, 0x29, 0x54, 0xaa, 0x39, 0x01, 0xde, 0xd7, 0x07, 0x22, 0xd1, 0x54, 0x1c, 0x38, 0x70, 0xc0, 0x8b, 0x56, 0x47, 0x8f, 0x1e, 0x8d, 0x6d, 0xdb, 0x56, 0x42, 0xa5, 0x5a, 0x85, 0x86, 0x86, 0x19, 0xb8, 0x70, 0x61, 0x3a, 0xac, 0xd6, 0xc7, 0xf0, 0xd8, 0x63, 0x57, 0xf6, 0x76, 0xa3, 0x57, 0x77, 0x6f, 0x28, 0x5d, 0xeb, 0x6a, 0xa3, 0xaf, 0x5f, 0xbf, 0x0e, 0x8b, 0x16, 0xd5, 0xa2, 0xae, 0xae, 0x0e, 0xc1, 0xc1, 0xc1, 0x48, 0x48, 0x48, 0x80, 0x42, 0xa1, 0xf0, 0x03, 0x19, 0x26, 0x93, 0x09, 0x7c, 0xbe, 0xaa, 0x17, 0x5f, 0x12, 0x0a, 0xb3, 0xb9, 0x1d, 0x5d, 0xce, 0xda, 0x6c, 0x6e, 0x87, 0x46, 0x13, 0xda, 0xcb, 0x5a, 0x15, 0x4c, 0xa6, 0xab, 0x77, 0x01, 0x04, 0x02, 0x01, 0x8f, 0x88, 0x68, 0xec, 0xd8, 0xb1, 0x38, 0x7b, 0xf6, 0x2c, 0x1c, 0x0e, 0x07, 0x22, 0x23, 0x23, 0x11, 0x1b, 0x1b, 0x0b, 0x3e, 0x9f, 0x7f, 0xc3, 0xb7, 0x42, 0x6f, 0x38, 0x5f, 0xed, 0x7a, 0x01, 0x11, 0x91, 0xef, 0x97, 0x20, 0xdd, 0x5f, 0x9c, 0x9a, 0x9a, 0x8a, 0x0f, 0x3f, 0x0c, 0x7c, 0x4d, 0xc5, 0xe1, 0x38, 0x89, 0x41, 0x83, 0xfa, 0x7b, 0x1b, 0xaf, 0x83, 0x06, 0xf5, 0x47, 0x5b, 0xdb, 0xc9, 0x00, 0xcd, 0x19, 0x82, 0xdd, 0x5e, 0x8e, 0xd4, 0xd4, 0x19, 0x01, 0x0f, 0x62, 0xc4, 0x88, 0x11, 0xbd, 0xbe, 0xff, 0xb6, 0x98, 0x40, 0xf7, 0x4d, 0xf8, 0x8e, 0xee, 0xcf, 0xb3, 0xb2, 0xb2, 0x10, 0x1b, 0x7b, 0x09, 0x26, 0x93, 0x7f, 0x62, 0xc2, 0xb2, 0x4d, 0xb8, 0x7c, 0x79, 0x05, 0x9e, 0x7f, 0xfe, 0x29, 0x08, 0x85, 0x42, 0x08, 0x85, 0x42, 0x3c, 0xff, 0xfc, 0x53, 0xb8, 0x7c, 0x79, 0x05, 0x58, 0xb6, 0xc9, 0x8f, 0x79, 0x93, 0x69, 0x17, 0x62, 0x63, 0x2f, 0x21, 0x2b, 0x2b, 0xeb, 0x86, 0xdf, 0x7f, 0xd7, 0x87, 0xc7, 0xe3, 0xa1, 0x8a, 0x8a, 0x0a, 0xd2, 0xeb, 0xc7, 0x92, 0x4a, 0xf5, 0x24, 0x45, 0x45, 0x6d, 0xa1, 0x88, 0x88, 0x95, 0xa4, 0x52, 0x8d, 0xa0, 0x15, 0x2b, 0x5e, 0x27, 0xbb, 0xdd, 0xee, 0x75, 0x6c, 0x76, 0xbb, 0x9d, 0x56, 0xac, 0x78, 0x9d, 0x54, 0xaa, 0x11, 0x14, 0x11, 0xb1, 0x92, 0xa2, 0xa2, 0xb6, 0x90, 0x4a, 0xf5, 0x24, 0xe9, 0xf5, 0x63, 0xa9, 0xa2, 0xa2, 0x82, 0x3c, 0x1e, 0xcf, 0x6d, 0xfb, 0x54, 0x96, 0x77, 0xbb, 0x85, 0x60, 0x36, 0x9b, 0x51, 0x5c, 0x5c, 0x8c, 0xe3, 0xc7, 0x8f, 0x43, 0xa9, 0x54, 0x62, 0xea, 0xd4, 0xa9, 0x48, 0x4a, 0x4a, 0xf2, 0xfb, 0x5a, 0xbc, 0xeb, 0x6b, 0xf2, 0x53, 0xa7, 0x4e, 0xa1, 0xa8, 0xa8, 0x08, 0xad, 0xad, 0xad, 0xd0, 0xeb, 0xf5, 0xc8, 0xce, 0xce, 0x86, 0x42, 0xa1, 0xb8, 0xe6, 0x27, 0x2f, 0xf7, 0xb4, 0x00, 0x7a, 0x2b, 0xb3, 0xf7, 0xa6, 0xb2, 0x37, 0xb2, 0xf6, 0xb7, 0x1a, 0xff, 0x07, 0x0d, 0x60, 0x29, 0xa2, 0x56, 0x90, 0xc6, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; #endif /* ICON_H */ gplanarity-master/levelstate.c000066400000000000000000000215631510662254600170530ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include "graph.h" #include "timer.h" #include "levelstate.h" #include "gameboard.h" #include "dialog_pause.h" #include "dialog_finish.h" #include "dialog_level.h" #include "main.h" #include "graph_generate.h" #define CHUNK 64 #define SAVENAME "levelstate" typedef struct levelstate{ struct levelstate *prev; struct levelstate *next; graphmeta gm; int in_progress; long highscore; } levelstate; static levelstate *head=0; static levelstate *tail=0; static levelstate *curr=0; static levelstate *pool=0; static int graph_dirty = 1; static int aboutflag = 0; static int pauseflag = 0; static int finishflag = 0; static int selectflag = 0; static int level_limit = 1; static levelstate *new_level(){ levelstate *ret; int num=0; if(pool==0){ int i; pool = calloc(CHUNK,sizeof(*pool)); for(i=0;inext points to nothing */ pool[i].next=pool+i+1; } ret=pool; if(tail) num=tail->gm.num+1; if(generate_get_meta(num, &ret->gm)) return 0; pool=ret->next; ret->next=0; ret->prev=tail; if(tail){ ret->prev->next=ret; }else{ head=ret; } tail=ret; ret->highscore=0; ret->in_progress=0; /* write out a 'fresh' board icon if it doesn't already exist */ if(!gameboard_icon_exists(ret->gm.id,"1")){ // generate a graph we can use to make the icon graph g; memset(&g,0,sizeof(g)); g.width=gameboard->g.orig_width; g.height=gameboard->g.orig_height; g.orig_width=gameboard->g.orig_width; g.orig_height=gameboard->g.orig_height; generate_board(&g,num); impress_location(&g); gameboard_write_icon(ret->gm.id,"1",gameboard,&g,1,1); // releases the temporary graph memory graph_release(&g); } return ret; } static levelstate *ensure_level_num(int level){ if(level<0)return 0; if(!tail)new_level(); if(level <= tail->gm.num){ // find it in the existing levels levelstate *l=tail; while(l){ if(level == l->gm.num) return l; l=l->prev; } return 0; }else{ // make new levels to fill while(tail->gm.numin_progress || gameboard->finish_dialog_active)){ gameboard_write(curr->gm.id,gameboard); gameboard_write_icon(curr->gm.id,"2",gameboard,&gameboard->g, !gameboard->hide_lines,gameboard->show_intersections); } f = fopen(name,"wb"); if(f==NULL){ fprintf(stderr,_("ERROR: Could not save game state file \"%s\":\n\t%s\n"), curr->gm.id,strerror(errno)); return errno; } fprintf(f,"current %d : %s\n",(int)strlen(curr->gm.id),curr->gm.id); { levelstate *l=head; while(l){ fprintf(f,"level %ld %d %d : %s\n", l->highscore,l->in_progress, (int)strlen(l->gm.id),l->gm.id); l=l->next; } } if(gameboard->about_dialog_active) fprintf(f,"about 1\n"); if(gameboard->pause_dialog_active) fprintf(f,"pause 1\n"); if(gameboard->finish_dialog_active) fprintf(f,"finish 1\n"); if(gameboard->level_dialog_active) fprintf(f,"select 1\n"); fclose(f); return 0; } // also functions as the levelstate init; always called once upon startup int levelstate_read(){ char *line=NULL; size_t n=0; FILE *f; char *name=alloca(strlen(statedir)+strlen(SAVENAME)+1); name[0]=0; strcat(name,statedir); strcat(name,SAVENAME); if(!head)new_level(); if(!curr)curr=head; f = fopen(name,"rb"); if(f==NULL){ if(errno!=ENOENT){ fprintf(stderr,_("ERROR: Could not read game state file \"%s\":\n\t%s\n"), curr->gm.id,strerror(errno)); } return errno; } // get all levels we've seen. while(getline(&line,&n,f)>0){ long l; int i; unsigned int j; if (sscanf(line,"level %ld %d %d : ",&l,&i,&j)==3){ char *name=strchr(line,':'); // guard against bad edits if(name && (strlen(line) - (name - line + 2) >= j)){ levelstate *le; name += 2; name[j]=0; le = ensure_level(name); if(le){ le->highscore=l; le->in_progress=i; if(le->highscore) if(le->gm.unlock_plus + le->gm.num > level_limit) level_limit = le->gm.unlock_plus + le->gm.num; } } } } rewind(f); // get current while(getline(&line,&n,f)>0){ int i; if (sscanf(line,"current %d : ",&i)==1){ char *name=strchr(line,':'); // guard against bad edits if(name && (strlen(line) - (name - line + 2) >= (unsigned)i)){ levelstate *le; name += 2; name[i]=0; le = ensure_level(name); if(le) curr=le; } } if(sscanf(line,"about %d",&i)==1) if(i==1) aboutflag=1; if(sscanf(line,"pause %d",&i)==1) if(i==1) pauseflag=1; if(sscanf(line,"finish %d",&i)==1) if(i==1) finishflag=1; if(sscanf(line,"select %d",&i)==1) if(i==1) selectflag=1; } while(curr->gm.num >= level_limit){ levelstate_prev(); } return 0; } void levelstate_resume(){ levelstate_go(); if(pauseflag){ prepare_reenter_game(gameboard); pause_dialog(gameboard); }else if (aboutflag){ prepare_reenter_game(gameboard); about_dialog(gameboard); }else if (finishflag){ prepare_reenter_game(gameboard); finish_level_dialog(gameboard); }else if (selectflag){ prepare_reenter_game(gameboard); level_dialog(gameboard,0); }else{ prepare_reenter_game(gameboard); reenter_game(gameboard); } aboutflag=0; pauseflag=0; finishflag=0; selectflag=0; } void set_in_progress(){ curr->in_progress=1; } long levelstate_total_hiscore(){ long score=0; levelstate *l=head; while(l){ score+=l->highscore; l=l->next; } return score; } long levelstate_get_hiscore(){ if(!curr)return 0; return curr->highscore; } int levelstate_next(){ if(!curr->next) new_level(); if(curr->next){ curr=curr->next; graph_dirty=1; return 1; } return 0; } int levelstate_prev(){ if(curr->prev){ curr=curr->prev; graph_dirty=1; return 1; } return 0; } int get_level_num(){ return curr->gm.num; } char *get_level_desc(){ return _(curr->gm.desc); } void levelstate_finish(){ int score = graphscore_get_score(&gameboard->g) + graphscore_get_bonus(&gameboard->g); curr->in_progress=0; if(score > curr->highscore) curr->highscore = score; if(curr->gm.unlock_plus + curr->gm.num > level_limit) level_limit = curr->gm.unlock_plus + curr->gm.num; } void levelstate_reset(){ curr->in_progress=0; graph_dirty=1; } int levelstate_in_progress(){ return curr->in_progress; } int levelstate_limit(){ return level_limit; } /* commit to the currently selected level and set the game state to readiness using it */ void levelstate_go(){ // we need to load the board if we're currently playing the board or sitting in the finish dialog right after if(curr->in_progress || finishflag){ if(gameboard_read(curr->gm.id,gameboard)){ /* not on disk or couldn't load it. clear level state flags and get a fresh version */ aboutflag=0; pauseflag=0; finishflag=0; selectflag=0; generate_board(&gameboard->g,curr->gm.num); activate_verticies(&gameboard->g); impress_location(&gameboard->g); set_timer(0); } }else{ /* no board in progress; fetch a new board */ generate_board(&gameboard->g,curr->gm.num); activate_verticies(&gameboard->g); impress_location(&gameboard->g); set_timer(0); } graph_dirty=0; } cairo_surface_t *levelstate_get_icon(int num){ levelstate *l=ensure_level_num(num); if(l==0)return 0; return gameboard_read_icon(l->gm.id,(l->in_progress?"2":"1"),gameboard); } gplanarity-master/levelstate.h000066400000000000000000000031051510662254600170500ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef LEVELSTATE_H #define LEVELSTATE_H #include extern int levelstate_write(); extern int levelstate_read(); extern long levelstate_total_hiscore(); extern long levelstate_get_hiscore(); extern int levelstate_in_progress(); extern int levelstate_next(); extern int levelstate_prev(); extern int get_level_num(); extern char *get_level_desc(); extern void levelstate_finish(); extern void levelstate_go(); extern void levelstate_resume(); extern void levelstate_reset(); extern void set_in_progress(); extern int levelstate_limit(); extern cairo_surface_t* levelstate_get_icon(int num); #endif /* LEVELSTATE_H */ gplanarity-master/main.c000066400000000000000000000251541510662254600156270ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include "version.h" #include "graph.h" #include "gameboard.h" #include "levelstate.h" #include "main.h" #define boardstate "/.gPlanarity/boards/" #define mainstate "/.gPlanarity/" char *boarddir; char *statedir; Gameboard *gameboard; GtkWidget *toplevel_window; graph maingraph; char *version = ""; static cairo_font_face_t *font_face=0; static cairo_font_face_t *bold_face=0; static cairo_font_face_t *ital_face=0; static float adjust_x_normal; static float adjust_y_normal; static float adjust_x_bold; static float adjust_y_bold; static int dir_create(char *name){ if(mkdir(name,0700)){ switch(errno){ case EEXIST: // this is ok return 0; default: fprintf(stderr,_("ERROR: Could not create directory (%s) to save game state:\n\t%s\n"), name,strerror(errno)); return errno; } } return 0; } void request_resize(int width, int height){ gtk_window_resize(GTK_WINDOW(toplevel_window),width,height); if(gameboard->resize_timeout) gameboard->resize_timeout = time(NULL)+3; gameboard->resize_w = width; gameboard->resize_h = height; } static void clean_exit(int sig){ signal(sig,SIG_IGN); if(sig!=SIGINT) fprintf(stderr, _("\nTrapped signal %d; saving state and exiting!\n"),sig); levelstate_write(); gtk_main_quit(); exit(0); } static void clean_exit_delete_post(Gameboard *g){ gameboard = 0; gtk_main_quit(); } static gint clean_exit_delete(gpointer p){ levelstate_write(); undeploy_buttons(gameboard,clean_exit_delete_post); return 1; // we're handling it, don't continue the delete chain } /* font handling... still a pain in the ass! ...but mostly due to lack of documentation. Try first to find one of the default fonts we prefer (FontConfig can search for a list, Cairo cannot). Regardless of what's found, try to determine the approximate best aspect ratio of the text; gPlanarity looks best with a relatively tall/narrow font that renders with horizontal/vertical strokes of approximately identical width */ static cairo_font_face_t *init_font(char *list, int slant,int bold){ cairo_font_face_t *ret; char *fontface; FcPattern *fc_pattern; FcBool scalable; FcResult fc_result; fc_pattern = FcNameParse((unsigned char *)list); // load the system config FcConfigSubstitute(0, fc_pattern, FcMatchPattern); FcPatternDel(fc_pattern,FC_SLANT); FcPatternDel(fc_pattern,FC_WEIGHT); if(slant) FcPatternAddInteger(fc_pattern,FC_SLANT,FC_SLANT_ITALIC); if(bold) FcPatternAddInteger(fc_pattern,FC_WEIGHT,FC_WEIGHT_BOLD); // fill in missing defaults FcDefaultSubstitute(fc_pattern); // find a font face on our list if possible fc_pattern = FcFontMatch(0, fc_pattern, &fc_result); if(!fc_pattern){ fprintf(stderr,_("\nUnable to find any suitable %s fonts!\n" "Continuing, but the the results are likely to be poor.\n\n"), (slant?(bold?_("bold italic"):_("italic")):(bold?_("bold"):_("medium")))); } FcPatternGetString (fc_pattern, FC_FAMILY, 0, (FcChar8 **)&fontface); /* if(!strstr(list,fontface)){ fprintf(stderr,"\nUnable to find any of gPlanarity's preferred %s fonts (%s);\n" "Using system default font \"%s\".\n\n", (slant?(bold?"bold italic":"italic"):(bold?"bold":"medium")), list,fontface); }*/ FcPatternGetBool(fc_pattern, FC_SCALABLE, 0, &scalable); if (scalable != FcTrue) { fprintf(stderr,_("\nSelected %s font \"%s\" is not scalable! This is almost as bad\n" "as not finding any font at all. Continuing, but this may look\n" "very poor indeed.\n\n"), (slant?(bold?_("bold italic"):_("italic")):(bold?_("bold"):_("medium"))), fontface); } /* Set the hinting behavior we want; only the autohinter is giving decent results across a wide range of sizes and face options. Don't obey the system config with respect to hinting; every one of my systems installed a default config that resulted in the available fonts looking like ass. Bitstream Vera Sans especially looks bad without the autohinter, and that's the font most systems will have as the only sans default. */ // Must remove the preexisting settings! The settings are a list, // and we're tacking ours on the end; Cairo only inspects first hit FcPatternDel(fc_pattern,FC_HINT_STYLE); FcPatternDel(fc_pattern,FC_HINTING); FcPatternDel(fc_pattern,FC_AUTOHINT); // Add ours requesting autohint FcPatternAddBool(fc_pattern,FC_HINTING,FcTrue); FcPatternAddBool(fc_pattern,FC_AUTOHINT,FcTrue); // Make the font face ret = cairo_ft_font_face_create_for_pattern(fc_pattern); FcPatternDestroy(fc_pattern); return ret; } static void init_fonts(char *list){ font_face = init_font(list,0,0); bold_face = init_font(list,0,1); ital_face = init_font(list,1,0); // We've done the best we can, font-choice-wise. Determine an // aspect ratio correction for whatever font we've got. Arial is // declared to be the ideal aspect, correct other fonts to the same // rough proportions (it looks better). This is a rough hack, but // yields an unmistakable improvement. { cairo_text_extents_t ex; char *test_string = "Practice Before the Handbasket: Three of Three"; cairo_surface_t *s = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,16,16); cairo_t *c = cairo_create(s); cairo_matrix_t m; cairo_set_font_face (c, font_face); cairo_matrix_init_scale (&m, 50.,50.); cairo_set_font_matrix (c,&m); cairo_text_extents (c, test_string, &ex); adjust_x_normal = 1058 / ex.width; adjust_y_normal = -37 / ex.y_bearing; cairo_set_font_face (c, bold_face); cairo_text_extents (c, test_string, &ex); adjust_x_bold = 1130 / ex.width; adjust_y_bold = -37 / ex.y_bearing; cairo_destroy(c); cairo_surface_destroy(s); } } void set_font (cairo_t *c, float w, float h, int slant, int bold){ cairo_matrix_t m; if(slant){ cairo_set_font_face(c,ital_face); cairo_matrix_init_scale (&m, ceil(w*adjust_x_normal),ceil(h*adjust_y_normal)); }else if (bold){ cairo_set_font_face(c,bold_face); cairo_matrix_init_scale (&m, ceil(w*adjust_x_bold),ceil(h*adjust_y_bold)); }else{ cairo_set_font_face(c,font_face); cairo_matrix_init_scale (&m, ceil(w*adjust_x_normal),ceil(h*adjust_y_normal)); } cairo_set_font_matrix (c,&m); } #include "icon.h" void set_icons(){ GError *error=NULL; GList *pb=NULL; //GdkPixbufLoader *pbl1 = gdk_pixbuf_loader_new(); GdkPixbufLoader *pbl2 = gdk_pixbuf_loader_new(); GdkPixbufLoader *pbl3 = gdk_pixbuf_loader_new(); //gdk_pixbuf_loader_write(pbl1,icon134,sizeof(icon134),&error); gdk_pixbuf_loader_write(pbl2,icon64,sizeof(icon64),&error); gdk_pixbuf_loader_write(pbl3,icon32,sizeof(icon32),&error); //gdk_pixbuf_loader_close(pbl1,NULL); gdk_pixbuf_loader_close(pbl2,NULL); gdk_pixbuf_loader_close(pbl3,NULL); //pb = g_list_append(pb, gdk_pixbuf_loader_get_pixbuf(pbl1)); pb = g_list_append(pb, gdk_pixbuf_loader_get_pixbuf(pbl2)); pb = g_list_append(pb, gdk_pixbuf_loader_get_pixbuf(pbl3)); gtk_window_set_icon_list(GTK_WINDOW(toplevel_window),pb); } int main(int argc, char *argv[]){ #ifdef ENABLE_NLS setlocale(LC_ALL, ""); textdomain(GT_DOMAIN); bindtextdomain(GT_DOMAIN, GT_DIR); #endif char *homedir = getenv("home"); if(!homedir) homedir = getenv("HOME"); if(!homedir) homedir = getenv("homedir"); if(!homedir) homedir = getenv("HOMEDIR"); if(!homedir){ fprintf(stderr, _("No homedir environment variable set! gPlanarity will be\n" "unable to permanently save any progress or board state.\n")); boarddir=NULL; statedir=NULL; }else{ boarddir=calloc(strlen(homedir)+strlen(boardstate)+1,1); strcat(boarddir,homedir); strcat(boarddir,boardstate); statedir=calloc(strlen(homedir)+strlen(mainstate)+1,1); strcat(statedir,homedir); strcat(statedir,mainstate); dir_create(statedir); dir_create(boarddir); } version=strstr(VERSION,"version.h"); if(version){ char *versionend=strchr(version,' '); if(versionend)versionend=strchr(versionend+1,' '); if(versionend)versionend=strchr(versionend+1,' '); if(versionend)versionend=strchr(versionend+1,' '); if(versionend){ int len=versionend-version-9; version=strdup(version+10); version[len-1]=0; } }else{ version=""; } init_fonts(""); gtk_init (&argc, &argv); toplevel_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (toplevel_window), "delete-event", G_CALLBACK (clean_exit_delete), NULL); gameboard = gameboard_new(); levelstate_read(); gtk_container_add (GTK_CONTAINER (toplevel_window), GTK_WIDGET(gameboard)); gtk_widget_realize(toplevel_window); gtk_widget_realize(GTK_WIDGET(gameboard)); memset(&maingraph,0,sizeof(maingraph)); /* get the setup processed before we fire up animations */ while (gtk_events_pending ()){ gtk_main_iteration (); gdk_window_process_updates(gtk_widget_get_window (toplevel_window),1); gdk_flush(); } levelstate_resume(); set_icons(); gtk_widget_show_all(toplevel_window); signal(SIGINT,clean_exit); //signal(SIGSEGV,clean_exit); /* would be a bad idea; corrupt state //could prevent us from restarting */ gtk_main (); if(gameboard !=0 ) levelstate_write(); cairo_font_face_destroy(font_face); cairo_font_face_destroy(bold_face); cairo_font_face_destroy(ital_face); return 0; } gplanarity-master/main.h000066400000000000000000000024721510662254600156320ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef MAIN_H #define MAIN_H #include #include "gameboard.h" #include "nls.h" extern char *boarddir; extern char *statedir; extern char *fontface; extern char *version; extern Gameboard *gameboard; extern void request_resize(int width, int height); extern void set_font(cairo_t *c, float w, float h, int slant, int bold); #endif /* MAIN_H */ gplanarity-master/meson.build000066400000000000000000000031421510662254600166720ustar00rootroot00000000000000project( 'gplanarity', 'c', version: '1.0', default_options: [ 'warning_level=3', 'prefix=/usr', ], ) subdir('po') executable( 'gPlanarity', [ 'dialog_finish.c', 'dialog_level.c', 'dialog_level_icons.c', 'dialog_pause.c', 'gameboard.c', 'gameboard_draw_box.c', 'gameboard_draw_buttonbar.c', 'gameboard_draw_button.c', 'gameboard_draw_curtain.c', 'gameboard_draw_edge.c', 'gameboard_draw_intersection.c', 'gameboard_draw_main.c', 'gameboard_draw_score.c', 'gameboard_draw_selection.c', 'gameboard_draw_text.c', 'gameboard_draw_vertex.c', 'gameboard_logic_buttonbar.c', 'gameboard_logic_button.c', 'gameboard_logic.c', 'gameboard_logic_fade.c', 'gameboard_logic_mouse.c', 'gameboard_logic_push.c', 'graph_arrange.c', 'graph.c', 'graph_generate.c', 'graph_generate_data.c', 'graph_generate_mesh1.c', 'graph_generate_mesh2.c', 'graph_region.c', 'graph_score.c', 'levelstate.c', 'main.c', 'random.c', 'timer.c', ], dependencies: [ dependency('cairo'), dependency('freetype2'), dependency('fontconfig'), dependency('gtk+-3.0'), meson.get_compiler('c').find_library('m') ], c_args: [ '-ffast-math', '-DUGT_DOMAIN="gPlanarity"', '-DUGT_DIR="/usr/share/locale"', '-DENABLE_NLS', ], install: true, install_dir: '/usr/games' ) gplanarity-master/nls.h000066400000000000000000000005511510662254600154760ustar00rootroot00000000000000#ifndef NLS_H #define NLS_H #ifdef ENABLE_NLS #include #include #define GT_DOMAIN X_GT_DOMAIN(UGT_DOMAIN) #define X_GT_DOMAIN(x) XX_GT_DOMAIN(x) #define XX_GT_DOMAIN(x) #x #define GT_DIR X_GT_DIR(UGT_DIR) #define X_GT_DIR(x) XX_GT_DIR(x) #define XX_GT_DIR(x) #x #define _(x) gettext(x) #else #define _(x) x #endif #endif /* NLS_H */ gplanarity-master/po/000077500000000000000000000000001510662254600151465ustar00rootroot00000000000000gplanarity-master/po/LINGUAS000066400000000000000000000000251510662254600161700ustar00rootroot00000000000000ca cs de es_ES fr_FR gplanarity-master/po/Makefile000066400000000000000000000012721510662254600166100ustar00rootroot00000000000000#GT_DOMAIN:=gPlanarity SRC=../*.c ifeq ($(origin WANT_LINGUAS), undefined) PO=$(wildcard *.po) else PO=$(addsuffix .po,$(WANT_LINGUAS)) endif GMO=$(PO:.po=.gmo) HEADER=--msgid-bugs-address="Monty " all: $(GT_DOMAIN).pot $(GMO) $(GT_DOMAIN).pot: $(SRC) xgettext --strict $(HEADER) -d $(GT_DOMAIN) -o /dev/stdout \ -L C --keyword=_ $(SRC) | sed -f header.sed >$@ %.gmo: %.po $(GT_DOMAIN).pot msgmerge -o$, 2010. # msgid "" msgstr "" "Project-Id-Version: 16723\n" "Report-Msgid-Bugs-To: Monty \n" "POT-Creation-Date: 2012-03-25 11:48-0400\n" "PO-Revision-Date: 2010-11-27 12:01+0100\n" "Last-Translator: Àngel Mompó \n" "Language-Team: \n" "Language: ca_ES\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1\n" # # File: ../dialog_finish.c, line: 80 # File: ../dialog_level.c, line: 67 # File: ../dialog_pause.c, line: 67 # File: ../gameboard_logic_buttonbar.c, line: 54 msgid "exit gPlanarity" msgstr "surt del gPlanarity" # # File: ../dialog_finish.c, line: 81 # File: ../gameboard_logic_buttonbar.c, line: 55 msgid "level selection menu" msgstr "menú de selecció del nivell" # # File: ../dialog_finish.c, line: 82 msgid "play next level!" msgstr "Juga al següent nivell!" # # File: ../dialog_finish.c, line: 160 msgid "Level Complete!" msgstr "Nivell completat!" # # File: ../dialog_finish.c, line: 164 #, c-format msgid "Elapsed: %s" msgstr "Transcorregut: %s" # # File: ../dialog_finish.c, line: 168 #, c-format msgid "Base score: %d points" msgstr "Puntuació base: %d punts" # # File: ../dialog_finish.c, line: 176 #, c-format msgid "Objective Exceeded! %d%%" msgstr "Objectiu superat! %d%%" # # File: ../dialog_finish.c, line: 181 #, c-format msgid "Time bonus: %d points" msgstr "Bonificació de temps: %d punts" # # File: ../dialog_finish.c, line: 186 #, c-format msgid "Final score: %d points" msgstr "Puntuació final: %d punts" # # File: ../dialog_finish.c, line: 191 msgid "A high score!" msgstr "És un rècord!" # # File: ../dialog_finish.c, line: 194 #, c-format msgid "Previous best: %ld points" msgstr "Rècord anterior: %ld punts" # # File: ../dialog_finish.c, line: 199 msgid "Total score to date:" msgstr "Puntuació total:" # # File: ../dialog_finish.c, line: 201 #, c-format msgid "%ld points" msgstr "%ld punts" # # File: ../dialog_level.c, line: 68 msgid "reset level" msgstr "Torna a iniciar el nivell" # # File: ../dialog_level.c, line: 69 msgid "play level!" msgstr "Juga el nivell!" # # File: ../dialog_level.c, line: 139 msgid "Available Levels" msgstr "Nivells disponibles" # # File: ../dialog_level_icons.c, line: 246 #, c-format msgid "Level %d:" msgstr "Nivell %d:" # # File: ../dialog_level_icons.c, line: 264 #, c-format msgid "[not yet completed]" msgstr "[encara no l'heu completat]" # # File: ../dialog_level_icons.c, line: 267 #, c-format msgid "level high score: %ld" msgstr "rècord del nivell: %ld" # # File: ../dialog_level_icons.c, line: 277 #, c-format msgid "total score all levels: %ld" msgstr "puntuació total sumant tots els nivells: %ld" # # File: ../dialog_pause.c, line: 68 msgid "resume game!" msgstr "continueu jugant!" # # File: ../dialog_pause.c, line: 131 msgid "Game Paused" msgstr "Joc en pausa" # # File: ../dialog_pause.c, line: 134 msgid "Time Elapsed:" msgstr "Temps transcorregut:" # # File: ../dialog_pause.c, line: 186 msgid "gPlanarity" msgstr "gPlanarity" # # File: ../dialog_pause.c, line: 190 msgid "Untangle the mess!" msgstr "Desfés l'embolic!" # # File: ../dialog_pause.c, line: 194 msgid "Drag vertices to eliminate crossed lines." msgstr "Arrossegueu els vèrtex per desfer els encreuaments." # # File: ../dialog_pause.c, line: 195 msgid "The objective may be a complete solution or" msgstr "L'objectiu ha de ser una solució completa o" # # File: ../dialog_pause.c, line: 196 msgid "getting as close as possible to solving an" msgstr "estar-hi tant a prop com sigui possible en un" # # File: ../dialog_pause.c, line: 197 msgid "unsolvable puzzle. Work quickly and" msgstr "puzle sense solució. Aneu de pressa i" # # File: ../dialog_pause.c, line: 198 msgid "exceed the objective for bonus points!" msgstr "supereu l'objectiu per obtenir una bonificació!" # # File: ../dialog_pause.c, line: 207 msgid "gPlanarity written by Monty " msgstr "El gPlanarity ha estat escrit per Monty " # # File: ../dialog_pause.c, line: 208 msgid "as a demonstration of Gtk+/Cairo" msgstr "com a demostració del GTK+/Cairo" # # File: ../dialog_pause.c, line: 210 msgid "Original Flash version of Planarity by" msgstr "La versió en Flash original és de" # # File: ../dialog_pause.c, line: 211 msgid "John Tantalo " msgstr "John Tantalo " # # File: ../dialog_pause.c, line: 213 msgid "Original game concept by Mary Radcliffe" msgstr "El concepte original és de Mary Radcliffe" # # File: ../gameboard.c, line: 75 #, c-format msgid "" "\n" "\n" "ERROR: The windowmanager appears to be ignoring resize requests.\n" "This stands a pretty good chance of scrambling any saved board larger\n" "than the default window size.\n" "\n" msgstr "" "\n" "\n" "Error: El gestor de finestres sembla que ignora les peticions de canvi de " "mida.\n" "El més probable és que s'estigui intentant descodificar un tauler desat \n" "més gran que la mida de la finestra per defecte.\n" # # File: ../gameboard.c, line: 78 # File: ../gameboard.c, line: 189 #, c-format msgid "" "Clipping and/or expanding this board to the current window size...\n" "\n" msgstr "Retallant i/o expandint el tauler a la mida actual de la finestra...\n" # # File: ../gameboard.c, line: 184 #, c-format msgid "" "\n" "\n" "ERROR: The window size granted by the windowmanager is not the\n" "window size gPlanarity requested. If the windowmanager is\n" "configured to ignore application sizing requests, this stands\n" "a pretty good chance of scrambling saved boards later (and\n" "making everything look funny now).\n" "\n" msgstr "" "\n" "\n" "ERROR: La mida de la finestra que pot oferir el gestor de finestres no és\n" "la mida que ha demanat el gPlanarity. Si el gestor de finestres està\n" "configurat per ignorar les peticions de mida, el més probable és que\n" "es barregin els taulers desats (i fa que ara tot es vegi divertit).\n" "\n" # # File: ../gameboard_draw_intersection.c, line: 65 msgid "rather many, really" msgstr "N'hi ha masses" # # File: ../gameboard_draw_main.c, line: 370 #, c-format msgid "ERROR: Could not load board icon \"%s\"\n" msgstr "ERROR: No es pot carregar la icona del tauler «%s»\n" # # File: ../gameboard_draw_main.c, line: 436 #, c-format msgid "ERROR: Could not save board icon \"%s\"\n" msgstr "ERROR: No es pot desar la icona del tauler «%s»\n" # # File: ../gameboard_draw_score.c, line: 67 #, c-format msgid "Level %d: %s" msgstr "Nivell %d: %s" # # File: ../gameboard_draw_score.c, line: 68 #, c-format msgid "Score: %d" msgstr "Puntuació: %d" # # File: ../gameboard_draw_score.c, line: 69 #, c-format msgid "%d%%" msgstr "%d%%" # # File: ../gameboard_draw_score.c, line: 70 #, c-format msgid "Intersections: %ld" msgstr "Interseccions: %ld" # # File: ../gameboard_draw_score.c, line: 71 #, c-format msgid "Objective: %s" msgstr "Objectiu: %s" # # File: ../gameboard_logic_buttonbar.c, line: 56 msgid "reset board" msgstr "torna a iniciar el taulell" # # File: ../gameboard_logic_buttonbar.c, line: 57 msgid "pause" msgstr "pausa" # # File: ../gameboard_logic_buttonbar.c, line: 58 msgid "help / about" msgstr "ajuda / quant a" # # File: ../gameboard_logic_buttonbar.c, line: 59 msgid "expand" msgstr "expandeix" # # File: ../gameboard_logic_buttonbar.c, line: 60 msgid "shrink" msgstr "encongeix" # # File: ../gameboard_logic_buttonbar.c, line: 61 msgid "hide/show lines" msgstr "mostra/amaga les línies" # # File: ../gameboard_logic_buttonbar.c, line: 62 msgid "mark intersections" msgstr "marca les interseccions" # # File: ../gameboard_logic_buttonbar.c, line: 63 msgid "click when finished!" msgstr "cliqueu quan acabeu!" # # File: ../gameboard_logic.c, line: 371 #, c-format msgid "" "ERROR: Could not save board state for \"%s\":\n" "\t%s\n" msgstr "" "ERROR: No es pot desar l'estat del tauler per «%s»:\n" "\t%s\n" # # File: ../gameboard_logic.c, line: 401 #, c-format msgid "" "ERROR: Could not read saved board state for \"%s\":\n" "\t%s\n" msgstr "" "ERROR: No es pot llegir l'estat del tauler per «%s»:\n" "\t%s\n" # # File: ../graph.c, line: 923 #, c-format msgid "WARNING: edge references out of range vertex in save file\n" msgstr "" "AVÍS: referències de les cantonades fora del rang dels vèrtex al fitxer " "desat\n" "\n" # # File: ../graph_generate.c, line: 196 # File: ../graph_generate.c, line: 215 #, c-format msgid "Couldn't allocate memory for level name.\n" msgstr "No es pot assignar memòria pel nom del nivell.\n" # # File: ../graph_generate.c, line: 210 #, c-format msgid "Couldn't allocate memory for level description.\n" msgstr "No es pot assignar memòria per la descripció del nivell.\n" # # File: ../graph_region.c, line: 459 #, c-format msgid "" "region overlap adjustment failed in arc_arc_adj; \n" " This is an internal error that should never happen.\n" msgstr "" "ha fallat l'ajust del sobreposat de la regió a arc_arc_adj; \n" " És un error intern que no hauria de passar mai.\n" # # File: ../graph_score.c, line: 67 msgid "zero intersections" msgstr "zero interseccions" # # File: ../graph_score.c, line: 70 msgid "1 intersection or fewer" msgstr "1 intersecció o menys" # # File: ../graph_score.c, line: 72 msgid "1 intersection" msgstr "1 intersecció" # # File: ../graph_score.c, line: 75 #, c-format msgid "%d intersections%s" msgstr "%d interseccions%s" # # File: ../graph_score.c, line: 77 msgid " or fewer" msgstr " o menys" # # File: ../levelstate.c, line: 169 #, c-format msgid "" "ERROR: Could not save game state file \"%s\":\n" "\t%s\n" msgstr "" "ERROR: No es pot desar el fitxer d'estat del joc «%s»:\n" "\t%s\n" # # File: ../levelstate.c, line: 216 #, c-format msgid "" "ERROR: Could not read game state file \"%s\":\n" "\t%s\n" msgstr "" "ERROR: No es pot llegir el fitxer d'estat del joc «%s»:\n" "\t%s\n" # # File: ../main.c, line: 73 #, c-format msgid "" "ERROR: Could not create directory (%s) to save game state:\n" "\t%s\n" msgstr "" "ERROR: No es pot crear el directori (%s) per desar l'estat del joc:\n" "\t%s\n" # # File: ../main.c, line: 93 #, c-format msgid "" "\n" "Trapped signal %d; saving state and exiting!\n" msgstr "" "\n" "S'ha atrapat el senyal %d. Deso l'estat i surto!\n" # # File: ../main.c, line: 146 #, c-format msgid "" "\n" "Unable to find any suitable %s fonts!\n" "Continuing, but the the results are likely to be poor.\n" "\n" msgstr "" "\n" "No es pot trobar cap font %s disponible!\n" "Continuo, però el resultat podria ser pobre.\n" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "bold italic" msgstr "negreta cursiva" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "italic" msgstr "cursiva" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "bold" msgstr "negreta" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "medium" msgstr "normal" # # File: ../main.c, line: 164 #, c-format msgid "" "\n" "Selected %s font \"%s\" is not scalable! This is almost as bad\n" "as not finding any font at all. Continuing, but this may look\n" "very poor indeed.\n" "\n" msgstr "" "\n" "La font %s seleccionada «%s» no es pot escalar! això és tant dolent\n" "com no trobar cap font. Continuo, però es veurà molt pobre.\n" "\n" # # File: ../main.c, line: 288 #, c-format msgid "" "No homedir environment variable set! gPlanarity will be\n" "unable to permanently save any progress or board state.\n" msgstr "" "No està declarada la variable homedir! gPlanarity no podrà\n" "desar el progrés o l'estat del tauler de manera permanent.\n" # # File: ../timer.c, line: 51 #, c-format msgid "%d:%02d:%02d" msgstr "%d:%02d:%02d" # # File: ../timer.c, line: 53 #, c-format msgid "%d:%02d" msgstr "%d:%02d" # # File: ../timer.c, line: 55 #, c-format msgid "%d seconds" msgstr "%d segons" gplanarity-master/po/cs.po000066400000000000000000000206131510662254600161150ustar00rootroot00000000000000# Czech translation for gPlanarity # Copyright (C) 2007 # This file is distributed under the same license as the gPlanarity package. # Petr Pisar , 2007 # msgid "" msgstr "" "Project-Id-Version: gPlanarity 11496\n" "Report-Msgid-Bugs-To: Monty \n" "POT-Creation-Date: 2012-03-25 11:48-0400\n" "PO-Revision-Date: 2007-05-15 17:58+0200\n" "Last-Translator: Petr Pisar \n" "Language-Team: Czech \n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "exit gPlanarity" msgstr "ukončit gPlanarity" msgid "level selection menu" msgstr "nabídka výběru kol" #, fuzzy msgid "play next level!" msgstr "hrát kolo!" msgid "Level Complete!" msgstr "Kolo hotovo!" #, c-format msgid "Elapsed: %s" msgstr "Uplynulo: %s" #, c-format msgid "Base score: %d points" msgstr "Základní skóre: %d bodů" #, c-format msgid "Objective Exceeded! %d%%" msgstr "Úkol překonán! %d%%" #, c-format msgid "Time bonus: %d points" msgstr "Časový bonus: %d bodů" #, c-format msgid "Final score: %d points" msgstr "Konečné skóre: %d bodů" msgid "A high score!" msgstr "Rekord!" #, c-format msgid "Previous best: %ld points" msgstr "Předchozí nejlepší: %ld bodů" msgid "Total score to date:" msgstr "Celkové skóre k datu:" #, c-format msgid "%ld points" msgstr "%ld bodů" msgid "reset level" msgstr "znovu začít kolo" msgid "play level!" msgstr "hrát kolo!" msgid "Available Levels" msgstr "Dostupná kola" #, c-format msgid "Level %d:" msgstr "Kolo %d:" #, c-format msgid "[not yet completed]" msgstr "[ještě nedokončeno]" #, c-format msgid "level high score: %ld" msgstr "rekord pro kolo: %ld" #, c-format msgid "total score all levels: %ld" msgstr "celkové skóre za všechna kola: %ld" msgid "resume game!" msgstr "pokračovat ve hře!" msgid "Game Paused" msgstr "Hra zastavena" msgid "Time Elapsed:" msgstr "Uplynulý čas:" msgid "gPlanarity" msgstr "gPlanarity" msgid "Untangle the mess!" msgstr "Rozmotejte šmodrchanec!" msgid "Drag vertices to eliminate crossed lines." msgstr "Přesunujte vrcholy, abyste odstranili křížící se čáry." msgid "The objective may be a complete solution or" msgstr "Zadání může být uplné řešení nebo" msgid "getting as close as possible to solving an" msgstr "dobrání se podoby co nejblížší řešení" msgid "unsolvable puzzle. Work quickly and" msgstr "neřešitelného rébusu. Pracujte rychle a" msgid "exceed the objective for bonus points!" msgstr "získejte body navíc za překonání zadání!" msgid "gPlanarity written by Monty " msgstr "gPlanarity napsal Monty " msgid "as a demonstration of Gtk+/Cairo" msgstr "jako demo Gtk+/Caira" msgid "Original Flash version of Planarity by" msgstr "Původní verzi Planarity ve flashy napsal" msgid "John Tantalo " msgstr "John Tantalo " msgid "Original game concept by Mary Radcliffe" msgstr "Koncepci hry vymysla Mary Radcliffe." #, c-format msgid "" "\n" "\n" "ERROR: The windowmanager appears to be ignoring resize requests.\n" "This stands a pretty good chance of scrambling any saved board larger\n" "than the default window size.\n" "\n" msgstr "" "\n" "\n" "CHYBA: Zdá se, že správce oken ignoruje požadavky na změnu velikosti okna.\n" "Což znamená docela dobrou šanci, že uložená deska větší než výchozí " "velikost\n" "okna bude poškozená.\n" "\n" #, c-format msgid "" "Clipping and/or expanding this board to the current window size...\n" "\n" msgstr "" "Lze očekávat oříznutí a/nebo roztažení takové desky na rozměry okna…\n" "\n" #, c-format msgid "" "\n" "\n" "ERROR: The window size granted by the windowmanager is not the\n" "window size gPlanarity requested. If the windowmanager is\n" "configured to ignore application sizing requests, this stands\n" "a pretty good chance of scrambling saved boards later (and\n" "making everything look funny now).\n" "\n" msgstr "" "\n" "\n" "CHYBA: Požadovaná velikost okna gPlanarity a velikost zaručena správcem " "oken\n" "se liší. Pokud je správce oken nastaven, aby ignoroval požadavky na změnu\n" "velikosti okna, je docela dobrá šance na poškození později uložených desek\n" "(a na veselý vzhled čehokoliv již od teď).\n" "\n" msgid "rather many, really" msgstr "raději mnoho, opravdu" #, c-format msgid "ERROR: Could not load board icon \"%s\"\n" msgstr "CHYBA: Nelze načíst ikonu desky „%s“\n" #, c-format msgid "ERROR: Could not save board icon \"%s\"\n" msgstr "CHYBA: nelze uložit ikonu desky „%s“\n" #, c-format msgid "Level %d: %s" msgstr "Kolo %d: %s" #, c-format msgid "Score: %d" msgstr "Skóre: %d" #, c-format msgid "%d%%" msgstr "%d%%" #, c-format msgid "Intersections: %ld" msgstr "Průniků: %ld" #, c-format msgid "Objective: %s" msgstr "Zadání: %s" msgid "reset board" msgstr "resetovat desku" msgid "pause" msgstr "pauza" msgid "help / about" msgstr "nápověda / o programu" msgid "expand" msgstr "roztáhnout" msgid "shrink" msgstr "smrštit" msgid "hide/show lines" msgstr "skrýt/zobrazit čáry" msgid "mark intersections" msgstr "označit průniky" msgid "click when finished!" msgstr "po dokončení klikněte!" #, c-format msgid "" "ERROR: Could not save board state for \"%s\":\n" "\t%s\n" msgstr "" "CHYBA: Nelze uložit stav desky pro „%s“:\n" "\t%s\n" #, c-format msgid "" "ERROR: Could not read saved board state for \"%s\":\n" "\t%s\n" msgstr "" "CHYBA: Nelze načíst uložený stav desky pro „%s“:\n" "\t%s\n" #, c-format msgid "WARNING: edge references out of range vertex in save file\n" msgstr "VAROVÁNÍ: hrana odkazuje na vrchol mimo rozsah uložený v souboru\n" #, c-format msgid "Couldn't allocate memory for level name.\n" msgstr "Nelze vyhradit paměť pro jméno kola.\n" #, c-format msgid "Couldn't allocate memory for level description.\n" msgstr "Nelze vyhradit paměť pro popis kola.\n" #, c-format msgid "" "region overlap adjustment failed in arc_arc_adj; \n" " This is an internal error that should never happen.\n" msgstr "" "přizpůsobení překrývajících se oblastí selhalo v arc_arc_arj;\n" " Toto je vnitřní chyba a nemělo by k ní nikdy dojít.\n" msgid "zero intersections" msgstr "žádné průniky" msgid "1 intersection or fewer" msgstr "1 průnik nebo méně" msgid "1 intersection" msgstr "1 průnik" #, c-format msgid "%d intersections%s" msgstr "%d průniků%s" msgid " or fewer" msgstr " nebo méně" #, c-format msgid "" "ERROR: Could not save game state file \"%s\":\n" "\t%s\n" msgstr "" "CHYBA: Nelze uložit soubor se stavem hry „%s“:\n" "\t%s\n" #, c-format msgid "" "ERROR: Could not read game state file \"%s\":\n" "\t%s\n" msgstr "" "CHYBA: Nelze načíst soubor se stavem hry „%s“:\n" "\t%s\n" #, c-format msgid "" "ERROR: Could not create directory (%s) to save game state:\n" "\t%s\n" msgstr "" "CHYBA: Nelze vytvořit adresář (%s) pro ukládání stavu hry:\n" "\t%s\n" #, c-format msgid "" "\n" "Trapped signal %d; saving state and exiting!\n" msgstr "" "\n" "Zachycen signál %d; uložím stav a skončím!\n" #, c-format msgid "" "\n" "Unable to find any suitable %s fonts!\n" "Continuing, but the the results are likely to be poor.\n" "\n" msgstr "" "\n" "Nelze najít žádný vhodný font s %s!\n" "Pokračuji, ale výsledek asi bude ošklivý.\n" "\n" msgid "bold italic" msgstr "tučnou kurzívou" msgid "italic" msgstr "kurzívou" msgid "bold" msgstr "tučným řezem" msgid "medium" msgstr "středním řezem" #, c-format msgid "" "\n" "Selected %s font \"%s\" is not scalable! This is almost as bad\n" "as not finding any font at all. Continuing, but this may look\n" "very poor indeed.\n" "\n" msgstr "" "\n" "Vybraný font s %s „%s“ není škálovatelný!\n" "Toto situace je téměř tak špatná jako když se nenajde font žádný.\n" "Pokračuji, ale výsledek bude asi ošklivý\n" "\n" #, c-format msgid "" "No homedir environment variable set! gPlanarity will be\n" "unable to permanently save any progress or board state.\n" msgstr "" "Žádná proměnná prostředí neudává domovský adresář! gPlanatiry nebude " "schopné\n" "trvale uložit postup hráče nebo stav hrací desky.\n" #, c-format msgid "%d:%02d:%02d" msgstr "%d:%02d:%02d" #, c-format msgid "%d:%02d" msgstr "%d:%02d" #, c-format msgid "%d seconds" msgstr "%d sekund" gplanarity-master/po/de.po000066400000000000000000000301611510662254600160770ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) 2007 Monty # This file is distributed under the same license as the gPlanarity package. # FIRST AUTHOR , YEAR. # Nuke System , 2011. # msgid "" msgstr "" "Project-Id-Version: 16723\n" "Report-Msgid-Bugs-To: Monty \n" "POT-Creation-Date: 2012-03-25 11:48-0400\n" "PO-Revision-Date: 2011-03-13 15:08+0100\n" "Last-Translator: Nuke System \n" "Language-Team: deutsch <>\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" # # File: ../dialog_finish.c, line: 80 # File: ../dialog_level.c, line: 67 # File: ../dialog_pause.c, line: 67 # File: ../gameboard_logic_buttonbar.c, line: 54 msgid "exit gPlanarity" msgstr "gPlanarity verlassen" # # File: ../dialog_finish.c, line: 81 # File: ../gameboard_logic_buttonbar.c, line: 55 msgid "level selection menu" msgstr "Auswahl des Spielabschnitts" # # File: ../dialog_finish.c, line: 82 msgid "play next level!" msgstr "nächsten Abschnitt spielen!" # # File: ../dialog_finish.c, line: 160 msgid "Level Complete!" msgstr "Abschnitt gelöst!" # # File: ../dialog_finish.c, line: 164 #, c-format msgid "Elapsed: %s" msgstr "Verstrichen: %s" # # File: ../dialog_finish.c, line: 168 #, c-format msgid "Base score: %d points" msgstr "Grundbonus: %d Punkte" # # File: ../dialog_finish.c, line: 176 #, c-format msgid "Objective Exceeded! %d%%" msgstr "Ziel übertroffen! %d%%" # # File: ../dialog_finish.c, line: 181 #, c-format msgid "Time bonus: %d points" msgstr "Zeitbonus: %d Punkte" # # File: ../dialog_finish.c, line: 186 #, c-format msgid "Final score: %d points" msgstr "Endstand: %d Punkte" # # File: ../dialog_finish.c, line: 191 msgid "A high score!" msgstr "Ein Höchststand!" # # File: ../dialog_finish.c, line: 194 #, c-format msgid "Previous best: %ld points" msgstr "Voriger bester: %ld Punkte" # # File: ../dialog_finish.c, line: 199 msgid "Total score to date:" msgstr "Bisheriger Gesamtpunktestand:" # # File: ../dialog_finish.c, line: 201 #, c-format msgid "%ld points" msgstr "%ld Punkte" # # File: ../dialog_level.c, line: 68 msgid "reset level" msgstr "Abschnitt zurücksetzen" # # File: ../dialog_level.c, line: 69 msgid "play level!" msgstr "Abschnitt spielen!" # # File: ../dialog_level.c, line: 139 msgid "Available Levels" msgstr "Verfügbare Abschnitte" # # File: ../dialog_level_icons.c, line: 246 #, c-format msgid "Level %d:" msgstr "Abschnitt %d:" # # File: ../dialog_level_icons.c, line: 264 #, c-format msgid "[not yet completed]" msgstr "[noch ungelöst]" # # File: ../dialog_level_icons.c, line: 267 #, c-format msgid "level high score: %ld" msgstr "Abschnittshöchststand: %ld" # # File: ../dialog_level_icons.c, line: 277 #, c-format msgid "total score all levels: %ld" msgstr "Gesamtpunktestand für alle Abschnitte: %ld" # # File: ../dialog_pause.c, line: 68 msgid "resume game!" msgstr "Spiel fortsetzen!" # # File: ../dialog_pause.c, line: 131 msgid "Game Paused" msgstr "Spiel pausiert" # # File: ../dialog_pause.c, line: 134 msgid "Time Elapsed:" msgstr "Verstrichene Zeit:" # # File: ../dialog_pause.c, line: 186 msgid "gPlanarity" msgstr "gPlanarity" # # File: ../dialog_pause.c, line: 190 msgid "Untangle the mess!" msgstr "Entwirre das Durcheinander!" # # File: ../dialog_pause.c, line: 194 msgid "Drag vertices to eliminate crossed lines." msgstr "Verschiebe Knoten um Linienüberscheidungen zu beseitigen." # # File: ../dialog_pause.c, line: 195 msgid "The objective may be a complete solution or" msgstr "Das Ziel kann eine vollständige Lösung oder bei" # # File: ../dialog_pause.c, line: 196 msgid "getting as close as possible to solving an" msgstr "unlösbaren Puzzles eine möglichst vollständige" # # File: ../dialog_pause.c, line: 197 msgid "unsolvable puzzle. Work quickly and" msgstr "Lösung sein. Sei schnell und übertreffe die Zeit-" # # File: ../dialog_pause.c, line: 198 msgid "exceed the objective for bonus points!" msgstr "vorgabe um Bonuspunkte zu erhalten!" # # File: ../dialog_pause.c, line: 207 msgid "gPlanarity written by Monty " msgstr "gPlanarity wurde geschrieben von Monty " # # File: ../dialog_pause.c, line: 208 msgid "as a demonstration of Gtk+/Cairo" msgstr "als eine Demonstration von GTK+/Cairo." # # File: ../dialog_pause.c, line: 210 msgid "Original Flash version of Planarity by" msgstr "Die ursprüngliche Flash-Version von Planarity stammt" # # File: ../dialog_pause.c, line: 211 msgid "John Tantalo " msgstr "von John Tantalo " # # File: ../dialog_pause.c, line: 213 msgid "Original game concept by Mary Radcliffe" msgstr "Ursprüngliches Spielkonzept von Mary Radcliffe" # # File: ../gameboard.c, line: 75 #, c-format msgid "" "\n" "\n" "ERROR: The windowmanager appears to be ignoring resize requests.\n" "This stands a pretty good chance of scrambling any saved board larger\n" "than the default window size.\n" "\n" msgstr "" "\n" "\n" "FEHLER: Die Fensterverwaltung scheint Anfragen zur Änderung der\n" "Fenstergröße zu ignorieren. Dies bringt möglicherweise gespeicherte\n" "Aufstellungen durcheinander, die größer als die Vorgabefenstergröße sind.\n" "\n" # # File: ../gameboard.c, line: 78 # File: ../gameboard.c, line: 189 #, c-format msgid "" "Clipping and/or expanding this board to the current window size...\n" "\n" msgstr "" "Beschneide und/oder erweitere Spielbrett auf derzeitige Fenstergröße...\n" "\n" # # File: ../gameboard.c, line: 184 #, fuzzy, c-format msgid "" "\n" "\n" "ERROR: The window size granted by the windowmanager is not the\n" "window size gPlanarity requested. If the windowmanager is\n" "configured to ignore application sizing requests, this stands\n" "a pretty good chance of scrambling saved boards later (and\n" "making everything look funny now).\n" "\n" msgstr "" "\n" "\n" "FEHLER: Die von der Fensterverwaltung gewährte Fenstergröße\n" "entspricht nicht der angeforderten. Sollte die Fensterverwaltung\n" "eingestellt sein, die Größenangaben der Anwendung zu übergehen,\n" "so sind spätere Störungen in gespeicherten Aufstellungen\n" "wahrscheinlich (und jetzt ein seltsames Aussehen).\n" "\n" # # File: ../gameboard_draw_intersection.c, line: 65 msgid "rather many, really" msgstr "ziemlich viele" # # File: ../gameboard_draw_main.c, line: 370 #, c-format msgid "ERROR: Could not load board icon \"%s\"\n" msgstr "FEHLER: Konnte Aufstellungsvorschau \"%s\" nicht laden\n" # # File: ../gameboard_draw_main.c, line: 436 #, c-format msgid "ERROR: Could not save board icon \"%s\"\n" msgstr "FEHLER: Konnte Aufstellungsvorschau \"%s\" nicht speichern\n" # # File: ../gameboard_draw_score.c, line: 67 #, c-format msgid "Level %d: %s" msgstr "Abschnitt %d: %s" # # File: ../gameboard_draw_score.c, line: 68 #, c-format msgid "Score: %d" msgstr "Punktestand: %d" # # File: ../gameboard_draw_score.c, line: 69 #, c-format msgid "%d%%" msgstr "%d%%" # # File: ../gameboard_draw_score.c, line: 70 #, c-format msgid "Intersections: %ld" msgstr "Überschneidungen: %ld" # # File: ../gameboard_draw_score.c, line: 71 #, c-format msgid "Objective: %s" msgstr "Ziel: %s" # # File: ../gameboard_logic_buttonbar.c, line: 56 msgid "reset board" msgstr "Aufstellung zurücksetzen" # # File: ../gameboard_logic_buttonbar.c, line: 57 msgid "pause" msgstr "Pause" # # File: ../gameboard_logic_buttonbar.c, line: 58 msgid "help / about" msgstr "Hilfe / Über" # # File: ../gameboard_logic_buttonbar.c, line: 59 msgid "expand" msgstr "ausdehnen" # # File: ../gameboard_logic_buttonbar.c, line: 60 msgid "shrink" msgstr "schrumpfen" # # File: ../gameboard_logic_buttonbar.c, line: 61 msgid "hide/show lines" msgstr "verberge/zeige Linien" # # File: ../gameboard_logic_buttonbar.c, line: 62 msgid "mark intersections" msgstr "markiere Überschneidungen" # # File: ../gameboard_logic_buttonbar.c, line: 63 msgid "click when finished!" msgstr "klicke wenn fertig!" # # File: ../gameboard_logic.c, line: 371 #, c-format msgid "" "ERROR: Could not save board state for \"%s\":\n" "\t%s\n" msgstr "" "FEHLER: Konnte Spielbrettstatus nicht speichern für \"%s\":\n" "\t%s\n" # # File: ../gameboard_logic.c, line: 401 #, c-format msgid "" "ERROR: Could not read saved board state for \"%s\":\n" "\t%s\n" msgstr "" "FEHLER: Konnte gespeicherten Spielbrettstatus nicht lesen für \"%s\":\n" "\t%s\n" # # File: ../graph.c, line: 923 #, fuzzy, c-format msgid "WARNING: edge references out of range vertex in save file\n" msgstr "" "WARNUNG: Kante referenziert Knoten jenseits darstellbaren\n" "Bereichs in Speicherdatei\n" # # File: ../graph_generate.c, line: 196 # File: ../graph_generate.c, line: 215 #, c-format msgid "Couldn't allocate memory for level name.\n" msgstr "Konnte Speicher für Abschnittsname nicht belegen.\n" # # File: ../graph_generate.c, line: 210 #, c-format msgid "Couldn't allocate memory for level description.\n" msgstr "Konnte Speicher für Abschnittsbeschreibung nicht belegen.\n" # # File: ../graph_region.c, line: 459 #, fuzzy, c-format msgid "" "region overlap adjustment failed in arc_arc_adj; \n" " This is an internal error that should never happen.\n" msgstr "" "Anpassung der Überlappung von Regionen schlug fehl in arc_arc_adj;\n" "Dies ist ein interner Fehler, der nie vorkommen sollte.\n" # # File: ../graph_score.c, line: 67 msgid "zero intersections" msgstr "keine Überschneidungen" # # File: ../graph_score.c, line: 70 msgid "1 intersection or fewer" msgstr "1 Überschneidung oder weniger" # # File: ../graph_score.c, line: 72 msgid "1 intersection" msgstr "1 Überschneidung" # # File: ../graph_score.c, line: 75 #, c-format msgid "%d intersections%s" msgstr "%d Überschneidungen%s" # # File: ../graph_score.c, line: 77 msgid " or fewer" msgstr " oder weniger" # # File: ../levelstate.c, line: 169 #, c-format msgid "" "ERROR: Could not save game state file \"%s\":\n" "\t%s\n" msgstr "" "FEHLER: Konnte Spielstanddatei \"%s\" nicht speichern:\n" "\t%s\n" # # File: ../levelstate.c, line: 216 #, c-format msgid "" "ERROR: Could not read game state file \"%s\":\n" "\t%s\n" msgstr "" "FEHLER: Konnte Spielstanddatei \"%s\" nicht lesen:\n" "\t%s\n" # # File: ../main.c, line: 73 #, c-format msgid "" "ERROR: Could not create directory (%s) to save game state:\n" "\t%s\n" msgstr "" "FEHLER: Konnte Verzeichnis (%s) zum Speichern des Spielstandes nicht " "anlegen:\n" "\t%s\n" # # File: ../main.c, line: 93 #, c-format msgid "" "\n" "Trapped signal %d; saving state and exiting!\n" msgstr "" "\n" "Signal %d empfangen; speichere Status und beende!\n" # # File: ../main.c, line: 146 #, c-format msgid "" "\n" "Unable to find any suitable %s fonts!\n" "Continuing, but the the results are likely to be poor.\n" "\n" msgstr "" "\n" "Kann keine passenden %s-Schriftarten finden!\n" "Setze fort, doch armselige Ergebnisse sind zu erwarten.\n" "\n" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "bold italic" msgstr "fett kursiv" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "italic" msgstr "kursiv" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "bold" msgstr "fett" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 #, fuzzy msgid "medium" msgstr "mittel" # # File: ../main.c, line: 164 #, fuzzy, c-format msgid "" "\n" "Selected %s font \"%s\" is not scalable! This is almost as bad\n" "as not finding any font at all. Continuing, but this may look\n" "very poor indeed.\n" "\n" msgstr "" "\n" "Gewählte %s-Schriftart \"%s\" ist nicht skalierbar! Das ist\n" "fast so schlecht wie überhaupt keine. Fahre fort, obwohl\n" "es tatsächlich sehr armselig aussehen könnte.\n" "\n" # # File: ../main.c, line: 288 #, c-format msgid "" "No homedir environment variable set! gPlanarity will be\n" "unable to permanently save any progress or board state.\n" msgstr "" "Es wurde kein Basisverzeichnis angegeben! gPlanarity wird\n" "Fortschritte und Aufstellungen nicht dauerhaft speichern können.\n" # # File: ../timer.c, line: 51 #, c-format msgid "%d:%02d:%02d" msgstr "%d:%02d:%02d" # # File: ../timer.c, line: 53 #, c-format msgid "%d:%02d" msgstr "%d:%02d" # # File: ../timer.c, line: 55 #, c-format msgid "%d seconds" msgstr "%d Sekunden" gplanarity-master/po/es_ES.po000066400000000000000000000300261510662254600165050ustar00rootroot00000000000000# # Copyright (C) 2007 Monty # This file is distributed under the same license as the gPlanarity package. # # Federico Vera 2009. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: Monty \n" "POT-Creation-Date: 2012-03-25 11:48-0400\n" "PO-Revision-Date: 2009-09-12 19:45-0300\n" "Last-Translator: Federico Vera \n" "Language-Team: Spanish \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 1.0\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" # # File: ../dialog_finish.c, line: 80 # File: ../dialog_level.c, line: 67 # File: ../dialog_pause.c, line: 67 # File: ../gameboard_logic_buttonbar.c, line: 54 msgid "exit gPlanarity" msgstr "cerrar gPlanarity" # # File: ../dialog_finish.c, line: 81 # File: ../gameboard_logic_buttonbar.c, line: 55 msgid "level selection menu" msgstr "menú de selección de nivel" # # File: ../dialog_finish.c, line: 82 msgid "play next level!" msgstr "jugar al siguiente nivel!" # # File: ../dialog_finish.c, line: 160 msgid "Level Complete!" msgstr "Nivel Completo!" # # File: ../dialog_finish.c, line: 164 #, c-format msgid "Elapsed: %s" msgstr "Tiempo transcurrido: %s" # # File: ../dialog_finish.c, line: 168 #, c-format msgid "Base score: %d points" msgstr "Puntaje: %d puntos" # # File: ../dialog_finish.c, line: 176 #, c-format msgid "Objective Exceeded! %d%%" msgstr "Superó el objetivo! %d%%" # # File: ../dialog_finish.c, line: 181 #, c-format msgid "Time bonus: %d points" msgstr "Bonus: %d puntos" # # File: ../dialog_finish.c, line: 186 #, c-format msgid "Final score: %d points" msgstr "Puntaje final: %d puntos" # # File: ../dialog_finish.c, line: 191 msgid "A high score!" msgstr "Un record!" # # File: ../dialog_finish.c, line: 194 #, c-format msgid "Previous best: %ld points" msgstr "Record anterior: %ld puntos" # # File: ../dialog_finish.c, line: 199 msgid "Total score to date:" msgstr "Puntaje total al día de hoy:" # # File: ../dialog_finish.c, line: 201 #, c-format msgid "%ld points" msgstr "%ld puntos" # # File: ../dialog_level.c, line: 68 msgid "reset level" msgstr "reiniciar nivel" # # File: ../dialog_level.c, line: 69 msgid "play level!" msgstr "jugar nivel!" # # File: ../dialog_level.c, line: 139 msgid "Available Levels" msgstr "Niveles disponibles" # # File: ../dialog_level_icons.c, line: 246 #, c-format msgid "Level %d:" msgstr "Nivel %d:" # # File: ../dialog_level_icons.c, line: 264 #, c-format msgid "[not yet completed]" msgstr "[sin completar]" # # File: ../dialog_level_icons.c, line: 267 #, c-format msgid "level high score: %ld" msgstr "record para este nivel: %ld" # # File: ../dialog_level_icons.c, line: 277 #, c-format msgid "total score all levels: %ld" msgstr "puntaje total para todos los niveles: %ld" # # File: ../dialog_pause.c, line: 68 msgid "resume game!" msgstr "continuar juego!" # # File: ../dialog_pause.c, line: 131 msgid "Game Paused" msgstr "Juego Pausado" # # File: ../dialog_pause.c, line: 134 msgid "Time Elapsed:" msgstr "Tiempo Transcurrido:" # # File: ../dialog_pause.c, line: 186 msgid "gPlanarity" msgstr "gPlanarity" # # File: ../dialog_pause.c, line: 190 msgid "Untangle the mess!" msgstr "Desenrrede este lío!" # # File: ../dialog_pause.c, line: 194 msgid "Drag vertices to eliminate crossed lines." msgstr "Arrastre los vértices para eliminar los cruces de" # # File: ../dialog_pause.c, line: 195 msgid "The objective may be a complete solution or" msgstr "líneas. El objetivo puede ser una solución" # # File: ../dialog_pause.c, line: 196 msgid "getting as close as possible to solving an" msgstr "completa o acercarse lo más posible a resolver" # # File: ../dialog_pause.c, line: 197 msgid "unsolvable puzzle. Work quickly and" msgstr "un rompezabezas irresolvible. Trabaje rápido y" # # File: ../dialog_pause.c, line: 198 msgid "exceed the objective for bonus points!" msgstr "supere los objetivos para obtener un bonus!" # # File: ../dialog_pause.c, line: 207 msgid "gPlanarity written by Monty " msgstr "gPlanarity escrito por Monty " # # File: ../dialog_pause.c, line: 208 msgid "as a demonstration of Gtk+/Cairo" msgstr "como una demostración de Gtk+/Cairo" # # File: ../dialog_pause.c, line: 210 msgid "Original Flash version of Planarity by" msgstr "Versión Original en Flash de Planarity por" # # File: ../dialog_pause.c, line: 211 msgid "John Tantalo " msgstr "John Tantalo " # # File: ../dialog_pause.c, line: 213 msgid "Original game concept by Mary Radcliffe" msgstr "Concepto original del juego por Mary Radcliffe" # # File: ../gameboard.c, line: 75 #, c-format msgid "" "\n" "\n" "ERROR: The windowmanager appears to be ignoring resize requests.\n" "This stands a pretty good chance of scrambling any saved board larger\n" "than the default window size.\n" "\n" msgstr "" "\n" "\n" "ERROR: El manejador de ventanas parece estar ignorando la petición de " "redimensionamiento.\n" "Hay grandes chances de que se arruine algún tablero guardado más grande que\n" "el tamaño predeterminado de ventana.\n" "\n" # # File: ../gameboard.c, line: 78 # File: ../gameboard.c, line: 189 #, c-format msgid "" "Clipping and/or expanding this board to the current window size...\n" "\n" msgstr "" "Recortando y/o expandiendo este tablero al tamaño actual de ventana...\n" "\n" # # File: ../gameboard.c, line: 184 #, c-format msgid "" "\n" "\n" "ERROR: The window size granted by the windowmanager is not the\n" "window size gPlanarity requested. If the windowmanager is\n" "configured to ignore application sizing requests, this stands\n" "a pretty good chance of scrambling saved boards later (and\n" "making everything look funny now).\n" "\n" msgstr "" "\n" "\n" "ERROR: El tamaño de ventana concedido por el manejador de ventanas no es\n" "el tamaño pedido por gPlanarity. Si el manejador de ventanas está " "configurado\n" "para ignorar los tamaños pedidos por las aplicaciones, hay grandes\n" "chances de que se arruinen los tableros guardados (y de\n" "que ahora todo se vea raro).\n" "\n" # # File: ../gameboard_draw_intersection.c, line: 65 msgid "rather many, really" msgstr "realmente, más bien muchas" # # File: ../gameboard_draw_main.c, line: 370 #, c-format msgid "ERROR: Could not load board icon \"%s\"\n" msgstr "ERROR: No se pudo cargar el icono de tablero \"%s\"\n" # # File: ../gameboard_draw_main.c, line: 436 #, c-format msgid "ERROR: Could not save board icon \"%s\"\n" msgstr "ERROR: no se pudo guardar el icono de tablero \"%s\"\n" # # File: ../gameboard_draw_score.c, line: 67 #, c-format msgid "Level %d: %s" msgstr "Nivel %d: %s" # # File: ../gameboard_draw_score.c, line: 68 #, c-format msgid "Score: %d" msgstr "Puntaje: %d" # # File: ../gameboard_draw_score.c, line: 69 #, c-format msgid "%d%%" msgstr "%d%%" # # File: ../gameboard_draw_score.c, line: 70 #, c-format msgid "Intersections: %ld" msgstr "Intersecciones: %ld" # # File: ../gameboard_draw_score.c, line: 71 #, c-format msgid "Objective: %s" msgstr "Objetivo: %s" # # File: ../gameboard_logic_buttonbar.c, line: 56 msgid "reset board" msgstr "reiniciar tablero" # # File: ../gameboard_logic_buttonbar.c, line: 57 msgid "pause" msgstr "pausa" # # File: ../gameboard_logic_buttonbar.c, line: 58 msgid "help / about" msgstr "ayuda/acerca de" # # File: ../gameboard_logic_buttonbar.c, line: 59 msgid "expand" msgstr "expandir" # # File: ../gameboard_logic_buttonbar.c, line: 60 msgid "shrink" msgstr "achicar" # # File: ../gameboard_logic_buttonbar.c, line: 61 msgid "hide/show lines" msgstr "ocultar/mostrar lineas" # # File: ../gameboard_logic_buttonbar.c, line: 62 msgid "mark intersections" msgstr "marcar intersecciones" # # File: ../gameboard_logic_buttonbar.c, line: 63 msgid "click when finished!" msgstr "haga click cuando termine!" # # File: ../gameboard_logic.c, line: 371 #, c-format msgid "" "ERROR: Could not save board state for \"%s\":\n" "\t%s\n" msgstr "" "ERROR: No se pudo guardar el estado del tablero para \"%s\":\n" "\t%s\n" # # File: ../gameboard_logic.c, line: 401 #, c-format msgid "" "ERROR: Could not read saved board state for \"%s\":\n" "\t%s\n" msgstr "" "ERROR: No se pudo leer el estado de tablero guardado para \"%s\":\n" "\t%s\n" # # File: ../graph.c, line: 923 #, c-format msgid "WARNING: edge references out of range vertex in save file\n" msgstr "" "ADVERTENCIA: las referencias de las esquinas están fuera de rango en el " "archivo guardado\n" # # File: ../graph_generate.c, line: 196 # File: ../graph_generate.c, line: 215 #, c-format msgid "Couldn't allocate memory for level name.\n" msgstr "No se pudo reservar memoria para el nombre del nivel.\n" # # File: ../graph_generate.c, line: 210 #, c-format msgid "Couldn't allocate memory for level description.\n" msgstr "No se pudo reservar memoria para la descripción del nivel.\n" # # File: ../graph_region.c, line: 459 #, c-format msgid "" "region overlap adjustment failed in arc_arc_adj; \n" " This is an internal error that should never happen.\n" msgstr "" "falló el ajuste de la región de superposición en arc_arc_adj; \n" " Este es un error interno que nunca debería ocurrir.\n" # # File: ../graph_score.c, line: 67 msgid "zero intersections" msgstr "cero intersecciones" # # File: ../graph_score.c, line: 70 msgid "1 intersection or fewer" msgstr "1 intersección o menos" # # File: ../graph_score.c, line: 72 msgid "1 intersection" msgstr "1 intersección" # # File: ../graph_score.c, line: 75 #, c-format msgid "%d intersections%s" msgstr "%d intersecciones%s" # # File: ../graph_score.c, line: 77 msgid " or fewer" msgstr " o menos" # # File: ../levelstate.c, line: 169 #, c-format msgid "" "ERROR: Could not save game state file \"%s\":\n" "\t%s\n" msgstr "" "ERROR: No se pudo guardar el archivo de estado del juego \"%s\":\n" "\t%s\n" # # File: ../levelstate.c, line: 216 #, c-format msgid "" "ERROR: Could not read game state file \"%s\":\n" "\t%s\n" msgstr "" "ERROR: No se pudo leer el archivo de estado del juego \"%s\":\n" "\t%s\n" # # File: ../main.c, line: 73 #, c-format msgid "" "ERROR: Could not create directory (%s) to save game state:\n" "\t%s\n" msgstr "" "ERROR: No se pudo crear el directorio (%s) para guardar el estado del " "juego:\n" "\t%s\n" # # File: ../main.c, line: 93 #, c-format msgid "" "\n" "Trapped signal %d; saving state and exiting!\n" msgstr "" "\n" "Señal atrapada %d; guardando estado y saliendo!\n" # # File: ../main.c, line: 146 #, c-format msgid "" "\n" "Unable to find any suitable %s fonts!\n" "Continuing, but the the results are likely to be poor.\n" "\n" msgstr "" "\n" "Imposible encontrar tipografias %s adecuadas!\n" "Se continuará, pero los resultados pueden ser pobres.\n" "\n" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "bold italic" msgstr "negrita cursiva" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "italic" msgstr "cursiva" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "bold" msgstr "negrita" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "medium" msgstr "media" # # File: ../main.c, line: 164 #, c-format msgid "" "\n" "Selected %s font \"%s\" is not scalable! This is almost as bad\n" "as not finding any font at all. Continuing, but this may look\n" "very poor indeed.\n" "\n" msgstr "" "\n" "La tipografía %s seleccionada \"%s\" no es escalable! Esto es casi tan malo\n" "como no encontrar ninguna tipografía. Se continuará, pero se verá\n" "realmente pobre.\n" "\n" # # File: ../main.c, line: 288 #, c-format msgid "" "No homedir environment variable set! gPlanarity will be\n" "unable to permanently save any progress or board state.\n" msgstr "" "No hay asignada una variable de entorno homedir! gPlanarity será\n" "incapaz de guardar permanentemente su prograso o el estado del tablero.\n" # # File: ../timer.c, line: 51 #, c-format msgid "%d:%02d:%02d" msgstr "%d:%02d:%02d" # # File: ../timer.c, line: 53 #, c-format msgid "%d:%02d" msgstr "%d:%02d" # # File: ../timer.c, line: 55 #, c-format msgid "%d seconds" msgstr "%d segundos" gplanarity-master/po/fr_FR.po000066400000000000000000000305031510662254600165050ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) 2007 Monty # This file is distributed under the same license as the gPlanarity package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: gplanarity 01.10\n" "Report-Msgid-Bugs-To: Monty \n" "POT-Creation-Date: 2012-03-25 11:48-0400\n" "PO-Revision-Date: 2009-11-23 20:59+0100\n" "Last-Translator: Lerique Julien \n" "Language-Team: french \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: French\n" "X-Poedit-Country: FRANCE\n" "X-Poedit-SourceCharset: utf-8\n" # # File: ../dialog_finish.c, line: 80 # File: ../dialog_level.c, line: 67 # File: ../dialog_pause.c, line: 67 # File: ../gameboard_logic_buttonbar.c, line: 54 msgid "exit gPlanarity" msgstr "quitter gPlanarity" # # File: ../dialog_finish.c, line: 81 # File: ../gameboard_logic_buttonbar.c, line: 55 msgid "level selection menu" msgstr "menu de sélection des niveaux" # # File: ../dialog_finish.c, line: 82 msgid "play next level!" msgstr "jouer le niveau suivant!" # # File: ../dialog_finish.c, line: 160 msgid "Level Complete!" msgstr "Niveau Terminé!" # # File: ../dialog_finish.c, line: 164 #, c-format msgid "Elapsed: %s" msgstr "Temps écoulé : %s" # # File: ../dialog_finish.c, line: 168 #, c-format msgid "Base score: %d points" msgstr "Score de base: %d points" # # File: ../dialog_finish.c, line: 176 #, c-format msgid "Objective Exceeded! %d%%" msgstr "Objectif Dépassé! %d%%" # # File: ../dialog_finish.c, line: 181 #, c-format msgid "Time bonus: %d points" msgstr "Bonus temps: %d points" # # File: ../dialog_finish.c, line: 186 #, c-format msgid "Final score: %d points" msgstr "Score final: %d points" # # File: ../dialog_finish.c, line: 191 msgid "A high score!" msgstr "Un meilleur score!" # # File: ../dialog_finish.c, line: 194 #, c-format msgid "Previous best: %ld points" msgstr "Meilleur score précédent: %ld points" # # File: ../dialog_finish.c, line: 199 msgid "Total score to date:" msgstr "Agrégation des scores:" # # File: ../dialog_finish.c, line: 201 #, c-format msgid "%ld points" msgstr "%ld points" # # File: ../dialog_level.c, line: 68 msgid "reset level" msgstr "réinitialiser le niveau" # # File: ../dialog_level.c, line: 69 msgid "play level!" msgstr "jouer à ce niveau!" # # File: ../dialog_level.c, line: 139 msgid "Available Levels" msgstr "Niveaux Disponibles" # # File: ../dialog_level_icons.c, line: 246 #, c-format msgid "Level %d:" msgstr "Niveau %d:" # # File: ../dialog_level_icons.c, line: 264 #, c-format msgid "[not yet completed]" msgstr "[Pas encore achevé]" # # File: ../dialog_level_icons.c, line: 267 #, c-format msgid "level high score: %ld" msgstr "meilleur score sur ce niveau: %ld" # # File: ../dialog_level_icons.c, line: 277 #, c-format msgid "total score all levels: %ld" msgstr "score total sur tous les niveaux: %ld" # # File: ../dialog_pause.c, line: 68 msgid "resume game!" msgstr "retour au jeu!" # # File: ../dialog_pause.c, line: 131 msgid "Game Paused" msgstr "Partie Suspendue" # # File: ../dialog_pause.c, line: 134 msgid "Time Elapsed:" msgstr "Temps écoulé:" # # File: ../dialog_pause.c, line: 186 msgid "gPlanarity" msgstr "gPlanarity" # # File: ../dialog_pause.c, line: 190 msgid "Untangle the mess!" msgstr "Démêlez ce désordre!" # # File: ../dialog_pause.c, line: 194 msgid "Drag vertices to eliminate crossed lines." msgstr "Faîtes glisser les points afin d'éradiquer les lignes qui" # # File: ../dialog_pause.c, line: 195 msgid "The objective may be a complete solution or" msgstr "se croisent. L'objectif peut être une solution complète" # # File: ../dialog_pause.c, line: 196 msgid "getting as close as possible to solving an" msgstr "ou, pour un puzzle insoluble, s'approcher d'aussi près" # # File: ../dialog_pause.c, line: 197 msgid "unsolvable puzzle. Work quickly and" msgstr "que possible d'une solution. Oeuvrez rapidement et" # # File: ../dialog_pause.c, line: 198 msgid "exceed the objective for bonus points!" msgstr "dépassez l'objectif afin d'obtenir des points bonus." # # File: ../dialog_pause.c, line: 207 msgid "gPlanarity written by Monty " msgstr "gPlanarity, écrit par Monty " # # File: ../dialog_pause.c, line: 208 msgid "as a demonstration of Gtk+/Cairo" msgstr "comme une démonstration de Gtk+/Cairo" # # File: ../dialog_pause.c, line: 210 msgid "Original Flash version of Planarity by" msgstr "Version originale en flash de Planarity par" # # File: ../dialog_pause.c, line: 211 msgid "John Tantalo " msgstr "John Tantalo " # # File: ../dialog_pause.c, line: 213 msgid "Original game concept by Mary Radcliffe" msgstr "Concept original du jeu par Mary Radcliffe" # # File: ../gameboard.c, line: 75 #, c-format msgid "" "\n" "\n" "ERROR: The windowmanager appears to be ignoring resize requests.\n" "This stands a pretty good chance of scrambling any saved board larger\n" "than the default window size.\n" "\n" msgstr "" "\n" "\n" "ERREUR: le gestionnaire de fenêtre semble ignorer les demandes d'ajustement\n" "de taille. Cela pourrait perturber la sauvegarde de n'importe quelle partie\n" "dont le plateau est plus grand que la taille de fenêtre par défaut.\n" "\n" # # File: ../gameboard.c, line: 78 # File: ../gameboard.c, line: 189 #, c-format msgid "" "Clipping and/or expanding this board to the current window size...\n" "\n" msgstr "" "Découper et/ou étendre l'espace de jeu sur la taille courante de la " "fenêtre...\n" "\n" # # File: ../gameboard.c, line: 184 #, c-format msgid "" "\n" "\n" "ERROR: The window size granted by the windowmanager is not the\n" "window size gPlanarity requested. If the windowmanager is\n" "configured to ignore application sizing requests, this stands\n" "a pretty good chance of scrambling saved boards later (and\n" "making everything look funny now).\n" "\n" msgstr "" "\n" "ERREUR: La taille de la fenêtre allouée par le gestionnaire de fenêtre\n" "n'est pas celle demandée par gPlanarity. Si le gestionnaire de fenêtre\n" "est configuré pour ignorer les demandes d'ajustement de taille, Cela\n" "pourrait perturber les prochaines sauvegarde des activités (et\n" "actuellement entraîner une drôle d'apparence).\n" " \n" # # File: ../gameboard_draw_intersection.c, line: 65 msgid "rather many, really" msgstr "en fait plutôt nombreux" # # File: ../gameboard_draw_main.c, line: 370 #, c-format msgid "ERROR: Could not load board icon \"%s\"\n" msgstr "ERREUR: Impossible de charger l'activité \"%s\"\n" # # File: ../gameboard_draw_main.c, line: 436 #, c-format msgid "ERROR: Could not save board icon \"%s\"\n" msgstr "ERREUR: Impossible de sauvegarder l'activité \"%s\"\n" # # File: ../gameboard_draw_score.c, line: 67 #, c-format msgid "Level %d: %s" msgstr "Niveau %d: %s" # # File: ../gameboard_draw_score.c, line: 68 #, c-format msgid "Score: %d" msgstr "Score: %d" # # File: ../gameboard_draw_score.c, line: 69 #, c-format msgid "%d%%" msgstr "%d%%" # # File: ../gameboard_draw_score.c, line: 70 #, c-format msgid "Intersections: %ld" msgstr "Intersections: %ld" # # File: ../gameboard_draw_score.c, line: 71 #, c-format msgid "Objective: %s" msgstr "Objectif: %s" # # File: ../gameboard_logic_buttonbar.c, line: 56 msgid "reset board" msgstr "réinitialiser le niveau" # # File: ../gameboard_logic_buttonbar.c, line: 57 msgid "pause" msgstr "pause" # # File: ../gameboard_logic_buttonbar.c, line: 58 msgid "help / about" msgstr "aide / à propos" # # File: ../gameboard_logic_buttonbar.c, line: 59 msgid "expand" msgstr "agrandir" # # File: ../gameboard_logic_buttonbar.c, line: 60 msgid "shrink" msgstr "réduire" # # File: ../gameboard_logic_buttonbar.c, line: 61 msgid "hide/show lines" msgstr "cacher/afficher les lignes" # # File: ../gameboard_logic_buttonbar.c, line: 62 msgid "mark intersections" msgstr "signaler les intersections" # # File: ../gameboard_logic_buttonbar.c, line: 63 msgid "click when finished!" msgstr "si vous avez terminé, cliquez!" # # File: ../gameboard_logic.c, line: 371 #, c-format msgid "" "ERROR: Could not save board state for \"%s\":\n" "\t%s\n" msgstr "" "ERREUR: Impossible de sauvegarder l'état de l'activité \"%s\":\n" "\t%s\n" # # File: ../gameboard_logic.c, line: 401 #, c-format msgid "" "ERROR: Could not read saved board state for \"%s\":\n" "\t%s\n" msgstr "" "ERREUR: Impossible de lire l'état de l'activité \"%s\":\n" "\t%s\n" # # File: ../graph.c, line: 923 #, c-format msgid "WARNING: edge references out of range vertex in save file\n" msgstr "" "AVERTISSEMENT: les références d'arêtes dépassent le sommet dans le fichier " "sauvegardé\n" # # File: ../graph_generate.c, line: 196 # File: ../graph_generate.c, line: 215 #, c-format msgid "Couldn't allocate memory for level name.\n" msgstr "Impossible d'allouer de la mémoire pour le nom du niveau.\n" # # File: ../graph_generate.c, line: 210 #, c-format msgid "Couldn't allocate memory for level description.\n" msgstr "Impossible d'allouer de la mémoire pour la description du niveau.\n" # # File: ../graph_region.c, line: 459 #, c-format msgid "" "region overlap adjustment failed in arc_arc_adj; \n" " This is an internal error that should never happen.\n" msgstr "" "L'adaptation de la zone de chevauchement a échoué dans arc_arc_adj; \n" " Ceci est une erreur interne qui ne devrait jamais se produire.\n" # # File: ../graph_score.c, line: 67 msgid "zero intersections" msgstr "zero intersection" # # File: ../graph_score.c, line: 70 msgid "1 intersection or fewer" msgstr "1 intersection ou moins" # # File: ../graph_score.c, line: 72 msgid "1 intersection" msgstr "1 intersection" # # File: ../graph_score.c, line: 75 #, c-format msgid "%d intersections%s" msgstr "%d intersections%s" # # File: ../graph_score.c, line: 77 msgid " or fewer" msgstr "ou moins" # # File: ../levelstate.c, line: 169 #, c-format msgid "" "ERROR: Could not save game state file \"%s\":\n" "\t%s\n" msgstr "" "ERREUR: Impossible de sauvegarder le fichier sur l'état d'avancement du jeu " "\"%s\":\n" "\t%s\n" # # File: ../levelstate.c, line: 216 #, c-format msgid "" "ERROR: Could not read game state file \"%s\":\n" "\t%s\n" msgstr "" "ERREUR : Impossible de lire le fichier sur l'état d'avancement du jeu \"%s" "\":\n" "\t%s\n" # # File: ../main.c, line: 73 #, c-format msgid "" "ERROR: Could not create directory (%s) to save game state:\n" "\t%s\n" msgstr "" "ERREUR: Impossible de créer le répertoire (%s) pour sauvegarder l'état " "d'avancement du jeu:\n" "\t%s\n" # # File: ../main.c, line: 93 #, c-format msgid "" "\n" "Trapped signal %d; saving state and exiting!\n" msgstr "" "\n" "Le signal %d est piégé; sauvegarde et quitte!\n" # # File: ../main.c, line: 146 #, c-format msgid "" "\n" "Unable to find any suitable %s fonts!\n" "Continuing, but the the results are likely to be poor.\n" "\n" msgstr "" "\n" "Incapable de trouver une police %s acceptable!\n" "Continuons, mais le résultat obtenu sera probablement pauvre.\n" "\n" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "bold italic" msgstr "police grasse" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "italic" msgstr "italique" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "bold" msgstr "gras" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "medium" msgstr "moyen" # # File: ../main.c, line: 164 #, c-format msgid "" "\n" "Selected %s font \"%s\" is not scalable! This is almost as bad\n" "as not finding any font at all. Continuing, but this may look\n" "very poor indeed.\n" "\n" msgstr "" "\n" "L'échelle de la police %s sélectionnée \"%s\" est fixe! Ceci est presque\n" "aussi grave que de ne pas du tout trouver de police. Continuons, mais\n" "l'apparence pourrait être vraiment misérable.\n" "\n" # # File: ../main.c, line: 288 #, c-format msgid "" "No homedir environment variable set! gPlanarity will be\n" "unable to permanently save any progress or board state.\n" msgstr "" "La variable d'environnement homedir n'est pas définie! gPlanarity\n" "ne parviendra pas à sauvegarder les progrès ou l'état d'avancement de " "l'activité.\n" # # File: ../timer.c, line: 51 #, c-format msgid "%d:%02d:%02d" msgstr "%d:%02d:%02d" # # File: ../timer.c, line: 53 #, c-format msgid "%d:%02d" msgstr "%d:%02d" # # File: ../timer.c, line: 55 #, c-format msgid "%d seconds" msgstr "%d secondes" gplanarity-master/po/gPlanarity.pot000066400000000000000000000212261510662254600200070ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) 2007 Monty # This file is distributed under the same license as the gPlanarity package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: Monty \n" "POT-Creation-Date: 2012-03-25 11:48-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" # # File: ../dialog_finish.c, line: 80 # File: ../dialog_level.c, line: 67 # File: ../dialog_pause.c, line: 67 # File: ../gameboard_logic_buttonbar.c, line: 54 msgid "exit gPlanarity" msgstr "" # # File: ../dialog_finish.c, line: 81 # File: ../gameboard_logic_buttonbar.c, line: 55 msgid "level selection menu" msgstr "" # # File: ../dialog_finish.c, line: 82 msgid "play next level!" msgstr "" # # File: ../dialog_finish.c, line: 160 msgid "Level Complete!" msgstr "" # # File: ../dialog_finish.c, line: 164 #, c-format msgid "Elapsed: %s" msgstr "" # # File: ../dialog_finish.c, line: 168 #, c-format msgid "Base score: %d points" msgstr "" # # File: ../dialog_finish.c, line: 176 #, c-format msgid "Objective Exceeded! %d%%" msgstr "" # # File: ../dialog_finish.c, line: 181 #, c-format msgid "Time bonus: %d points" msgstr "" # # File: ../dialog_finish.c, line: 186 #, c-format msgid "Final score: %d points" msgstr "" # # File: ../dialog_finish.c, line: 191 msgid "A high score!" msgstr "" # # File: ../dialog_finish.c, line: 194 #, c-format msgid "Previous best: %ld points" msgstr "" # # File: ../dialog_finish.c, line: 199 msgid "Total score to date:" msgstr "" # # File: ../dialog_finish.c, line: 201 #, c-format msgid "%ld points" msgstr "" # # File: ../dialog_level.c, line: 68 msgid "reset level" msgstr "" # # File: ../dialog_level.c, line: 69 msgid "play level!" msgstr "" # # File: ../dialog_level.c, line: 139 msgid "Available Levels" msgstr "" # # File: ../dialog_level_icons.c, line: 246 #, c-format msgid "Level %d:" msgstr "" # # File: ../dialog_level_icons.c, line: 264 #, c-format msgid "[not yet completed]" msgstr "" # # File: ../dialog_level_icons.c, line: 267 #, c-format msgid "level high score: %ld" msgstr "" # # File: ../dialog_level_icons.c, line: 277 #, c-format msgid "total score all levels: %ld" msgstr "" # # File: ../dialog_pause.c, line: 68 msgid "resume game!" msgstr "" # # File: ../dialog_pause.c, line: 131 msgid "Game Paused" msgstr "" # # File: ../dialog_pause.c, line: 134 msgid "Time Elapsed:" msgstr "" # # File: ../dialog_pause.c, line: 186 msgid "gPlanarity" msgstr "" # # File: ../dialog_pause.c, line: 190 msgid "Untangle the mess!" msgstr "" # # File: ../dialog_pause.c, line: 194 msgid "Drag vertices to eliminate crossed lines." msgstr "" # # File: ../dialog_pause.c, line: 195 msgid "The objective may be a complete solution or" msgstr "" # # File: ../dialog_pause.c, line: 196 msgid "getting as close as possible to solving an" msgstr "" # # File: ../dialog_pause.c, line: 197 msgid "unsolvable puzzle. Work quickly and" msgstr "" # # File: ../dialog_pause.c, line: 198 msgid "exceed the objective for bonus points!" msgstr "" # # File: ../dialog_pause.c, line: 207 msgid "gPlanarity written by Monty " msgstr "" # # File: ../dialog_pause.c, line: 208 msgid "as a demonstration of Gtk+/Cairo" msgstr "" # # File: ../dialog_pause.c, line: 210 msgid "Original Flash version of Planarity by" msgstr "" # # File: ../dialog_pause.c, line: 211 msgid "John Tantalo " msgstr "" # # File: ../dialog_pause.c, line: 213 msgid "Original game concept by Mary Radcliffe" msgstr "" # # File: ../gameboard.c, line: 75 #, c-format msgid "" "\n" "\n" "ERROR: The windowmanager appears to be ignoring resize requests.\n" "This stands a pretty good chance of scrambling any saved board larger\n" "than the default window size.\n" "\n" msgstr "" # # File: ../gameboard.c, line: 78 # File: ../gameboard.c, line: 192 #, c-format msgid "" "Clipping and/or expanding this board to the current window size...\n" "\n" msgstr "" # # File: ../gameboard.c, line: 187 #, c-format msgid "" "\n" "\n" "ERROR: The window size granted by the windowmanager is not the\n" "window size gPlanarity requested. If the windowmanager is\n" "configured to ignore application sizing requests, this stands\n" "a pretty good chance of scrambling saved boards later (and\n" "making everything look funny now).\n" "\n" msgstr "" # # File: ../gameboard_draw_intersection.c, line: 65 msgid "rather many, really" msgstr "" # # File: ../gameboard_draw_main.c, line: 374 #, c-format msgid "ERROR: Could not load board icon \"%s\"\n" msgstr "" # # File: ../gameboard_draw_main.c, line: 440 #, c-format msgid "ERROR: Could not save board icon \"%s\"\n" msgstr "" # # File: ../gameboard_draw_score.c, line: 67 #, c-format msgid "Level %d: %s" msgstr "" # # File: ../gameboard_draw_score.c, line: 68 #, c-format msgid "Score: %d" msgstr "" # # File: ../gameboard_draw_score.c, line: 69 #, c-format msgid "%d%%" msgstr "" # # File: ../gameboard_draw_score.c, line: 70 #, c-format msgid "Intersections: %ld" msgstr "" # # File: ../gameboard_draw_score.c, line: 71 #, c-format msgid "Objective: %s" msgstr "" # # File: ../gameboard_logic_buttonbar.c, line: 56 msgid "reset board" msgstr "" # # File: ../gameboard_logic_buttonbar.c, line: 57 msgid "pause" msgstr "" # # File: ../gameboard_logic_buttonbar.c, line: 58 msgid "help / about" msgstr "" # # File: ../gameboard_logic_buttonbar.c, line: 59 msgid "expand" msgstr "" # # File: ../gameboard_logic_buttonbar.c, line: 60 msgid "shrink" msgstr "" # # File: ../gameboard_logic_buttonbar.c, line: 61 msgid "hide/show lines" msgstr "" # # File: ../gameboard_logic_buttonbar.c, line: 62 msgid "mark intersections" msgstr "" # # File: ../gameboard_logic_buttonbar.c, line: 63 msgid "click when finished!" msgstr "" # # File: ../gameboard_logic.c, line: 371 #, c-format msgid "" "ERROR: Could not save board state for \"%s\":\n" "\t%s\n" msgstr "" # # File: ../gameboard_logic.c, line: 401 #, c-format msgid "" "ERROR: Could not read saved board state for \"%s\":\n" "\t%s\n" msgstr "" # # File: ../graph.c, line: 923 #, c-format msgid "WARNING: edge references out of range vertex in save file\n" msgstr "" # # File: ../graph_generate.c, line: 196 # File: ../graph_generate.c, line: 215 #, c-format msgid "Couldn't allocate memory for level name.\n" msgstr "" # # File: ../graph_generate.c, line: 210 #, c-format msgid "Couldn't allocate memory for level description.\n" msgstr "" # # File: ../graph_region.c, line: 459 #, c-format msgid "" "region overlap adjustment failed in arc_arc_adj; \n" " This is an internal error that should never happen.\n" msgstr "" # # File: ../graph_score.c, line: 67 msgid "zero intersections" msgstr "" # # File: ../graph_score.c, line: 70 msgid "1 intersection or fewer" msgstr "" # # File: ../graph_score.c, line: 72 msgid "1 intersection" msgstr "" # # File: ../graph_score.c, line: 75 #, c-format msgid "%d intersections%s" msgstr "" # # File: ../graph_score.c, line: 77 msgid " or fewer" msgstr "" # # File: ../levelstate.c, line: 170 #, c-format msgid "" "ERROR: Could not save game state file \"%s\":\n" "\t%s\n" msgstr "" # # File: ../levelstate.c, line: 217 #, c-format msgid "" "ERROR: Could not read game state file \"%s\":\n" "\t%s\n" msgstr "" # # File: ../main.c, line: 73 #, c-format msgid "" "ERROR: Could not create directory (%s) to save game state:\n" "\t%s\n" msgstr "" # # File: ../main.c, line: 93 #, c-format msgid "" "\n" "Trapped signal %d; saving state and exiting!\n" msgstr "" # # File: ../main.c, line: 146 #, c-format msgid "" "\n" "Unable to find any suitable %s fonts!\n" "Continuing, but the the results are likely to be poor.\n" "\n" msgstr "" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "bold italic" msgstr "" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "italic" msgstr "" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "bold" msgstr "" # # File: ../main.c, line: 149 # File: ../main.c, line: 167 msgid "medium" msgstr "" # # File: ../main.c, line: 164 #, c-format msgid "" "\n" "Selected %s font \"%s\" is not scalable! This is almost as bad\n" "as not finding any font at all. Continuing, but this may look\n" "very poor indeed.\n" "\n" msgstr "" # # File: ../main.c, line: 288 #, c-format msgid "" "No homedir environment variable set! gPlanarity will be\n" "unable to permanently save any progress or board state.\n" msgstr "" # # File: ../timer.c, line: 51 #, c-format msgid "%d:%02d:%02d" msgstr "" # # File: ../timer.c, line: 53 #, c-format msgid "%d:%02d" msgstr "" # # File: ../timer.c, line: 55 #, c-format msgid "%d seconds" msgstr "" gplanarity-master/po/header.sed000066400000000000000000000000711510662254600170710ustar00rootroot000000000000002 c \# Copyright (C) 2007 Monty 3 s/PACKAGE/gPlanarity/ gplanarity-master/po/meson.build000066400000000000000000000000711510662254600173060ustar00rootroot00000000000000i18n = import('i18n') i18n.gettext( 'gPlanarity', ) gplanarity-master/random.c000066400000000000000000000041761510662254600161640ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include "random.h" // Portable 32 bit random number generator. It's not crypto-grade, // but we don't need crypto-grade. We need complete control over the // result sequence and reproducability, so we can't use any local // generator. As long as it's 100% consistent across // platforms/OSes/compilers and fairly uniform (doesn't always return // 17), we're all set. // This is a C derivative of the PASCAL "Integer Version 2" minimal // standard number generator thich appears in the article: // Park, Steven K. and Miller, Keith W., "Random Number // Generators: Good Ones are Hard to Find", Communications of the // ACM, October, 1988. static int32_t next = 123456789; void random_seed(int32_t seed){ next = seed; } #define MPLIER 16807 #define MOBYMP 127773 #define MOMDMP 2836 int32_t random_number(){ int32_t hival, loval, testval; hival = next / MOBYMP; loval = next % MOBYMP; testval = MPLIER*loval - MOMDMP*hival; if (testval > 0) next = testval; else next = testval + MAX_G_RAND; return next; } int random_yes(int per128_yes){ u_int32_t num = (u_int32_t)random_number(); return (num < (unsigned int)per128_yes << 24U); } gplanarity-master/random.h000066400000000000000000000022601510662254600161610ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef RANDOM_H #define RANDOM_H #include #define MAX_G_RAND 2147483647 extern void random_seed(int32_t seed); extern int32_t random_number(); extern int random_yes(int per128_yes); #endif /* RANDOM_H */ gplanarity-master/readme.md000066400000000000000000000006651510662254600163160ustar00rootroot00000000000000gPlanarity is a simple puzzle game involving untangling planar graphs for fun and prizes. If you tend to get addicted to cute little math puzzles, this one is a doozy. **This is an unoffial version of gPlanarity, that has been ported to gtk3. The original can be found [here](http://web.mit.edu/xiphmont/Public/gPlanarity.html).** ![screenshot 1](screenshot_1.png) ![screenshot 2](screenshot_2.png) ![screenshot 3](screenshot_3.png) gplanarity-master/screenshot_1.png000066400000000000000000001065221510662254600176410ustar00rootroot00000000000000PNG  IHDR X'sBITO IDATxT/g %cȘ`LViB!1}4mf&wsN?ۓ=ߜ޽nmv4lc`G!dƲ! iI?ơ6hFI쏟3< l2 ,  ``h6#b1}>A>G"qG"1Bc"d"r9EQ(d CѴR)/(`t:&?fUNQQIi.C*Lch͕dR)MSU^b1:qxX$  |0۽;wϞܜJb5?uul٢BAm;H+P?PAA1p86۶)79$@qW[W_|9e@BJ|ٟor ~y ^/\ vL$ol4Ru#.,/Ƃ4-3+*4w>>4BR)3Gn۵K}}RܣCoEv- : 'VSwszW7R#G\~o YyZዱ?$@ ~IRG8sBǥߺ R?Jz\^^;6 hzNvTۙfQ:qͳo_Æ߾k|hH|>>/?/O?a`F}^?8~Ȏ7n lZ oOxzC.^;p`ˉgw0?]&>[GFrrͅl綵xqǟ93 E CUU:!mO$0}ra55z_~W-zZ--듄'iȧǃX,7#70ϻ~|lRbNccޛvn|>w'~Kׇzxo$ CȦff\,K"߼x Cm߮">x<197|wؓWY5W gx~ˇ|gw?So~WFrǃ9ʕo~s{7B"xC9BOx9ƍ0!$ 26T*eWpp>CW]CCwwvۧ])tdy$vTڕƏ n-%Aq\T">"BLF[AOd!D.(*.FFT&[ !ccÇcc!BȞ=IF 16$L;d۰ZDt纻vP}EBi8qc wtx\39 ݹ>4E}8p>ʈzZӨ{<\^?vtxIEVIVU>fǥi*ZP(3X(BLFvp_,7;{a ]|_޽;SS'n8A =5(!D[= QBHn"#J&!$p0b3SSlaro qP( E#[<b)R99t^02ba-a(T f]p\blYPec~??11(rˉZMDT2쨐aVJKs}቉o%%eb,FvG .Whl,+1MNG9_¯:ke #:2>CFlYzU{Yqe2%Z{ IBB,պuUţ0 o[3=5Ϝ#xk+|.g$V0BAq\ Bx>&f)c/~'?q{T4p8 xFY6Fss99N'i*'G02RdgԓɈL&cB*b1q1B1|$Bp( \T2rsiR&P!gfp9q^5J8Np}ccH$ǔJFC75m b<UZ:T  p\2w|PP##A?j4*ȲOCX ILV:i=ɪJMժǥiJ8_~W=P*e~?z[;v!mɑ,,XI⥥9v@4'|pl``\ <#.}e C\lj+I_J32υBP(H$PȴZNdj<'Gd(2R较p8 Fυlta!FӔBAjyn.f'k72TdN855mB>BȞ=BZFɥ΅Ej9!$8%u!ۖ~~ סCzI55f8Pj|Օ X'lݪi鼓{#x,_ h򄟆A]?tH[xR$ orGc]㡿aB F Kݼ J&X6kWEQ&zG{wXir=jZzƄ];w] -F|_$+=d_R$JFb1> XbP^ F#ɡ5! BдXQ|sWX\5Z*>)|QQ}c_Ae 3;ddn5!$`(ݔqk:~4G]҃67!ܸ ۮyc񏕕;Մ4X3EQݧٱC0Tp?Z-(j-g+^ݔQ^ۤ"Y+LٻWsr Mb/}ɘy}v),TJN&#`Pޝ FU3R'yNk$q;<<BZZ:zSSB!n6?| Hoi9X^mrvu^sT$[.͛I4ZWRYna!ZXXZ?/|oOiZf4* [ }ƹsޜc& #T0;v AS +#7nwxfC%/l7nDrrdO ;.Zg"x5\RCsc.aao0(S`l9BH$׷nU2[¦{sTe  AQQ]l9\NLlAR : !'n񓟺f~~,9oM:P(:o}+h c-,DoތES=4[2^Owij2\t;J%wE]Z˸I9J3AEYU!~??L_`yMNX}~룣 jG>'K+8ռyssg?O_fڵkH$^R.)Q>4'ssRImݪ۾]*;l)ʕ`4&1fqq#LQ3ee®̡Z#꣏jg-6,}k|>~ж|G<˄_.[|W_p;Up߿rA󣏼Kp/(`{?}\^Y>|/.}gw0b-3gB~~{p8Nt84M7ߜrV\LK@Aˣe2{ '9۾]UWon"tW@!21<ȶJ;웚 ? tzRXv#g&'oP~?[`ƍ;$"&Жp\bx0kӗIq#OMǃmm7^_Ύ$:%%j3==c_-2.Wpl,T !d|,-7MW~k3&Sq¸2}ф ) ja!:=ㄭ*pBV4eep867MM0[*3~Q ڦec_q -ٲ|ۿ?W^)g]! ٓW4ty_<WY, +,(򷶖CB~zqFa&I,OW(pMJ{MB?a…@,b/d B_+`||B$Kٷ/oV: #kl40 %-17W.»z{}+)ԧįk(Ԯ]ZwFJQYY??yN!{s?ط -[G5|\§%B<|Dw_.EQ2pk䄟m>Î+/6 ސ3yOU{'LqJ.O$UG`DxLk4tS֞P(q-}6qH$0BAq!O]\`Yt _ 27!|X,G'+x" sg}|l.Fwv<7=:!]n߲V}vGy, ݚ F8EQuKph;sf,+۳G38ḘMBH{YѬt-,+ ɣZ0Է{llax8h> 0$'L9.F':Mj+Hq?XW׬@j>C]A**MMMSS~ˁJK!d6նmx< ǎCE뮝P(׮FG(ڶC[±"#WB>B!kМwuͨղ͛WzRkb[[ˡ''٫WC9>jaM%LH,''њ >XuXcer=ݻsƂO|PkzNkW^#[ɤ޵K=>V(d`4 C8P9+ Zzjum^ śdu )VZ>׿6>*|FmR8Ryg:Br饷T'AD~[/dZٲd2{zW^-|/#Pa2 >}Z,}k7~7PP2Ų]r(ڐso*a bOpkr:FIRɴZg)ڷOPPY}x^ 薖%|ٯ~l 8gZ kj  *?w`wXr~p ?}]45~3:LvJ;2ZK>\qq|G SZ-/jٶm'4OadC[±G zK5sOR)O+HkWu[[۷54-w%c'\כZ)r>V{bWUc8\ɤ6UoN ~=DnތNGtL~>`^ 㥥9/hZѐ"Ƿ/_0Mv匌,TT@vD^odvx,^ LMA͕1[(0( #ݻs3>PRp!TTh;:nᄗM,Fs QzHuCYܙLlE͕k4M(FIyС;] ,=o<%B*Ti@D> X8͕*)(`TAv ssz#LFrsZMi40  D"WC33GYqӊ !$^pjPrrdZ-PFFQq V7H#Fc88N"#5E IDATCh$pdZ|Nn )P(S((RRɔJBA1L.5p`S cݻsɽm5Xǘx<`0 qH$FI;4%Sr90M(*.SZ"7WFӔFCT9vVXX@(h8Dbh<c4BQDX]4PPr9R:G,X`l04X C`l04X C`l04X C'O?tUURj{ַuqsH *`UT<;w?~7JJJR @jP)k ky gagx~ ӧ~avh 9|d\Ѩ;wCvB l/ݽ?\ko}ٔT v.f2sdݻ/wuuutt,DR d{mwf{G:͖dRJX/4XՄ_kypnn !wHJX/Zbr\b-yr^{mSSH$묔ׯon&i,(!$@҄JD"b`AV3LYfe{BHII fHAyW[)&isH`AVkhh ͽ/,/> R dz23hԛwB׿T$T zpСht~ds9>htСCHM6@ʁlFsh7/ڱd3T _~e3i֭Ooxvusdr6gnO^`Ǐb*`]p Bv??::o~#H^)o&.4X^{mffwu:4Mܹ~ǟ|IHmrJh|ᇏ9r^C@~#GTUU jzWK- SO=UQ52fByh1*l6l6eS @`A E Jij|&4X~l IR{zzU$lh q$vI[WXVaN<٩ d/yZV+vZotK.9 Yh {l6FC@RyV{ԩK qh K fJ%v麳Jiarrܹs @`A6bYfL&,v麛J0LX,Fpj@RhX,@ @`AzFQ,us x< }h 봶2 ,vIېJX,4M8qbR 4X]Nqo;@U)ZW\ިli dcǎt:,VJUU^Ǻm`A뛙iiiiZ,ҵ"vϜ9s.`A`YnL2HfTJEEEiiiWWl 0ѣbMFeq;d4X<Oooouu`; tm^OOOo+H, *^ R__% {p8\.fHn+ER566ah 󵷷ZHZ *fz9"vIKM48;;׷,d~D,?TJYYYiin},LVA$n,J!uڵ:N'vvٳgSY)ŋ9"@u)FmRjfKAR d!UWWR '''G* 2h TJJKKv; ,βj;uvvaTJ‡A `&&&Ξ=[WW ] CMMŋ'&& ɓ&k7SX#T׫j&vvh@LCCC.@A; d54X ڊ ]2EEE6 `hzzzb;R֋id CXl6c9@ *...//zbg, q\SSA$yTZ ` ,jbg.Tt555.]r:bgl D`0`U$N;d#4Xjn@=&''ϝ;'v:h Xmkk3LfY,҅J(&K6@ƶBlӧ ﯬ4bg.T*..޿; d4X: 477@P)b0 s @A)t:GGG<;v@lV[WWwʕa@@)r1N ɡR6IUU^Ǻ2h fffZZZh; tR6Mv9sF,`cYd2@P) K6@ M'L8?zA$ ,nwH4X<Oooouu`; tRRh4VWW?~zzZ,`jmmUTb4TJcH4X„sP)R,lM 6Q{{^;RRfK6BFpn61 Tx^@@㸦&H*EV+0X6,NshhVՊ@P)Ҥjjj.]t: l ͆ BH:uJ !`t͘p*Ehnhh-vH{hxJ(vB x<@zCwafH*%X,aN8!vHoh9у]$P)E]rexxX,`;vNÄsP)iJcQh̴4-vB#->sY ];lggd*++; tRWEEEiiiWWl; 0ѣb4TJZklldYwÝAxz{{ Y Fcuu秧 [kkJ;R2@}}=l; p\.L8HT*bÒ ^h`}z}mmA$ 1*++ m6bgt n{#G@P)DؠpvvO,N`ZH*%󔕕v/vHh`v;˲VU JH_(vCk211qٺ:N'vBd*PSSsʼn @z@krIFCdzZm nhhra9@&lP899p8i *H*%梢"͆ aUh`===@b@P)ـid $#L87͘p*%{x^d9kjj;RjeK6@rh`ENshhVՊ@P)F\tt fa9P)YHO:%v.4XnnnƄs$P)ى醆sΉ$ $l[[d2bg.TJ60LXB twwc35URMӍ@bg)BzFQ,҅J x<۵2 ,vIC!b0 s ?t:GGG<;v@@]rexxX, -h;vLa9@rXTUU( I__LKK Mbg.T ,EӴbqgΜ; H,eNTVV&vBr]]]X[ G;R Feq;,Bxz{{ Y +1ϟ; H, VJU__/vIC@Xp8\.&$JT*bÒ @`!]֊@P)BY@dhnzG;R`- ggg"C~yyyIIY kWVVVZZj~Y@LhngYj@P).?`egt:H*`0\xqbbB, 4Xɓ$J;P__Vm6A@4hА媫Äs$P)pg '''Y@hmmmEEEUUUbg.T \TTdٰAavBzzzb;Rn4mZ}>lNh0l6c9@{===^W,jhN{{;qMMMb4T l0 lBhjbg.T lNWSSs%)vH)4Xfa9P)NԩSbBEnwss3&$JEtCCs+[,f2fY d2utt`Ɇ+[twwc35UR`34N>-vH4XYWVVFH*6Oqq<Y `eVa iTa'NR Vs:IR`iں+W 6w1N ɡR z=h2\__LKK Mbg.T Mv9sF,`e2e;;;M&SYYY TQQQZZՅ%2L&L8?zA$ )Ȳ,vlh26 bg.T h>Y`X*^ JQcɆ̆+39˅ ɡR@,*baɆL+3ZH*DTYYYXXY`@v9rD Jq 6LKJJ ]R V,ZVH*$BG3211qCt:HP)uuu`xĄY`#('Oh4; mA"jf;l$4Xchhra9@aI!v0h2mmmEEEUUUbg.T Hl.**lؠ0c===@b@P) M4M[Vw@ f@zbg +s$vICYVlP1`=944tAV+v*jjj._t:w VڳlX`UB`i8w;`A܌ IR ]4055u9]AXmkk3LfY,҅JRQQa2:::dCZCƺP)^hnll O; 94XWVVFH*Qqq<YJW4M777@Z[[A@ڱX,X!JKNsttw$!TQ)vZm]]ݕ+Ww VZ:vNÄsP)֪z=lHShO__LKK Mbg.T ;- VaYd2@P)***JKK;;;dCAf G;R c466a\(L;h҉6 bg.T dX]]=888==-vX4Xy8 IDATUT׋@Z[[U**2F}}=lH;h҆p\X 9R4dJeXưdCA6z}mmA$ fG9}?,vX)zz{{x$c|w^)3X)p880??_PEWrF^ss9!_}rr6,1Ep{JGw@uv6/i~~;rNstt0H9~xWWl39d2ݿ󻺺:::R -;vLai)+u{=Bȶme)Bl6[*0H~uj5w}wS#e;;;M&SYYYć1Ep{(H$τdFJE m\.!d2d~~t|S4OA6 8%Y"DQH+!)HD Y1dj4/FwBJJJ0CXAj^{5e_xL+SpV>p+u!sso Orrai0Hyꩧ!33Fq |+_IE2ikoob;S"B`RCCáC%עyGatrv9rD Ҳ1СCHM6 hRE~~~ ur]_XnN;zt:S@t~[|,1ERF/!lݺ͛ξqn,W.l0xի ~jٜ7>>Go۶ !R ٮڵk< ,1;ov:X"p8w7X:O'>|2֛ `bb7M]]Ç ]vMc ,?~7u\Jh4>Ï?O>n_xq˖-޷o_g4XRk̼K8}P)lh̵kZ[[nwQQѣGF؉2, G; tR$ 7;w~8r¯]e.@yc@)C~hz饗*++ϟ??y^\'X,H*E`+=/{Ǐp8f3nH"qhқ`SOb7|??p]{{;qMMMb6Ta&(++6MeL&l; t,kP)҇Kk߾}6ҥK>࣏>=v@YZbp8J> L1k׮]v>; M^$JI#D {wy׿ءLkk+0b4TJA-H=x H^p0W +++O>Ç?C1 u1N ɡR `e}_|q޽N~CA뛙iiiA*%RY_(zw><Mr$ <(T )Ң jl՞=;=cUc-so5szOٵ{fnA6E|(ZР 1!@ \ron~\;EM~OB߇9sn;(H8E]zU pQe2)VB+,,7 Ox;(H ܭ8w ݚ[0Ә踍Yeeel~mm-z]]]UUUX 0A {ɓ'cFkkBؽ{7߁2%FՊ!Sb!XΕ+W+**z=r#33@ P`AƬ+W桡={`cDdr8G;AD.,‚T*1+33b<]RRRXXw,…Lu(`,zϞ=;B&}]zuvvDC٬j5߱׳gܹLi@B;[l1LFݻ555|ʕ+J3ȔX%BXαcHlnnnjj;( VUP*@Ȕ #??v755ac,am۶ p!S ,X&ncɓ'+**z{{n߾0 q@ݸqrݻ@Ȕ V$Ƀ]|q``@peee8p2%(h4G9|0˲.\8}ŋN`;AC=LK pfkkkc'*Fw,…LIQ(}ɓ'c'*ݻw!S ,؉QVC$,@z ^#!̬;AC$X \Ƭh6كYd2w LIX"STƬ̖FwP NX PP`Al6f {YDQԾ}@А) K3cGFFFfNS| \ȔD+Ζ-[L&h{nMMMyy9q%+W(J4ShD1s1$FGG*[VNa S ,aǏ7 n 0yyy۶m;B$&X۸Y'Omhh}60|Ǖnܸrw LIL( $y˗/766 T9@Ȕ F9rÇYpbz:::h;AC$,"xSZZZ\\ihh@`Xu:J;B$2Xcg9) K=vrrrZZZN:C===6a S ,s\C,{ܹ> VvV[VVw,…L,BB(///--ikkܺu^Ge~:, @6fL[n=z=vptwwWVV p!S!$YVTZWWw L$&Y2<裓'Offf466Z,ZENX  A ={l1LE۷@  !$B٬j5߱2ˆKZzlٲd2ƻwԔWt\rET@xK9vIMMM|RVU%aIe@@x(V*??v755,amw,…LE@ކ۷o3 w\Kv ˵w^4d , @Ԑ$y˗/766 pp d D@i4#G>|e .?>VV ;::h;AC@$p`Us=vcbt:Jw,…LX-c La`uz䴴:uÇ|f y w ,9t˲Ντ1vV[VVw,…L%!)///--ikkܺu^L `QXXkۘUPP`2nݺ#~{8\b>d ,x ;Rb2 oxcXw܉a S`D'nŰfk1ҥKjC2` $IM6ƾ͛}=!S`yP`1ѣA4779snXE]zUqˆ @X O8a0&&&N>}EQ3d ,&<ۘUVVf6߿_[[;vJD92V3XP(;yyyڪP(vgWX X;VC a z ^ O)B(b1h4桡={,ucdr8AEX2VKDRq233[ZZ-Kt:KJJ W5HL@{Y={6;&}A Q%B;###fYө5 S ZP`0Ζ-[L&h{nMMMyyG^rET@x,<αcHlnnnjj~ժp d D ,8qvioo۶m12 K#1?s8.СC|G h7n@@7$I  -)+%B8t0KKK{zznݪg J- 8܅1d2ݺuѣG Wd a ޴JҺEh8y, ,ݚaΝ]@[F, ʥKjRztvvvwwl߾ ^-/S",q/0"IRoڴh4666E=Hޭ0S" NPuUV[\\6f=z 3g(he @x(wQy'N ӧO_xtFLXfGnꪪh4zNncVYYY[[l~mm-z@L[L 3X񠵵UP޽;ϬP(;yyyn2  ,700`ZW9z@XL!@̬^=vF`EE^ǵ bŚe  ֙L&[Ƭh6كY |k)X"aNp-UTƬ̖FŲ, _ @ 3LE۷ѹY={=v@HLX"U###fYөjb@>!d $ Ī+W(J!4Szlٲd2ƻwԔA)S ` &[VN'C|\cǎ$4::wP) P`amw,?n0nwSS6f)P`Ğ7n\{HhƬ'OVTT644ܾ}aや#L p~$Ƀ]|q`` J@Bc:::h;h4#G>|e .?+6b+S !@,X,:NRs=vcV[f X-FX"===6.v~=vrrrZZZN:Cxq@l(]ՖJq=v:IJs>3l̂hL%Bp8kV^^^ZZ688uV^;B)^Gwwweeenn.߱D1d2ݺuѣG+K1$ɺ:Y*J5S :2<<\]];vcV˔;ww@!]tIV'snŰfؘHL,Ay IRoڴh4666]f  ,(իZX1ѣA4779snT"g  ,8p@xSXXx 011q/:NAa*@v{WWWUUF;>qfkkkc) LV\{nBCUP S@hP`j[3,z@.Spk ,QGGGfffuu5߁Qǎh&&d  ,1L;@!qJJJFlڳg6f%d tvwwЩT*ncVfffKKKccb;(XXР IDAT#8Xb2(ڷo߁ nc`zgϞEL!]vjc%豓hLt,ȕ+WJ;$&q=vlb2Fݻwkjj !!P[VNq+9vIMMM|фL @ioo_~m%?~`0&l̊\!S@P`7\.ׇ~w ۘuɊކ۷o3 w\"\ݻ@ ܁͛7yԑ$y˗/766 ,)eee>Xi@F9rÇYpbL;!,K]T*߱ĹbNCCz.St:2b , k=vb)5 ,𩧧fae-z䴴:uÇ| S  EQZXcСC,˞;w>,aB@,!o_fj+///--ikkܺu^GAA@,›?Gwwweeenn.߱$:ncVAAduNC@@!?Z[[Iĭ#cG"ǎpJRd X}z``˔2d X麺:h4G9|pbeJmm-߁DNDbߵkJ;b!)P`D_[[CA@!@lĜz䴴444<|2 ,h(]Ֆ ΡC|>߹s~&,d =,DL [nqcq/n`9\cm*((0LnzQMMM\A@"!@ԴJRܚV"c$_c$Id 7XaXw܉r;'zpR]]L%BtZ޾};߁@V +++;;;{zzjjjo) 07o߿_@hH6m2}}}||H(VWjbcm:z(AgΜ|dH((V;p~8WXXx 011qVwPKLIZ]]]UUUX qܹ_WW=v)h0"r|| DPp=vc2 ,Z8p;H@X"Xjc4*++?C1H@(d29`Y%%%FΝ;<سgp6f!S 1a`9NgwwwIIIaa!߱AT*ncVfffKKKccb;(d $.Xa2(ڷo߁|1`0x޳g^xߍYHXX"X٬j5߱ W.SvڅL `ɮ\T*L 뱳ed4޽[SSS^^1pcǎ@ D4VU |\cǎ$_btttmF@C ôm۶X"qx`c2ܸqrݻ@ۘuɊކ۷o3 J!SP`D;pyf8E닊._800Q) ,utt4]WWw +h9rae/\p"S"bt*X8cBׯ|C:2 "mmm5ę=vf{ S8X"X\OOfÁs?;999---Nz  | _|~^Do۷oϞ=;=LO3)Dz"%a+bHDH$"T*"B*HIR,IN&%bD,K8 0nXi?Mq]/R$$ItZ-MK#E"opL&V2()I"HJ$]p!"iiz>i*$#CVK$@BʩIzf7>/e2BdB,%L&bw a4"f?=͸݌nؐ[)ɒakjvm<#CI2h^ y~q:xX!RF#ʒKҤ|tWSS\.NN$'KJIjW H33/gfW,ajrr$@ `Ybv75LNz].AɜEfl,KLLxf'&v;-bJJRCf>>0K. ?qf6lH^,M{yc6zbrR'lNX'[O.TI%%MT łwhm?33>N DYv<~ގoW,] i)7p'9^>[Ǐwo.d 3Phr~t(!IQRJ[VKW2PbY''IZ,&|39'G `A,Kl##Tif&f!.@>Νm[BXmٍ>R3/sfjJnXQzi,;'ÑOeQWz25żnzОI˾s&zfdv"R ߺ5I~a ZJQQի?a}2xJ$|źu TZ .ot۽/^PTR`K( r[(*J |l+"vǿ(U)e,㣆+z;  f3yX|TA_z׮ٶn꫉;4J7FgАsz ^ ۶!&6isqmj\@0̌+Ą D$l\ӧ3^/"ȐegcP`{V䤗a$)Ron`_\Ϟ͈w ^ Q`ݸ1.nRrf\.In d2>OWx{H"k4gRxa_~9oeܸa7?sS"}64`"^-^؎ڜ054y}{R)pJ$?~k3wN7֯W҂r=66"'VWo~'?y ]_ַ2|>fF2D"%ERPTU.)QNO&x{ )zpdKJァ޸1[bBT*~]]Y?!& իYR*o̰^}QyE6}r^B~,3! ,U(QșhQ Iә~yT?jXκ?׏_^jX&U1i|::Fx#y̞}|тOR?,|cy/WKh;࠳6'jhxDQ )6$?{6?3}U*WWk=sG2,IJdÆ*uaaAxk뫯zlk!%?nv\8z8aC{碑QWŖBtF`/@/?^h^*ju|Wfݛ:vPcmB52tb1! QHyH'suO [oΝf?XΝq޼3KsOҴw$rEA$or\R3AtMtպsg?,%M3gTUemx/.V^:FQZZ^p]bY9A63euu__d ""yEhgg}ロjs{eee׭KF6mRrVV1@DIĤ$u}#zw+,wwXM+;嘆n wsKr֭j*ǩ?;n Q\ܩټٯXl^}Adg+|"n>Xr䍟|󙼼*D@n7zLu),L~t&=]:$ݻLaaJ"?B_Q~7tI̽{>+++쁟[`Pl+U TP 5Z(ߕ+RINNF4W]TPu)*R~I/D$͝NJʕnE$]LJRvN$}se g4 " Q3L`$ gglddvn+RqD܁*φL_.Xi42~wV2yz+77xwfjja@[r9%ʒ /p,K8`&&( :F#{T|쳣Go^M?dqizwۗ7+*Rdܿ]`?LTt+*$)Je|>j{AAoU ?y=}W,?%q?tM,k0?,ِw%!~ IDATr~^_gI6Lj_9S\oe _Q^GO?- hKh{lH[N'p.33<5LO^\>lv;-JJEj `= 纰޽Gz}N^fCCѤ$B#H&UT{[^^BVϵkm+݊ ,iF *j.Ν Yc\NiF 2+dd60lo_5=>o}fZZ^dgu:M7͆h^Q^kiyqdNB@ >p4tW(G"J%OKIQo%<ĄnE""9YRI7&cIs]XHR)WYV.+/(~nկ Sc=yRYl+݊ ,YV6rY_XvvP}: k,cR.&,ˊ=; &/Xy#VK?tCē'wߩa-۲(_?g4BI 1w pxիYzJ$=].U*IDɵroznĄe21WQZm**XK^]d3LA[".x^z4߽{'qU.p/ݻ7=2Z>I$VO*@K+bx* 7r.T]?xzL3 ATT[[_.=! "IQI}f/\)+K ylaعFGg<~/ 'Ee xؗ/g<YHIղ R)IN&%)N@ø\puJBA*Vy ?@PͩA&wZhr~bfdͩWMNA7h\@\ƲZ=<Y]hIBX$)i6_yq;2׽y7ѱRO,CAXlq^4/O1>> v?3Ä<f듞>tߘK;`72DqQ*=}y0ATij*z3)vs}~XHj2)I"U*R.Oavx|ozz cy,IrQr$)I#+*,` 17}5ɑk4X(dZꕎِ3,+"Uʲʙᡔ\/_殨?ݑ!}޿Og2OA*L=<*-]B 9yGth:;**Wm2UU\@Kfof AKA,1;뛙a)gβ33>D (5U,MIHb\P4z<>33>i4#KS(DR8;[ՊєKPׅUh+BX~E\_>cmq*|u~% Q`dbK#;ΒQkxv'I EN}"x?9B:pF +ԑ#o.c Rn]--/֭K se%- ? DR$)IBxGi,cOӬҴaH)dR'%IbT*J\"*li?M>8i0,KQP>$  d2R)Œb@ =BWX+|Eyklꅪe\/xQ`~6DdYi۫o}za݅w=HsI`^MV|Mog4!o@sw[|ȭpvZX@8RTJ,Ԫ+fgYx|N'>#Xi˲ }F"dbTD_ V$)]ʲ"%3 E Ҵβ"!H*DT*HH$$\.V*rX&ai`µkcf#-rr~02g?s(+X"WW{z?(8{dZZF!@z}3AMoבFֆ{ ?I6mRnOU}~;;!w_q:qJ Ǚ߮2Є2߉#YX]h NwDRaoϘ(^TwozԠ+hkIJ~]X_wVi0}۽]! ^'M3ox3㜶柽/?g>K;ou>ϑTWoF^#doݚ ? \\._gݻsv_E}5xE +!+гg3bwBXαٷZ4=<}KQ1i[bق><N۱KK֗nMߣVϓ';4/ar|sh_B{V8t(ÞlyQQrmf+֭\_9{ҌLyVD.R$2?IOؽ1ջU{վ/:22dYYIj5PR1M.r&&fwM߻7g%[1вB tԶm!nbYuwSWrqN ?}jy<>[,WH32eY)+ފ|M0<v>pwU%,iEE)Z@.@^wn\BXAL92V ģGnRZQbO}9RfW90d{'&=z;w2(4kR>\^ XAx~ܭpc3m 0niݰ!孷R 11᝜:>aD8/ _\-zm D")ZM*dn|gX%@2XQ P`D%r`TIENDB`gplanarity-master/screenshot_2.png000066400000000000000000002054451510662254600176460ustar00rootroot00000000000000PNG  IHDR X'sBITO IDATxytS׹0}l6%dc3@ If뺫oڮmvݦ%7$%pb^ Nll# H,۲cEeY5Ėُْ@a${ X1@Ac`9#~d6{VjN^o^!DQp"f@L&b,A D3;%Hk%*"BVmeD,$|&Ap8 $G4}g!zv;pPN"|9& FG}/.`xrѽZ:;;1,̀Dω mpd'4{N+8"KmMλ L^~YOA!7bF6h^~Y;o?-yW;,ڵkd#|3*}x؛޼9O{$"fixlIƿ~/ˣ >BW~iLf)8bBގMa!&`t߸a$IL)J(/-/S4 f\jQ(㷤9 f{ᆆA;,1Fu(ftI??2 x<02YmI#,a|Z믛ҥoo)|ޔbd,Y"谻\߲yY,;™$..a1~}%&[^V,+#$G ^44ki>@*,7Yj}zݳe D"8!N{}رA0Ѐaz4(/f6ib_XU* I&Zۚ59 ٬Y:B~Zczu:Ǭɻ뮬oZ`R>rb1g+Ex$c٨4;żnƜe\tdd0?gG}yH^y`0^ziј}iA%%|͛@Z?H9mT;2;y xΜ1}?ѭRI1]磣'<ଯ)6xHw[ 8NE[&V遶7~$lVk'b!B$ !˱ i4~NB`pszA2Fc:#tG'xY`pw4Nh=씏yD!c¾36b1:rO1"ϼcӰp:.(EDR%@'N7Rٗ-F&`h="1fy<[ vOFkϞBlt.Z'"'m6b1vs h:@n[rK `0bf(ɅF<1=" O?2}<\0{z<K8YbZۍaY}@O;qI1#A80S~ ͆gKJKGV+b(c|>x^t4)( @nCLWpùS%"B'[S;A4MBAQ~|wVp d p d$I$0H`X (<7h9B!i08^@_? DMBxܹ!&;z,rxhdyo{ !fv'bY~_ J$rErѯ` L B   ,txr`NOam ޼y^'l4j^4!3BD;P/T}z%`57[\eؑhH>].Ӝ( ~$\.#33I`,EX`2܉]|Z- PTnFL.1fr822H&q8 .#x$D3Ti)1׳hQƘ?BV }%A7+ EQ}gFF|}kWۣ"DBBeeBc` ?ï`M\f"6no'xXď~-V<~qxya# Y[5Eل~aG(?XDejX_X,ƾ}EyLƛ葡;RƘh< raogzR)<{'C4XxN"ϼ/ٗ_ZkkO |و|׮YoGC $7mfCo<΂\PKڵ9<Ssܺww}@i)O*hnt Dou]wb͛+Dczdf]6 |؉ AGWKsTT FS(B(;o֬|~1T 6m\.EST )qD"FFc pE@adwNm6ǃIp3Ną 2DxV+BG3eAfI*abv"PHRm滉 @ݗg##7a̛!IBn1dgFG^57:IB5B,f5T*0\f8c/`a pR) $c.Xw/1 .V_|Qt $ߏl6j\~٬\XL L`!t'f! B~?r:iZ}6`s&22|>S \&\)( _P٬@e NIb&@a!{+F|X!B._:(*R13xZB'׮Y~x;lY&Bҥ!i0D`)( zm6J($Ǽ^WIL&#l4.=$rŠ !_O&rI2EvA'SXY)d > sPI>ȼ-"$,Px<&MeW8.BRtv:_^j.7BUUG߱`Exyy"c0@ً񫪄։m+[2==/^biit>OJ &pE yߤsYUTd"JKEi.|jŊLFc۩Ly9jM^ a ?RB=d4:Bxl<-hOsݗ7X|mlfn.+7`deAyMl6АlB! )E05ͣG9_^ѶmTԩ E/]yc~=XY?k.rr X"x <"r:w`R! |>)p+\$IL7͒JmۦvD1ս`2Ȉj9L2?3~Ff& kT)[kd;8vTv!lXc yI=h@t9pGQSQ )_N"Z}w떓$ksF8q/-<s U٬ ,K GAghV*h<Ve?=|RyO5Q3%FRؤjq@NGŜXEhN/o&(m(/#L&q C.|;`Y6j!;"[|>#7EffB 8>Hk4 \w_D\OϰEAL2CqBI% `$~I]gUNI6uxFcgw-aGGcz;;Y>+YS_߿uk\.8vWsx̚B!lmO7PRQR:~4fq8ļy"s|.UsӘ`k`yI|,kCCĞ=YYL Z[m{&k,'OEb1_{+ZS?S{/˂y.s=/~qS(d9yw{?}\^.?} }Oohf_~;E4Z?qhvm6nY=7E!'#5I-gmm. tHw[ 8Nw'y-ZmV+u@[-Qɓ}O!tTv$l6z ទ`zf&`  9q~ʈ?n]nMMBB1|y֖-6 xF_xbCP^wCᕅ;3F;t> &v.@ N? ':r&zzaȈ~79sT}mmv?~_xBK q)+BnPeefNk͚SzzXXN!FF|⎘gGk ]lr8TW*PUL((pFG}fmZMB5Sấݙw\ƪUJKjߍo`& ΕsB`pށ*+_nd4i4VkN롇MM#aBeÏ&'2,`ܙ95~?tlp☼c)1# G`ed5a{TcHC`p!ӃA#pyfO -0B }w14B(67q@ @Q} m8tgp o, b@٬lL&ii08^v6+/ D(d"B;Bg'BN7 ΕZZɃ)M!/3?^ ?}c^?}ّ*H L2(2M4 pzz< hbfN|ؑ=r @0aޙ+Xc{Ly@0]4r)*!Z,㗁_z,f>B(?wFM:Eq0W"Vdf?rRf/M,zէ~zСζ66=M6mڴGӘArrpb訯ϭ׻n ^T;;t  硂vjÍ̕-^,hi^0e2DGFL3g}˗g-^,%剦C ќ"~En9ZCÛ7ϋɛ9&?# {dO[& :ZŋFGEddܩJ|MwlTs!f}_2--8g "k..nu杌6\MM֞Z6&ѕJٸq{zvV-[}z>~/$^ ?qP~8o\bh}}KP~>7?1iӧ AUUwv\WG\ 1Ε!\G l ZB8BҤxq(#cy6QN}iќ}CB! S}QaG^ W!ہ FG'[]-B-\h-_bbH*(.r7:@$C*0\f8t,fM D/5HAU dw_.wyQ&3+/G5<@֏CMMMrܹssOl_H}MN'u.Zٶ-.?nQ~>/p>BH&ge[NmaJX6y/( Cv6+'587w«.ְp!aF8<={Rc^ڤ?[^. IX(.ĩSzQd<v+X^~?]2 n`R=:X(IFA7 IDATV׭[wŬGNNٹj=v . YtolzLB$"E"VV AnvJKy?/`Vz͖[/U&BZ,^bM^obSv;۲e P|bm#-mmR={ b8H)<##ޞ(f|>33Æ;"PGC~8nh0ܼid] _E~'lZGvjGG}MDn.;o;~ūjkkB?<"LQAϺCRv`k`c0 $ I3E4*/];J ,jx,mnp8Di X>v:)|Fn.W,fegStZV[6mOo(n޼xHOGF|fbR IA,|<s}54 a0B9͛۷l61B``j|iG4|?~墽ހC{<~B!3'-23ɤXp8^w21 4mii6-@jJOG6nE;~6p\.aZl6b1;GR 4!>' t-/^S,T <:saq:##>B^!;)$ &`2  IALB(dD $ex̴L\`vH'`,VV+GN'mSN'pn<M`i f3H` &rɼ<{T1/ jD:_;>O@'` )0ͻHxhp\ >)M  Eڵ !44M["?B詧J@|'l)jÆ k׮Qn[G hztڵk֬I@qΝ;ؘw^HWX?۳gO'GO~QikiiG}[ߒd<ѣa?qV[WWgٶlٲlvHzjJRחQ(~{(+'n2J&=SEEEtL  jPEEEBmmmW^yElܸgRFOT"T*UߊD={lٲ^1`Z  h4D~P(H$8i˯BhwT>'Nʕ+yo}ܹ0`꺺FGG,_aeeeÐ%L}U}}R44w rᦦ˗߿)b={֮]_t! )!TVV6***h,aiii9xݻ{Xv8I<ݻ~gH`%IE"Q^^@*(ĉ~X,R(Die2O?-Jkkka; fuww/:^eedr݉jmmFM//, |-[7| eW`Ԥ\.i*&]վ}Q*z C,,RZb1d v*))fƅ***.^Cx eٌFc KDzW^I'Ir?|   Ei44DhX ,scR*z1 WTT<3E4  E (wIdeeA0B\=쳱*sX21,R(Q*++3 %L8^¡lAAAG4I---n;B?'jkkM&͛Q,RJiz,Yva{̅zS0DL&SN,[ L{OII UB(% /Z(7w.f H----~:Ieee kpT(s= eUTT9sv0)H!Zv&ALT:Nd:x`SSӪU^*z8KOn߾ e H!F  2Bp._ꫯ4o߾͛7'{8S9 `Bf$҄M@ʖ{h4&쌡C  UhZdztҙ g ᆯhrGYcڽ{BY"&AƼ,\7>ի=Kݣ2쩧***=y$  Thfĸ\D"ioof+\檱q/bʖRS( vA@Jv}ɒ%:T*Z}}}:l~С(s$= e۷ΝKH5`C WZmmm:,se'ɒ[c|x",RF)//RP(H$j:VҴUp0wBYt@ lxx˗x wޝ^e"5fq,&w0gA@u A0̕\.ei1RX,~竪wH9,Oє|P(\`A*LId2fA(q\T"w$cP( A`dz~ttT. b```nf qW_})J՚:5fC e?~<H`d8?XQQvuub9rqҥH2WѓJ1 etttO1,LH$8D"т Z_B\檿;vi1Baiiid H\zw](H&4::+LP͑,.s1 Ʉ rp/a__,.sT{4P֡CP  jD" ;X,KJDvÇ=,.sԯ1 eB,0A@lJ4[ӧKKK_|Ź#k̊X e ,=yhN;b%w9=%LE,I7oBY` QT$[ fep1!uhwyg9,fĩxa^7ޘek̚ddrBYP( `x=)aVUUլ2W&i׮]sU޾t Vpg} eY,-1AlG$tqZ__ EGұlAAX$&`{{I:.}f\MI:֘S(+5y H J%MiZڵk2WS5fq> e4Iޞ5bv\I$(s5%i]cV,ٳgڵP( )H4f4(,hLQh{~J$I>P( )H4NnwYv%(s5C% …R).KY ]@@ n*))p8!\ٳPjp0DO>-[:;;|t8H(f2JeRNBHM92W?89\> j̒$w#PH `P:ŋ;\S*lP(fMYX @ d @&q8,X,ÇC ŗ- em۶vTvH,++K׮]p8Ȗ$Y^^> y" eRh.//O0Jed e{9(si]cv"P( 8HF#JJJ;ڿP(Lfb.;kAc e]z5#k`8:.W!$Ri{{{rqe(s$I*ʴDL&;pT* u@@`r7`)Jj2rv\檾^TBĘY . eF(RX$Hggg*1TJʭ2W۶m۹s'Jٚ% S(!#sX$H{{{YYYGqP(,--UՉ<2WՉ<G\.ON,C$X$Vx72Ϭ/Eva$ߟD'󫖖zз-(0>| HX,'Nv믿t:`;ѬG-+BIoef><::FqCRl0$IRB%( \br|``%.u% F0U`x"/- E2Y/^O6wW*//i:xdzW:;;7nef%\ lFp̙V6i Pmm-B(?g,ȏd2E?C}ljYz]DRRRr[[[QHw} HTXX?q\AB G`>nЉ':A$I\n4C\*`}}}3D9LX!F#BUD`o9B7cJ[L:X\ e掙t  ,0eEyd$E]~9{,Bhʕf(1 &F ,B!t~̓mOB .ғf3R4rᦦ˗C9d2A0,|ҵ_N І B##Gyq!}ȑ/ˡp~ߜ.ZZZ:4::{{p@/Qr1=k#@&{ %ڵСCCCo-X𫰅^|ށ?wvv>}Z**ʲtZ? ]zPuׯܹ%2t:8G,F뮻=$sjZiNNή]]6kSO=@ 6]ŋ:ݶ i0ѵk׾KEvvv2̢9il6ɔ.M&o6nZ$ITTBq%=7ok0&IV蜜{S:uԔk֬IиAjV9``EG}ݝ۬3aAfZ600#-R)T_>3_"h֭WT*{w/D__ߡCnݺlٲd%qUKR rrr*++r^Z]] /m#O$ڞ!rݰXNx MDZr\.x7-v;vST>aW,nA9}~~={= F⪊ר788ژUWW͞AXT*Տ3g΄\.yg*++'=biooW\\u}l6۟+Wnڴ)c^\.׃>Ñ#G$ll N:K/,lnkkSjٲeTTioo?x+W]V:z(]P̗_~9c)d޼y{]jr:VfdfER ]x4*>|xhha{ر.X]`jb֭[{sMuDW^z5t:]ccccc숴 CuuuGF{{ӧBwdQ>K(J$Z ARliiI{ q\aXLfYYRihh~'̔JeGGɥd IDATdJ)˗_rE*F?a FZ6 _\#--32T*Je a\Eٳ}}}uCT677kh6Yp\hqՆ d2 #Eظ|KJJ\J ͛7{n&B!jMQV~zSSSEZ F\Y,u֭_~G:{Zk(..ri`Q[[[Fng2r<&qv}ȋ\.W"@80X`:HܹsÇO:|'&T( "i655|\#d[C.'{_ ڷoߴ>PXXXR% ^"t:qUyyB%رc.oEUUF,!#ug, |WưFhoܸ#e4V_OcHպK&{ EW*zrٳ6mN˛zBHXa|\UYYhѢU˗;;;kjjYqd `[rN/))yQ$e2L&۲e T*UGG`T*S'h48AzfD.s %.usQt (RTFV4OJKK# %c@$m۶k /^huuNhpSɍp~0LrssXŻ"(//9$I\j; u:\neeŋQuĉ;wFN# ̈P(|Gɓ;vH,)))))(*4:}T*U*Iz}(sϧ[K,iiijӻGx&qUGGB(''gŊ\nhh߽{+6@X`d2=(Vz{{[[[u:]mmӧg&1?82W۰`kYBv!s=$ZnjjZjT_;ԍAbUϟ?BFdqq1njkkqDZ&Y`Zpze$!K8$YZZXl6tԸ X,'N(,,ܼy4u` Irǿ%e bxfZnkkÑVAAAUU\.Gv… c~I\% d \Aǣ[/4tyݺu1QfN8AĔ^u K !kjj>'lX,>|WTuuuuuu999rxWm`1VfffEET#-Z6(:w\ccH$zgN6`ڦ7]MRu늋S0 :ybygfA(.XK ,c%%%7n<{lQQQwl6niևDV&`E'eTPPFmMq___{{{0*++ajiiqƍcFP@``[z`S  8 vhnnƑ\.EZ ƻUp`)R4Bw h4iWa1qw.X p W^yĉOn($YYYYYY)LHlLpP)s=R Y9W'% Fݎoذ!NM㇢G"xV$-X5eA¤H#Bp۶m^CC% I BP͛ׯ_ojjR>$I]"d:qЪUR ,..,Zw WuvvnW=ĉy M jR… GqUeeE=k %Tհ5AhӦMK/s$Id2Lp~&ITpIR\Ei: %%*Y]]= *vq*@`"IrΝ>q޽{= FZ_9NqqNh4vtRP(f%Um!(jootEANNΊ+F۶m[G3ǎ(jKnBw) VPPiӦӧO_zuv|l8(KuiiMt\E g ;::Rd[ ۭVC{G.6.]Mu._YSSח#q_q+WjYpƓ\.G$YRRRRRiӦ`颢h"-r Ѹt͛7Wŋ,a*tC3a6 ^E_U[Hw͂?޾O>4+b,;v8t?ϔj3=1EH,.....^~}m0R*r|}{Δl6Ѹqi8ih46V(iL 0H$ҢRK.LZ(:vAzJ._pAR-[,,PbxӦM~aCCCMf(-seXiEn  UׯJ12;į?&@UWWL+Wםh M544-s%V^zjͦh Õ+Wpwħ[ 0H$z{{q `\aÆu.]׾!@:|/.{(\ •+W\2U7NH+ p2P[[[FnMWJ,D"Q#nnn,H$mo?~;Np`]vE^&dzLJT*dkT;1tvvr\P$(V8vf{gF.o_T\\קK V@}FleB#j[#&c*HBv܉RZhi *VP;uT;sy15koyq539i]uYǢ@J Ғ.G4lCv0Np"nlasyq= *HSc$ﺾ_2 rдX 6@9Ue۶m\*q(&瑠(j407 E9NNMAt$HXܹs鲹bC"I q^RiaI\XX`urbQF4Bq } `P!EQ )z˗׭[d5555>>#.W>8%L/ x^Z~b)++KqQ0LGGǚ5kZ[[AD"V!% d={{|PHe>΂m^}i6dadp8Z-(-`=55j`u P(v2%%%|J%Hgffѣi((:g î]n7aL;N$pf-\edFnw(jǁ౱1QD$I$BX,BV @`xxRP8%MOCCԔn뭷p_1}}}.~+@Q93@ `[(zӈHtU2B 4M_pHh07 ?(ꫂЙJJKJemmmmmm,#IRV`H7ǰ\SSc6~~:;;iiiچN#ފBr6Br ?|0_VKT*A4XIt b`H 9~]UWWat``Q[8:: sdiZpX烫ViqKr\ ðUΧDg`Jxfgg*,IP+LMM8 t:D266&_$@oO<)KEbX[[LZlD.J @4PZ+ SBڼys}}=a١XH&ky((b.P`AD"9pӧ:w9 A`#s6W\†L/RZfyYJ L ~ ,ZVf&M+|x]ؾ}n@Xaz{{z=h@"رc#kshZ[[~5OVi4MEQJKק2뇆rmJ|1~?Uze! zoܸQSS#}t(( cϞ=Euvv;[Ibs%2 (-6ڵk@iaaJd2 ;-p8u p_ǻjumm-e!}Dp(zw}l͚5---<ְ,@/ \4@9|OO_w{Phnn'6??,X2v \DШT122իW{{{ AQTt:a^t:`0t8Z LD"Ad0l,d "ǥ "=nXcHt::.)c6WHDՊ/Pp\!VU J+a0DVH$Fz9 hʕ+J( BEу~ǟ~i"tmN>-ͳB5niiQTl1p0{]OOO#P(jjjwhZύV`mݺu"ex `Jq=P`ADpm\"nAfs_()++K6fCYu%өRzlhKx<7oD8xqɍVuѣGZFQNWUU50024MwvvAǛ$IF#8/[ Yǽ^/I.rOb|34hڑd$Lk |j (  [lIJz|cccEEH$rΝg}vϟ_[~= ( o\.WiǻÇUFh4w!/OQjkk{{{5##t\=a4MOOOק؜C&֜ ]D"?? ]fL8[YaX__M.e9;@x ,XٳgO8^:B6W{Zj*$$ a@WaC"IC;0-Xz&X0 "V@|g::6W#00<dgy&sE `ShrrMMl~ءT*kkkkkkcI(-JeZ eS¶2"EAeЇ$u͕?]( fBQ0t(J}j#IҥK( Œ^Z1>oΝ /1$dD6W&@|llL*f7y㙝EDP<3ӟrt?-J+{^$].R(e7X.Rp+:NS9}E "E6WˊСi:TTTdl&nt͛1 7u#"YzZ d(-CCC˚&? u( b% ?~ՁN>}Сx~p]E]jZv-xg6dz*,,4Pi-400)˗c!4`J([Ȋ ">mwlt{KSVo IDAT8 ~zҡi9 Ңi 0 0Nw"@RIRߟzccc5559SB!ߊ@ XlsK/g,))yD"Dl6[@tX,2 (-6DB (F۝VCVrRpѭ$E H+E>7|s'| 8V0 Aņ.c /Le7Lb5GQbiJk8޶E8>::EnkkC] B ,8` TlJe}}}gggOOҎR6$_WY,m۶-WW`rVvt_ (j2L&LLLDh!ɔH$ X===ӇndoX, ( " \p麺bl6АV]v|@2RʶJR*aVccc(qIA)Pi!(KO #;8%2__V^.UbLtIJ6E ``EQ~(-ј!`J AJ$.\شiSifP`A".W(677:u^~_*^10( A Ů]2};M9UZ LMMp8Z-㹩pll'Nofi0 "PBŋdR\\/:Αo 0,RIɺ7Eu:NJ  YS!(bFZā!ȡ"Xg &(tt DbǎWb1G8U,lXy|>...Z9ov7AFQUZZ8dYCDX6W[}{ Eу~}ɓ''̅ l<== B1ͼ.)'+AQTTֲجqð,VZ:N"P ,p K"^["p8%mVL&;pٳgk͛7uқr6dU.]r:*Jd0%$333sQ( lM ,\] ba?|||<`0*++GGGzd Bsss۷oOK,(VWՙf 6]ϰJ LIt\. Ls9倲2 t:] KM&9X6Wxt<v) D*mWpe!Ӌ1 h4xtuu~믿D"L=~ b2ds,HDd߾}O>*-2m2WZΝC"qZm0FY`9~@,\Ch4?iUA P(z) ò;~z=\n2 A`p88VZ U[^$I)H )z$Ei4d(T^^"t2-`0HGDPTUUeUqt6CJ!$v(..Zz>siPHLhHmeP@`,Ƚ4}Eo߾IowՉbEyioAU[n@Q_d#v{~~~V"8|QQ?z}oo/l[. 6 ,1$$\8qB8ӱ1$i>ȂhKKˇ~oؕ ]1y^3;;MWf4pi\.R(-w`4rJii[0 m# X4 Na(駩Db1fgg7mT__avX,|H$ILe2X0L[[ۺuX_b6{{{J~ ^H$q֭Jnzfi\N>DUAeV[[[j3w&+m(K !ӋVaal^BiܺuѣKߙrZ=66A|n#E XU!( Nq\Ɲh4v~?Uz^B.UZ4MAQPZaezUUṴ0 NF( +ھ}|SK(n?}U.G&f:iVimܸD8saUu)H hs^WV;h4~ F$C\nb0 J jMyJ͛ SB1 `/傲z4MONN>3K?]6`"YZZ uU˭@Qd2L&/]t:#[- r@A<okk.//饗Dq} l~࿲oXmfXHW[F~?͡Pƍ$I8?Li @QTtq$UՏ?(@%zRtQmH$,yc{ss{g_?sKwϷsNkJ"p\.ojjBQ`0 Ʃq~?PZ` mKֲZ~?<5"<'|WEdDt$dRl Ů]bAQԩSu* L ]]]x|ѽ20Lr8ZqViL~ض\qA%<۷o{zE-,,d]UUUQ5Hu:Ё< [pU b-N jl[. D ,Rܾ};KRqXO gϞE(j:ԱlphWѤr|E⦦&*v;ס!^MzSG)X?]D6Wr\\@2Irj6W,h N< Ofa]Ѵ] d)o߾_j r8c#i??`K7D"|͛7qRa2Xڵk/ =c7o}#GvYPPg^vO<188x=ѵDA^^^<qFee%BtNLL9rhORPPu-[mݺak׮ q]TokvvH$Dz)k<x-l._wE;ܼyABQWWg6r3gRiZL Cyy^+8>::, ߵ@L LWD"H$x7LB(bF$P`AD`sF^/@V]bWl0L|ETwvvWWW!l߾vB!epp0 ק mK\Bb{Z@i\W޼pJ(|uh[[m B`'G&0,Ul6קjtz>p ,ADN'iuOm*-ذah|Kpvb ի/_^nplIpðu $;vdC'Oì4[ %sHL<mKLfX, {J+N)!EQpJ(pQXm۶꫼  U l{>~T*-))DO>tP&^"g)++m%Iwww<?vX.+h[(j2L&"UPPPVVm۶]4,BH$pMio/ 6tUe۶m|y(P`\1 Ln@Ml6[iiiz75!H24dAQ 6Y?  ikֆ HKKK_(mKVi1 3555>>*-2m2FiaG4,pU<6WDfuUUUa@~?AR/_x/t6|>(xgzztg3ѶDQTt:G(-0%$Ir|y0P`e?͕Zniil0I~ʴ)s(Sՙ{d,K8js)H$FzfH$200c+e&7J!$v(..Zz^ 0%tP` (X,633ÙU,lڴ3LM4&<6BZhzH$?qiE_|Epx,ǯR^|E922tb}ےUZ d$K.!i&OK&r|Aˎ0+ *3;;MWf~ HD#TTTPt:Et+d"D+W|-CꫯM6L] N  XFooolb|6m0L FP$IrAQg}vIڰJ`0 cq@$Iii)K Ba  d͕jmhhH jkkkZ5dd/ٳg?sJ`=zF^i[!Ӌֆ pR*pJ(XX ]4}v<w'rC(AF#5  86>3Hjq)%h&زzZ:)`K zMNN!vF*׫hxo=a˖-pB* j>xgg'Ǿ Dd2PZl]i)۹s'/@X&;wn6Wl.=ah|DŽgL4AEAΛow9"(z^~ȳAZ[[.ADҶDQbX, q:] ,Ybl۶d2 hcccARY__ח(fɃ * (L&.@i75M&S? (DIÇ;c[$I.,,JA,6~F OHeH$rp2`id2ZVi566B7n$Iغxa. N Xc6W x^Zvb)++vl.hnn~wN< o+W}6xB*CtuuzKh8L3 V6t: ) ,ǻoQ"-~ABQUU%dK dI2:`Vf`kWWW',;ܐѨvUZ l@@;=(A6WX '''UaYaΊSBVNSVWWW]˃hήՃhqq1Pl+...ZTZ*J*p7? z<|˖- /rRbcAB1Y, Bw8~8YTaܹs mIdjRY[[[[[^RTVð(-EݻoFk 3|אs|+((8yfknnfe"]y;wb9]%իW/~ 0c޻woM;Kv׿Α6$w6l8~Xwy嗳uJHҢ(Ma!ө)6l~:cq `q/۷ooдmg|@~\=pΝ?\D$S?xXayymhno{ * IDAT^ /?t3hD"|**p첱2JJJ$ +WJKK,a‚OyWJJJ:;;e)/_V P`q_| LVʃׯ Ah4 uJtJ\Cd> jea4B߅ a֭['d_ƿ]dCtttd6H2P`qث(WPP s< 0qBD"9plww7ߵ N'H.Dd|nzWx0ye)_2[$ (ʚ5AB F Y :f||]h@QðH$w!bԈf[XX| 5{F _K4 [nlM T*eAjZ}ҥxb٬V<"8߽{&\;v䁰h|"D^xͶ5駟6 o!سgϙ3ghzܰ!?qd? jsgÆ /_޸qc^^ކ ZSO=e6Rk׆µkf`ۍ fϛL& .$ zzQ>7]ZJ"O$Ikkk|x Ȃ'4gq.K XOرOyye?k7o??aÆK.رc/((غuݻYv'&&,@ݛW'|ի333ЦE"oވ?h4z1Y֬YsuZO]Pggg?) @ ߽;pF[߽;pʕ+KXe bȈsRiZi޻wo^^ ׫j:׮]|"8ݛ] FFFپ};ߵ0N*?iYYݻwYfjjbk $+L&yҥ LNN]VRUUU8pW^IA^1U zb(z,E0,ˆE9NNT*.G~':LF].FW$#hp; xܹs333C$:ΊJ˚I#k~Gk6zfɴԩS?~<5P(tcǎeE4K|䓀A^zJjhhp8###wa0nwvO A$N}}xbil6.(vuuYѣ)I#^dL0>aaK(-׫h`Ht::.RflE+W#\.$a._<::V[ZZRH, ,w(jX, 0@ 2 ;i`?O?ry#N2*J"auֵ]KPksUSS8@CxEQd2Қ^~V5& EQ0S#8p?СC|#Pq<[===n:zhh y\>88t:rcR_M5P`AUZPƍ$IcޏN0 p)G\.߼y3AXD- 8Դ,t7nvYXA`0 Ң(jnn֭[Νq`09~rrnoٲ PAJJJoJF۷Z`-XTlHj@PZ|gq|zzŋoϜ9sD"whss3 |"P0lrrakIWðw!a?'N,W$1 ѱf͚ U$RiKK 0SSSA`0p8Z-L RY__'Tfn; e4_R))a<?wLyy}Vpgff'''A EQNAc󋋋Vk*-FQTFYڬDI$@`E"?L W`s}@'wR=-ܸqݻ7=//oÆ Z!׮]o s-Flll,XwmˋF@ZVE"O$ѣGs=}$BJ7W\QTǎS+x6^K{ | ,ӹlݺuݬr}AAA$Kܾ}(\fh47n他155+ k:Rݾ}H$r*++򓟬Fފx{4MG"TT*%IWP`fXN-..fGM)vQWWW\\w-⠤/ \-Vf\.OVZla.(={ahiiK/w-+!9NZ]]]w-%|;wrZo!d)x>r>4d֭6fr^֮]+;tpxǎyykz^t20gΜwޛok[ WCAA0˽%[1SSSgΜy޽{ݻ}rD̙3p]QH$H$-N.x|OOO.R>Oto.{D?7Į./r'V8 XapOsJi0 0nId2;H$Fz5%GW7AIZ niT!#******@4A d:k־}@oVѨX֭D"qŢ"qBAPu8jhFd7P`A`2Hi_qVk0ĸ%E{7~qtz<f1~@F ꖖ89>CD H|piJ+??0(iR98872Lѐ$)`0sUb4GGGCPz"HGGǭ[*++ӸFP`AJ%%%ܿ46 @i$ID~~^q\DJf|+WnwZŸFQi4sS pall,kppʕ+2,]cAo;@A`$YiMMMS2&IJСC~{{ɓ'_mڱZ&?rZD<[m/^VsoD(D"W! $+-ájqҒH$8}twwC.kd2Z(JSx<~1~nw Xeg(\pw;::iiiIB X|piV4uݡPn;bժxdOԸ\.^0!O ^xMM 0% +XiZ5߯| EQvWS,z>n SiUWWΒ\ީ) xTEOOÇ pԗԯ$.O8!"$@~h4 y>HXǽ^/I.r) , _JfMMM U^j DvY2qN)a4mkkK" Vg93HzB҃\.giix f#t1wJ͛ bD~SH$oիW/_nݺ hrH ,$ Hӳ!ӋVaalRi(|ԩ^{E8S¶68'4,[\:t(soAF&o"\n7 >U\\\^^WDR\\lvUXXx޽ׯ_~}nn.//oƍyj:/'񑑑M6mٲJGFF݋ad7(F"o駟~"'|rͽ{۷/Nđ#G2*;X Bwyg. d2i1 ~k@O 0 2Ϳ(өJe^H8T*0%ܹs'e9z)aOOOlA$qLEQbX Aiz}&.(N<)#SRRvy9FñhJiEN"dHh49+EQd2ҚJkZDQ d={{zZ!cFGG}>_MG쇜cd2Yii)IYB`s5??ȑ4A/ā P`A%|piX nܸA$A dq2 ccczņ_T*D"@ Dܣj`4U*\-D@3X> F ( *-2Fo߾K.mٲ%EqeJHŋrwVkoo_~y֭L\-ɵm 'G*O8JaqViiZM&pmȝGGGǡםv7 6l011!J3jsI~!A͛7.D(t:PZA`0p8ZA4ח%%% .V07 Z`uVZZ ,sri={w[nݽ{lJn{xxxbbΝ;RaEѢAD FFF֮]v_]Pd x<~ܹׯرܶ}^feag޻w?9oa? I#J z$I\.B-':WkwQP0 L&zA;`m>|vl6L}C3 _3\.OVZE)={Pp8JJJxGvYYB۔ZK@af.\ IDAT +\V2*`$a@'''.$IVZ$I$ Vaal6L˂Ç}ݎǏgQ9u9ws ,asPSw?Cr01&$(H !H"neRKcܙ;wݿg:ŎkJhSĄ '&iB6h0q5c7D'^R@nn8 8,^oX`G=:L@ P( t:Fhi4OKKSTsss8Fs\f*vھ}"q}+Wi& / osU[[dCHT a$x&X ڬV+ 'Cɤ566f6Ϝ9s\.d2YœBQT( jvttxzEJR*6WA~X,nbA3yK͆fƟ\ӓj5C\.7N6 *fArݝr|݋{vZLa耑8 `qt[. OP(0 s8---8cFN d$`\/BڳgOh7dK.QU%H  Dj|Pg(ٳ/hoo?tD"ٵkNZd"Ld%8N~~>aW Xr%em'M&Sta$,Ud}\9SWWw^{?d Ҳl===K1il6D__۷w*Hl6h4DQ"5,=KH$J1&-E6Feeeb8!ӱUVVFz'` Z]UU}"ʕ+466FQPՆY%8`Q `1L>0 AٴiDwwwff ܉2 &Np8B0*$w#dm'GGG-KIIIhW #5:fّTh}}ѣGϝ;;}H&- Ο? իKJJRiuU\\ߏaXKZ (*CB!X/,BZ.] A>6  ^Z*K Jh2^zt\]]]BpΝYH:(d2LFbvEӥRiaa!C׮]k6W 7U"*xd0)"h42 /$IyyX,Pqǟve1 3t:],r L&tR*bݔhyVkw$Ԁ@ęfX crλPH$ğVl&VaaaCRdz`Ϟ=a$N8*H(kڧ0P>@dX/PE=z믿~뭷d"brrRӑI'77W.lh|bz A,ٳg^o ˂ r*!w YF:.]ڸqcԞEQH$Ȥe4ff'FQT7DD__Zʪc*aGG#qE `ȲX,x d͍~Cvھ};9d2CAYYYITNRqĤUP FqAp``0P>@{7B@DkG9wbGPErȴ^'-\.J''H0ŪUfn#q `0 AxJTL&㽽ZLI ð+ʌ X\\\*r*aoonjj k׮eee544VL&Hom`I"ð|J`"zppP,/jnDY=0lppppp2]RRM@aa(9A`0tjh,X6W7oɼp8|FH"tB}p9ظqΎ hҲZCCCCCC 9Aell,33&k_bm&/6r9"F@3<<<99ꫯ2 FcccOlvLfNNBP(<q0::hW\zO?t}(. ###rqձ^QPRSS/_v^#q` D aBpQ̃%*==}ΝgϞ<2v1 it7337-n?}t\  6fC_ @D8~Ν_|1 QRRRp8sssƱI qzUӉ H__T*3XmlA^z%ذ D ^Ç/O,#ɾ;Atzvv69d:%%E*FnosU^^cǎ`0mqZ@bZz*eEцsν^"tttܿ_^xzb4ɤj*T* e2RL6W j6XPׯz! 222l٢T*GFF֯_?gݺuj"d2Ai8::J䬕X/<u:]z&HrB@9XzƻT*B@ [j*JHr\.ŋB`03CwE&-rLZKU`)..( P`0¥-{/:55 :;;7=>AOZiNOZiLI7\xYYYZvl%$~ApvyW_}5y7o666T2M&-h6m6[OOO&-arݻwđ8Rt``?( @QHFzbYo Liii^WV5kz9O`X.\PQQaDQt:gvhL&srrRժT~i~~f'@]~񩩩m۶m۶-#v֭>b\.y,-  {`ӦMd׆xvϞ=럠E@ زe 9dZwwwt@PVV&6W|>ߎt俛a+vZUB@-XJ8OLLK^=E=zܹwy'_:;;9pTVV߯C82 iedd-Shs())*!A -;w-2blZF$777]v=qI pܸqbX+ 555uՑ^}&@ éS/hX(\A?~<))a %  6 7<?BaZ/]$ 3&2\XLUo$GinaիRiIII\cI6W ݾ}ѻ fBepw:֭B@|OCŶCDvad0 ϣI 0 !dҒdOo1j6Wn&`PՁdK.APJ E1 r^XJh4WT8dsrr7\zu1 zHg0L@P( q`0h4F3==`0RRR(gRTL&s߾}?|!nԩS|>޽d2GFF2336` Pfllfgggz! D͛7 XUaZhܼys0{ER*+++++q7Vuxxxhh2-JSQM6Wy#lhL| b A`#V#tnR r 9Að(AC&- L&l&LG!inkkkx{ݒ(ZXXjJ Pj|X/)r_Χ!A!dx<^{#(ZRRRRRBb1dZj\.ŁO-UZZ|TGt GC.Z, ,5F#͎@p8uuuO{gG,궸FBQT&d22i]vLZt:]*9d:\-@Fdgg3L P"]Xq8'LV^^>::J~Lv]VWTT,cXz>֮]v;yhbX. COO y /ꇃ\.*! ,@ry;v#t{HϐxBqFzPAZrmܸqƍdҲZCCCCCC 5'dw1  z ~iZAt (Ph4ZNNF ,'߿DaJNNj|>SuH BT^x755eee=aL&3''GP( `h4 #%%%+.//o~C5i42UUUT],CBgۧ>@kkkyv'$z#9۷oWTT9Cn7a=bX7端wF @s0!OP8K. >ҜNࢆ?({nyÇ/"4C:n{#y<\q8rȴh$LI+j#~#P F1ރHF"~= =eEcǎ;w7Xvvv8&o Xkkk8IbdfEI#f$B 0A(/ǀL lٲET.jJ2 {#Ehlx<^KKKDqҲiZrȴ\.'Kizl"Nc ay$,]֭ZJR$?.kppP(Fn'?nwggDii;oEQD"HvE&-rtLH{Ed2sssJB  BPݳg_CCى ȁ"896WQOZALNNt:"Ldj&m6ZM@ AZz! #tN<ꫯxd__͛7$EbAD__ZjhhEPD"LZFl6l%-&˕J^B `0B녀$HƤRi,ZFt <_mƟor0 3L===L,S^AHgp8B0@8Aرcbbw}|gFd佄&)ʕ+.\XreʂABQT w*LMMa뻻t:%I8P%!mll 0E8psν; 644DY !j檠^[B$->P(QNshh?BҥK7nw]!\*a\E?iC1 ;< iii9`(oX*j*!X,X`qp~zmmmBa2rssLt:J\._n]CzB/ m-HZ??VXXXRRz1Ã*! ?@j6hl6[C9D"f /d666Ƥ8p87nذaCv nA1̜rBݻg0FGG ݻwWXr}JٶmT*ɂSRRy<^NNNL(C?xo n1̺Ǐ"v}g\۷/Dȴ0 ð!rȴ\.JQ:0 {N 3AA"zppAwIxTN=[h'-ǍF&AؗiRpl6#z{`S^sjj?'z,t(SYYy߻wܜ{{{v{V\\ v" eb, ;wފ,?jKU4(htjzժUr\,Dhxk׮5 ձ^Xv&tӧ3_\\?99fo 7G/L&#b\gR IDATvLZt:]*FmtIIし  AL JX^^><<X8*BL&dvF:.ryT*%&,,f &si>i&G{1?S[[`'##c===###Nm?lsz_([#qx4i\.VkXI+!~ &j AAcٱ^X.wT()SeQ˹U@ ۤMMM Deeea& 2UCH@9b5kܹ??b4,:33s}8_h?0&]>ӝ;w>skjj͛;vJT*)??55a^uN(++J%o}VTTD( ,7j}vKKK_{Q}9x`\Aq\ aׯ_\.D*y7ł;w޽{N]/)),Vgn~ޅ#ss+V﫪bX0 ꫯ侾?Of OxZ[[}>6 dBdR$@҂FXL&Ӌ/xgD|>{r5 "v9r$--%qر۷o?t:=ZWW-[;wN555E]LZVubbI2~-<|ܻ/LNZǎyѣG׮];Dtm#O>:pb b09t:kAzGǫd2ݻgLaĉ/@!y׶`<33 Hjj'4MDBD[[ (ٳgʕAPr'r:Gq8Rڵk{DB޲e˒h`{#BH Ⱦ}}H[>!͛_E&-ǣV@n޼wpF.pvy>J:z( ---dтY^B9ûp4_ ߎ@܋T^y啗_~~Zp4|w_~?AR8,<N>LV^^>::*8]]]6M.޽_H$L&pA>k V/bԖ4fx'X0^ !i'x<| miiAQ#?{Kh0zzz^׭[O;::vR\ )V#q{#Xqš5kJKK/]ݹsE9٫n?쬎?tXׯkZZ}ڵ{l ħ;w466D4-''GV\0FRx"onn{1IIIZV(t `0 TWW?>1΅-d裏'iEEE[[[TM&Ӎ7FփeW[[80vݼy"@# ?oݺ5JT6'7exϟ>}zhhhbb`dddTUUݻ7=qd=$er#ԩS69&[ZVT"wgjkks\}Q( Mho^ D{#Hl@,YR\\,l/ @x_R8.5A_\m۶̘L˗W\ƒn?|EE[X ȤUZZ /dffzޱ1Vhn7R9juZZU*U{{;ljjZԦ p:NsÆ /7x|h2 Ѝ7\.={pF8bj.H?dols%C~p8nܸ̫.h۶m^ T N(*H$ɮ]vj5t:],rr8I t v% brrrxx877_}Ubqrz<޽;k f `xOZALNNt:͕2 VxRyڵ}9=:vcmX,֚5kT*Laa!OGNX&]E#qy `d2srr ͞1 "b\p!~>k6Wϟ,(( {ZZccck֬|6"rYYY^9H%Bn 0 @$%%X& X/-q8嶴gmnݺ`IAK퍄|g^6ὢ`e2P( #8FLOOh42;w455Vꫯ۷aÆǧ-h4H4::`NfffCFDrD&^x!33iZFvQK.v%A={;ojj PA$7750̑L /W\.W_}%a$ $U<))))))!bFNVSRRRX,t:rBJΜ9xm jtR~~~vv6UHOOgF8Ax0AAEQL&$UVI$|Hvq<˅ƴX\ظQ*jzz³DZO  Dݟ Lx2&JɤE&&&T*$ `uuuYYY`O8155E IMMEQiiiT!322bJ.'nS|޽{c|< (J$DBtVl6Ld\"9 j5i_YYiZ233)i\.O*a[[#qvA*VTTD":>11U*?l62رc'Vqnǯ]V^^0{ChWNLL=!d0++^K_=T,LZEEE,kbbBժ~i~~~$-򳶡!&Z éS6W/"%y`T9J!%'10 AС(QSS2M\.J'ˌݮV+**a Zeee544Pۄ]&RҧEQTjX(Y[ly<ӧO[z-;I֭[t:=##C,Sr'~x677G8HrA A{~DX,'Olll\m`$!cX999ׯW(,kjjJ׏$ؐ鶶;w466R>/0Jd2i4ZNNZv\? Yre~~>%ˋ @ RLfNNNyyB`333att4VL>k=O[[[hmBfY,l64r檪*e0ł@đI?dq2iC FJJJ׸.#//oΝQ{R~[n*k׮q(y+C8JJJjBp)x<ߘLfcc#~ Hrȴ?it:FC&-X8~xRRRssst>k P*ϟ_jUsssAAADD"h,++ MMMa0KJ_OLL曫WZX2 `d*--}233^ؘVh4nEѸMZJj644DgˣmxU 9BqLun?4k`)@,EEEUUUsssCۍ H G=`0\x1j="*^ʕ+|>?_d0??R8 Ee2L&#bFNGH$yyy2,_ȑ8=܎;"\7hsM6MLL#tB^H$b2eggS!F2@"ncxtX,$&Ci;r>Hih955uѵk׾;!_GGQU о !qFIl611166Rnܸ1??r500066{܈>ѣm^xᅈ>עX,6VE"Qh5R4;tH%BD"199Vl鹹r\&EtOt)=lr|1٥ LPX1777%˕J^N0ALZFl6OOOX,|9r ~BYq|˖-z駟hC8v{F!r$|`&( ***ZVVOl6`P\ls7߬Zq>F ۷o0==UBh @` hl6;77wÆ l6W^%MII 'iiڿ7o.))p~ \-)))+VPTIMM|rvu:0AD355a^uNŋ-\o|>94 ===ݻwiݧF/z?H-)Lb_^PX)^?22!A/%%FÇSi 9B{뭷U~Ν;aF `0|~QQQUUUffį lvyޙ n&mB@QT(U&_hs`H"$xhjj۷  htjzժU$//O&-v;::_^^^uD-?) 400    rD@'@"ncxtX,$L@D5Br9r矏F9P" 클o>s&J+++i4ؘJq<}➖ڵk~jF!(|JL& Kld{niiiD0!1 :_D)D"Cu:j5!2̿mt:;;;o߾]QQcǎ~$bqZmLNST%=X,wn'++kӦMH$Dd2ffIv+W\mܸptuueggxg>^PL(W =ϙ3gx<ޫ`Y!݉'fggUPPPQQQTTbv|MMM^^^8C(&&''L,kdd (,ϯsrrFQXo1(fQ5L^O^7%%eY%-kZzLfQ088#q4(|9ΡҐwPx<^KKKFF SSS+ʌ X\\\LnUS(ùϬQ/oܸ1 OrmXt:%Cnsbbtǎ_v  î_ իRiII AÇl , 8Um9NeJ,Smmmn:x`0DZg0N:5==7yb2]^^P(l 9dZ߻woժUl6;#hZ}[S46mݺu*k׮߿?333O@ `<{ 0fA`zI?dq2iC FJJJHGb+V [F5MVVVD`[, .H`Ժe IDAT\z \\xJۍajJII)..OlĵD[j*JHH$b2#!x_TTTUU977aY=t,^M c͚5*jffijB0555;wb/x(X,Z]QQ'ykkk#7YEQL&X,F짵j*D'ɢ,BbttT,?H϶ZG[+[zV8NY٩G\EڣIncjtX,dJuׯwuueff>MEƨ=##q!(\:ujff9tvJKK8Z7ph4TZYYM&&&T*Ս7\"6h4#t(Hbh 7700011gϞ s`zmABQT"H$rȴNZfNCe2Yivuu}OMKHa`0͛7G@9X$>988XTTP(` juVVVCCC7@QT$D"2iFlzzzȤ%GBZ?D" d BHIsHb4ȑ8晚yfhm ;wt@PVVI O?F:tʕ+===s88@#曫W+W744,~4fnذf_~իj~z))) #'U*=9˗W\γH,Vy~GahbX999ׯ'-VV]v=6bbF$55E˗/s`87nna$q vW|>>ÜN_~y֭m۶޽{Iܗ?i) 555GFFds=wƍozzz||\*BǏ?FQ^@( `8~ijj pҥKgΜa2MMM! ~srBfgff!ӱMZ4M$]z.--}4 ^|`V%loosNSSSl$@z6W,&mLZ BPx<ɤjqg0)))\HKKSTsssv'nZ~bIĩˣtP@ 8c0N:vjjj,$&)It:FC&-iOf5Mff棍@ bNhX,`ѠM|'\.MUL8p8f3a>JR> ?|nnSpݟ|ɢ>. : `hN8p88:, .6W2m<bc/jmm o?"E:::Fc ! lʕ́WE裏J$~>*=Q\E FKKKJ1J?|>?{g0 FtUB'%y D`0*QvwttnAJ}INOLLzb١>$C 5kְXa.6f08gXnwOOOVV֭[b0zzz^={ ElPD"hSSSn:.bbϺmܸjvwwgff]l6?gϞWo Kw}wͦWX}۷ܹ>ǃ6W1OZn"\.J'G]w?|Fq+NvC8 xg2>o*Jkkk[ZZUX|D")..&i+W<2l۶mͰ7 @<@\ڹsݻwtڵRb{]:277 R*zD{cnaYzT*-))y֭[gggWUUE[,,dz޽ 7'&vu!BQ__e8D&-:11<=is\Fy>@ ~UWW\n=CͶ޽o F@n7aI)7z_~-SϟߵkWr2_&$'gxs}JVA&-jr333ӟ 1P{`X,:Eg))I}2vODx~-CZ RbEɫWÇܜ]1|̴OW^ybk[033Dh1 s?1w΃)oRb8c㡒@L\Icݺ574tg˖5 1=#ŗnE>'ޙGqe枵/Ԧ$$16xkO{z~f;b"L| O,;bvnmٌad,@ ZjjZ2RNTUI̪J)Ͽ=y 0cU?Zd!,ɓ'׮];ǀ̒3. 0!n7ps/.ތE\*dl~guKB48|;E/[݁QωdҾlgI h4p|Պ$EFFxp:IPI,b9 ۛa[Zl ֹsI Sjk]s7s-].{]<^S]YyfK:uA9z4#޳g'֮˥R]M||&B/B<[ڳeAbB+qnHQH.'ĄV_[(tҏ~CnrWs;ti`Ndz@F|҈ńL<.BA-X`e?f 8j~`?>P!~_pRU1HҹfǒE)}rORF !~N'}Իukؑ#ug/]۹< h"T& w#v[_U.:!QT]ۺ5h5^t#|h: sZ XjkJցsɁaBкu{^z32SgNHݝHglD&#]>Z+\|G#nD:b1!=o`e\LڟcꜨ`O4PRɟ?|7?<\:nkķyC.$;: ]gL[wP޽f4?~OQTN;m3[DLڿa'?fM uw'V9~<>)S1%ӊD$-X`xB_R& L'=d,jaBcG:QBUs&=I*F#GF6 G$]@LG?tW_)*יSdVkiu}ϝ:ptK:.D# xh+W?d;}}Yݞ$uvzNFUlJ$`" 06=W|wDj}+Ir$"#(hltv,Rȑ/r8T$e#щ dlC<.Pj?fsR +E᯼2?[9##DSO?p!9:W="WbKd-?}߈{r2'ci_ώH^iRB͟o-bpW E᯿pt4בigJ*e ]m>5lMM֡~}CCraMMN…D81o_PN](Y3?aرqdpX0 ,Kp\YfmR|2PE62==pƍ;6UcUpȲE.$] N?|WNW܃`OOjF[O7+4ngWWh/Cw[uؔBqr.lHDr%)PARE룣x:ļymޯLXO&SwPI\&UEf nŝpa}hcΆVHS3?_΋KJ=jN5Rz{wo>ݸzq$(;sP__tE날93Ku--vkhn^?<Ւ$vS/s\*qb(l5q1e\q]н0M7[eoŝ"A]Jnf*,IRx$,ᱸo,vW*t6'eǟ=_]\^HGgt4wC!oş*HP\?HD&oDA׭ӗ6ͅLRń[C7ſ[gm X[[J18VBT=\r> 2.փjqaxODsՒ%v47.==ۦ0 o3X ?ZLcMPHwzEhW8Eb2WR1XE:%ɠr`) (3 YZ "a,_B(/[6(Pnh(ѯ֨32B!,hQZ84GgV+Д%DžkJU//|xh'=,u.iO1*n/cb_҆ͨh2qW*z~EQjkoۧHhM\ +2XFv/~ !lVڵ(NpnhvrbB_ e2b0h\qčم 9*A 2_-.\h3*|D7D{/mD_~>7!ĝFKk!5WA^Ņ/hR -?F Ne RiiZ{cVǚH7-%e҄qpv>6qpA/m7nQ7Un㰻;Gہapۿ6ͤj) %Z IX*E۶~g\I4y>NKB^[q#;<_/id$ot¬nbb8$*288>.$ĄLά wT>zU}j_rj e 5ӡ^žiSOFmaf$M`6{,Y9й+S +P~$xgwMBy2uU(Oϳ,/VY}塇GD:: '/ou-ZQyLhGd"$ʵk]>ttxB+tfDiIy(q:I'R:-B$ Mcv;p ,j3{]ZӓeKnr1c QL!ܟ~ Nc` {hd:_aDi,;OJs:Uiw =(AK3i5QBh.qiϷo=uf }Fy6"QZhy^ڻw+ 7tBTJ lVs8q(B~. tTB,1 XALsM"4fO\ B$-X`x\eYl)[BjM`37=it2P }IDATX? 95dd;]P챤D1(tZLH$D-;v-'ڵI?s*ySCBUSK__j ½^\ J"!$0g2 (v;ev;,fTJL&a&#MLi\uTN'`A Q346*]*'.ժW ( ӓɪ={nAϥT~UZ0 3XYCwe"T2X~.lVrW|1-#~dą;-T*}bĚ戴<֦MG#mmRH' M\# +knv ўn U΁w6|t\g֬WM?ܰg"jl 4Wc(\i"!ăEJ-բگ|^98N$YI,Cɲ,h( ЮV$kˮ[e$ I(NS((*2 Qap4F8v;08Mchj12.=-}fs2O_'?"c}uRb 5X C/hw˶Pyv?j%h# -n7ɲ8E鴘NKX,j')FBU !b:̽0:zA%`߾UӹFR )a)<YZ?'hL__zp0vUf~b-$@ {܋ sFHs7s10X%D x@v-cSmm59K٬!@ܗb\8eR_Օiņ @@( † J*i٬ۛ4pV+AeIڪ ?F 1P NȢdYd$QTR)MMŋmVk.3iLLqR6+"PWI@ ĽE]e u-A`,KݤNB0B @TC aB aB aB aB accIENDB`gplanarity-master/screenshot_3.png000066400000000000000000001415251510662254600176450ustar00rootroot00000000000000PNG  IHDR X'sBITO IDATxyT[׹(} H3 Ǝc;xqm$uw%+m{{[IZ'ıSIp<q1c,@`3[HzlGQ@t$A:?. à;H < `A0 g䔏p:Zm(2(e(e9B7! b2 `d$p11,%,ST2 &Ccrb1$ >`@$I <@xq:`"nw\ٜhL&\>u Vke/Zfzalv Z5jꘘxOV #RiTb"'Aݻ͛9/y Cl,+8b1K{M]]trs+6kf #X=v/ /KČrۿ)MEQ7oj󅓷{9Zm"{~xwXpERvS>=iγ5LFC wSOdijZmm|?oF9I2,f{y/i4h;$9o]\.ӽ.DַR`Q_yyܒ%&[}Ҕ͟Y.sǰl0ߟ2Bb1 _f= rvcYG@PvW^,rs:\_R"] K~1I5kb/^aUUİ~NB Q'Ovvy<- =$|Ï=QׯSVrG2!:sfH0Ẋo?/ܳZ-u`W1*n]lyyB.'G+===^ZH.&d~oQ6a2yy{x(WUUzL 6"_k^Owy,c};w oqOGwNBl%<s8Bh߾oDbM]G*g4~==w"O֦-* ~h69BfC/OO&w|PpR(^N! d>@1`0IdX $v ^+*Bݦn3B(7gh7Q,,633j: Z[c6K&ݺ__DxН;M$8`v?Ǿ}xeلiFAz:6M9`tju=X@]5ߟ*otu!E~Dijqfr0ŹwoRJ W{YHDJ*M*xi/fyu ewȱX \^,Em2,`MO}}fo"if ErB/d$̌jo7 [߷{ `v/U1a c^߁Nju,>W0(e!Vfs k$!_[W~ppyylG*nwa=hNjR,ӉHr .$`0 w"X,b0Dfvnwf\2S8c0p&EEL&p\.g`52get־>+η R:qbY`WM&'sGMx ,r߲hW=eW4en^>g:' BH$"BxAqW B&W{9Qox^Wxv֯O;.&@N{i`2bB!!id֯Rx}OwwJӕ+׮mׯ#41S5Eل=x (ʉ?$y>ta_-^`QNd:fHI)a8"B&Xb1$ b18\` b!DvbqNi0P62샃VrlfTeXOr8 |y^B&]]ݨzX,Hܬ^/Ξd2utHAV}Ҩ͝ʃl׃Oyƙy>/Oc08\.DȽ";L&"[&\p|IZeS:ED$ <_>~7kCG=>E55ibyrFFTzzԽ{eݺX?{;: Kt"fb 'BDL +.%#'i._wuu[nݺuA^11,\r:X:]wXܡNWTg $\){x~Ӽ^cbX1;/By:}8zJ($7)?tY&RV0 JWTHtpFO>& X,Ft4}{|q@#*&iD"a$!d\cdFF]]͛ݳ HNoOܽ;<(zb^BJ.oٲeӦMޭ[l6`P*_vT*c0@H؋󋋅K*+lIX2&)rFݍ&]gqhtu-o\rhpHfiiQ>:ͻ+,Feeew4ǃOg8GB!gORT#1I~uO^WYY<н{kB m N,-@r:FchFC̸8V\;:BzEڵk۷ojL(!'[xbtuf'k׮;XNd8z}tԦV xL^K-{&? `xvv=򈸲߼/gՍg}-)^:gO/0Fc3fjuűbcًD"3R'qvW*۷߾};33p}c0_-"1>nXJ !$B!'b W^wLDA։|11 n{r6OokKQ߰A@xTvn29DNrrTt4sT~ ZV$ڹx?>gdph UUUuuuAppw]\m12. [6:j#Isg@wovAv%I$3xP:5m"IFR,.ȥ5)÷okx̍Soo/B͟΃y``cՄdkd:0`spM 0-V OȜܬp44hGB*M"a[,7߼^ĩ/~@r oyO.7Ǚ\_ e#{Beeӧ}Rϰ=GbbXUU11 Ac*tfC"ᔕsi*O~v뾮Mݦ?e!~UoFA[}ݥQ}4ڪw?^WWY.ѣr$ {f_^ָot4` rwV >˗_nWlI,).j٦1 ))ؑqc|Bgdږ.!kpЊJH`>w!n=?Wf{b{ d0\~k8vPkt XNяVҥB\]w B߂**eYs8y"pWq֋;4dCp Oϳu#W8Rm/(oUqFR9>~|: x?%q.IJ,[&jj]KGVh(2V!0 [p-ό& ^G^?9B!cr\*!oiM>21XO`ğr qZmcL1SOfsİذ)FB!!oj!>/\dFW%ב׿,^Sg֌8d0_1 TA&p/޿xm(ٶ-~^~,S*G\%:ߤrS }41IQ.hvb6B_6In|:E9qJ_6Np:]$=)6*f%K`ʧ7wvV á-++[fM S& ZАE2[,F)>6{AشZ )PjꃻM&"^/@y84+hjՍΜ##CLy1;U`dqwQ4]2zضmcLN4U(dH^"T%niѫTfuK_lmՍۯ_K&IN B~P|cjz:&޵TQ;5F*+۲%)rCBnriQ*t\G.V~G04dY̻Dnb"rvRi裑3AΛ7A$&~c:PzyB +nn!rs| !d29fݿ3H_1xܽkUT Lr2\ye#_VKUWl!hQżnO⌌{̿]'~u(FedD%0~XĚ51uucD/5AU))Qq^o^Tk׮=}W//}V,~<*j BlRy|-m8::瞫H$999tܛM&Gypkp1wW~X 8}zp!rr"@uEI$l?tdzoÊe xq#y3 ?莎&͟g?Y֔1ܿo}6`0ř#b^~,U0 ^ze* &?$Fq  IDAT\BkWEEB6IҳϦdMn_\jQx))Fxdx6U^~eX| \Nwac$;w&-_.f0wntvaZ+prr?EHDVT0ܳ')*y$M] ƃ%*בB󚃋5,Zp~h2dn^$Nk'LęXٽnҋD~8rh!(4֮PzgJQII\ط>;MMM|AjjϜ9c0޽pE"ю; ?~o֭/f08j}IŤXHr/BB.l6׭[K\& ^g1?_76KQūիWkkkssswήBB_ܿ+Ǐ,N}˗/SaÆ)Z@|sz|60`2όfƲᎢ o݇ZGw,cf&k!hQ/z]V`q:`ZhtJMdza8{[.]{nϯT*N7a^XP=(H䷿횚z***zqwkO PHL<e6;'i@hk4G,C1niFGmYYٍͥFDN3⸋cbXT#[ZZJJJv5B/J.,I[nj'$9 f3BLqZm*|cFE EIfs@/uytԶn]O>/@ {ݺ;woklc,6b1b1pu ˆӉE8NtfZV\6fXvr27:*@(:~xWWז-[V^= "++s!$ &T$}oېc/=t"n08htrld d>8~L/B.a;V{&sb n(DQNe9B~jH`2 &`d$BX IB \&DŽA`X><<<\YYlٲPTZt򷲳&|kÆ 111|ѣGw-f@"K$b;8dr Di4RVfs:.#p}v6AM0K&$l{xBzȑ#'(**NP^^o?urZl?qѣGyȱ@S `"wV jhhh]!ۥRPvfP(J-rrrg2p7?qA#G 8K}Fj'lo=66644999 o7`f R<|0?p=6c}+..F9HRRҁH<|Rm0c`رcb[[[}bSbb ,@0444:ujѢEUUU.LGFFbSb8KKK;uԧ~:`V ŋ?gyf !ގ0M9j#J/_'L/j=Hu̙k׮-]t?ڤRbqjj4p;<f ,@PuɖkNh2^dyL&y0I۶m+++kllon# yh/`ASSӉ'D"g4iجW 1X'''8q͛;x 0W |4&f1W q~6;BRP0w`)((x]==??gv.U__9` ̞ ޽{xN1A Nm/$I>k׮?s\X &(ooo_v ,f˗% $+**H7 ` 0cn9yәH3368q}+..*[ii}z{{|M()H3068~e}KNNp8spLo߾#G@H568X,9$y\tBN0#`emp|c1١` Lmmps?Tzz:Ù]_B?$ $X)Kǟ UB f,?ET W t Ͻ  B *ass|L$XΜ9XRR268~eggct${{{T ,DE---ׯߵkWNT*VҥKK,X,)++kii9z(EQ: |AΝ;=׼bg~; kzy'P/>Uy/0 Zo꧟~(ЧSTXrssFcB;W` b9xR{{;˝A,''tvvυKCCCA8# A@*ȑ#\.7}Q(2l1$Ta2N$CAw [oD^"*`0Y%p;X| ȱ`555:u*55J(xz@sLKK;q׃v^@ ի|AnnTݗμbA^%ĸ\Rimm-z`! vҥ]T*VU¾@nSPPP__`:(nii))) hv_:::B>8*}.O$IڵK \vMV? `a(---6m%B) Lq܌@h2w;;wN,rСRZb2,8tA^%t۰aCeeewwѣG ) $X, ZN_> rypN7ٲe˾C  njB!J^(feeᬎ.9993LN," ΁{>V+,##cll&6999@tW ,"-mp|%ybPkkk0O:YRRҁH<|0z A@$ R4%BBP*һJbw;,"]mp|###A^IJi_%b /vԩO?p 685A^Bd#Iӹ|2 RA@ r<냘P(LII fgp;h@ BQԙ3gKJJvMw8_A/:Y~~H(b$In۶ڵkP #ގ1{ݻGW$ah@D  mphmmJbbqJJ R ,"^?tmp|}}1 @@_j4ioB@b# bMt0`ކ9 mmm4bb8!! ANH aLT9r8p68^ڧ>Bw A;"$XcǎDB_Bd}d#D*zt `N:hѢ)%U[[@ P"*!t`~.^G>3!]Aܩ&D*!tw`fΜ9s5$IÙN"Xvv7v:tHE^{MR'HQwvB] dffw\.7V 1NG(;a p@@(jjj:qnC{ +IJ>99ĉ7oޤ;`r>h ^ XnaJ HCwB$X !Xb{VVV}}=XH!68{;9ikkΦ;)Up\%H|'׮][__| ,BB8ETZ֥K,KXߎGdEEEYYYKK  t@±  B 233zͳNNI faǏl$dj$Idv:HSETZ,XĖ,Yb4^ d2پ}FGG99 68!F^%I,U;^`@wp,BA$ɬf7NP 468T*dID"v: ,-o p8NONzA@P}BFIّJA;h S]]}%Ku_`p*V 1h]  HΜ9ظbŊ'|X!&233#ov:,w}lΝt( "+++1.Fw t>H˗/۷oʕG(?>w Ν;w*++7l@cRZL&;+..t}}}t(Lr$ӟ^pwWZuqD;ʢ GL_|<|?k׮v~tttceH$}vB`,f^j"ŋ1ydB1⌌X,/ |Gw sU\\jmm;okXjUUUA 3sܹz+Q*1ŋO0˗/--U0 3#JB&St_v?%"#´/8_I,x`037nD΃D$|X>%SSSr9݁ H۷#FGr84i?ЁY?L&tO={xϞ=  EQ'|Ғph;;+?YC[VVf͚Ddx}0"B7n,++{8##ƍ՞-A(jhhxW닋O8! zb*ӢTn.DÇ= 舼AL,'$$ ^{ԩS۷-/!MT;v5..z衇RSS.]zg﷌m0|&SrYLƑܽ"Ν;tR_A@+W.ZXjZ$IcZJ& }筭tB4{'Z]SSyo ?O/\V:~xmhh裏~D BHV+۷o衇%Pfnmm|FYxm$IP" @z֭[\.wӦM+Wsν{׮]p8IIIk׮}Ǟx`|6?$^}ըou<0EQMMMuuufxݺud0` xՕ+W(*..rtrzGydt@W^rK/(ijjB^:"R5{k }F),,ܴi|.EP rF0LV[[FΝ;W^}ʕ۷of@?x`` !!a999tG><::/HBptݻwّ fBh.].x >%^g_Z$ϿzbUB?ӿ555}gǎ+((ؼy3L,pQ7662ח&t8>d:\|rc i$I\rٲe uuu,p0U[[kXJJJ6inniiit III`MIW.((tRcc;w6n?:0ARy9F#JqHfdAb999MMMJ8}Bp֭^ VO>]__v޽i&2g/غuktt4ݱ ǻuV\\\rr2ݱtҸΔ@@w\ `رcAM̯>%%%q\BK]PTT:t ,(zիWB%%%v.,KOOϲe$H,((UYsOnܸ\ZZ o܅Ca'P*@֭[J6I˗/rJ]]]kkkii)L  L}}}###{YPKZ+"/\.9H${---={,uV(L "$X ҨK.) (: +)) H ŋpMZX^^ޭ[T*U~~>ݱD$/_^TT+¤B0H.jKJJ2 B =233\nss3$X˫mlllnn޴iC=@71{MM IDATMuuu&++kΝ 2l|$Id!@B?^ZZzҥ .444@aR(cCCC'Oq.a Jۏ>hLL ݱІd޾};===..X"+,,J P;’pX,\;ibxz }{PDH@,v 6zM,A o۶X"¤P"}a BRY,KrssT*,dIܹqF(L $X <(si4(|_rrr*!$X @aR^ NVtuuBPZ( XHjnn;D"߿ǎͭH$t?p]8رcʕtGT*Jw V (??W{`;q`PDQTCCC]]. [iގ4`Fx{aaaMMMssssssyy9l ޔ wmݺ>KTFT*UBq\\ʕ+o߆¤ AQB{[nEGGWVV_&RիWKa2MMMtDzpx%Kdggwvv644rX 5`AO $x졣!TXXHw Wp7+܅IO8QXXX^^ @hFQŋ &~RX YYY08˕JmmmJ ܅IͶ6(L Bd6E> J֭[Gw (##CP$V Ir2 {=JcZ[[fx SL$]~=***++X׸\L&+,,[[[ ,DpY8ϧ;"]GGT*+P(J;::`0y&}RSSwܙDw\`a Fkjj¡ή;4 ~g¤ @QիW^¡a!Gw 'ܸq `78we˖_>AVT* $t*a Ib¤lr.SOZ &‚^tRii)`0|2L  0ioooCCCkkkll,& Z}ܹ3۷o۶ j^7oT]vq8c i111ׯ_p8p/a^tiLLLOO͛7juJJ |K`Y,/666B) NX% #$I._`~ .Z[[kKJJz}-[$Ctdra+V $X`܅CKJJDikkKMMH$vH"ga//ܸq#&3 Jj4={*R6m;STTtSC"ݻs;13{ӧO_rBHڪT*}QK>S<ƍ"(55X|K.¤`F` L]8رcʕtGM S(??߳0)S 4phEE|n`x}G;pͳ0issssssyyիQ 3wP8tDpdggr ܅I\R[[{m(L |B`~(>|xtt_;0ꫯ ꑑ]vM?`_h4.]jooO<|,[8z}__l̆X%\ Ҿ555}g.,,,//~ @!pa=KKKacp8 $޸qV wa҆K.vU uuu .X8())I ( H$W^};w@aR ZJspЧ~_,K__߲e$$ D"kjjpa͛7 ]pz>k׮-[@m"&&XjjjJLLLLL;@.Lz-J Wׅ fFSWWCP(Aff&݁Dt.,d¤uuuZlYii)Xh Z@(;1BP8uvv|!IV {; .4^(܅C-[~z,0\p8 $rܺuKT$ Ib0iSS፱@@܅CSRR{1X `}p~*!@"ݻwէO۲e px`E2( qI2V '¤ǎ[dIEE,&D0H"bxbcc#,++[n,ɔJbYt)݁D%K455T*Kxrojjje˖m޼n|믿fnݺu۷{}<.Z[[kWX?ti233\;w 4+//֭[mmm[l)**1x9t.\UV?~|wЬ;wBjwLVYYIw >P*/݁Vkjjbcc'l(B$X!ڵk۷ojL(!'[xbtuf'k׮E ]t nݺO))cǎ=pw`JrҥKccc)))vM5f: P V(k֬j11{ҿ1'Mo!Je{{@ X~=t_|EQ  xwg}닋}io߆I!Aw^xAՊD;/+?{ԝ Oٖ]MJ(!M 0㨥jkCrZ:p;Y5yqΚY̛{3h SQ;:/U(H8!2 F 46>/~3LyqYk$WuQxٴiSOOOAA]]Al6dBw&4MN i Yv*,,|(++xhhD~޼$3<ǘEĹ\u>93NSB@2H0izz S>X 4Xs)~:o3?2&FHT2MQ ae0+WP8| YA%:䋈R*/XPHQԉ'Zȏf307,Nll7|d׏={::ccc"PАJxoV ,ixCQ GFF.d| |7Ba@ ::n߻׮P<:ڄ>(*-- w@~_.\pB9rB~S@Ӆ.\^x:ȃǛ'@ N(xQe.$KtnJQo30+v@zzz(hLQj | ,yVX#8!#˗/Lm ===ziT*zb^x!777O+VS@`QUUU\\XͶo<v?̟?1Y[惂HMMuBxjjj"^&>ƍz^Z@,Çm۶nݺ@>jkk.,Zޅ ݜO?$q8qv[0_-jjj8O~"t! R>ŋ---Zv˖-*(x: 9D Wk…ofAAyݻ7666|NK/n۶mo[ZZF#6la]rg366??&IP] 9pǂ_} |…=Z^x@IIr.uׯ_?.]IJ,AwްaÒ%K"^,9h4 ]H4ɹtRWWF?nw___yye˄* K0LSSӤ_7 ;wLNN>uÇqrtJRBRt8yރ={699?farss)KyRT۷o_vo~t:Ć㸁?(K˲.kڵeee8#//+K{9\~izٲeE:tˑ.ħ(4X"$\CCþ}(aG1.4XRR/^z|Z޵kWVVV}}=bt:rkBRiZDG9SSSsҥ슊v84͘K, +,,yM 4MoڴiÆ ՟y$8g2,KUU˲͛g޿8Ah0F[[[E痗'%%:u>/bH`>(YYY߹s?V}GޮqϩGjWX`\mzzz0JH]n?cccEEE) =3izե<ؽ{7ƅу㸾t ŋ,;Ugֽ{޿tݺu7nhZDK,+..ps`0[N{l_oaL&绺.n"Jڵᘫ)Ya<(h$`0TT*m۶aÆ#(K,˓O>HjL ۷'b~eРP(H`IMӅ}}}J4M#(+ŋ.SBy#67f/}%h䀜sY)e6?# e A”P<gNssBSyIh䀦邂5S8h޼y󫯾z]l˒bQ([TȔ '$ݻ3\Mippf-]0UK&/_N:rrD48efЅd. SBp},`&++mn!ѓC^!D^oo/y}bDvβK>g>9gfAYUUU7o myy "99YB`2ZP(p/ 455߿c{q6Je4ۃ; ^_[[,I|Ph6J3Ls N1 k!(K|h4 ]L-77y.t!01W[l rzqJf`ɊFtA>Ϥs΅:nB6DK0 )s5ׯzLe ܬ\rtt4$ AY---ʒrpJh6ͽJٻwoccc^^ޮ]B566VXXSV;UIHP֭[%!Ny,`lƔPBHHiiiIIIҪYqB%74M ];##FP8/%%SBIIՔvd *ٞ33JŲlBAÔPn߾gϞ~1Wӹ~:v+4X24qsh 7n!v;Ra4yǽDw/Y+**8KϡGf %N6MP]???|/C%gh4&psNe teff ]γ>;>>uF|O?ɓ!嚛z}HA`\aaxWWW_AYb0 E%`0`J(sݽf͚\Mjժp ̥t:Mn$(kǎ$(xQgL&惒CӴ^GXCM\S~VβK GGGVkd^.--l#(+|P ]̅lƔ08 wՔV)**ˁ`ɟ`HHH93#ʊ0%B”0N֘\~]ReddDA(h䏦7:$(+&&СC|ݮ1(u:bJHHkՔv{aaa$_+*s"yPՕ999dq:&IB`rrrFGGqHL\/j:  Q VTirE钒rD4§, #[61W֭AñtR\fhE~~yo&e;+ zj&i `J>8 V`&338A AYk׮mooBFjj*Ų={Gbq\WWlƷ+|93izٲe$(СC r2`6)”0TGQTyyybʕ+" VQTf] Bbt:|3RFcR̕x[nFU`Eb+E,?(k߾}v]z$eQ\a-t!fX9gD4XEt?\ T$('͸BHKKads/!jll˓VՔ^[f3vhJ"An:00 .MfYSBs544TZZZRR"ZSSƁhz.q222d`?檢B쓴z_CsdsO,-tEsp80fR,+) ],,--MJ䜙eݻWAYBWid2IrSSӾ}x߱cDcsMVo>04X0a\" CEEhbPnzBBz!1WuuufBfj804X0 J,t!!0͛e EJJЅq\B(\M`Jh` 䜾> u9Il rdJ(5,Ͼo߾\Mtc  0ׅ.$,&ZZZ?.t:9>>.{ =޽{[ZZ*++z{]ssB804X05rrIMe <(a”\+^vx<6mҥrCZtyyOAY6d2}(iZwvv ]|>ӧs5Y>!T`Jefff[[tJbYV <>>.He޾rJ9\M㸎\C|ߗ93ʪUh 0LooЅ (jǎVkjjy`fh`&*h4K1pHPVVV֥KijnٌF#0ATSBy\MFZ-t- jh^DgaM6'()lӹg\Mbhg,xdN*t!#c{ ߱cN< 1WS8 P(^*t! AYk֬!AY21(J^)!YfcCv4XqI4Mر|r_eYaf8j"檬,js}}}EEE69C"?>ttiiipeяh KPֻO8󏹊[_0 ._A`A),,93#GDOe0btJ2L2T*u: G[Ք8X,yyyf m>e=z4Ǎb)==}xx8SBs6!!!bDf ̂JZxq[[[433Z]^^C6C;.$`>)DUAAA\M[n2 ,h89 |A!_[[^h4B fp||\sĆe]? 2((4X ;˲cڵQs5UV ]H,4Nw -[oE'HRi`L\c{7nhhΧ9CsQXX8::X ́dC~ʤ+L&Zh:an`\ Juu ea>sl\mذ!csuJ4X0(<9$(+!!aAYAaVT*Ubb"Ab?燵|xMdŢP(pE@V<%z<{lRR??!jfMMM111Xo`c&333DPᨩrq's0Ô\cpH8? >N  ʪ.(v tSB\VCC+W64XJe4qrN jtAY AD0gdJH6SSSSWWy[nF\ `Zb+@X5BWҖrȷR]]Ͳƍ7oތiWAB# XFӵ._w(???55̙3].FyAdzjWW`KKVݲe nf^q x8Xr,Y"t-Vo~ڵz !HjZPRUPP "G;Br!@JJVŪl4zjn>66Ƞ,W^yܸq#11h h{0!11ehDk*>00|r @P(prtww+wygÆ c8f?wa&s aիW V!!T`AhsXq\F\(jʠ,)]x?抦iۋYaYw@Yl0׮])Z"_;w***222&=S"oYB BIR-^ 쁰IHP֊+?\Xjii)(((//.Dh4<%q\[[ҥKq6,"q+6MPLUZZݻw<(ZSSsҙcXm<._AȡSF;==w- ZlG+ɴk׮G&a4m2pK#|fш!`A޿c ӱ^7;;;3 m6rD4Ֆ-[\ǽ3zEEEB2 B/--M!ttfN2)(ŋDM ϒ)aoooتWt  ¢pddj ]xl@惓Le566~Gʘٻwoccc^^UȔa 3ZcccB `0$&&^rEBDteffϒ[#(KHHiiiII}q suJp@Hizɒ%xsRww70sNeϤG`0`J8N-4X. \zUBf O=[de={<2*@4Mz5LYPl4X.4M,{mk2LMM jjj%iMMMd}ǎ3\l6cJ0p8 q3,y浵 ]~u&AY& AYEbfsEEE0I0%Rsssll,E!`A1 mX8'af˖-ʒ"94,KS8Vh /_|SSЅ5Lxrsa]>bbbfsQMhhhy~ʕB2 KRf30=DPVKK Č\UVV猪^֭[fG;C+..E ===z>{!(K&\u՚aTL &[\\,t! Ntw駟pB9d>?O8qԩS,ˮ[7L;}[Z-[ bPzz`Y6999/'}YuuϹwުUp3D;kZ׮]w 9ۦŋ?O#]]V__SOm޼9>_EeǏ{<5kD" q/_|1b/* {]paO= «q###11q'Οw{/_ ]l򗿌/++Z㊊V^WNRˑt8'?I_7" j._|dd$>~NaLi{~We}mذAw̙EDf2q'Ot8f^$ҥKs84ZZ%wʑ-tEĨRS 㸁_e#&1WeeejZ芨a-t!4X.䫡R*/XPHQԉ'ZBBQEtII 9"AY)/b=D K__EQ ȃϣ(Ν;I8EӉj`0ܹ399ԩSOF~H|cǎ#C"l(ixǎ<8t˗HGQTyyhOb![r ^(ꫯ?"?"NF㏱>+= &Fw{{nfgg ]oqwE ],O){1á6m$ Wٳ~{NZ"s@<`A~'}}}?xlllaao+]Z Ѕ̝kmmK/E˲Ǐ8?T6<>v---j4_{,%''oٲEBˆ_W˖-~ t--V^-t9hjjSTDGrJCCÿۿcn߾//BK F_ ]ExqvPAAAӴdӏe HF $Fun{l MӫWgPVkk޽{߿/effz^I:۷)tBQ 칓wCyl "%%EBD`0[ND̕^ߵkc0! .jh@HsNOO֑ Jm2Տ~#ٌÂGr k†; LN{N4M "Qsg}v||\6:Nl`4lܻ|pJAY}QƅQs8 )!p_4 ,))I6{6d2a>8ꫯ Df\ݽ{4:cDӴ^;,lܝNس>+t!bo#O>*>ܹsǏOHH>#qK w |) ` <~P^eO8Y!S^gbDWW;.} IDAT@x2hl6h|0@AYUUU7o 3755*$(k֭ÁeҒa]!*Ӈ%7%t BWh@,jP raEٻT*UOOϹsDr$:%td@ 0"jH|.*x?3O  E{$z9cYvϞ=c͚5aH֮]b}E>%Ć;,wvv* (*1WNizٲe$(СCʚFH  NHr;q, ]pwIa6_zY1e9seْ|VFFFCCڬ` W@tļ<想eXs<}H { VЅL  Nh@tļNx7:~xBB»;瘫G"(kVjB罄pB#=w24B"1WgZ.++[t)firDx/!6A`< ]dd>h4.DZ[[c./h^nfl6*xAYb>F@dJ({ b Hl{vl I1WBW4w$(+!!ɓʚhx~0b DJT{6MP`1ࠨbG54a:;;./b DJT{4;j||\T1WizʚM&I$ˑpC"Ocn{^'L\%''ڵK1WKY233ݻ'{ " DJVdAb$8añ~, L ].Ѕ` M bTlW\PUh&E!(iZwtt]6A`xi4`9αLazjvvbVl6߻wO/?pC%=(ںu͛e<DP_|w0Loo5` … )m6[jjj'\edd]~mAYbb/J?6@s' pwǎ*((SC0jۯ]V__r|\6NSp,/ɱkN'ֽ{޿_f1WuM+SBlQvnhN\L&\`0[QNglQptLȿcxls$)m۶#0(+''gddDIl$QpϽȿ |>ŋ**x.^(tECȏIa$ sdӣjllˋMe566~GQ2.dF 2%{nLL 6A`4OF~6$jhh$Jz"AY[nOn7@`إDEIKg4#sUQQ} eddDUPl(+¯ w4X vZlXt:RF˲UUU--- ZbE{{| 9T*u:]װyOHH,~잻z{SSӾ}x߱cbB?(k޽JOOdI *4X vs|\ՙ把 |P`0Lɡ";%Ć;H,wuuu>Hb-㠬O R $ { o>Hu9mGxJ w 4X s'>2;ݻ%//1W6"q!6bZ#Zp A@ܿPN$jdd\Eъ"15<<,,Jj#3%$ @`=weB&_>}1W!נ,400+swޥ(JV $칓ְ"Ay4X,ٳ}ʕJ5UUU @v=/vu:‚$iHIIl$抢;vZJrLe<_SS tE"SŽp˲~@Ҡjd>(v\I ʺt 6M&ݻw^o^lk@i k_~e^fQvHܳgbBNAY&& wd4Tibyg$:$1WX`Aee%b$DAYj:11l1 6AZ`4{ϝ㸾>c $9$(+''Jŋ,)!6AZ`du]\M%%%d]AYb HFX-BVĹ;vɓ's%aΝ "SB]%/ {!qDzl~~~h6X=~8qk֬)..tҥ 6HhrzC~pOJJ `dꘘpZ "%%%rǝ߹s?SO{i+++53g|t0SBMQTBBB4X Ijwl6`UUb@Xjz+VhkkdPV0SB.x ܠIi:11|2LOOGUkmm>b@p4M^:AYdJxA˕ w(4X Uss(*+++ +N+J"p)$Y/҅ jn{===z> 1Wo&ATT*նm6lp8,at:lGR j{Nsttd2&(ŋilSԑYM R j{F\$D,(l6S 6A`TaϽGӅi`Gbn֭[sRA6n_o]TY5X.+11 ]h@fβh8._M\%$$TVVfdd%*77&GD)(+55uxx8oD_~3<2" HجܭV+EQF15,;sU^^+(> œdž;,Yt:RZ[[kjjs0ݻw߼y3OT*u:]SBl  |ϝ㸁'bF#b>{cccJ>ϵB%["556N 2 $,=wrRG1Wj]v͚5|I[[7|366f{Æ pZ Ðe>%Ć;,@u}>b"q.\{0/YunWZccu---&QJiRPŋNRj9 h@j{fs8?|QdzwƥK"*VGFF,^zWxǘK4'##>of>AY}QB4000Ugl<i dϝdEb<OiiK/`XUVVŽhbb13&Fz'add,Fu1py@FgBlXt:ݜ&\a=jkkK~={YhLL\}}g}SFFΝ;RTZbl<i#{3H|e={ *N:EQTRO{zGĨ4RuHT&e`A&v0dž;,m65`SSg߱cb"\R*W ):qDXK?(ks y~@,l<STzSbjDb233+**BQ)( ġ(sNxk?$(d2-(KR%&&ȇ PT $\KOOt|@֬Y3't:N8nڵb+_{<322266x| EQh@`ѡp'1W--- b<D566W_?,66vjv߻׮P<3FQZsΤ 111 èT*J{+P~~~jjC:t_|1)tҥ{noSpY@0LbbI |<ȑ#w[nvlg~^whhh"T*-ZRϟ?q\#4XEmܸ'? nu^x<<װ`xσ^ ,@5+$(̙3---,˾kj2%|bY6!!?} G rbZ'" ٳ}]ii)f0eCI 0j:999+++..O .|d֭[<7eքo30+vI~a?\H#\ES* *b? 2.\ؽ{ ,Y?5ݔΝ;- [ `b͚}>ӧoݺjlق|>!sQ)gpd2-X ゜ +Vh4^.YbJRT><%{`_~ą?O$W||RT*ddd<'N8u˲LV'V7 whSyrϽSP̼=Ϛ5k_|>r-jlllxxx.(9ǧM,3"LUUU-_|df[hё<:GGWSSk4=s心?66Ff^^3G2KRm߾ڵk.kӦM3i42%or-? osDzl~~ NRرCA SަG#cccjTJJ0-222~Osպ䩧vTx"W_曻qqqn&.=˲aE>BV&G\[[իWO p9Ar{oo/?qɓ'lM/>>d2TXZ- -ׯ?{w…wݻw 9"TgLӴZ$kjodhhz<`0zeKJJ&M&իW,>Sb07w 2pBd|099G:_bM.ꑷIEFFF]]]mm'|h_~W^Ͱh?-wMd=99y,rUJ w}wB>??{zzqFVׯ_j6mdHS~sg0 6=)or|]r79:tN??|y󺻻͛0 /PVV~z 4X mVL])bq= IDATf{@Bɑkhor|Νkooꩧ|M2. '@`566_~dd$&&.1<{st`}?˗ϟ_WWGQ+ަG:ܦ20Mccc Mv 6|>f Hj]|H|Ç)yo΃ܪ|_Kkv/m@x y$Tjޛ$US 5e<&SU3@H{IM71q۽7IJWWqYjl+Ut:s}}bkZ\vLsUezFSww/[ 1ۧNzWDQrΞ= X`f[>|wKmlI;:: &.^g|L/rbw"GEQ֭[w ߹[lr0mA3޽{w0eBOU.j?p2=1̽L|_`;=ًo;iRi`g?B宯[~nMLn]qxx`%GeL/r;>#`%l!^ ^r-[`V+9;hܷ~em;Bd=̢i(hvl TwkfY!YO?D82HD>u*v=&q< { Id*5wMkFcO cGkm-\h3OdY(z_x횰~}cO62)T`k)AP%IibNv3S)4iq,c1Lh|k0|/J4 eoܐaIUuv::詚B4 NN[ TWӡPvɝԤk/+cm'V4 gNߪ+K^M$k=c*c1|x}QT3gbo6UR*efeĉB H:2"f?$fe* tZ p8KQds3CG*H<4$9I|CY͂B9VpI:s&Azc#_kRo~Me+5E/򋗗2Ae/*dӮUIƒ$7j˖9 eнzOno(zwL*vU)TL)$u<۶tlb>߻wd:NOȗɨr4*#D47TJqCȲfQ^/h7@9חdEip8 7Ǵ=|$׮-C7ɉolg/]`~?2wMtm2W.bںhiBw]O,=d#B]K56^WEQYQ] UWڵ/~z۶ŎwUW…DKUF]0ę3f^(Řw:x_$\eHZӓ>u*~z Pk2oZ$3gbu\ 0hș- -;/FGo>gM(/^L>h a#2}T6ndY(4D浒,#u_ĂgǟX ,7y滪,KI_#Y{"yp0|b($lϲDSi[ea`:>qU6[[u` __>w.a0;t%lT[ӽ`-ǎ3zTb` c,@4 J'O}wȑ1f]n\5oxM0<,=HT=Ð&` P0s|柁`f] IRR]* ɲ[o;S) dHWv{U$`NQ}>74,ώ6?۲8]gVWWn/Tljazpĉ͛}(~B87 ;~|,K,C!YM @|2/Tf'B}{}⿭Sb6cQ8-UI"zD.\.A!lFA)T,Y/nJr lq{ j]WX:P%ꓒ}-ǑsLtZ5l!te(&Q&#M gFK[{-z@^ƪ$]!S"ŅBl[-Sx;w駞jp'{~tTp!j9*X39jL `8OT/'zɴI+Sh\#HWs?b-_>VT}` 30 |sϵ*njmZndR5*xئ&~*8e.pX{+WLglU]HQFFGJ~(UL,K\/R),pF55UE6v^/cSV+mR^S<SRJ<JtynZZ+ |\X,ja*iy(CCΪ+p2Bi뿮2&$`4V,Yh2&YZ&zxZ(1i.cifD ElE+(z&^WPc?sxd[zVW 5,42"y<%E3I"q:Q}`Rb:mWY]Qt&fcnb8t8h[!DQE5IJ 4qJY,T0ȶC޴mnG!8EǙvbUW4cOWm0L{XԃE;k2=ݶe+糹{+y滽?Ah]*}ѱurBr'l$.[XmzuhB+W wtxrW8>t(iޙYuɚb^薖t)fS!MC٬hBlVdTYydVf#iyH#y~FvziXEo&A c=THÐB¢4Up[ 2Ī꫽;w,Z(ŲLexxW "4] `LF~{gB۷_|˅ SLܙ:8(}(dS w54XLGLФLPq/tՅCb, [>0dYOlV tE1dYXW'xZi'-$ !4 Eo+#6ac~b+j"I$骪Fӈh#) |,v;3##Ip 2vbMrX>8|8.hEgYEfj9pm؜ Ɛ¤ aHAj1W6ɲ& (H4 Mes%@E>h-nܫij!UerT:(ƺ٬F E CbA,KPqqɲJg:7@廯 ŝXS?"#c}MR骒B0* XG/XwԅsUk(7=z[mgh˻}GB۶3Lq޾|!&.u΍Eo9bku ]Q殩u5&{DW>MCK!E)t}dTI"cT%rCfE3 IQdMƗpnm|>_3SvM2XCCcZQC?hGT@׉|^ѣcS&SmWij*}6* 嗯ltn=CrE(s.^Lf2~ >,jm-ʫI΂UЃ5B⮷ wPqs QuKȱ.oΟ0V͛8SdAG&si2Nކte7gIDATNOLeY?q"=Z WP*<8CW5/t|-@$ɵk LB8]xiSqueb-8wMqm{X۳gĉhk=Y^aFOzN2R)5?]ݾBJb!S1Z:(T1 OךP({T{<)+C>Οau?H=o!VDz9v~2'g?(t|e~M<0$Z*Rj4DkzTfC .̾Bg&֭3$`iڳgdZT.QdLOw*&9ֱmE}qӓIƬGyϭXjopW̾vae7P * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #include #include "timer.h" #include "nls.h" static int paused; static time_t begin_time_add; static time_t begin_time; static char timebuffer[160]; time_t get_timer(){ if(paused) return begin_time_add; else{ time_t ret = time(NULL); return ret - begin_time + begin_time_add; } } char *get_timer_string(){ int ho = get_timer() / 3600; int mi = get_timer() / 60 - ho*60; int se = get_timer() - ho*3600 - mi*60; if(ho){ snprintf(timebuffer,160,_("%d:%02d:%02d"),ho,mi,se); }else if (mi){ snprintf(timebuffer,160,_("%d:%02d"),mi,se); }else{ snprintf(timebuffer,160,_("%d seconds"),se); } return timebuffer; } void set_timer(time_t off){ begin_time_add = off; begin_time = time(NULL); } void pause_timer(){ begin_time_add = get_timer(); paused=1; } void unpause_timer(){ paused=0; set_timer(begin_time_add); } int timer_paused_p(){ return paused; } gplanarity-master/timer.h000066400000000000000000000024361510662254600160260ustar00rootroot00000000000000/* * * gPlanarity: * The geeky little puzzle game with a big noodly crunch! * * gPlanarity copyright (C) 2005 Monty * Original Flash game by John Tantalo * Original game concept by Mary Radcliffe * * gPlanarity 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, or (at your option) * any later version. * * gPlanarity 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 Postfish; see the file COPYING. If not, write to the * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * */ #ifndef TIMER_H #define TIMER_H #define _GNU_SOURCE #include #include #include #include "nls.h" extern time_t get_timer(); extern char *get_timer_string(); extern void set_timer(time_t off); extern void pause_timer(); extern void unpause_timer(); extern int timer_paused_p(); #endif /* TIMER_H */ gplanarity-master/touch-version000077500000000000000000000005721510662254600172670ustar00rootroot00000000000000#!/usr/bin/perl if(open F,"version.h"){ $line=; close F; if(open F,">version.h"){ print F "$line"; chomp($line=`date`); print F "/* DO NOT EDIT: Automated versioning hack [$line] */\n"; close F; 0; }else{ print "touch-version: Failed to write new version.h\n"; 1; } }else{ print "touch-version: Failed to open version.h\n"; 1; } gplanarity-master/version.h000066400000000000000000000001441510662254600163650ustar00rootroot00000000000000#define VERSION "$Id$ " /* DO NOT EDIT: Automated versioning hack [Sun Mar 25 11:57:36 EDT 2012] */