pax_global_header00006660000000000000000000000064137340660220014515gustar00rootroot0000000000000052 comment=c65c6df221be66464ef8e4a8b5ffc4b5396fda0c morris-0.3/000077500000000000000000000000001373406602200126725ustar00rootroot00000000000000morris-0.3/.gitignore000066400000000000000000000004161373406602200146630ustar00rootroot00000000000000# Prerequisites *.d # Compiled Object files *.slo *.lo *.o *.obj # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Fortran module files *.mod *.smod # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app morris-0.3/ABOUT-NLS000066400000000000000000002253261373406602200141330ustar00rootroot000000000000001 Notes on the Free Translation Project *************************************** Free software is going international! The Free Translation Project is a way to get maintainers of free software, translators, and users all together, so that free software will gradually become able to speak many languages. A few packages already provide translations for their messages. If you found this `ABOUT-NLS' file inside a distribution, you may assume that the distributed package does use GNU `gettext' internally, itself available at your nearest GNU archive site. But you do _not_ need to install GNU `gettext' prior to configuring, installing or using this package with messages translated. Installers will find here some useful hints. These notes also explain how users should proceed for getting the programs to use the available translations. They tell how people wanting to contribute and work on translations can contact the appropriate team. When reporting bugs in the `intl/' directory or bugs which may be related to internationalization, you should tell about the version of `gettext' which is used. The information can be found in the `intl/VERSION' file, in internationalized packages. 1.1 Quick configuration advice ============================== If you want to exploit the full power of internationalization, you should configure it using ./configure --with-included-gettext to force usage of internationalizing routines provided within this package, despite the existence of internationalizing capabilities in the operating system where this package is being installed. So far, only the `gettext' implementation in the GNU C library version 2 provides as many features (such as locale alias, message inheritance, automatic charset conversion or plural form handling) as the implementation here. It is also not possible to offer this additional functionality on top of a `catgets' implementation. Future versions of GNU `gettext' will very likely convey even more functionality. So it might be a good idea to change to GNU `gettext' as soon as possible. So you need _not_ provide this option if you are using GNU libc 2 or you have installed a recent copy of the GNU gettext package with the included `libintl'. 1.2 INSTALL Matters =================== Some packages are "localizable" when properly installed; the programs they contain can be made to speak your own native language. Most such packages use GNU `gettext'. Other packages have their own ways to internationalization, predating GNU `gettext'. By default, this package will be installed to allow translation of messages. It will automatically detect whether the system already provides the GNU `gettext' functions. If not, the included GNU `gettext' library will be used. This library is wholly contained within this package, usually in the `intl/' subdirectory, so prior installation of the GNU `gettext' package is _not_ required. Installers may use special options at configuration time for changing the default behaviour. The commands: ./configure --with-included-gettext ./configure --disable-nls will, respectively, bypass any pre-existing `gettext' to use the internationalizing routines provided within this package, or else, _totally_ disable translation of messages. When you already have GNU `gettext' installed on your system and run configure without an option for your new package, `configure' will probably detect the previously built and installed `libintl.a' file and will decide to use this. This might not be desirable. You should use the more recent version of the GNU `gettext' library. I.e. if the file `intl/VERSION' shows that the library which comes with this package is more recent, you should use ./configure --with-included-gettext to prevent auto-detection. The configuration process will not test for the `catgets' function and therefore it will not be used. The reason is that even an emulation of `gettext' on top of `catgets' could not provide all the extensions of the GNU `gettext' library. Internationalized packages usually have many `po/LL.po' files, where LL gives an ISO 639 two-letter code identifying the language. Unless translations have been forbidden at `configure' time by using the `--disable-nls' switch, all available translations are installed together with the package. However, the environment variable `LINGUAS' may be set, prior to configuration, to limit the installed set. `LINGUAS' should then contain a space separated list of two-letter codes, stating which languages are allowed. 1.3 Using This Package ====================== As a user, if your language has been installed for this package, you only have to set the `LANG' environment variable to the appropriate `LL_CC' combination. If you happen to have the `LC_ALL' or some other `LC_xxx' environment variables set, you should unset them before setting `LANG', otherwise the setting of `LANG' will not have the desired effect. Here `LL' is an ISO 639 two-letter language code, and `CC' is an ISO 3166 two-letter country code. For example, let's suppose that you speak German and live in Germany. At the shell prompt, merely execute `setenv LANG de_DE' (in `csh'), `export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). This can be done from your `.login' or `.profile' file, once and for all. You might think that the country code specification is redundant. But in fact, some languages have dialects in different countries. For example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The country code serves to distinguish the dialects. The locale naming convention of `LL_CC', with `LL' denoting the language and `CC' denoting the country, is the one use on systems based on GNU libc. On other systems, some variations of this scheme are used, such as `LL' or `LL_CC.ENCODING'. You can get the list of locales supported by your system for your language by running the command `locale -a | grep '^LL''. Not all programs have translations for all languages. By default, an English message is shown in place of a nonexistent translation. If you understand other languages, you can set up a priority list of languages. This is done through a different environment variable, called `LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' for the purpose of message handling, but you still need to have `LANG' set to the primary language; this is required by other parts of the system libraries. For example, some Swedish users who would rather read translations in German than English for when Swedish is not available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. Special advice for Norwegian users: The language code for Norwegian bokma*l changed from `no' to `nb' recently (in 2003). During the transition period, while some message catalogs for this language are installed under `nb' and some older ones under `no', it's recommended for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and older translations are used. In the `LANGUAGE' environment variable, but not in the `LANG' environment variable, `LL_CC' combinations can be abbreviated as `LL' to denote the language's main dialect. For example, `de' is equivalent to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' (Portuguese as spoken in Portugal) in this context. 1.4 Translating Teams ===================== For the Free Translation Project to be a success, we need interested people who like their own language and write it well, and who are also able to synergize with other translators speaking the same language. Each translation team has its own mailing list. The up-to-date list of teams can be found at the Free Translation Project's homepage, `http://translationproject.org/', in the "Teams" area. If you'd like to volunteer to _work_ at translating messages, you should become a member of the translating team for your own language. The subscribing address is _not_ the same as the list itself, it has `-request' appended. For example, speakers of Swedish can send a message to `sv-request@li.org', having this message body: subscribe Keep in mind that team members are expected to participate _actively_ in translations, or at solving translational difficulties, rather than merely lurking around. If your team does not exist yet and you want to start one, or if you are unsure about what to do or how to get started, please write to `coordinator@translationproject.org' to reach the coordinator for all translator teams. The English team is special. It works at improving and uniformizing the terminology in use. Proven linguistic skills are praised more than programming skills, here. 1.5 Available Packages ====================== Languages are not equally supported in all packages. The following matrix shows the current state of internationalization, as of November 2007. The matrix shows, in regard of each package, for which languages PO files have been submitted to translation coordination, with a translation percentage of at least 50%. Ready PO files af am ar az be bg bs ca cs cy da de el en en_GB eo +----------------------------------------------------+ Compendium | [] [] [] [] | a2ps | [] [] [] [] [] | aegis | () | ant-phone | () | anubis | [] | ap-utils | | aspell | [] [] [] [] [] | bash | [] | bfd | | bibshelf | [] | binutils | | bison | [] [] | bison-runtime | [] | bluez-pin | [] [] [] [] [] | cflow | [] | clisp | [] [] [] | console-tools | [] [] | coreutils | [] [] [] [] | cpio | | cpplib | [] [] [] | cryptonit | [] | dialog | | diffutils | [] [] [] [] [] [] | doodle | [] | e2fsprogs | [] [] | enscript | [] [] [] [] | fetchmail | [] [] () [] [] | findutils | [] | findutils_stable | [] [] [] | flex | [] [] [] | fslint | | gas | | gawk | [] [] [] | gcal | [] | gcc | [] | gettext-examples | [] [] [] [] [] | gettext-runtime | [] [] [] [] [] | gettext-tools | [] [] | gip | [] | gliv | [] [] | glunarclock | [] | gmult | [] [] | gnubiff | () | gnucash | [] [] () () [] | gnuedu | | gnulib | [] | gnunet | | gnunet-gtk | | gnutls | [] | gpe-aerial | [] [] | gpe-beam | [] [] | gpe-calendar | | gpe-clock | [] [] | gpe-conf | [] [] | gpe-contacts | | gpe-edit | [] | gpe-filemanager | | gpe-go | [] | gpe-login | [] [] | gpe-ownerinfo | [] [] | gpe-package | | gpe-sketchbook | [] [] | gpe-su | [] [] | gpe-taskmanager | [] [] | gpe-timesheet | [] | gpe-today | [] [] | gpe-todo | | gphoto2 | [] [] [] [] | gprof | [] [] | gpsdrive | | gramadoir | [] [] | grep | [] [] | gretl | () | gsasl | | gss | | gst-plugins-bad | [] [] | gst-plugins-base | [] [] | gst-plugins-good | [] [] [] | gst-plugins-ugly | [] [] | gstreamer | [] [] [] [] [] [] [] | gtick | () | gtkam | [] [] [] [] | gtkorphan | [] [] | gtkspell | [] [] [] [] | gutenprint | [] | hello | [] [] [] [] [] | herrie | [] | hylafax | | idutils | [] [] | indent | [] [] [] [] | iso_15924 | | iso_3166 | [] [] [] [] [] [] [] [] [] [] [] | iso_3166_2 | | iso_4217 | [] [] [] | iso_639 | [] [] [] [] | jpilot | [] | jtag | | jwhois | | kbd | [] [] [] [] | keytouch | [] [] | keytouch-editor | [] | keytouch-keyboa... | [] | latrine | () | ld | [] | leafpad | [] [] [] [] [] | libc | [] [] [] [] | libexif | [] | libextractor | [] | libgpewidget | [] [] [] | libgpg-error | [] | libgphoto2 | [] [] | libgphoto2_port | [] [] | libgsasl | | libiconv | [] [] | libidn | [] [] [] | lifelines | [] () | lilypond | [] | lingoteach | | lprng | | lynx | [] [] [] [] | m4 | [] [] [] [] | mailfromd | | mailutils | [] | make | [] [] | man-db | [] [] [] | minicom | [] [] [] | nano | [] [] [] | opcodes | [] | parted | [] [] | pilot-qof | | popt | [] [] [] | psmisc | [] | pwdutils | | qof | | radius | [] | recode | [] [] [] [] [] [] | rpm | [] | screem | | scrollkeeper | [] [] [] [] [] [] [] [] | sed | [] [] [] | shared-mime-info | [] [] [] [] () [] [] [] | sharutils | [] [] [] [] [] [] | shishi | | skencil | [] () | solfege | | soundtracker | [] [] | sp | [] | system-tools-ba... | [] [] [] [] [] [] [] [] [] | tar | [] [] | texinfo | [] [] [] | tin | () () | tuxpaint | [] [] [] [] [] [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] [] [] | util-linux-ng | [] [] [] [] | vorbis-tools | [] | wastesedge | () | wdiff | [] [] [] [] | wget | [] [] [] | xchat | [] [] [] [] [] [] [] | xkeyboard-config | [] | xpad | [] [] [] | +----------------------------------------------------+ af am ar az be bg bs ca cs cy da de el en en_GB eo 6 0 2 1 8 26 2 40 48 2 56 88 15 1 15 18 es et eu fa fi fr ga gl gu he hi hr hu id is it +--------------------------------------------------+ Compendium | [] [] [] [] [] | a2ps | [] [] [] () | aegis | | ant-phone | [] | anubis | [] | ap-utils | [] [] | aspell | [] [] [] | bash | [] | bfd | [] [] | bibshelf | [] [] [] | binutils | [] [] [] | bison | [] [] [] [] [] [] | bison-runtime | [] [] [] [] [] | bluez-pin | [] [] [] [] [] | cflow | [] | clisp | [] [] | console-tools | | coreutils | [] [] [] [] [] [] | cpio | [] [] [] | cpplib | [] [] | cryptonit | [] | dialog | [] [] [] | diffutils | [] [] [] [] [] [] [] [] [] | doodle | [] [] | e2fsprogs | [] [] [] | enscript | [] [] [] | fetchmail | [] | findutils | [] [] [] | findutils_stable | [] [] [] [] | flex | [] [] [] | fslint | | gas | [] [] | gawk | [] [] [] [] () | gcal | [] [] | gcc | [] | gettext-examples | [] [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] | gettext-tools | [] [] [] [] | gip | [] [] [] [] | gliv | () | glunarclock | [] [] [] | gmult | [] [] [] | gnubiff | () () | gnucash | () () () | gnuedu | [] | gnulib | [] [] [] | gnunet | | gnunet-gtk | | gnutls | | gpe-aerial | [] [] | gpe-beam | [] [] | gpe-calendar | | gpe-clock | [] [] [] [] | gpe-conf | [] | gpe-contacts | [] [] | gpe-edit | [] [] [] [] | gpe-filemanager | [] | gpe-go | [] [] [] | gpe-login | [] [] [] | gpe-ownerinfo | [] [] [] [] [] | gpe-package | [] | gpe-sketchbook | [] [] | gpe-su | [] [] [] [] | gpe-taskmanager | [] [] [] | gpe-timesheet | [] [] [] [] | gpe-today | [] [] [] [] | gpe-todo | [] | gphoto2 | [] [] [] [] [] | gprof | [] [] [] [] [] | gpsdrive | [] | gramadoir | [] [] | grep | [] [] [] | gretl | [] [] [] () | gsasl | [] [] | gss | [] [] | gst-plugins-bad | [] [] [] [] | gst-plugins-base | [] [] [] [] | gst-plugins-good | [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] | gstreamer | [] [] [] | gtick | [] [] [] | gtkam | [] [] [] [] | gtkorphan | [] [] | gtkspell | [] [] [] [] [] [] [] | gutenprint | [] | hello | [] [] [] [] [] [] [] [] [] [] [] [] [] | herrie | [] | hylafax | | idutils | [] [] [] [] [] | indent | [] [] [] [] [] [] [] [] [] [] | iso_15924 | [] | iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] | iso_3166_2 | [] | iso_4217 | [] [] [] [] [] [] | iso_639 | [] [] [] [] [] [] | jpilot | [] [] | jtag | [] | jwhois | [] [] [] [] [] | kbd | [] [] | keytouch | [] [] [] | keytouch-editor | [] | keytouch-keyboa... | [] [] | latrine | [] [] | ld | [] [] [] [] | leafpad | [] [] [] [] [] [] | libc | [] [] [] [] [] | libexif | [] | libextractor | [] | libgpewidget | [] [] [] [] [] | libgpg-error | [] | libgphoto2 | [] [] [] | libgphoto2_port | [] [] | libgsasl | [] [] | libiconv | [] [] [] | libidn | [] [] | lifelines | () | lilypond | [] [] [] | lingoteach | [] [] [] | lprng | | lynx | [] [] [] | m4 | [] [] [] [] | mailfromd | | mailutils | [] [] | make | [] [] [] [] [] [] [] [] | man-db | [] | minicom | [] [] [] [] | nano | [] [] [] [] [] [] [] | opcodes | [] [] [] [] | parted | [] [] [] | pilot-qof | | popt | [] [] [] [] | psmisc | [] [] | pwdutils | | qof | [] | radius | [] [] | recode | [] [] [] [] [] [] [] [] | rpm | [] [] | screem | | scrollkeeper | [] [] [] | sed | [] [] [] [] [] | shared-mime-info | [] [] [] [] [] [] | sharutils | [] [] [] [] [] [] [] [] | shishi | [] | skencil | [] [] | solfege | [] | soundtracker | [] [] [] | sp | [] | system-tools-ba... | [] [] [] [] [] [] [] [] [] | tar | [] [] [] [] [] | texinfo | [] [] [] | tin | [] () | tuxpaint | [] [] | unicode-han-tra... | | unicode-transla... | [] [] | util-linux | [] [] [] [] [] [] [] | util-linux-ng | [] [] [] [] [] [] [] | vorbis-tools | | wastesedge | () | wdiff | [] [] [] [] [] [] [] [] | wget | [] [] [] [] [] [] [] [] | xchat | [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] | xpad | [] [] [] | +--------------------------------------------------+ es et eu fa fi fr ga gl gu he hi hr hu id is it 85 22 14 2 48 101 61 12 2 8 2 6 53 29 1 52 ja ka ko ku ky lg lt lv mk mn ms mt nb ne nl nn +--------------------------------------------------+ Compendium | [] | a2ps | () [] [] | aegis | () | ant-phone | [] | anubis | [] [] [] | ap-utils | [] | aspell | [] [] | bash | [] | bfd | | bibshelf | [] | binutils | | bison | [] [] [] | bison-runtime | [] [] [] | bluez-pin | [] [] [] | cflow | | clisp | [] | console-tools | | coreutils | [] | cpio | [] | cpplib | [] | cryptonit | [] | dialog | [] [] | diffutils | [] [] [] | doodle | | e2fsprogs | [] | enscript | [] | fetchmail | [] [] | findutils | [] | findutils_stable | [] | flex | [] [] | fslint | | gas | | gawk | [] [] | gcal | | gcc | | gettext-examples | [] [] [] | gettext-runtime | [] [] [] | gettext-tools | [] [] | gip | [] [] | gliv | [] | glunarclock | [] [] | gmult | [] [] [] | gnubiff | | gnucash | () () () | gnuedu | | gnulib | [] [] | gnunet | | gnunet-gtk | | gnutls | [] | gpe-aerial | [] | gpe-beam | [] | gpe-calendar | [] | gpe-clock | [] [] [] | gpe-conf | [] [] [] | gpe-contacts | [] | gpe-edit | [] [] [] | gpe-filemanager | [] [] | gpe-go | [] [] [] | gpe-login | [] [] [] | gpe-ownerinfo | [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] | gpe-su | [] [] [] | gpe-taskmanager | [] [] [] [] | gpe-timesheet | [] | gpe-today | [] [] | gpe-todo | [] | gphoto2 | [] [] | gprof | [] | gpsdrive | [] | gramadoir | () | grep | [] [] | gretl | | gsasl | [] | gss | | gst-plugins-bad | [] | gst-plugins-base | [] | gst-plugins-good | [] | gst-plugins-ugly | [] | gstreamer | [] | gtick | [] | gtkam | [] [] | gtkorphan | [] | gtkspell | [] [] | gutenprint | [] | hello | [] [] [] [] [] [] [] | herrie | [] | hylafax | | idutils | [] | indent | [] [] | iso_15924 | [] | iso_3166 | [] [] [] [] [] [] [] [] | iso_3166_2 | [] | iso_4217 | [] [] [] | iso_639 | [] [] [] [] | jpilot | () () | jtag | | jwhois | [] | kbd | [] | keytouch | [] | keytouch-editor | [] | keytouch-keyboa... | | latrine | [] | ld | | leafpad | [] [] | libc | [] [] [] | libexif | | libextractor | | libgpewidget | [] | libgpg-error | | libgphoto2 | [] | libgphoto2_port | [] | libgsasl | [] | libiconv | [] | libidn | [] [] | lifelines | [] | lilypond | [] | lingoteach | [] | lprng | | lynx | [] [] | m4 | [] [] | mailfromd | | mailutils | | make | [] [] [] | man-db | | minicom | [] | nano | [] [] [] | opcodes | [] | parted | [] [] | pilot-qof | | popt | [] [] [] | psmisc | [] [] [] | pwdutils | | qof | | radius | | recode | [] | rpm | [] [] | screem | [] | scrollkeeper | [] [] [] [] | sed | [] [] | shared-mime-info | [] [] [] [] [] [] [] | sharutils | [] [] | shishi | | skencil | | solfege | () () | soundtracker | | sp | () | system-tools-ba... | [] [] [] [] | tar | [] [] [] | texinfo | [] [] | tin | | tuxpaint | () [] [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] | util-linux-ng | [] [] | vorbis-tools | | wastesedge | [] | wdiff | [] [] | wget | [] [] | xchat | [] [] [] [] | xkeyboard-config | [] [] [] | xpad | [] [] [] | +--------------------------------------------------+ ja ka ko ku ky lg lt lv mk mn ms mt nb ne nl nn 51 2 25 3 2 0 6 0 2 2 20 0 11 1 103 6 or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta +--------------------------------------------------+ Compendium | [] [] [] [] [] | a2ps | () [] [] [] [] [] [] | aegis | () () | ant-phone | [] [] | anubis | [] [] [] | ap-utils | () | aspell | [] [] [] | bash | [] [] | bfd | | bibshelf | [] | binutils | [] [] | bison | [] [] [] [] [] | bison-runtime | [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] [] [] | cflow | [] | clisp | [] | console-tools | [] | coreutils | [] [] [] [] | cpio | [] [] [] | cpplib | [] | cryptonit | [] [] | dialog | [] | diffutils | [] [] [] [] [] [] | doodle | [] [] | e2fsprogs | [] [] | enscript | [] [] [] [] [] | fetchmail | [] [] [] | findutils | [] [] [] | findutils_stable | [] [] [] [] [] [] | flex | [] [] [] [] [] | fslint | [] | gas | | gawk | [] [] [] [] | gcal | [] | gcc | [] [] | gettext-examples | [] [] [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] [] [] | gettext-tools | [] [] [] [] [] [] [] | gip | [] [] [] [] | gliv | [] [] [] [] [] [] | glunarclock | [] [] [] [] [] [] | gmult | [] [] [] [] | gnubiff | () [] | gnucash | () [] | gnuedu | | gnulib | [] [] [] | gnunet | | gnunet-gtk | [] | gnutls | [] [] | gpe-aerial | [] [] [] [] [] [] [] | gpe-beam | [] [] [] [] [] [] [] | gpe-calendar | [] [] [] [] | gpe-clock | [] [] [] [] [] [] [] [] | gpe-conf | [] [] [] [] [] [] [] | gpe-contacts | [] [] [] [] [] | gpe-edit | [] [] [] [] [] [] [] [] [] | gpe-filemanager | [] [] | gpe-go | [] [] [] [] [] [] [] [] | gpe-login | [] [] [] [] [] [] [] [] | gpe-ownerinfo | [] [] [] [] [] [] [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] [] [] [] [] [] [] | gpe-su | [] [] [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] [] [] [] | gpe-timesheet | [] [] [] [] [] [] [] [] | gpe-today | [] [] [] [] [] [] [] [] | gpe-todo | [] [] [] [] | gphoto2 | [] [] [] [] [] [] | gprof | [] [] [] | gpsdrive | [] [] | gramadoir | [] [] | grep | [] [] [] [] | gretl | [] [] [] | gsasl | [] [] [] | gss | [] [] [] [] | gst-plugins-bad | [] [] [] | gst-plugins-base | [] [] | gst-plugins-good | [] [] | gst-plugins-ugly | [] [] [] | gstreamer | [] [] [] [] | gtick | [] | gtkam | [] [] [] [] [] | gtkorphan | [] | gtkspell | [] [] [] [] [] [] [] [] | gutenprint | [] | hello | [] [] [] [] [] [] [] [] | herrie | [] [] [] | hylafax | | idutils | [] [] [] [] [] | indent | [] [] [] [] [] [] [] | iso_15924 | | iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] | iso_3166_2 | | iso_4217 | [] [] [] [] [] [] [] | iso_639 | [] [] [] [] [] [] [] | jpilot | | jtag | [] | jwhois | [] [] [] [] | kbd | [] [] [] | keytouch | [] | keytouch-editor | [] | keytouch-keyboa... | [] | latrine | | ld | [] | leafpad | [] [] [] [] [] [] | libc | [] [] [] [] | libexif | [] [] | libextractor | [] [] | libgpewidget | [] [] [] [] [] [] [] [] | libgpg-error | [] [] [] | libgphoto2 | [] | libgphoto2_port | [] [] [] | libgsasl | [] [] [] [] | libiconv | [] [] [] | libidn | [] [] () | lifelines | [] [] | lilypond | | lingoteach | [] | lprng | [] | lynx | [] [] [] | m4 | [] [] [] [] [] | mailfromd | [] | mailutils | [] [] [] | make | [] [] [] [] | man-db | [] [] [] [] | minicom | [] [] [] [] [] | nano | [] [] [] [] | opcodes | [] [] | parted | [] | pilot-qof | | popt | [] [] [] [] | psmisc | [] [] | pwdutils | [] [] | qof | [] [] | radius | [] [] | recode | [] [] [] [] [] [] [] | rpm | [] [] [] [] | screem | | scrollkeeper | [] [] [] [] [] [] [] | sed | [] [] [] [] [] [] [] [] [] | shared-mime-info | [] [] [] [] [] [] | sharutils | [] [] [] [] | shishi | [] | skencil | [] [] [] | solfege | [] | soundtracker | [] [] | sp | | system-tools-ba... | [] [] [] [] [] [] [] [] [] | tar | [] [] [] [] | texinfo | [] [] [] [] | tin | () | tuxpaint | [] [] [] [] [] [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] [] [] | util-linux-ng | [] [] [] [] | vorbis-tools | [] | wastesedge | | wdiff | [] [] [] [] [] [] [] | wget | [] [] [] [] | xchat | [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] | xpad | [] [] [] | +--------------------------------------------------+ or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta 0 5 77 31 53 4 58 72 3 45 46 9 45 122 3 tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu +---------------------------------------------------+ Compendium | [] [] [] [] | 19 a2ps | [] [] [] | 19 aegis | [] | 1 ant-phone | [] [] | 6 anubis | [] [] [] | 11 ap-utils | () [] | 4 aspell | [] [] [] | 16 bash | [] | 6 bfd | | 2 bibshelf | [] | 7 binutils | [] [] [] [] | 9 bison | [] [] [] [] | 20 bison-runtime | [] [] [] [] | 18 bluez-pin | [] [] [] [] [] [] | 28 cflow | [] [] | 5 clisp | | 9 console-tools | [] [] | 5 coreutils | [] [] [] | 18 cpio | [] [] [] [] | 11 cpplib | [] [] [] [] [] | 12 cryptonit | [] | 6 dialog | [] [] [] | 9 diffutils | [] [] [] [] [] | 29 doodle | [] | 6 e2fsprogs | [] [] | 10 enscript | [] [] [] | 16 fetchmail | [] [] | 12 findutils | [] [] [] | 11 findutils_stable | [] [] [] [] | 18 flex | [] [] | 15 fslint | [] | 2 gas | [] | 3 gawk | [] [] [] | 16 gcal | [] | 5 gcc | [] [] [] | 7 gettext-examples | [] [] [] [] [] [] | 29 gettext-runtime | [] [] [] [] [] [] | 28 gettext-tools | [] [] [] [] [] | 20 gip | [] [] | 13 gliv | [] [] | 11 glunarclock | [] [] [] | 15 gmult | [] [] [] [] | 16 gnubiff | [] | 2 gnucash | () [] | 5 gnuedu | [] | 2 gnulib | [] | 10 gnunet | | 0 gnunet-gtk | [] [] | 3 gnutls | | 4 gpe-aerial | [] [] | 14 gpe-beam | [] [] | 14 gpe-calendar | [] [] | 7 gpe-clock | [] [] [] [] | 21 gpe-conf | [] [] [] | 16 gpe-contacts | [] [] | 10 gpe-edit | [] [] [] [] [] | 22 gpe-filemanager | [] [] | 7 gpe-go | [] [] [] [] | 19 gpe-login | [] [] [] [] [] | 21 gpe-ownerinfo | [] [] [] [] | 21 gpe-package | [] | 6 gpe-sketchbook | [] [] | 16 gpe-su | [] [] [] [] | 21 gpe-taskmanager | [] [] [] [] | 21 gpe-timesheet | [] [] [] [] | 18 gpe-today | [] [] [] [] [] | 21 gpe-todo | [] [] | 8 gphoto2 | [] [] [] [] | 21 gprof | [] [] | 13 gpsdrive | [] | 5 gramadoir | [] | 7 grep | [] | 12 gretl | | 6 gsasl | [] [] [] | 9 gss | [] | 7 gst-plugins-bad | [] [] [] | 13 gst-plugins-base | [] [] | 11 gst-plugins-good | [] [] [] [] [] | 16 gst-plugins-ugly | [] [] [] | 13 gstreamer | [] [] [] | 18 gtick | [] [] | 7 gtkam | [] | 16 gtkorphan | [] | 7 gtkspell | [] [] [] [] [] [] | 27 gutenprint | | 4 hello | [] [] [] [] [] | 38 herrie | [] [] | 8 hylafax | | 0 idutils | [] [] | 15 indent | [] [] [] [] [] | 28 iso_15924 | [] [] | 4 iso_3166 | [] [] [] [] [] [] [] [] [] | 54 iso_3166_2 | [] [] | 4 iso_4217 | [] [] [] [] [] | 24 iso_639 | [] [] [] [] [] | 26 jpilot | [] [] [] [] | 7 jtag | [] | 3 jwhois | [] [] [] | 13 kbd | [] [] [] | 13 keytouch | [] | 8 keytouch-editor | [] | 5 keytouch-keyboa... | [] | 5 latrine | [] [] | 5 ld | [] [] [] [] | 10 leafpad | [] [] [] [] [] | 24 libc | [] [] [] | 19 libexif | [] | 5 libextractor | [] | 5 libgpewidget | [] [] [] | 20 libgpg-error | [] | 6 libgphoto2 | [] [] | 9 libgphoto2_port | [] [] [] | 11 libgsasl | [] | 8 libiconv | [] [] | 11 libidn | [] [] | 11 lifelines | | 4 lilypond | [] | 6 lingoteach | [] | 6 lprng | [] | 2 lynx | [] [] [] | 15 m4 | [] [] [] | 18 mailfromd | [] [] | 3 mailutils | [] [] | 8 make | [] [] [] | 20 man-db | [] | 9 minicom | [] | 14 nano | [] [] [] | 20 opcodes | [] [] | 10 parted | [] [] [] | 11 pilot-qof | [] | 1 popt | [] [] [] [] | 18 psmisc | [] [] | 10 pwdutils | [] | 3 qof | [] | 4 radius | [] [] | 7 recode | [] [] [] | 25 rpm | [] [] [] [] | 13 screem | [] | 2 scrollkeeper | [] [] [] [] | 26 sed | [] [] [] [] | 23 shared-mime-info | [] [] [] | 29 sharutils | [] [] [] | 23 shishi | [] | 3 skencil | [] | 7 solfege | [] | 3 soundtracker | [] [] | 9 sp | [] | 3 system-tools-ba... | [] [] [] [] [] [] [] | 38 tar | [] [] [] | 17 texinfo | [] [] [] | 15 tin | | 1 tuxpaint | [] [] [] | 19 unicode-han-tra... | | 0 unicode-transla... | | 2 util-linux | [] [] [] | 20 util-linux-ng | [] [] [] | 20 vorbis-tools | [] [] | 4 wastesedge | | 1 wdiff | [] [] | 23 wget | [] [] [] | 20 xchat | [] [] [] [] | 29 xkeyboard-config | [] [] [] | 14 xpad | [] [] [] | 15 +---------------------------------------------------+ 76 teams tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu 163 domains 0 3 1 74 51 0 143 21 1 57 7 45 0 2036 Some counters in the preceding matrix are higher than the number of visible blocks let us expect. This is because a few extra PO files are used for implementing regional variants of languages, or language dialects. For a PO file in the matrix above to be effective, the package to which it applies should also have been internationalized and distributed as such by its maintainer. There might be an observable lag between the mere existence a PO file and its wide availability in a distribution. If November 2007 seems to be old, you may fetch a more recent copy of this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date matrix with full percentage details can be found at `http://translationproject.org/extra/matrix.html'. 1.6 Using `gettext' in new packages =================================== If you are writing a freely available program and want to internationalize it you are welcome to use GNU `gettext' in your package. Of course you have to respect the GNU Library General Public License which covers the use of the GNU `gettext' library. This means in particular that even non-free programs can use `libintl' as a shared library, whereas only free software can use `libintl' as a static library or use modified versions of `libintl'. Once the sources are changed appropriately and the setup can handle the use of `gettext' the only thing missing are the translations. The Free Translation Project is also available for packages which are not developed inside the GNU project. Therefore the information given above applies also for every other Free Software Project. Contact `coordinator@translationproject.org' to make the `.pot' files available to the translation teams. morris-0.3/AUTHORS000066400000000000000000000003431373406602200137420ustar00rootroot00000000000000GNU Nine Mens Morris authors (in chronological order of contribution): Dirk Farin Ryan Dibble http://www.dibble.net/~dibbler/ morris-0.3/COPYING000066400000000000000000001045131373406602200137310ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state 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) 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 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program 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, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . morris-0.3/ChangeLog000066400000000000000000000056201373406602200144470ustar00rootroot000000000000002009-10-25 Dirk Farin * gtk_prefRules.cc: added 6MM and 7MM to board selection dialog * configure.ac: increased version number to 0.2 * gtkcairo_boardgui.cc: bugfix to correctly draw the board at program start * boardspec.cc: added sun-mill variant 2009-08-02 gettextize * Makefile.am (EXTRA_DIST): Add build-aux/config.rpath, m4/ChangeLog. * configure.in (AC_CONFIG_FILES): Add po/Makefile.in. 2009-08-02 gettextize * m4/gettext.m4: New file, from gettext-0.17. * m4/iconv.m4: New file, from gettext-0.17. * m4/lib-ld.m4: New file, from gettext-0.17. * m4/lib-link.m4: New file, from gettext-0.17. * m4/lib-prefix.m4: New file, from gettext-0.17. * m4/nls.m4: New file, from gettext-0.17. * m4/po.m4: New file, from gettext-0.17. * m4/progtest.m4: New file, from gettext-0.17. * Makefile.am (SUBDIRS): Add po. (EXTRA_DIST): Add build-aux/config.rpath. * configure.in (AC_CONFIG_FILES): Add po/Makefile.in. 2009-08-02 gettextize * Makefile.am (ACLOCAL_AMFLAGS): New variable. (EXTRA_DIST): Add build-aux/config.rpath. 2009-07-20 gettextize * m4/codeset.m4: New file, from gettext-0.17. * m4/glibc2.m4: New file, from gettext-0.17. * m4/glibc21.m4: New file, from gettext-0.17. * m4/intdiv0.m4: New file, from gettext-0.17. * m4/intl.m4: New file, from gettext-0.17. * m4/intldir.m4: New file, from gettext-0.17. * m4/intlmacosx.m4: New file, from gettext-0.17. * m4/intmax.m4: New file, from gettext-0.17. * m4/inttypes_h.m4: New file, from gettext-0.17. * m4/inttypes-pri.m4: New file, from gettext-0.17. * m4/lcmessage.m4: New file, from gettext-0.17. * m4/lock.m4: New file, from gettext-0.17. * m4/longlong.m4: New file, from gettext-0.17. * m4/printf-posix.m4: New file, from gettext-0.17. * m4/size_max.m4: New file, from gettext-0.17. * m4/stdint_h.m4: New file, from gettext-0.17. * m4/uintmax_t.m4: New file, from gettext-0.17. * m4/visibility.m4: New file, from gettext-0.17. * m4/wchar_t.m4: New file, from gettext-0.17. * m4/wint_t.m4: New file, from gettext-0.17. * m4/xsize.m4: New file, from gettext-0.17. * Makefile.am (SUBDIRS): Add intl. * configure.in (AC_OUTPUT): Add intl/Makefile. 2009-07-20 gettextize * m4/gettext.m4: New file, from gettext-0.17. * m4/iconv.m4: New file, from gettext-0.17. * m4/lib-ld.m4: New file, from gettext-0.17. * m4/lib-link.m4: New file, from gettext-0.17. * m4/lib-prefix.m4: New file, from gettext-0.17. * m4/nls.m4: New file, from gettext-0.17. * m4/po.m4: New file, from gettext-0.17. * m4/progtest.m4: New file, from gettext-0.17. * Makefile.am (ACLOCAL_AMFLAGS): New variable. (EXTRA_DIST): Add config.rpath. version 0.1.3 - bugfix: human players are not allowed to take stones from mills anymore - jumping with three pieces can be disabled - new translations: it, nl, mk morris-0.3/LICENSE000066400000000000000000001045151373406602200137050ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state 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) 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 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program 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, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . morris-0.3/Makefile.am000066400000000000000000000011501373406602200147230ustar00rootroot00000000000000## Makefile.am for morris SUBDIRS = src po pixmaps EXTRA_DIST = build-aux/config.rpath m4/ChangeLog build-aux/config.rpath \ debian/changelog debian/compat debian/control debian/copyright debian/docs debian/rules ACLOCAL_AMFLAGS = -I m4 # morris.desktop.in.in morris.schemas.in sysdir = $(datadir)/applications sys_in_files = morris.desktop.in sys_DATA = $(sys_in_files:.desktop.in=.desktop) schema_in_files = morris.schemas.in gsettings_SCHEMAS = net.nine-mens-morris.gschema.xml EXTRA_DIST += $(gsettings_SCHEMAS) $(sys_in_files) DISTCLEANFILES = $(sys_DATA) @INTLTOOL_DESKTOP_RULE@ @GSETTINGS_RULES@ morris-0.3/NEWS000066400000000000000000000000001373406602200133570ustar00rootroot00000000000000morris-0.3/README000066400000000000000000000052541373406602200135600ustar00rootroot00000000000000 Morris -------- A computer implementation of Nine Men's Morris and its variants. ====================================================================== OVERVIEW Morris is an implementation of the board game "Nine Men's Morris". Sometimes simply called Mills, Morris, Merrills, or Mühle in German. The implementation supports not only the standard game, but also several rule-variants and different boards. Furthermore, the game supports: -- a strong computer AI player -- advanced AI controls to tweak AI playing style -- giving hints for good moves -- showing the principal variation -- move takeback (undo and redo) -- internationalization -- many board and rule variations -- configurable display AI ALGORITHM The AI algorithm is a standard alpha-beta search in a NegaMax implementation using iterative deepening. It employs a transposition table to quickly find previously computed positions. A special feature is the automatic learning capability: whenever the computer wins or loses a game, it will prefer to obtain or avoid similar situations in the future. This results in a better long-term motivation, since the computer will not make the same mistake twice and the gameplay will be more randomized. The evaluation function consists of four parts: - material: the number of pieces each player has left - freedom: the number of possible moves a player can conduct - mills: the number of closed mills - experience: the learning-bias from previous games ====================================================================== AUTHOR & CREDITS Dirk Farin - main author Ryan Dibble - provided many features to GNMM, which was the predecessor program of Morris ====================================================================== COPYRIGHT Morris Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . Send inquiries, comments, bug reports, suggestions, patches, etc. to: Dirk Farin See also the Morris home page on the web: https://nine-mens-morris.net/ morris-0.3/bootstrap000077500000000000000000000000331373406602200146310ustar00rootroot00000000000000#!/bin/bash autoreconf -vi morris-0.3/build-aux/000077500000000000000000000000001373406602200145645ustar00rootroot00000000000000morris-0.3/build-aux/config.rpath000066400000000000000000000000001373406602200170570ustar00rootroot00000000000000morris-0.3/configure.ac000066400000000000000000000030601373406602200151570ustar00rootroot00000000000000 AC_PREREQ([2.63]) AC_INIT([morris],[0.3],[dirk.farin@gmail.com]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_SRCDIR([src/morris.cc]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([-Wall -Werror foreign dist-bzip2]) #AM_MAINTAINER_MODE #AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. AC_PROG_CXX AC_PROG_INTLTOOL AC_PROG_LIBTOOL # Checks for libraries. PKG_CHECK_MODULES(GTK, [ glib-2.0 gthread-2.0 gtk+-2.0 >= 2.4 ]) GLIB_GSETTINGS # gdk-pixbuf-2.0 # libgnome-2.0 libgnomeui-2.0 #ACLOCAL_AMFLAGS = -I build-aux BOOST_REQUIRE BOOST_SIGNALS2() # Checks for header files. AC_CHECK_HEADERS([libintl.h locale.h stdlib.h string.h sys/time.h]) # Checks for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOL AC_C_INLINE AC_TYPE_SIZE_T # Checks for library functions. AM_GNU_GETTEXT([external]) GETTEXT_PACKAGE=morris AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [The gettext package name]) AC_FUNC_MALLOC AC_CHECK_FUNCS([dup2 gettimeofday memset]) # === target specific options === AC_MSG_CHECKING([for target architecture]) case x"$target" in xNONE | x) target_or_host="$host" ;; *) target_or_host="$target" ;; esac AC_MSG_RESULT([$target_or_host]) AC_MSG_CHECKING([for Win32 platform]) case "$target_or_host" in *-*-mingw* | *-*-cygwin*) os_win32=yes ;; *) os_win32=no ;; esac AC_MSG_RESULT([$os_win32]) AM_CONDITIONAL(OS_WIN32, test "$os_win32" = "yes") #GNOME_COMPILE_WARNINGS AC_CONFIG_FILES([po/Makefile.in Makefile src/Makefile pixmaps/Makefile ]) AC_OUTPUT # morris.spec morris-0.3/debian/000077500000000000000000000000001373406602200141145ustar00rootroot00000000000000morris-0.3/debian/changelog000066400000000000000000000002031373406602200157610ustar00rootroot00000000000000morris (0.1-1) unstable; urgency=low * Initial release. -- Dirk Farin Thu, 24 Sep 2009 01:05:00 +0200 morris-0.3/debian/compat000066400000000000000000000000021373406602200153120ustar00rootroot000000000000007 morris-0.3/debian/control000066400000000000000000000015021373406602200155150ustar00rootroot00000000000000Source: morris Section: games Priority: optional Maintainer: Dirk Farin Build-Depends: debhelper (>= 7), autotools-dev, libglib2.0-dev, libgtk2.0-dev, libcairo2-dev, libfreetype6-dev, libboost-signals-dev, libgconf2-dev, intltool Build-Conflicts: autoconf2.13, automake1.4 Standards-Version: 3.8.3 Homepage: http://www.morris.org/ Package: morris Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Nine men's morris game for the gnome desktop. Morris is an implementation of the board game "Nine Men's Morris". Sometimes simply called Mills, Morris, Merrills, or Mühle in German. . The implementation supports not only the standard game, but also several rule-variants and different boards. The game supports a strong computer player which learns from past games played. morris-0.3/debian/copyright000066400000000000000000000021131373406602200160440ustar00rootroot00000000000000This work was packaged for Debian by: Dirk Farin on Thu, 24 Sep 2009 01:05:00 +0200 It was downloaded from Upstream Author(s): Dirk Farin Copyright: Copyright (C) 2009 Dirk Farin License: Morris 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 3 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, see . The Debian packaging is: Copyright (C) 2009 Dirk Farin and is licensed under the GPL version 3, see `/usr/share/common-licenses/GPL-3'. morris-0.3/debian/docs000066400000000000000000000000071373406602200147640ustar00rootroot00000000000000README morris-0.3/debian/rules000077500000000000000000000011361373406602200151750ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 %: dh $@ build: dh_testdir dh_auto_configure -- --bindir=/usr/games dh_auto_build dh_auto_test #override_dh_auto_configure: # dh_auto_configure -- --bindir=/usr/games morris-0.3/m4/000077500000000000000000000000001373406602200132125ustar00rootroot00000000000000morris-0.3/m4/ChangeLog000066400000000000000000000006151373406602200147660ustar00rootroot000000000000002009-08-02 gettextize * gettext.m4: New file, from gettext-0.17. * iconv.m4: New file, from gettext-0.17. * lib-ld.m4: New file, from gettext-0.17. * lib-link.m4: New file, from gettext-0.17. * lib-prefix.m4: New file, from gettext-0.17. * nls.m4: New file, from gettext-0.17. * po.m4: New file, from gettext-0.17. * progtest.m4: New file, from gettext-0.17. morris-0.3/m4/ax_boost_base.m4000066400000000000000000000166001373406602200162670ustar00rootroot00000000000000# =========================================================================== # http://www.nongnu.org/autoconf-archive/ax_boost_base.html # =========================================================================== # # SYNOPSIS # # AX_BOOST_BASE([MINIMUM-VERSION]) # # DESCRIPTION # # Test for the Boost C++ libraries of a particular version (or newer) # # If no path to the installed boost library is given the macro searchs # under /usr, /usr/local, /opt and /opt/local and evaluates the # $BOOST_ROOT environment variable. Further documentation is available at # . # # This macro calls: # # AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS) # # And sets: # # HAVE_BOOST # # LICENSE # # Copyright (c) 2008 Thomas Porschberg # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. AC_DEFUN([AX_BOOST_BASE], [ AC_ARG_WITH([boost], AS_HELP_STRING([--with-boost@<:@=DIR@:>@], [use boost (default is yes) - it is possible to specify the root directory for boost (optional)]), [ if test "$withval" = "no"; then want_boost="no" elif test "$withval" = "yes"; then want_boost="yes" ac_boost_path="" else want_boost="yes" ac_boost_path="$withval" fi ], [want_boost="yes"]) AC_ARG_WITH([boost-libdir], AS_HELP_STRING([--with-boost-libdir=LIB_DIR], [Force given directory for boost libraries. Note that this will overwrite library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]), [ if test -d $withval then ac_boost_lib_path="$withval" else AC_MSG_ERROR(--with-boost-libdir expected directory name) fi ], [ac_boost_lib_path=""] ) if test "x$want_boost" = "xyes"; then boost_lib_version_req=ifelse([$1], ,1.20.0,$1) boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'` boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'` boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'` boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` if test "x$boost_lib_version_req_sub_minor" = "x" ; then boost_lib_version_req_sub_minor="0" fi WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req) succeeded=no dnl first we check the system location for boost libraries dnl this location ist chosen if boost libraries are installed with the --layout=system option dnl or if you install boost with RPM if test "$ac_boost_path" != ""; then BOOST_LDFLAGS="-L$ac_boost_path/lib" BOOST_CPPFLAGS="-I$ac_boost_path/include" else for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then BOOST_LDFLAGS="-L$ac_boost_path_tmp/lib" BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" break; fi done fi dnl overwrite ld flags if we have required special directory with dnl --with-boost-libdir parameter if test "$ac_boost_lib_path" != ""; then BOOST_LDFLAGS="-L$ac_boost_lib_path" fi CPPFLAGS_SAVED="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" export CPPFLAGS LDFLAGS_SAVED="$LDFLAGS" LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" export LDFLAGS AC_LANG_PUSH(C++) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @%:@include ]], [[ #if BOOST_VERSION >= $WANT_BOOST_VERSION // Everything is okay #else # error Boost version is too old #endif ]])],[ AC_MSG_RESULT(yes) succeeded=yes found_system=yes ],[ ]) AC_LANG_POP([C++]) dnl if we found no boost with system layout we search for boost libraries dnl built and installed without the --layout=system option or for a staged(not installed) version if test "x$succeeded" != "xyes"; then _version=0 if test "$ac_boost_path" != ""; then if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` V_CHECK=`expr $_version_tmp \> $_version` if test "$V_CHECK" = "1" ; then _version=$_version_tmp fi VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" done fi else for ac_boost_path in /usr /usr/local /opt /opt/local ; do if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` V_CHECK=`expr $_version_tmp \> $_version` if test "$V_CHECK" = "1" ; then _version=$_version_tmp best_path=$ac_boost_path fi done fi done VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" if test "$ac_boost_lib_path" = "" then BOOST_LDFLAGS="-L$best_path/lib" fi if test "x$BOOST_ROOT" != "x"; then if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/lib" && test -r "$BOOST_ROOT/stage/lib"; then version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'` stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'` V_CHECK=`expr $stage_version_shorten \>\= $_version` if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT) BOOST_CPPFLAGS="-I$BOOST_ROOT" BOOST_LDFLAGS="-L$BOOST_ROOT/stage/lib" fi fi fi fi CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" export CPPFLAGS LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" export LDFLAGS AC_LANG_PUSH(C++) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @%:@include ]], [[ #if BOOST_VERSION >= $WANT_BOOST_VERSION // Everything is okay #else # error Boost version is too old #endif ]])],[ AC_MSG_RESULT(yes) succeeded=yes found_system=yes ],[ ]) AC_LANG_POP([C++]) fi if test "$succeeded" != "yes" ; then if test "$_version" = "0" ; then AC_MSG_ERROR([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation.]]) else AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).]) fi else AC_SUBST(BOOST_CPPFLAGS) AC_SUBST(BOOST_LDFLAGS) AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available]) fi CPPFLAGS="$CPPFLAGS_SAVED" LDFLAGS="$LDFLAGS_SAVED" fi ]) morris-0.3/m4/ax_boost_signals.m4000066400000000000000000000077241373406602200170240ustar00rootroot00000000000000# =========================================================================== # http://www.nongnu.org/autoconf-archive/ax_boost_signals.html # =========================================================================== # # SYNOPSIS # # AX_BOOST_SIGNALS # # DESCRIPTION # # Test for Signals library from the Boost C++ libraries. The macro # requires a preceding call to AX_BOOST_BASE. Further documentation is # available at . # # This macro calls: # # AC_SUBST(BOOST_SIGNALS_LIB) # # And sets: # # HAVE_BOOST_SIGNALS # # LICENSE # # Copyright (c) 2008 Thomas Porschberg # Copyright (c) 2008 Michael Tindal # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. AC_DEFUN([AX_BOOST_SIGNALS], [ AC_ARG_WITH([boost-signals], AS_HELP_STRING([--with-boost-signals@<:@=special-lib@:>@], [use the Signals library from boost - it is possible to specify a certain library for the linker e.g. --with-boost-signals=boost_signals-gcc-mt-d ]), [ if test "$withval" = "no"; then want_boost="no" elif test "$withval" = "yes"; then want_boost="yes" ax_boost_user_signals_lib="" else want_boost="yes" ax_boost_user_signals_lib="$withval" fi ], [want_boost="yes"] ) if test "x$want_boost" = "xyes"; then AC_REQUIRE([AC_PROG_CC]) CPPFLAGS_SAVED="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" export CPPFLAGS LDFLAGS_SAVED="$LDFLAGS" LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" export LDFLAGS AC_CACHE_CHECK(whether the Boost::Signals library is available, ax_cv_boost_signals, [AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[@%:@include ]], [[boost::signal sig; return 0; ]]), ax_cv_boost_signals=yes, ax_cv_boost_signals=no) AC_LANG_POP([C++]) ]) if test "x$ax_cv_boost_signals" = "xyes"; then AC_DEFINE(HAVE_BOOST_SIGNALS,,[define if the Boost::Signals library is available]) BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` if test "x$ax_boost_user_signals_lib" = "x"; then for libextension in `ls $BOOSTLIBDIR/libboost_signals*.{so,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_signals.*\)\.so.*$;\1;' -e 's;^lib\(boost_signals.*\)\.a*$;\1;'` ; do ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, [BOOST_SIGNALS_LIB="-l$ax_lib"; AC_SUBST(BOOST_SIGNALS_LIB) link_signals="yes"; break], [link_signals="no"]) done if test "x$link_signals" != "xyes"; then for libextension in `ls $BOOSTLIBDIR/boost_signals*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_signals.*\)\.dll.*$;\1;' -e 's;^\(boost_signals.*\)\.a*$;\1;'` ; do ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, [BOOST_SIGNALS_LIB="-l$ax_lib"; AC_SUBST(BOOST_SIGNALS_LIB) link_signals="yes"; break], [link_signals="no"]) done fi else for ax_lib in $ax_boost_user_signals_lib boost_signals-$ax_boost_user_signals_lib; do AC_CHECK_LIB($ax_lib, main, [BOOST_SIGNALS_LIB="-l$ax_lib"; AC_SUBST(BOOST_SIGNALS_LIB) link_signals="yes"; break], [link_signals="no"]) done fi if test "x$link_signals" != "xyes"; then AC_MSG_ERROR(Could not link against $ax_lib !) fi fi CPPFLAGS="$CPPFLAGS_SAVED" LDFLAGS="$LDFLAGS_SAVED" fi ]) morris-0.3/m4/boost.m4000066400000000000000000001735411373406602200146150ustar00rootroot00000000000000# boost.m4: Locate Boost headers and libraries for autoconf-based projects. # Copyright (C) 2007-2011, 2014 Benoit Sigoure # # 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 3 of the License, or # (at your option) any later version. # # Additional permission under section 7 of the GNU General Public # License, version 3 ("GPLv3"): # # If you convey this file as part of a work that contains a # configuration script generated by Autoconf, you may do so under # terms of your choice. # # 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, see . m4_define([_BOOST_SERIAL], [m4_translit([ # serial 32 ], [# ], [])]) # Original sources can be found at http://github.com/tsuna/boost.m4 # You can fetch the latest version of the script by doing: # wget http://github.com/tsuna/boost.m4/raw/master/build-aux/boost.m4 # ------ # # README # # ------ # # This file provides several macros to use the various Boost libraries. # The first macro is BOOST_REQUIRE. It will simply check if it's possible to # find the Boost headers of a given (optional) minimum version and it will # define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to # your configure so that users can specify non standard locations. # If the user's environment contains BOOST_ROOT and --with-boost was not # specified, --with-boost=$BOOST_ROOT is implicitly used. # For more README and documentation, go to http://github.com/tsuna/boost.m4 # Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry, # simply read the README, it will show you what to do step by step. m4_pattern_forbid([^_?(BOOST|Boost)_]) # _BOOST_SED_CPP(SED-PROGRAM, PROGRAM, # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # -------------------------------------------------------- # Same as AC_EGREP_CPP, but leave the result in conftest.i. # # SED-PROGRAM is *not* overquoted, as in AC_EGREP_CPP. It is expanded # in double-quotes, so escape your double quotes. # # It could be useful to turn this into a macro which extracts the # value of any macro. m4_define([_BOOST_SED_CPP], [AC_LANG_PUSH([C++])dnl AC_LANG_PREPROC_REQUIRE()dnl AC_REQUIRE([AC_PROG_SED])dnl AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])]) AS_IF([dnl eval is necessary to expand ac_cpp. dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell. dnl Beware of Windows end-of-lines, for instance if we are running dnl some Windows programs under Wine. In that case, boost/version.hpp dnl is certainly using "\r\n", but the regular Unix shell will only dnl strip `\n' with backquotes, not the `\r'. This results in dnl boost_cv_lib_version='1_37\r' for instance, which breaks dnl everything else. dnl Cannot use 'dnl' after [$4] because a trailing dnl may break AC_CACHE_CHECK dnl dnl Beware that GCC 5, when expanding macros, may embed # line directives dnl a within single line: dnl dnl # 1 "conftest.cc" dnl # 1 "" dnl # 1 "" dnl # 1 "conftest.cc" dnl # 1 "/opt/local/include/boost/version.hpp" 1 3 dnl # 2 "conftest.cc" 2 dnl boost-lib-version = dnl # 2 "conftest.cc" 3 dnl "1_56" dnl dnl So get rid of the # and empty lines, and glue the remaining ones together. (eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | grep -v '#' | grep -v '^[[[:space:]]]*$' | tr -d '\r' | tr -s '\n' ' ' | $SED -n -e "$1" >conftest.i 2>&1], [$3], [$4]) rm -rf conftest* AC_LANG_POP([C++])dnl ])# _BOOST_SED_CPP # BOOST_REQUIRE([VERSION], [ACTION-IF-NOT-FOUND]) # ----------------------------------------------- # Look for Boost. If version is given, it must either be a literal of the form # "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a # variable "$var". # Defines the value BOOST_CPPFLAGS. This macro only checks for headers with # the required version, it does not check for any of the Boost libraries. # On # success, defines HAVE_BOOST. On failure, calls the optional # ACTION-IF-NOT-FOUND action if one was supplied. # Otherwise aborts with an error message. AC_DEFUN_ONCE([BOOST_REQUIRE], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_PROG_GREP])dnl echo "$as_me: this is boost.m4[]_BOOST_SERIAL" >&AS_MESSAGE_LOG_FD boost_save_IFS=$IFS boost_version_req=$1 IFS=. set x $boost_version_req 0 0 0 IFS=$boost_save_IFS shift boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"` boost_version_req_string=$[1].$[2].$[3] AC_ARG_WITH([boost], [AS_HELP_STRING([--with-boost=DIR], [prefix of Boost $1 @<:@guess@:>@])])dnl AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl # If BOOST_ROOT is set and the user has not provided a value to # --with-boost, then treat BOOST_ROOT as if it the user supplied it. if test x"$BOOST_ROOT" != x; then if test x"$with_boost" = x; then AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT]) with_boost=$BOOST_ROOT else AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost]) fi fi AC_SUBST([DISTCHECK_CONFIGURE_FLAGS], ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])dnl boost_save_CPPFLAGS=$CPPFLAGS AC_CACHE_CHECK([for Boost headers version >= $boost_version_req_string], [boost_cv_inc_path], [boost_cv_inc_path=no AC_LANG_PUSH([C++])dnl m4_pattern_allow([^BOOST_VERSION$])dnl AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include #if !defined BOOST_VERSION # error BOOST_VERSION is not defined #elif BOOST_VERSION < $boost_version_req # error Boost headers version < $boost_version_req #endif ]])]) # If the user provided a value to --with-boost, use it and only it. case $with_boost in #( ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \ /usr/include C:/Boost/include;; #( *) set x "$with_boost/include" "$with_boost";; esac shift for boost_dir do # Without --layout=system, Boost (or at least some versions) installs # itself in /include/boost-. This inner loop helps to # find headers in such directories. # # Any ${boost_dir}/boost-x_xx directories are searched in reverse version # order followed by ${boost_dir}. The final '.' is a sentinel for # searching $boost_dir" itself. Entries are whitespace separated. # # I didn't indent this loop on purpose (to avoid over-indented code) boost_layout_system_search_list=`cd "$boost_dir" 2>/dev/null \ && ls -1 | "${GREP}" '^boost-' | sort -rn -t- -k2 \ && echo .` for boost_inc in $boost_layout_system_search_list do if test x"$boost_inc" != x.; then boost_inc="$boost_dir/$boost_inc" else boost_inc="$boost_dir" # Uses sentinel in boost_layout_system_search_list fi if test x"$boost_inc" != x; then # We are going to check whether the version of Boost installed # in $boost_inc is usable by running a compilation that # #includes it. But if we pass a -I/some/path in which Boost # is not installed, the compiler will just skip this -I and # use other locations (either from CPPFLAGS, or from its list # of system include directories). As a result we would use # header installed on the machine instead of the /some/path # specified by the user. So in that precise case (trying # $boost_inc), make sure the version.hpp exists. # # Use test -e as there can be symlinks. test -e "$boost_inc/boost/version.hpp" || continue CPPFLAGS="$CPPFLAGS -I$boost_inc" fi AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no]) if test x"$boost_cv_inc_path" = xyes; then if test x"$boost_inc" != x; then boost_cv_inc_path=$boost_inc fi break 2 fi done done AC_LANG_POP([C++])dnl ]) case $boost_cv_inc_path in #( no) boost_errmsg="cannot find Boost headers version >= $boost_version_req_string" m4_if([$2], [], [AC_MSG_ERROR([$boost_errmsg])], [AC_MSG_NOTICE([$boost_errmsg])]) $2 ;;#( yes) BOOST_CPPFLAGS= ;;#( *) AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"])dnl ;; esac if test x"$boost_cv_inc_path" != xno; then AC_DEFINE([HAVE_BOOST], [1], [Defined if the requested minimum BOOST version is satisfied]) AC_CACHE_CHECK([for Boost's header version], [boost_cv_lib_version], [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl _BOOST_SED_CPP([[/^boost-lib-version = /{s///;s/[\" ]//g;p;q;}]], [#include boost-lib-version = BOOST_LIB_VERSION], [boost_cv_lib_version=`cat conftest.i`])]) # e.g. "134" for 1_34_1 or "135" for 1_35 boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'` case $boost_major_version in #( '' | *[[!0-9]]*) AC_MSG_ERROR([invalid value: boost_major_version='$boost_major_version']) ;; esac fi CPPFLAGS=$boost_save_CPPFLAGS ])# BOOST_REQUIRE # BOOST_STATIC() # -------------- # Add the "--enable-static-boost" configure argument. If this argument is given # on the command line, static versions of the libraries will be looked up. AC_DEFUN([BOOST_STATIC], [AC_ARG_ENABLE([static-boost], [AS_HELP_STRING([--enable-static-boost], [Prefer the static boost libraries over the shared ones [no]])], [enable_static_boost=yes], [enable_static_boost=no])])# BOOST_STATIC # BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND]) # -------------------------------------------------------------------------- # Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for # some parts of the Boost library which are only made of headers and don't # require linking (such as Boost.Foreach). # # Default ACTION-IF-NOT-FOUND: Fail with a fatal error unless Boost couldn't be # found in the first place, in which case by default a notice is issued to the # user. Presumably if we haven't died already it's because it's OK to not have # Boost, which is why only a notice is issued instead of a hard error. # # Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_ in # case of success # (where HEADER-NAME is written LIKE_THIS, e.g., # HAVE_BOOST_FOREACH_HPP). AC_DEFUN([BOOST_FIND_HEADER], [AC_REQUIRE([BOOST_REQUIRE])dnl if test x"$boost_cv_inc_path" = xno; then m4_default([$2], [AC_MSG_NOTICE([Boost not available, not searching for $1])]) else AC_LANG_PUSH([C++])dnl boost_save_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_CHECK_HEADER([$1], [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], [Define to 1 if you have <$1>])])], [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])]) CPPFLAGS=$boost_save_CPPFLAGS AC_LANG_POP([C++])dnl fi ])# BOOST_FIND_HEADER # BOOST_FIND_LIBS([COMPONENT-NAME], [CANDIDATE-LIB-NAMES], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE], [CXX-POST-INCLUDE-PROLOGUE], # [ERROR_ON_UNUSABLE]) # -------------------------------------------------------------- # Look for the Boost library COMPONENT-NAME (e.g., `thread', for # libboost_thread) under the possible CANDIDATE-LIB-NAMES (e.g., # "thread_win32 thread"). Check that HEADER-NAME works and check that # libboost_LIB-NAME can link with the code CXX-TEST. The optional # argument CXX-PROLOGUE can be used to include some C++ code before # the `main' function. The CXX-POST-INCLUDE-PROLOGUE can be used to # include some code before the `main' function, but after the # `#include '. # # Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above). # # Boost libraries typically come compiled with several flavors (with different # runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one # or more of the following letters: sgdpn (in that order). s = static # runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build, # n = (unsure) STLPort build without iostreams from STLPort (it looks like `n' # must always be used along with `p'). Additionally, PREFERRED-RT-OPT can # start with `mt-' to indicate that there is a preference for multi-thread # builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp # ... If you want to make sure you have a specific version of Boost # (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro. # # ERROR_ON_UNUSABLE can be set to "no" if the caller does not want their # configure to fail AC_DEFUN([BOOST_FIND_LIBS], [AC_REQUIRE([BOOST_REQUIRE])dnl AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl AC_REQUIRE([BOOST_STATIC])dnl AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl if test x"$boost_cv_inc_path" = xno; then AC_MSG_NOTICE([Boost not available, not searching for the Boost $1 library]) else dnl The else branch is huge and wasn't indented on purpose. AC_LANG_PUSH([C++])dnl AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl AS_VAR_PUSHDEF([Boost_lib_LDPATH], [boost_cv_lib_$1_LDPATH])dnl AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl AS_IF([test x"$8" = "xno"], [not_found_header='true']) BOOST_FIND_HEADER([$4], [$not_found_header]) boost_save_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib], [_BOOST_FIND_LIBS($@)]) case $Boost_lib in #( (yes) _AC_MSG_LOG_CONFTEST AC_DEFINE(AS_TR_CPP([HAVE_BOOST_$1]), [1], [Defined if the Boost $1 library is available])dnl AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])dnl AC_SUBST(AS_TR_CPP([BOOST_$1_LDPATH]), [$Boost_lib_LDPATH])dnl AC_SUBST([BOOST_LDPATH], [$Boost_lib_LDPATH])dnl AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])dnl ;; (no) _AC_MSG_LOG_CONFTEST AS_IF([test x"$8" != "xno"], [ AC_MSG_ERROR([cannot find flags to link with the Boost $1 library (libboost-$1)]) ]) ;; esac CPPFLAGS=$boost_save_CPPFLAGS AS_VAR_POPDEF([Boost_lib])dnl AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl AS_VAR_POPDEF([Boost_lib_LDPATH])dnl AS_VAR_POPDEF([Boost_lib_LIBS])dnl AC_LANG_POP([C++])dnl fi ]) # BOOST_FIND_LIB([LIB-NAME], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE], [CXX-POST-INCLUDE-PROLOGUE], # [ERROR_ON_UNUSABLE]) # -------------------------------------------------------------- # Backward compatibility wrapper for BOOST_FIND_LIBS. # ERROR_ON_UNUSABLE can be set to "no" if the caller does not want their # configure to fail AC_DEFUN([BOOST_FIND_LIB], [BOOST_FIND_LIBS([$1], $@)]) # _BOOST_FIND_LIBS([LIB-NAME], [CANDIDATE-LIB-NAMES], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE], [CXX-POST-INCLUDE-PROLOGUE], # [ERROR_ON_UNUSABLE]) # -------------------------------------------------------------- # Real implementation of BOOST_FIND_LIBS: rely on these local macros: # Boost_lib, Boost_lib_LDFLAGS, Boost_lib_LDPATH, Boost_lib_LIBS # # The algorithm is as follows: first look for a given library name # according to the user's PREFERRED-RT-OPT. For each library name, we # prefer to use the ones that carry the tag (toolset name). Each # library is searched through the various standard paths were Boost is # usually installed. If we can't find the standard variants, we try # to enforce -mt (for instance on MacOSX, libboost_thread.dylib # doesn't exist but there's -obviously- libboost_thread-mt.dylib). # # ERROR_ON_UNUSABLE can be set to "no" if the caller does not want their # configure to fail AC_DEFUN([_BOOST_FIND_LIBS], [Boost_lib=no case "$3" in #( (mt | mt-) boost_mt=-mt; boost_rtopt=;; #( (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$3" : 'Xmt-*\(.*\)'`;; #( (*) boost_mt=; boost_rtopt=$3;; esac if test $enable_static_boost = yes; then boost_rtopt="s$boost_rtopt" fi # Find the proper debug variant depending on what we've been asked to find. case $boost_rtopt in #( (*d*) boost_rt_d=$boost_rtopt;; #( (*[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn') boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( (*) boost_rt_d='-d';; esac # If the PREFERRED-RT-OPT are not empty, prepend a `-'. test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" $boost_guess_use_mt && boost_mt=-mt # Look for the abs path the static archive. # $libext is computed by Libtool but let's make sure it's non empty. test -z "$libext" && AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?]) boost_save_ac_objext=$ac_objext # Generate the test file. AC_LANG_CONFTEST([AC_LANG_PROGRAM([$7 #include <$4> $6], [$5])]) dnl Optimization hacks: compiling C++ is slow, especially with Boost. What dnl we're trying to do here is guess the right combination of link flags dnl (LIBS / LDFLAGS) to use a given library. This can take several dnl iterations before it succeeds and is thus *very* slow. So what we do dnl instead is that we compile the code first (and thus get an object file, dnl typically conftest.o). Then we try various combinations of link flags dnl until we succeed to link conftest.o in an executable. The problem is dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always dnl remove all the temporary files including conftest.o. So the trick here dnl is to temporarily change the value of ac_objext so that conftest.o is dnl preserved accross tests. This is obviously fragile and I will burn in dnl hell for not respecting Autoconf's documented interfaces, but in the dnl mean time, it optimizes the macro by a factor of 5 to 30. dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left dnl empty because the test file is generated only once above (before we dnl start the for loops). AC_COMPILE_IFELSE([], [ac_objext=do_not_rm_me_plz], [AS_IF([test x"$8" != x"no"], [ AC_MSG_ERROR([cannot compile a test that uses Boost $1]) ]) ]) ac_objext=$boost_save_ac_objext boost_failed_libs= # Don't bother to ident the following nested for loops, only the 2 # innermost ones matter. for boost_lib_ in $2; do for boost_tag_ in -$boost_cv_lib_tag ''; do for boost_ver_ in -$boost_cv_lib_version ''; do for boost_mt_ in $boost_mt -mt ''; do for boost_rtopt_ in $boost_rtopt '' -d; do for boost_full_suffix in \ $boost_last_suffix \ x$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ x$boost_tag_$boost_rtopt_$boost_ver_ \ x$boost_tag_$boost_mt_$boost_ver_ \ x$boost_tag_$boost_ver_ do boost_real_suffix=`echo "$boost_full_suffix" | sed 's/^x//'` boost_lib="boost_$boost_lib_$boost_real_suffix" # Avoid testing twice the same lib case $boost_failed_libs in #( (*@$boost_lib@*) continue;; esac # If with_boost is empty, we'll search in /lib first, which is not quite # right so instead we'll try to a location based on where the headers are. boost_tmp_lib=$with_boost test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} for boost_ldpath in "$boost_tmp_lib/lib" '' \ /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ "$with_boost" C:/Boost/lib /lib* do # Don't waste time with directories that don't exist. if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then continue fi boost_save_LDFLAGS=$LDFLAGS # Are we looking for a static library? case $boost_ldpath:$boost_rtopt_ in #( (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext" test -e "$Boost_lib_LIBS" || continue;; #( (*) # No: use -lboost_foo to find the shared library. Boost_lib_LIBS="-l$boost_lib";; esac boost_save_LIBS=$LIBS LIBS="$Boost_lib_LIBS $LIBS" test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" dnl First argument of AC_LINK_IFELSE left empty because the test file is dnl generated only once above (before we start the for loops). _BOOST_AC_LINK_IFELSE([], [Boost_lib=yes], [Boost_lib=no]) ac_objext=$boost_save_ac_objext LDFLAGS=$boost_save_LDFLAGS LIBS=$boost_save_LIBS if test x"$Boost_lib" = xyes; then # Check or used cached result of whether or not using -R or # -rpath makes sense. Some implementations of ld, such as for # Mac OSX, require -rpath but -R is the flag known to work on # other systems. https://github.com/tsuna/boost.m4/issues/19 AC_CACHE_VAL([boost_cv_rpath_link_ldflag], [case $boost_ldpath in '') # Nothing to do. boost_cv_rpath_link_ldflag= boost_rpath_link_ldflag_found=yes;; *) for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" LIBS="$Boost_lib_LIBS $boost_save_LIBS" _BOOST_AC_LINK_IFELSE([], [boost_rpath_link_ldflag_found=yes break], [boost_rpath_link_ldflag_found=no]) done ;; esac AS_IF([test "x$boost_rpath_link_ldflag_found" != "xyes"], [AC_MSG_ERROR([Unable to determine whether to use -R or -rpath])]) LDFLAGS=$boost_save_LDFLAGS LIBS=$boost_save_LIBS ]) test x"$boost_ldpath" != x && Boost_lib_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" Boost_lib_LDPATH="$boost_ldpath" boost_last_suffix="$boost_full_suffix" break 7 else boost_failed_libs="$boost_failed_libs@$boost_lib@" fi done done done done done done done # boost_lib_ rm -f conftest.$ac_objext ]) # --------------------------------------- # # Checks for the various Boost libraries. # # --------------------------------------- # # List of boost libraries: http://www.boost.org/libs/libraries.htm # The page http://beta.boost.org/doc/libs is useful: it gives the first release # version of each library (among other things). # BOOST_DEFUN(LIBRARY, CODE) # -------------------------- # Define BOOST_ as a macro that runs CODE. # # Use indir to avoid the warning on underquoted macro name given to AC_DEFUN. m4_define([BOOST_DEFUN], [m4_indir([AC_DEFUN], m4_toupper([BOOST_$1]), [m4_pushdef([BOOST_Library], [$1])dnl $2 m4_popdef([BOOST_Library])dnl ]) ]) # BOOST_ANY() # ------------ # Look for Boost.Any BOOST_DEFUN([Any], [BOOST_FIND_HEADER([boost/any.hpp])]) # BOOST_ARRAY() # ------------- # Look for Boost.Array BOOST_DEFUN([Array], [BOOST_FIND_HEADER([boost/array.hpp])]) # BOOST_ASIO() # ------------ # Look for Boost.Asio (new in Boost 1.35). BOOST_DEFUN([Asio], [AC_REQUIRE([BOOST_SYSTEM])dnl BOOST_FIND_HEADER([boost/asio.hpp])]) # BOOST_BIMAP() # ------------ # Look for Boost.Bimap BOOST_DEFUN([Bimap], [BOOST_FIND_HEADER([boost/bimap.hpp])]) # BOOST_ASSIGN() # ------------- # Look for Boost.Assign BOOST_DEFUN([Assign], [BOOST_FIND_HEADER([boost/assign.hpp])]) # BOOST_ATOMIC([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ------------------------------- # Look for Boost.Atomic. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Atomic], [BOOST_FIND_LIB([atomic], [$1], [boost/atomic.hpp], [boost::atomic a;], [ ], [#ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_STDINT_H #include #endif], [$2]) ])# BOOST_ATOMIC # BOOST_BIND() # ------------ # Look for Boost.Bind. BOOST_DEFUN([Bind], [BOOST_FIND_HEADER([boost/bind.hpp])]) # BOOST_CAST() # ------------ # Look for Boost.Cast BOOST_DEFUN([Cast], [BOOST_FIND_HEADER([boost/cast.hpp])]) # BOOST_CHRONO([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # -------------- # Look for Boost.Chrono. BOOST_DEFUN([Chrono], [# Do we have to check for Boost.System? This link-time dependency was # added as of 1.35.0. If we have a version <1.35, we must not attempt to # find Boost.System as it didn't exist by then. if test $boost_major_version -ge 135; then BOOST_SYSTEM([$1], [$2]) fi # end of the Boost.System check. boost_filesystem_save_LIBS=$LIBS boost_filesystem_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" BOOST_FIND_LIB([chrono], [$1], [boost/chrono.hpp], [boost::chrono::thread_clock d;], [], [], [$2]) if test $enable_static_boost = yes && test $boost_major_version -ge 135; then BOOST_CHRONO_LIBS="$BOOST_CHRONO_LIBS $BOOST_SYSTEM_LIBS" fi LIBS=$boost_filesystem_save_LIBS LDFLAGS=$boost_filesystem_save_LDFLAGS ])# BOOST_CHRONO # BOOST_CONTEXT([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ----------------------------------- # Look for Boost.Context. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. # # * This library was introduced in Boost 1.51.0 # * The signatures of make_fcontext() and jump_fcontext were changed in 1.56.0 # * A dependency on boost_thread appears in 1.57.0 # * The implementation details were moved to boost::context::detail in 1.61.0 # * 1.61 also introduces execution_context_v2, which is the "lowest common # denominator" for boost::context presence since then. # * boost::context::fiber was introduced in 1.69 and execution_context_v2 was # removed in 1.72 BOOST_DEFUN([Context], [boost_context_save_LIBS=$LIBS boost_context_save_LDFLAGS=$LDFLAGS if test $boost_major_version -ge 157; then BOOST_THREAD([$1], [$2]) m4_pattern_allow([^BOOST_THREAD_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_THREAD_LIBS" LDFLAGS="$LDFLAGS $BOOST_THREAD_LDFLAGS" fi if test $boost_major_version -ge 169; then BOOST_FIND_LIB([context], [$1], [boost/context/fiber.hpp], [[ namespace ctx=boost::context; int a; ctx::fiber source{[&a](ctx::fiber&& sink){ a=0; int b=1; for(;;){ sink=std::move(sink).resume(); int next=a+b; a=b; b=next; } return std::move(sink); }}; for (int j=0;j<10;++j) { source=std::move(source).resume(); } return a == 34; ]], [], [], [$2]) elif test $boost_major_version -ge 161; then BOOST_FIND_LIB([context], [$1], [boost/context/execution_context_v2.hpp], [[ namespace ctx=boost::context; int res=0; int n=35; ctx::execution_context source( [n, &res](ctx::execution_context sink, int) mutable { int a=0; int b=1; while(n-->0){ auto result=sink(a); sink=std::move(std::get<0>(result)); auto next=a+b; a=b; b=next; } return sink; }); for(int i=0;i<10;++i){ auto result=source(i); source=std::move(std::get<0>(result)); res = std::get<1>(result); } return res == 34; ]], [], [], [$2]) else BOOST_FIND_LIB([context], [$1], [boost/context/fcontext.hpp],[[ // creates a stack void * stack_pointer = new void*[4096]; std::size_t const size = sizeof(void*[4096]); #if BOOST_VERSION <= 105100 ctx::make_fcontext(&fc, f); return ctx::jump_fcontext(&fcm, &fc, 3) == 6; #else fc = ctx::make_fcontext(stack_pointer, size, f); return ctx::jump_fcontext(&fcm, fc, 3) == 6; #endif ]],[dnl #include #if BOOST_VERSION <= 105100 namespace ctx = boost::ctx; static ctx::fcontext_t fcm, fc; static void f(intptr_t i) { ctx::jump_fcontext(&fc, &fcm, i * 2); } #elif BOOST_VERSION <= 105500 namespace ctx = boost::context; // context static ctx::fcontext_t fcm, *fc; // context-function static void f(intptr_t i) { ctx::jump_fcontext(fc, &fcm, i * 2); } #else namespace ctx = boost::context; // context static ctx::fcontext_t fcm, fc; // context-function static void f(intptr_t i) { ctx::jump_fcontext(&fc, fcm, i * 2); } #endif ], [], [], [$2]) fi LIBS=$boost_context_save_LIBS LDFLAGS=$boost_context_save_LDFLAGS ])# BOOST_CONTEXT # BOOST_CONVERSION() # ------------------ # Look for Boost.Conversion (cast / lexical_cast) BOOST_DEFUN([Conversion], [BOOST_FIND_HEADER([boost/cast.hpp]) BOOST_FIND_HEADER([boost/lexical_cast.hpp]) ])# BOOST_CONVERSION # BOOST_COROUTINE([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ----------------------------------- # Look for Boost.Coroutine. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. This library was introduced in Boost # 1.53.0 BOOST_DEFUN([Coroutine], [ boost_coroutine_save_LIBS=$LIBS boost_coroutine_save_LDFLAGS=$LDFLAGS # Link-time dependency from coroutine to context BOOST_CONTEXT([$1], [$2]) # Starting from Boost 1.55 a dependency on Boost.System is added if test $boost_major_version -ge 155; then BOOST_SYSTEM([$1], [$2]) fi m4_pattern_allow([^BOOST_(CONTEXT|SYSTEM)_(LIBS|LDFLAGS)]) LIBS="$LIBS $BOOST_CONTEXT_LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_CONTEXT_LDFLAGS" # in 1.53 coroutine was a header only library if test $boost_major_version -eq 153; then AS_IF([test x"$2" = "xno"], [not_found_header='true']) BOOST_FIND_HEADER([boost/coroutine/coroutine.hpp], [$not_found_header]) else BOOST_FIND_LIB([coroutine], [$1], [boost/coroutine/coroutine.hpp], [ #include #if BOOST_VERSION <= 105500 boost::coroutines::coroutine coro; coro.get(); #else boost::coroutines::asymmetric_coroutine::pull_type coro; coro.get(); #endif ], [], [], [$2]) fi # Link-time dependency from coroutine to context, existed only in 1.53, in 1.54 # coroutine doesn't use context from its headers but from its library. if test $boost_major_version -eq 153 || test $enable_static_boost = yes && test $boost_major_version -ge 154; then BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_CONTEXT_LIBS" BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_CONTEXT_LDFLAGS" fi if test $enable_static_boost = yes && test $boost_major_version -ge 155; then BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_SYSTEM_LIBS" BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_SYSTEM_LDFLAGS" fi LIBS=$boost_coroutine_save_LIBS LDFLAGS=$boost_coroutine_save_LDFLAGS ])# BOOST_COROUTINE # BOOST_CRC() # ----------- # Look for Boost.CRC BOOST_DEFUN([CRC], [BOOST_FIND_HEADER([boost/crc.hpp]) ])# BOOST_CRC # BOOST_DATE_TIME([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ----------------------------------- # Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Date_Time], [BOOST_FIND_LIB([date_time], [$1], [boost/date_time/posix_time/posix_time.hpp], [boost::posix_time::ptime t;], [], [], [$2]) ])# BOOST_DATE_TIME # BOOST_EXCEPTION() # ------------ # Look for Boost.Exception BOOST_DEFUN([Exception], [BOOST_FIND_HEADER([boost/exception/all.hpp])]) # BOOST_FILESYSTEM([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ------------------------------------ # Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see # the documentation of BOOST_FIND_LIB above. # Do not check for boost/filesystem.hpp because this file was introduced in # 1.34. BOOST_DEFUN([Filesystem], [# Do we have to check for Boost.System? This link-time dependency was # added as of 1.35.0. If we have a version <1.35, we must not attempt to # find Boost.System as it didn't exist by then. if test $boost_major_version -ge 135; then BOOST_SYSTEM([$1], [$2]) fi # end of the Boost.System check. boost_filesystem_save_LIBS=$LIBS boost_filesystem_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" BOOST_FIND_LIB([filesystem], [$1], [boost/filesystem/path.hpp], [boost::filesystem::path p;], [], [], [$2]) if test $enable_static_boost = yes && test $boost_major_version -ge 135; then BOOST_FILESYSTEM_LIBS="$BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS" fi LIBS=$boost_filesystem_save_LIBS LDFLAGS=$boost_filesystem_save_LDFLAGS ])# BOOST_FILESYSTEM # BOOST_FLYWEIGHT() # ----------------- # Look for Boost.Flyweight. BOOST_DEFUN([Flyweight], [dnl There's a hidden dependency on pthreads. AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl BOOST_FIND_HEADER([boost/flyweight.hpp]) AC_SUBST([BOOST_FLYWEIGHT_LIBS], [$boost_cv_pthread_flag]) ]) # BOOST_FOREACH() # --------------- # Look for Boost.Foreach. BOOST_DEFUN([Foreach], [BOOST_FIND_HEADER([boost/foreach.hpp])]) # BOOST_FORMAT() # -------------- # Look for Boost.Format. # Note: we can't check for boost/format/format_fwd.hpp because the header isn't # standalone. It can't be compiled because it triggers the following error: # boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std' # does not name a type BOOST_DEFUN([Format], [BOOST_FIND_HEADER([boost/format.hpp])]) # BOOST_FUNCTION() # ---------------- # Look for Boost.Function BOOST_DEFUN([Function], [BOOST_FIND_HEADER([boost/function.hpp])]) # BOOST_FUSION() # ----------------- # Look for Boost.Fusion BOOST_DEFUN([Fusion], [BOOST_FIND_HEADER([boost/fusion/sequence.hpp])]) # BOOST_GEOMETRY() # ---------------- # Look for Boost.Geometry (new since 1.47.0). BOOST_DEFUN([Geometry], [BOOST_FIND_HEADER([boost/geometry.hpp]) ])# BOOST_GEOMETRY # BOOST_GRAPH([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ------------------------------- # Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Graph], [boost_graph_save_LIBS=$LIBS boost_graph_save_LDFLAGS=$LDFLAGS # Link-time dependency from graph to regex was added as of 1.40.0. if test $boost_major_version -ge 140; then BOOST_REGEX([$1], [$2]) m4_pattern_allow([^BOOST_REGEX_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_REGEX_LIBS" LDFLAGS="$LDFLAGS $BOOST_REGEX_LDFLAGS" fi BOOST_FIND_LIB([graph], [$1], [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;], [], [], [$2]) LIBS=$boost_graph_save_LIBS LDFLAGS=$boost_graph_save_LDFLAGS ])# BOOST_GRAPH # BOOST_HASH() # ------------ # Look for Boost.Functional/Hash BOOST_DEFUN([Hash], [BOOST_FIND_HEADER([boost/functional/hash.hpp])]) # BOOST_IOSTREAMS([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ----------------------------------- # Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([IOStreams], [BOOST_FIND_LIB([iostreams], [$1], [boost/iostreams/device/file_descriptor.hpp], [boost::iostreams::file_descriptor fd; fd.close();], [], [], [$2]) ])# BOOST_IOSTREAMS # BOOST_ITERATOR() # ------------ # Look for Boost.Iterator BOOST_DEFUN([Iterator], [BOOST_FIND_HEADER([boost/iterator/iterator_adaptor.hpp])]) # BOOST_LAMBDA() # -------------- # Look for Boost.Lambda BOOST_DEFUN([Lambda], [BOOST_FIND_HEADER([boost/lambda/lambda.hpp])]) # BOOST_LOCALE([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # -------------- # Look for Boost.Locale BOOST_DEFUN([Locale], [ boost_locale_save_LIBS=$LIBS boost_locale_save_LDFLAGS=$LDFLAGS # require SYSTEM for boost-1.50.0 and up if test $boost_major_version -ge 150; then BOOST_SYSTEM([$1], [$2]) m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" fi # end of the Boost.System check. BOOST_FIND_LIB([locale], [$1], [boost/locale.hpp], [[boost::locale::generator gen; std::locale::global(gen(""));]], [], [], [$2]) LIBS=$boost_locale_save_LIBS LDFLAGS=$boost_locale_save_LDFLAGS ])# BOOST_LOCALE # BOOST_LOG([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ----------------------------- # Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Log], [boost_log_save_LIBS=$LIBS boost_log_save_LDFLAGS=$LDFLAGS BOOST_SYSTEM([$1], [$2]) BOOST_FILESYSTEM([$1], [$2]) BOOST_DATE_TIME([$1], [$2]) m4_pattern_allow([^BOOST_(SYSTEM|FILESYSTEM|DATE_TIME)_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_DATE_TIME_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_DATE_TIME_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS $BOOST_SYSTEM_LDFLAGS" BOOST_FIND_LIB([log], [$1], [boost/log/core/core.hpp], [boost::log::attribute a; a.get_value();], [], [], [$2]) LIBS=$boost_log_save_LIBS LDFLAGS=$boost_log_save_LDFLAGS ])# BOOST_LOG # BOOST_LOG_SETUP([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ----------------------------------- # Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Log_Setup], [boost_log_setup_save_LIBS=$LIBS boost_log_setup_save_LDFLAGS=$LDFLAGS BOOST_LOG([$1]) m4_pattern_allow([^BOOST_LOG_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_LOG_LIBS" LDFLAGS="$LDFLAGS $BOOST_LOG_LDFLAGS" BOOST_FIND_LIB([log_setup], [$1], [boost/log/utility/setup/from_settings.hpp], [boost::log::basic_settings bs; bs.empty();], [], [], [$2]) LIBS=$boost_log_setup_save_LIBS LDFLAGS=$boost_log_setup_save_LDFLAGS ])# BOOST_LOG_SETUP # BOOST_MATH() # ------------ # Look for Boost.Math # TODO: This library isn't header-only but it comes in multiple different # flavors that don't play well with BOOST_FIND_LIB (e.g, libboost_math_c99, # libboost_math_c99f, libboost_math_c99l, libboost_math_tr1, # libboost_math_tr1f, libboost_math_tr1l). This macro must be fixed to do the # right thing anyway. BOOST_DEFUN([Math], [BOOST_FIND_HEADER([boost/math/special_functions.hpp])]) # BOOST_MPI([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ------------------------------- # Look for Boost MPI. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. Uses MPICXX variable if it is # set, otherwise tries CXX # BOOST_DEFUN([MPI], [boost_save_CXX=${CXX} boost_save_CXXCPP=${CXXCPP} if test x"${MPICXX}" != x; then CXX=${MPICXX} CXXCPP="${MPICXX} -E" fi BOOST_FIND_LIB([mpi], [$1], [boost/mpi.hpp], [int argc = 0; char **argv = 0; boost::mpi::environment env(argc,argv);], [], [], [$2]) CXX=${boost_save_CXX} CXXCPP=${boost_save_CXXCPP} ])# BOOST_MPI # BOOST_MPL() # ------------------ # Look for Boost.MPL BOOST_DEFUN([MPL], [BOOST_FIND_HEADER([boost/mpl/for_each.hpp])]) # BOOST_MULTIARRAY() # ------------------ # Look for Boost.MultiArray BOOST_DEFUN([MultiArray], [BOOST_FIND_HEADER([boost/multi_array.hpp])]) # BOOST_MULTIINDEXCCONTAINER() # ------------------ # Look for Boost.MultiIndexContainer BOOST_DEFUN([MultiIndexContainer], [BOOST_FIND_HEADER([boost/multi_index_container.hpp])]) # BOOST_NUMERIC_UBLAS() # -------------------------- # Look for Boost.NumericUblas (Basic Linear Algebra) BOOST_DEFUN([Numeric_Ublas], [BOOST_FIND_HEADER([boost/numeric/ublas/vector.hpp]) ])# BOOST_NUMERIC_UBLAS # BOOST_NUMERIC_CONVERSION() # -------------------------- # Look for Boost.NumericConversion (policy-based numeric conversion) BOOST_DEFUN([Numeric_Conversion], [BOOST_FIND_HEADER([boost/numeric/conversion/converter.hpp]) ])# BOOST_NUMERIC_CONVERSION # BOOST_OPTIONAL() # ---------------- # Look for Boost.Optional BOOST_DEFUN([Optional], [BOOST_FIND_HEADER([boost/optional.hpp])]) # BOOST_PREPROCESSOR() # -------------------- # Look for Boost.Preprocessor BOOST_DEFUN([Preprocessor], [BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])]) # BOOST_PROPERTY_TREE([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ----------------------------------------- # Look for Boost.Property_Tree. For the documentation of PREFERRED-RT-OPT, # see the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Property_Tree], [BOOST_FIND_LIB([property_tree], [$1], [boost/property_tree/ptree.hpp], [boost::property_tree::ptree pt; boost::property_tree::read_xml d("test", pt);], [], [], [$2]) ])# BOOST_PROPERTY_TREE # BOOST_RANDOM() # -------------------- # Look for Boost.Random BOOST_DEFUN([Random], [BOOST_FIND_HEADER([boost/random/random_number_generator.hpp])]) # BOOST_RANGE() # -------------------- # Look for Boost.Range BOOST_DEFUN([Range], [BOOST_FIND_HEADER([boost/range/adaptors.hpp])]) # BOOST_UNORDERED() # ----------------- # Look for Boost.Unordered BOOST_DEFUN([Unordered], [BOOST_FIND_HEADER([boost/unordered_map.hpp])]) # BOOST_UUID() # ------------ # Look for Boost.Uuid BOOST_DEFUN([Uuid], [BOOST_FIND_HEADER([boost/uuid/uuid.hpp])]) # BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ----------------------------------------- # Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT, # see the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Program_Options], [BOOST_FIND_LIB([program_options], [$1], [boost/program_options.hpp], [boost::program_options::options_description d("test");], [], [], [$2]) ])# BOOST_PROGRAM_OPTIONS # _BOOST_PYTHON_CONFIG(VARIABLE, FLAG) # ------------------------------------ # Save VARIABLE, and define it via `python-config --FLAG`. # Substitute BOOST_PYTHON_VARIABLE. m4_define([_BOOST_PYTHON_CONFIG], [AC_SUBST([BOOST_PYTHON_$1], [`python-config --$2 2>/dev/null`])dnl boost_python_save_$1=$$1 $1="$$1 $BOOST_PYTHON_$1"]) # BOOST_PYTHON([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # -------------------------------- # Look for Boost.Python. For the documentation of PREFERRED-RT-OPT, # see the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Python], [_BOOST_PYTHON_CONFIG([CPPFLAGS], [includes]) _BOOST_PYTHON_CONFIG([LDFLAGS], [ldflags]) _BOOST_PYTHON_CONFIG([LIBS], [libs]) m4_pattern_allow([^BOOST_PYTHON_MODULE$])dnl BOOST_FIND_LIBS([python], [python python3], [$1], [boost/python.hpp], [], [BOOST_PYTHON_MODULE(empty) {}], [], [$2]) CPPFLAGS=$boost_python_save_CPPFLAGS LDFLAGS=$boost_python_save_LDFLAGS LIBS=$boost_python_save_LIBS ])# BOOST_PYTHON # BOOST_REF() # ----------- # Look for Boost.Ref BOOST_DEFUN([Ref], [BOOST_FIND_HEADER([boost/ref.hpp])]) # BOOST_REGEX([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ------------------------------- # Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Regex], [BOOST_FIND_LIB([regex], [$1], [boost/regex.hpp], [boost::regex exp("*"); boost::regex_match("foo", exp);], [], [], [$2]) ])# BOOST_REGEX # BOOST_SCOPE_EXIT() # ------------ # Look for Boost.ScopeExit. BOOST_DEFUN([SCOPE_EXIT], [BOOST_FIND_HEADER([boost/scope_exit.hpp])]) # BOOST_SERIALIZATION([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # --------------------------------------- # Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see # the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Serialization], [BOOST_FIND_LIB([serialization], [$1], [boost/archive/text_oarchive.hpp], [std::ostream* o = 0; // Cheap way to get an ostream... boost::archive::text_oarchive t(*o);], [], [], [$2]) ])# BOOST_SERIALIZATION # BOOST_SIGNALS([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # --------------------------------- # Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Signals], [BOOST_FIND_LIB([signals], [$1], [boost/signal.hpp], [boost::signal s;], [], [], [$2]) ])# BOOST_SIGNALS # BOOST_SIGNALS2() # ---------------- # Look for Boost.Signals2 (new since 1.39.0). BOOST_DEFUN([Signals2], [BOOST_FIND_HEADER([boost/signals2.hpp]) ])# BOOST_SIGNALS2 # BOOST_SMART_PTR() # ----------------- # Look for Boost.SmartPtr BOOST_DEFUN([Smart_Ptr], [BOOST_FIND_HEADER([boost/scoped_ptr.hpp]) BOOST_FIND_HEADER([boost/shared_ptr.hpp]) ]) # BOOST_STATICASSERT() # -------------------- # Look for Boost.StaticAssert BOOST_DEFUN([StaticAssert], [BOOST_FIND_HEADER([boost/static_assert.hpp])]) # BOOST_STRING_ALGO() # ------------------- # Look for Boost.StringAlgo BOOST_DEFUN([String_Algo], [BOOST_FIND_HEADER([boost/algorithm/string.hpp]) ]) # BOOST_SYSTEM([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # -------------------------------- # Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. This library was introduced in Boost # 1.35.0. BOOST_DEFUN([System], [BOOST_FIND_LIB([system], [$1], [boost/system/error_code.hpp], [boost::system::error_code e; e.clear();], [], [], [$2]) ])# BOOST_SYSTEM # BOOST_TEST([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ------------------------------ # Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Test], [m4_pattern_allow([^BOOST_CHECK$])dnl BOOST_FIND_LIB([unit_test_framework], [$1], [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);], [using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int argc, char ** argv) { return NULL; }], [], [$2]) ])# BOOST_TEST # BOOST_THREAD([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # --------------------------------- # Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Thread], [dnl Having the pthread flag is required at least on GCC3 where dnl boost/thread.hpp would complain if we try to compile without dnl -pthread on GNU/Linux. AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl boost_thread_save_LIBS=$LIBS boost_thread_save_LDFLAGS=$LDFLAGS boost_thread_save_CPPFLAGS=$CPPFLAGS # Link-time dependency from thread to system was added as of 1.49.0. if test $boost_major_version -ge 149; then BOOST_SYSTEM([$1], [$2]) fi # end of the Boost.System check. m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag" # When compiling for the Windows platform, the threads library is named # differently. This suffix doesn't exist in new versions of Boost, or # possibly new versions of GCC on mingw I am assuming it's Boost's change for # now and I am setting version to 1.48, for lack of knowledge as to when this # change occurred. if test $boost_major_version -lt 148; then case $host_os in (*mingw*) boost_thread_lib_ext=_win32;; esac fi BOOST_FIND_LIBS([thread], [thread$boost_thread_lib_ext], [$1], [boost/thread.hpp], [boost::thread t; boost::mutex m;], [], [], [$2]) case $host_os in (*mingw*) boost_thread_w32_socket_link=-lws2_32;; esac BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag $boost_thread_w32_socket_link" BOOST_THREAD_LDFLAGS="$BOOST_SYSTEM_LDFLAGS" BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag" LIBS=$boost_thread_save_LIBS LDFLAGS=$boost_thread_save_LDFLAGS CPPFLAGS=$boost_thread_save_CPPFLAGS ])# BOOST_THREAD AU_ALIAS([BOOST_THREADS], [BOOST_THREAD]) # BOOST_TOKENIZER() # ----------------- # Look for Boost.Tokenizer BOOST_DEFUN([Tokenizer], [BOOST_FIND_HEADER([boost/tokenizer.hpp])]) # BOOST_TRIBOOL() # --------------- # Look for Boost.Tribool BOOST_DEFUN([Tribool], [BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp]) BOOST_FIND_HEADER([boost/logic/tribool.hpp]) ]) # BOOST_TUPLE() # ------------- # Look for Boost.Tuple BOOST_DEFUN([Tuple], [BOOST_FIND_HEADER([boost/tuple/tuple.hpp])]) # BOOST_TYPETRAITS() # -------------------- # Look for Boost.TypeTraits BOOST_DEFUN([TypeTraits], [BOOST_FIND_HEADER([boost/type_traits.hpp])]) # BOOST_UTILITY() # --------------- # Look for Boost.Utility (noncopyable, result_of, base-from-member idiom, # etc.) BOOST_DEFUN([Utility], [BOOST_FIND_HEADER([boost/utility.hpp])]) # BOOST_VARIANT() # --------------- # Look for Boost.Variant. BOOST_DEFUN([Variant], [BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp]) BOOST_FIND_HEADER([boost/variant.hpp])]) # BOOST_POINTER_CONTAINER() # ------------------------ # Look for Boost.PointerContainer BOOST_DEFUN([Pointer_Container], [BOOST_FIND_HEADER([boost/ptr_container/ptr_deque.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_list.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_vector.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_array.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_set.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_map.hpp]) ])# BOOST_POINTER_CONTAINER # BOOST_WAVE([PREFERRED-RT-OPT], [ERROR_ON_UNUSABLE]) # ------------------------------ # NOTE: If you intend to use Wave/Spirit with thread support, make sure you # call BOOST_THREAD first. # Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Wave], [AC_REQUIRE([BOOST_FILESYSTEM])dnl AC_REQUIRE([BOOST_DATE_TIME])dnl boost_wave_save_LIBS=$LIBS boost_wave_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS \ $BOOST_THREAD_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS \ $BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS" BOOST_FIND_LIB([wave], [$1], [boost/wave.hpp], [boost::wave::token_id id; get_token_name(id);], [], [], [$2]) LIBS=$boost_wave_save_LIBS LDFLAGS=$boost_wave_save_LDFLAGS ])# BOOST_WAVE # BOOST_XPRESSIVE() # ----------------- # Look for Boost.Xpressive (new since 1.36.0). BOOST_DEFUN([Xpressive], [BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])]) # ----------------- # # Internal helpers. # # ----------------- # # _BOOST_PTHREAD_FLAG() # --------------------- # Internal helper for BOOST_THREAD. Computes boost_cv_pthread_flag # which must be used in CPPFLAGS and LIBS. # # Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3, # boost/thread.hpp will trigger a #error if -pthread isn't used: # boost/config/requires_threads.hpp:47:5: #error "Compiler threading support # is not turned on. Please set the correct command line options for # threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" # # Based on ACX_PTHREAD: http://autoconf-archive.cryp.to/acx_pthread.html AC_DEFUN([_BOOST_PTHREAD_FLAG], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_LANG_PUSH([C++])dnl AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag], [ boost_cv_pthread_flag= # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # (none): in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -lpthreads: AIX (must check this before -lpthread) # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads) # -pthreads: Solaris/GCC # -mthreads: MinGW32/GCC, Lynx/GCC # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # -lpthread: GNU Linux, etc. # --thread-safe: KAI C++ case $host_os in #( *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #( *) boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \ -pthreads -mthreads -lpthread --thread-safe -mt";; esac # Generate the test file. AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0);])]) for boost_pthread_flag in '' $boost_pthread_flags; do boost_pthread_ok=false dnl Re-use the test file already generated. boost_pthreads__save_LIBS=$LIBS LIBS="$LIBS $boost_pthread_flag" AC_LINK_IFELSE([], [if grep ".*$boost_pthread_flag" conftest.err; then echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD else boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag fi]) LIBS=$boost_pthreads__save_LIBS $boost_pthread_ok && break done ]) AC_LANG_POP([C++])dnl ])# _BOOST_PTHREAD_FLAG # _BOOST_gcc_test(MAJOR, MINOR) # ----------------------------- # Internal helper for _BOOST_FIND_COMPILER_TAG. m4_define([_BOOST_gcc_test], ["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl # _BOOST_mingw_test(MAJOR, MINOR) # ----------------------------- # Internal helper for _BOOST_FIND_COMPILER_TAG. m4_define([_BOOST_mingw_test], ["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC && \ (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw$1$2"])dnl # _BOOST_FIND_COMPILER_TAG() # -------------------------- # Internal. When Boost is installed without --layout=system, each library # filename will hold a suffix that encodes the compiler used during the # build. The Boost build system seems to call this a `tag'. AC_DEFUN([_BOOST_FIND_COMPILER_TAG], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], [boost_cv_lib_tag], [boost_cv_lib_tag=unknown if test x$boost_cv_inc_path != xno; then AC_LANG_PUSH([C++])dnl # The following tests are mostly inspired by boost/config/auto_link.hpp # The list is sorted to most recent/common to oldest compiler (in order # to increase the likelihood of finding the right compiler with the # least number of compilation attempt). # Beware that some tests are sensible to the order (for instance, we must # look for MinGW before looking for GCC3). # I used one compilation test per compiler with a #error to recognize # each compiler so that it works even when cross-compiling (let me know # if you know a better approach). # Known missing tags (known from Boost's tools/build/v2/tools/common.jam): # como, edg, kcc, bck, mp, sw, tru, xlc # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines # the same defines as GCC's). for i in \ "defined __clang__ && __clang_major__ == 8 && __clang_minor__ == 0 @ clang80" \ "defined __clang__ && __clang_major__ == 7 && __clang_minor__ == 0 @ clang70" \ "defined __clang__ && __clang_major__ == 6 && __clang_minor__ == 0 @ clang60" \ "defined __clang__ && __clang_major__ == 5 && __clang_minor__ == 0 @ clang50" \ "defined __clang__ && __clang_major__ == 4 && __clang_minor__ == 0 @ clang40" \ "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 9 @ clang39" \ "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 8 @ clang38" \ "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 7 @ clang37" \ _BOOST_mingw_test(9, 1) \ _BOOST_gcc_test(9, 1) \ _BOOST_mingw_test(9, 0) \ _BOOST_gcc_test(9, 0) \ _BOOST_mingw_test(8, 3) \ _BOOST_gcc_test(8, 3) \ _BOOST_mingw_test(8, 2) \ _BOOST_gcc_test(8, 2) \ _BOOST_mingw_test(8, 1) \ _BOOST_gcc_test(8, 1) \ _BOOST_mingw_test(8, 0) \ _BOOST_gcc_test(8, 0) \ _BOOST_mingw_test(7, 3) \ _BOOST_gcc_test(7, 3) \ _BOOST_mingw_test(7, 2) \ _BOOST_gcc_test(7, 2) \ _BOOST_mingw_test(7, 1) \ _BOOST_gcc_test(7, 1) \ _BOOST_mingw_test(7, 0) \ _BOOST_gcc_test(7, 0) \ _BOOST_mingw_test(6, 4) \ _BOOST_gcc_test(6, 4) \ _BOOST_mingw_test(6, 3) \ _BOOST_gcc_test(6, 3) \ _BOOST_mingw_test(6, 2) \ _BOOST_gcc_test(6, 2) \ _BOOST_mingw_test(6, 1) \ _BOOST_gcc_test(6, 1) \ _BOOST_mingw_test(6, 0) \ _BOOST_gcc_test(6, 0) \ _BOOST_mingw_test(5, 5) \ _BOOST_gcc_test(5, 5) \ _BOOST_mingw_test(5, 4) \ _BOOST_gcc_test(5, 4) \ _BOOST_mingw_test(5, 3) \ _BOOST_gcc_test(5, 3) \ _BOOST_mingw_test(5, 2) \ _BOOST_gcc_test(5, 2) \ _BOOST_mingw_test(5, 1) \ _BOOST_gcc_test(5, 1) \ _BOOST_mingw_test(5, 0) \ _BOOST_gcc_test(5, 0) \ _BOOST_mingw_test(4, 10) \ _BOOST_gcc_test(4, 10) \ _BOOST_mingw_test(4, 9) \ _BOOST_gcc_test(4, 9) \ _BOOST_mingw_test(4, 8) \ _BOOST_gcc_test(4, 8) \ _BOOST_mingw_test(4, 7) \ _BOOST_gcc_test(4, 7) \ _BOOST_mingw_test(4, 6) \ _BOOST_gcc_test(4, 6) \ _BOOST_mingw_test(4, 5) \ _BOOST_gcc_test(4, 5) \ _BOOST_mingw_test(4, 4) \ _BOOST_gcc_test(4, 4) \ _BOOST_mingw_test(4, 3) \ _BOOST_gcc_test(4, 3) \ _BOOST_mingw_test(4, 2) \ _BOOST_gcc_test(4, 2) \ _BOOST_mingw_test(4, 1) \ _BOOST_gcc_test(4, 1) \ _BOOST_mingw_test(4, 0) \ _BOOST_gcc_test(4, 0) \ "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \ && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \ _BOOST_gcc_test(3, 4) \ _BOOST_gcc_test(3, 3) \ "defined _MSC_VER && _MSC_VER >= 1500 @ vc90" \ "defined _MSC_VER && _MSC_VER == 1400 @ vc80" \ _BOOST_gcc_test(3, 2) \ "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \ _BOOST_gcc_test(3, 1) \ _BOOST_gcc_test(3, 0) \ "defined __BORLANDC__ @ bcb" \ "defined __ICC && (defined __unix || defined __unix__) @ il" \ "defined __ICL @ iw" \ "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \ _BOOST_gcc_test(2, 95) \ "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \ "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \ "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \ "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8" do boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '` boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'` AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if $boost_tag_test /* OK */ #else # error $boost_tag_test #endif ]])], [boost_cv_lib_tag=$boost_tag; break], []) done AC_LANG_POP([C++])dnl case $boost_cv_lib_tag in #( # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed # to "gcc41" for instance. *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there. gcc*) boost_tag_x= case $host_os in #( darwin*) if test $boost_major_version -ge 136; then # The `x' added in r46793 of Boost. boost_tag_x=x fi;; esac # We can specify multiple tags in this variable because it's used by # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ... boost_cv_lib_tag="$boost_tag_x$boost_cv_lib_tag -${boost_tag_x}gcc" ;; #( unknown) AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]]) boost_cv_lib_tag= ;; esac fi])dnl end of AC_CACHE_CHECK ])# _BOOST_FIND_COMPILER_TAG # _BOOST_GUESS_WHETHER_TO_USE_MT() # -------------------------------- # Compile a small test to try to guess whether we should favor MT (Multi # Thread) flavors of Boost. Sets boost_guess_use_mt accordingly. AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT], [# Check whether we do better use `mt' even though we weren't ask to. AC_LANG_PUSH([C++])dnl AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if defined _REENTRANT || defined _MT || defined __MT__ /* use -mt */ #else # error MT not needed #endif ]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false]) AC_LANG_POP([C++])dnl ]) # _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # ------------------------------------------------------------------- # Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile, # will break when Autoconf changes its internals. Requires that you manually # rm -f conftest.$ac_objext in between to really different tests, otherwise # you will try to link a conftest.o left behind by a previous test. # Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this # macro). # # Don't use "break" in the actions, as it would short-circuit some code # this macro runs after the actions. m4_define([_BOOST_AC_LINK_IFELSE], [m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl rm -f conftest$ac_exeext boost_save_ac_ext=$ac_ext boost_use_source=: # If we already have a .o, re-use it. We change $ac_ext so that $ac_link # tries to link the existing object file instead of compiling from source. test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && _AS_ECHO_LOG([re-using the existing conftest.$ac_objext]) AS_IF([_AC_DO_STDERR($ac_link) && { test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_executable_p conftest$ac_exeext dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough. }], [$2], [if $boost_use_source; then _AC_MSG_LOG_CONFTEST fi $3]) ac_objext=$boost_save_ac_objext ac_ext=$boost_save_ac_ext dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization) dnl information created by the PGI compiler (conftest_ipa8_conftest.oo), dnl as it would interfere with the next link command. rm -f core conftest.err conftest_ipa8_conftest.oo \ conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl ])# _BOOST_AC_LINK_IFELSE # Local Variables: # mode: autoconf # End: morris-0.3/m4/gettext.m4000066400000000000000000000345701373406602200151510ustar00rootroot00000000000000# gettext.m4 serial 60 (gettext-0.17) dnl Copyright (C) 1995-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2006. dnl Macro to add for using GNU gettext. dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The dnl default (if it is not specified or empty) is 'no-libtool'. dnl INTLSYMBOL should be 'external' for packages with no intl directory, dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. dnl If INTLSYMBOL is 'use-libtool', then a libtool library dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, dnl depending on --{enable,disable}-{shared,static} and on the presence of dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library dnl $(top_builddir)/intl/libintl.a will be created. dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext dnl implementations (in libc or libintl) without the ngettext() function dnl will be ignored. If NEEDSYMBOL is specified and is dnl 'need-formatstring-macros', then GNU gettext implementations that don't dnl support the ISO C 99 formatstring macros will be ignored. dnl INTLDIR is used to find the intl libraries. If empty, dnl the value `$(top_builddir)/intl/' is used. dnl dnl The result of the configuration is one of three cases: dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled dnl and used. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 2) GNU gettext has been found in the system's C library. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 3) No internationalization, always use English msgid. dnl Catalog format: none dnl Catalog extension: none dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. dnl The use of .gmo is historical (it was needed to avoid overwriting the dnl GNU format catalogs when building on a platform with an X/Open gettext), dnl but we keep it in order not to force irrelevant filename changes on the dnl maintainers. dnl AC_DEFUN([AM_GNU_GETTEXT], [ dnl Argument checking. ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT ])])])])]) ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT ])])])]) define([gt_included_intl], ifelse([$1], [external], ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), [yes])) define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) gt_NEEDS_INIT AM_GNU_GETTEXT_NEED([$2]) AC_REQUIRE([AM_PO_SUBDIRS])dnl ifelse(gt_included_intl, yes, [ AC_REQUIRE([AM_INTL_SUBDIR])dnl ]) dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Sometimes libintl requires libiconv, so first search for libiconv. dnl Ideally we would do this search only after the dnl if test "$USE_NLS" = "yes"; then dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT dnl the configure script would need to contain the same shell code dnl again, outside any 'if'. There are two solutions: dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not dnl documented, we avoid it. ifelse(gt_included_intl, yes, , [ AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) ]) dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation. gt_INTL_MACOSX dnl Set USE_NLS. AC_REQUIRE([AM_NLS]) ifelse(gt_included_intl, yes, [ BUILD_INCLUDED_LIBINTL=no USE_INCLUDED_LIBINTL=no ]) LIBINTL= LTLIBINTL= POSUB= dnl Add a version number to the cache macros. case " $gt_needs " in *" need-formatstring-macros "*) gt_api_version=3 ;; *" need-ngettext "*) gt_api_version=2 ;; *) gt_api_version=1 ;; esac gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" dnl If we use NLS figure out what method if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no ifelse(gt_included_intl, yes, [ AC_MSG_CHECKING([whether included gettext is requested]) AC_ARG_WITH(included-gettext, [ --with-included-gettext use the GNU gettext library included here], nls_cv_force_use_gnu_gettext=$withval, nls_cv_force_use_gnu_gettext=no) AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" if test "$nls_cv_force_use_gnu_gettext" != "yes"; then ]) dnl User does not insist on using GNU NLS library. Figure out what dnl to use. If GNU gettext is available we use this. Else we have dnl to fall back to GNU NLS library. if test $gt_api_version -ge 3; then gt_revision_test_code=' #ifndef __GNU_GETTEXT_SUPPORTED_REVISION #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) #endif changequote(,)dnl typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; changequote([,])dnl ' else gt_revision_test_code= fi if test $gt_api_version -ge 2; then gt_expression_test_code=' + * ngettext ("", "", 0)' else gt_expression_test_code= fi AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], [AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings;], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings], [eval "$gt_func_gnugettext_libc=yes"], [eval "$gt_func_gnugettext_libc=no"])]) if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then dnl Sometimes libintl requires libiconv, so first search for libiconv. ifelse(gt_included_intl, yes, , [ AM_ICONV_LINK ]) dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) dnl because that would add "-liconv" to LIBINTL and LTLIBINTL dnl even if libiconv doesn't exist. AC_LIB_LINKFLAGS_BODY([intl]) AC_CACHE_CHECK([for GNU gettext in libintl], [$gt_func_gnugettext_libintl], [gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" dnl Now see whether libintl exists and does not depend on libiconv. AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *);], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], [eval "$gt_func_gnugettext_libintl=yes"], [eval "$gt_func_gnugettext_libintl=no"]) dnl Now see whether libintl exists and depends on libiconv. if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *);], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], [LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" eval "$gt_func_gnugettext_libintl=yes" ]) fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS"]) fi dnl If an already present or preinstalled GNU gettext() is found, dnl use it. But if this macro is used in GNU gettext, and GNU dnl gettext is already preinstalled in libintl, we update this dnl libintl. (Cf. the install rule in intl/Makefile.in.) if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ && test "$PACKAGE" != gettext-runtime \ && test "$PACKAGE" != gettext-tools; }; then gt_use_preinstalled_gnugettext=yes else dnl Reset the values set by searching for libintl. LIBINTL= LTLIBINTL= INCINTL= fi ifelse(gt_included_intl, yes, [ if test "$gt_use_preinstalled_gnugettext" != "yes"; then dnl GNU gettext is not found in the C library. dnl Fall back on included GNU gettext library. nls_cv_use_gnu_gettext=yes fi fi if test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions used to generate GNU NLS library. BUILD_INCLUDED_LIBINTL=yes USE_INCLUDED_LIBINTL=yes LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` fi CATOBJEXT= if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions to use GNU gettext tools. CATOBJEXT=.gmo fi ]) if test -n "$INTL_MACOSX_LIBS"; then if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Some extra flags are needed during linking. LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" fi fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then AC_DEFINE(ENABLE_NLS, 1, [Define to 1 if translation of program messages to the user's native language is requested.]) else USE_NLS=no fi fi AC_MSG_CHECKING([whether to use NLS]) AC_MSG_RESULT([$USE_NLS]) if test "$USE_NLS" = "yes"; then AC_MSG_CHECKING([where the gettext function comes from]) if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then gt_source="external libintl" else gt_source="libc" fi else gt_source="included intl directory" fi AC_MSG_RESULT([$gt_source]) fi if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then AC_MSG_CHECKING([how to link with libintl]) AC_MSG_RESULT([$LIBINTL]) AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) fi dnl For backward compatibility. Some packages may be using this. AC_DEFINE(HAVE_GETTEXT, 1, [Define if the GNU gettext() function is already present or preinstalled.]) AC_DEFINE(HAVE_DCGETTEXT, 1, [Define if the GNU dcgettext() function is already present or preinstalled.]) fi dnl We need to process the po/ directory. POSUB=po fi ifelse(gt_included_intl, yes, [ dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL dnl to 'yes' because some of the testsuite requires it. if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then BUILD_INCLUDED_LIBINTL=yes fi dnl Make all variables we use known to autoconf. AC_SUBST(BUILD_INCLUDED_LIBINTL) AC_SUBST(USE_INCLUDED_LIBINTL) AC_SUBST(CATOBJEXT) dnl For backward compatibility. Some configure.ins may be using this. nls_cv_header_intl= nls_cv_header_libgt= dnl For backward compatibility. Some Makefiles may be using this. DATADIRNAME=share AC_SUBST(DATADIRNAME) dnl For backward compatibility. Some Makefiles may be using this. INSTOBJEXT=.mo AC_SUBST(INSTOBJEXT) dnl For backward compatibility. Some Makefiles may be using this. GENCAT=gencat AC_SUBST(GENCAT) dnl For backward compatibility. Some Makefiles may be using this. INTLOBJS= if test "$USE_INCLUDED_LIBINTL" = yes; then INTLOBJS="\$(GETTOBJS)" fi AC_SUBST(INTLOBJS) dnl Enable libtool support if the surrounding package wishes it. INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) ]) dnl For backward compatibility. Some Makefiles may be using this. INTLLIBS="$LIBINTL" AC_SUBST(INTLLIBS) dnl Make all documented variables known to autoconf. AC_SUBST(LIBINTL) AC_SUBST(LTLIBINTL) AC_SUBST(POSUB) ]) dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. m4_define([gt_NEEDS_INIT], [ m4_divert_text([DEFAULTS], [gt_needs=]) m4_define([gt_NEEDS_INIT], []) ]) dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) AC_DEFUN([AM_GNU_GETTEXT_NEED], [ m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) ]) dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) morris-0.3/m4/iconv.m4000066400000000000000000000137531373406602200146030ustar00rootroot00000000000000# iconv.m4 serial AM6 (gettext-0.17) dnl Copyright (C) 2000-2002, 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], [ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_LIB_LINKFLAGS_BODY([iconv]) ]) AC_DEFUN([AM_ICONV_LINK], [ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and dnl those with the standalone portable GNU libiconv installed). AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) dnl Add $INCICONV to CPPFLAGS before performing the following checks, dnl because if the user has installed libiconv and not disabled its use dnl via --without-libiconv-prefix, he wants to use it. The first dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. am_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) AC_CACHE_CHECK([for iconv], am_cv_func_iconv, [ am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], am_cv_func_iconv=yes) if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], am_cv_lib_iconv=yes am_cv_func_iconv=yes) LIBS="$am_save_LIBS" fi ]) if test "$am_cv_func_iconv" = yes; then AC_CACHE_CHECK([for working iconv], am_cv_func_iconv_works, [ dnl This tests against bugs in AIX 5.1 and HP-UX 11.11. am_save_LIBS="$LIBS" if test $am_cv_lib_iconv = yes; then LIBS="$LIBS $LIBICONV" fi AC_TRY_RUN([ #include #include int main () { /* Test against AIX 5.1 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); if (cd_utf8_to_88591 != (iconv_t)(-1)) { static const char input[] = "\342\202\254"; /* EURO SIGN */ char buf[10]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_utf8_to_88591, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) return 1; } } #if 0 /* This bug could be worked around by the caller. */ /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ { iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; char buf[50]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_88591_to_utf8, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if ((int)res > 0) return 1; } } #endif /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is provided. */ if (/* Try standardized names. */ iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) /* Try IRIX, OSF/1 names. */ && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) /* Try AIX names. */ && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) /* Try HP-UX names. */ && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) return 1; return 0; }], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no], [case "$host_os" in aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; *) am_cv_func_iconv_works="guessing yes" ;; esac]) LIBS="$am_save_LIBS" ]) case "$am_cv_func_iconv_works" in *no) am_func_iconv=no am_cv_lib_iconv=no ;; *) am_func_iconv=yes ;; esac else am_func_iconv=no am_cv_lib_iconv=no fi if test "$am_func_iconv" = yes; then AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function and it works.]) fi if test "$am_cv_lib_iconv" = yes; then AC_MSG_CHECKING([how to link with libiconv]) AC_MSG_RESULT([$LIBICONV]) else dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV dnl either. CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi AC_SUBST(LIBICONV) AC_SUBST(LTLIBICONV) ]) AC_DEFUN([AM_ICONV], [ AM_ICONV_LINK if test "$am_cv_func_iconv" = yes; then AC_MSG_CHECKING([for iconv declaration]) AC_CACHE_VAL(am_cv_proto_iconv, [ AC_TRY_COMPILE([ #include #include extern #ifdef __cplusplus "C" #endif #if defined(__STDC__) || defined(__cplusplus) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif ], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` AC_MSG_RESULT([$]{ac_t:- }[$]am_cv_proto_iconv) AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, [Define as const if the declaration of iconv() needs const.]) fi ]) morris-0.3/m4/lib-ld.m4000066400000000000000000000065311373406602200146240ustar00rootroot00000000000000# lib-ld.m4 serial 3 (gettext-0.13) dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl Subroutines of libtool.m4, dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision dnl with libtool.m4. dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. AC_DEFUN([AC_LIB_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by GCC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]* | [A-Za-z]:[\\/]*)] [re_direlt='/[^/][^/]*/\.\./'] # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(acl_cv_path_LD, [if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$acl_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT($LD) else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_LIB_PROG_LD_GNU ]) morris-0.3/m4/lib-link.m4000066400000000000000000000720551373406602200151660ustar00rootroot00000000000000# lib-link.m4 serial 13 (gettext-0.17) dnl Copyright (C) 2001-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_PREREQ(2.54) dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and dnl augments the CPPFLAGS variable. dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ AC_LIB_LINKFLAGS_BODY([$1], [$2]) ac_cv_lib[]Name[]_libs="$LIB[]NAME" ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" ac_cv_lib[]Name[]_cppflags="$INC[]NAME" ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX" ]) LIB[]NAME="$ac_cv_lib[]Name[]_libs" LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" INC[]NAME="$ac_cv_lib[]Name[]_cppflags" LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) AC_SUBST([LIB]NAME[_PREFIX]) dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the dnl results of this search when this library appears as a dependency. HAVE_LIB[]NAME=yes undefine([Name]) undefine([NAME]) ]) dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) dnl searches for libname and the libraries corresponding to explicit and dnl implicit dependencies, together with the specified include files and dnl the ability to compile and link the specified testcode. If found, it dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME dnl accordingly. AC_LIB_LINKFLAGS_BODY([$1], [$2]) dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, dnl because if the user has installed lib[]Name and not disabled its use dnl via --without-lib[]Name-prefix, he wants to use it. ac_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ ac_save_LIBS="$LIBS" LIBS="$LIBS $LIB[]NAME" AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) LIBS="$ac_save_LIBS" ]) if test "$ac_cv_lib[]Name" = yes; then HAVE_LIB[]NAME=yes AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) AC_MSG_CHECKING([how to link with lib[]$1]) AC_MSG_RESULT([$LIB[]NAME]) else HAVE_LIB[]NAME=no dnl If $LIB[]NAME didn't lead to a usable library, we don't need dnl $INC[]NAME either. CPPFLAGS="$ac_save_CPPFLAGS" LIB[]NAME= LTLIB[]NAME= LIB[]NAME[]_PREFIX= fi AC_SUBST([HAVE_LIB]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) AC_SUBST([LIB]NAME[_PREFIX]) undefine([Name]) undefine([NAME]) ]) dnl Determine the platform dependent parameters needed to use rpath: dnl acl_libext, dnl acl_shlibext, dnl acl_hardcode_libdir_flag_spec, dnl acl_hardcode_libdir_separator, dnl acl_hardcode_direct, dnl acl_hardcode_minus_L. AC_DEFUN([AC_LIB_RPATH], [ dnl Tell automake >= 1.10 to complain if config.rpath is missing. m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done ]) wl="$acl_cv_wl" acl_libext="$acl_cv_libext" acl_shlibext="$acl_cv_shlibext" acl_libname_spec="$acl_cv_libname_spec" acl_library_names_spec="$acl_cv_library_names_spec" acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" acl_hardcode_direct="$acl_cv_hardcode_direct" acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" dnl Determine whether the user wants rpath handling at all. AC_ARG_ENABLE(rpath, [ --disable-rpath do not hardcode runtime library paths], :, enable_rpath=yes) ]) dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_LINKFLAGS_BODY], [ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl Autoconf >= 2.61 supports dots in --with options. define([N_A_M_E],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit([$1],[.],[_])],[$1])]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_LIB_ARG_WITH([lib]N_A_M_E[-prefix], [ --with-lib]N_A_M_E[-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib --without-lib]N_A_M_E[-prefix don't search for lib$1 in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi ]) dnl Search the library and its dependencies in $additional_libdir and dnl $LDFLAGS. Using breadth-first-seach. LIB[]NAME= LTLIB[]NAME= INC[]NAME= LIB[]NAME[]_PREFIX= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='$1 $2' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" dnl See if it was already located by an earlier AC_LIB_LINKFLAGS dnl or AC_LIB_HAVE_LINKFLAGS call. uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" else dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined dnl that this library doesn't exist. So just drop it. : fi else dnl Search the library lib$name in $additional_libdir and $LDFLAGS dnl and the already constructed $LIBNAME/$LTLIBNAME. found_dir= found_la= found_so= found_a= eval libname=\"$acl_libname_spec\" # typically: libname=lib$name if test -n "$acl_shlibext"; then shrext=".$acl_shlibext" # typically: shrext=.so else shrext= fi if test $use_additional = yes; then dir="$additional_libdir" dnl The same code as in the loop below: dnl First look for a shared library. if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi dnl Then look for a static library. if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` dnl First look for a shared library. if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi dnl Then look for a static library. if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then dnl Found the library. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then dnl Linking with a shared library. We attempt to hardcode its dnl directory into the executable's runpath, unless it's the dnl standard /usr/lib. if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then dnl No hardcoding is needed. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl Use an explicit option to hardcode DIR into the resulting dnl binary. dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi dnl The hardcoding into $LIBNAME is system dependent. if test "$acl_hardcode_direct" = yes; then dnl Using DIR/libNAME.so during linking hardcodes DIR into the dnl resulting binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then dnl Use an explicit option to hardcode DIR into the resulting dnl binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else dnl Rely on "-L$found_dir". dnl But don't add it if it's already contained in the LDFLAGS dnl or the already constructed $LIBNAME haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" fi if test "$acl_hardcode_minus_L" != no; then dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH dnl here, because this doesn't fit in flags passed to the dnl compiler. So give up. No hardcoding. This affects only dnl very old systems. dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then dnl Linking with a static library. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" else dnl We shouldn't come here, but anyway it's good to have a dnl fallback. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" fi fi dnl Assume the include files are nearby. additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` LIB[]NAME[]_PREFIX="$basedir" additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then dnl Potentially add $additional_includedir to $INCNAME. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's /usr/local/include and we are using GCC on Linux, dnl 3. if it's already present in $CPPFLAGS or the already dnl constructed $INCNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INC[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $INCNAME. INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" fi fi fi fi fi dnl Look for dependencies. if test -n "$found_la"; then dnl Read the .la file. It defines the variables dnl dlname, library_names, old_library, dependency_libs, current, dnl age, revision, installed, dlopen, dlpreopen, libdir. save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" dnl We use only dependency_libs. for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's /usr/local/lib and we are using GCC on Linux, dnl 3. if it's already present in $LDFLAGS or the already dnl constructed $LIBNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LIBNAME. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LTLIBNAME. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) dnl Handle this in the next round. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) dnl Handle this in the next round. Throw away the .la's dnl directory; it is already contained in a preceding -L dnl option. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) dnl Most likely an immediate library name. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" ;; esac done fi else dnl Didn't find the library; assume it is in the system directories dnl known to the linker and runtime loader. (All the system dnl directories known to the linker should also be known to the dnl runtime loader, otherwise the system is severely misconfigured.) LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$acl_hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user must dnl pass all path elements in one option. We can arrange that for a dnl single library, but not when more than one $LIBNAMEs are used. alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" done dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" else dnl The -rpath options are cumulative. for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then dnl When using libtool, the option that works for both libraries and dnl executables is -R. The -R options are cumulative. for found_dir in $ltrpathdirs; do LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" done fi ]) dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, dnl unless already present in VAR. dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes dnl contains two or three consecutive elements that belong together. AC_DEFUN([AC_LIB_APPENDTOVAR], [ for element in [$2]; do haveit= for x in $[$1]; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then [$1]="${[$1]}${[$1]:+ }$element" fi done ]) dnl For those cases where a variable contains several -L and -l options dnl referring to unknown libraries and directories, this macro determines the dnl necessary additional linker options for the runtime path. dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) dnl sets LDADDVAR to linker options needed together with LIBSVALUE. dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, dnl otherwise linking without libtool is assumed. AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], [ AC_REQUIRE([AC_LIB_RPATH]) AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) $1= if test "$enable_rpath" != no; then if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then dnl Use an explicit option to hardcode directories into the resulting dnl binary. rpathdirs= next= for opt in $2; do if test -n "$next"; then dir="$next" dnl No need to hardcode the standard /usr/lib. if test "X$dir" != "X/usr/$acl_libdirstem"; then rpathdirs="$rpathdirs $dir" fi next= else case $opt in -L) next=yes ;; -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` dnl No need to hardcode the standard /usr/lib. if test "X$dir" != "X/usr/$acl_libdirstem"; then rpathdirs="$rpathdirs $dir" fi next= ;; *) next= ;; esac fi done if test "X$rpathdirs" != "X"; then if test -n ""$3""; then dnl libtool is used for linking. Use -R options. for dir in $rpathdirs; do $1="${$1}${$1:+ }-R$dir" done else dnl The linker is used for linking directly. if test -n "$acl_hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user dnl must pass all path elements in one option. alldirs= for dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="$flag" else dnl The -rpath options are cumulative. for dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="${$1}${$1:+ }$flag" done fi fi fi fi fi AC_SUBST([$1]) ]) morris-0.3/m4/lib-prefix.m4000066400000000000000000000150361373406602200155220ustar00rootroot00000000000000# lib-prefix.m4 serial 5 (gettext-0.15) dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't dnl require excessive bracketing. ifdef([AC_HELP_STRING], [AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], [AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed dnl to access previously installed libraries. The basic assumption is that dnl a user will want packages to use other packages he previously installed dnl with the same --prefix option. dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate dnl libraries, but is otherwise very convenient. AC_DEFUN([AC_LIB_PREFIX], [ AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_LIB_ARG_WITH([lib-prefix], [ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib --without-lib-prefix don't search for libraries in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi ]) if test $use_additional = yes; then dnl Potentially add $additional_includedir to $CPPFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's already present in $CPPFLAGS, dnl 3. if it's /usr/local/include and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= for x in $CPPFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $CPPFLAGS. CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" fi fi fi fi dnl Potentially add $additional_libdir to $LDFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's already present in $LDFLAGS, dnl 3. if it's /usr/local/lib and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= for x in $LDFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LDFLAGS. LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" fi fi fi fi fi ]) dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, dnl acl_final_exec_prefix, containing the values to which $prefix and dnl $exec_prefix will expand at the end of the configure script. AC_DEFUN([AC_LIB_PREPARE_PREFIX], [ dnl Unfortunately, prefix and exec_prefix get only finally determined dnl at the end of configure. if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" ]) dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the dnl variables prefix and exec_prefix bound to the values they will have dnl at the end of the configure script. AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], [ acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" $1 exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" ]) dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing dnl the basename of the libdir, either "lib" or "lib64". AC_DEFUN([AC_LIB_PREPARE_MULTILIB], [ dnl There is no formal standard regarding lib and lib64. The current dnl practice is that on a system supporting 32-bit and 64-bit instruction dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit dnl libraries go under $prefix/lib. We determine the compiler's default dnl mode by looking at the compiler's library search path. If at least dnl of its elements ends in /lib64 or points to a directory whose absolute dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the dnl default, namely "lib". acl_libdirstem=lib searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test -n "$searchpath"; then acl_save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) acl_libdirstem=lib64 ;; esac ;; esac fi done IFS="$acl_save_IFS" fi ]) morris-0.3/m4/nls.m4000066400000000000000000000022661373406602200142560ustar00rootroot00000000000000# nls.m4 serial 3 (gettext-0.15) dnl Copyright (C) 1995-2003, 2005-2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. AC_PREREQ(2.50) AC_DEFUN([AM_NLS], [ AC_MSG_CHECKING([whether NLS is requested]) dnl Default is enabled NLS AC_ARG_ENABLE(nls, [ --disable-nls do not use Native Language Support], USE_NLS=$enableval, USE_NLS=yes) AC_MSG_RESULT($USE_NLS) AC_SUBST(USE_NLS) ]) morris-0.3/m4/progtest.m4000066400000000000000000000055501373406602200153300ustar00rootroot00000000000000# progtest.m4 serial 4 (gettext-0.14.2) dnl Copyright (C) 1996-2003, 2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1996. AC_PREREQ(2.50) # Search path for a program which passes the given test. dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) AC_DEFUN([AM_PATH_PROG_WITH_TEST], [ # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "$2", so it can be a program name with args. set dummy $2; ac_word=[$]2 AC_MSG_CHECKING([for $ac_word]) AC_CACHE_VAL(ac_cv_path_$1, [case "[$]$1" in [[\\/]]* | ?:[[\\/]]*) ac_cv_path_$1="[$]$1" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in ifelse([$5], , $PATH, [$5]); do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD if [$3]; then ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" dnl If no 4th arg is given, leave the cache variable unset, dnl so AC_PATH_PROGS will keep looking. ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" ])dnl ;; esac])dnl $1="$ac_cv_path_$1" if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then AC_MSG_RESULT([$]$1) else AC_MSG_RESULT(no) fi AC_SUBST($1)dnl ]) morris-0.3/man/000077500000000000000000000000001373406602200134455ustar00rootroot00000000000000morris-0.3/man/morris.6000066400000000000000000000130351373406602200150510ustar00rootroot00000000000000.\" .TH "morris" "6" "0.2" "" "Games" .SH "NAME" morris \- Nine Men's Morris game for the Gnome desktop .SH "SYNOPSIS" .B morris .SH "DESCRIPTION" Morris is an implementation of the board game "Nine Men's Morris". Other names for this game are: Mills, Merrills, Morris, or Mühle in German. Nine Men's Morris, being probably 2000-3000 years old, appears to be one of the oldest board games, much older than chess. From the 12th to the 18th century, Nine Men's Morris was one of the most popular board games in Europe. However, it is still actively played today and exists in several variants, e.g., Morabaraba, which is particularly popular in South Africa. This implementation of Nine Men's Morris supports not only the standard game, but also several rule-variants and different board layouts. You can play against the computer, or simply use the program to present the board, but play against another human opponent. The computer opponent learns from previous games and tries not to make the same mistake twice. This ensures enough variation in game-play, should you once have managed to beat the program. .SH "FEATURES" .P Among others, the game plays the following variants: .TP - Lasker variant (moves are also allowed in the set-phase) .TP - The Möbius board (invented by Ingo Althöfer) .TP - The Windmill board .TP - The Windmill board .TP - Pentagon and Hexagon boards .TP - Morabaraba .TP - Six and Seven Men's Morris .TP - Tapatan, Achi, Nine Holes .P Furthermore, the game supports: .TP - Advanced AI controls to tweak AI playing style .TP - Giving hints for good moves .TP - Showing the principal variation .TP - Move takeback (undo and redo) .TP - Internationalization (English, German, Chinese) .TP - Many board and rule variations .TP - Free customization of rules .TP - Configurable display .SH "STANDARD RULES" Each player has nine pieces (hence the name, Nine Men's Morris) which are placed and moved on the line crossings of the board. Whenever three pieces of the same color are placed in a straight row, a mill is closed and one opponent piece may be removed. The goal of the game is to reduce the opponent to only two pieces (such that he cannot form a mill anymore), or to surround the opponent pieces in such a way that there are no valid moves for the opponent. The game proceeds in three distinct phases (opening, midgame, and endgame). Unlike chess, these phases are distinguished by special rules for each phase. .TP .B Opening - Setting pieces The white player begins. Each player places one piece on an unoccupied position on the board in turns. If a mill is closed by setting a piece, the player may take one of the opponent's pieces. Once all pieces are set, the midgame starts. .PP .TP .B Midgame - Moving pieces Each player moves one piece along the lines to a free, neighboring position. Again, if the move results in closing a mill, one of the opponent's pieces may be removed. Note that a player must move a piece in each turn. If there is no legal move, the player has lost. .PP .TP .B Endgame - Flying If a player has only three pieces left, he my jump (or fly) with one piece to any unoccupied position instead of moving only along the board lines. .PP .SH "RULE DETAILS AND GAME VARIATIONS" Some of these rules are often interpreted differently, such that a variety of rule variants exist. This game tries to support most of them. In particular, the following rule variations are supported: .TP .B Taking from opponent mills When a mill is closed, one opponent stone may be taken. However, usually, it is not allowed to take a piece from an opponent's mill, if he still has pieces that are not part of a mill. If you want, you can also allow players to take pieces from an opponent's mill. Note that you can always take pieces from an opponent's mill, if all of his pieces are within mills. .PP .TP .B Multiple mills In the setting phase, it may happen that two mills are closed simultaneously. In the multiple-mills variations, the player may take two opponent pieces, in this case. .PP .TP .B Flying Some people prefer to omit the flying rule, such that only standard moves may be conducted, even when a player is down to only three pieces. .PP .TP .B Lasker variant (proposed by the chess grandmaster Emanuel Lasker) There is no difference between opening and midgame. I.e., a player may decide to move a piece instead of setting a new piece. Usually, this variant is played with 10 pieces instead of only 9. .PP .TP .B Remis If the same board situation appeared for N times (with N usually 3), the game is declared remis. .PP .SH "AI ALGORITHM" The AI algorithm is a standard alpha-beta search in a NegaMax implementation using iterative deepening. It employs a transposition table to quickly find previously computed positions. A special feature is the automatic learning capability: whenever the computer wins or loses a game, it will prefer to obtain or avoid similar situations in the future. This results in a better long-term motivation, since the computer will not make the same mistake twice and the gameplay will be more randomized. The evaluation function is still quite basic and consists of four parts: .TP .B Material The number of pieces each player has left .PP .TP .B Freedom The number of possible moves a player can conduct .PP .TP .B Mills The number of closed mills .PP .TP .B Experience The learning-bias from previous games. .PP .SH "SEE ALSO" You can find more information at http://nine-mens-morris.net/ For bug reports, patches, or any kind of discussion, contact Dirk Farin morris-0.3/morris.desktop.in000066400000000000000000000002311373406602200162010ustar00rootroot00000000000000[Desktop Entry] Type=Application _Name=Morris _Comment=Nine Mens Morris game Icon=morris Exec=morris Terminal=false Categories=GNOME;GTK;Game;BoardGame; morris-0.3/net.nine-mens-morris.gschema.xml000066400000000000000000000162361373406602200210210ustar00rootroot00000000000000 false Show a game log Show a separate window with the history of the moves played in a game. false Pause on AI players If enabled, the program will pause before an AI-player makes a move. true Show game-over message-box Show a message box with the winner at the end of the game. true Show board coordinates Show the alpha-numeric board coordinates. true Color the board crossing while dragging If this is enabled, the crossings of the board are colored while the user drags a piece to show the valid moves. true Animate the computer moves Whether the computer moves should be shown as small animations. true Animate setting new pieces If enabled, setting new pieces by the computer will be animated. true Animate takes If enabled, taking of opponent stones by the computer will be animated. 1000 Animation speed Speed of pieces in the animation. Actually, the value is the number of milliseconds it takes to move a piece across the whole board. 2500 Delay between animations of takes Delay between the animation of takes and between the move-animation and the first take (in milliseconds). true Share transposition tables between Computer A and B Whether both AI players (Computer A and B) should use the same transposition table. If enables, one AI player will benefit from the calculations of the other. Note that if this is enabled, the evaluation weights of both players have to be set to identical values. 1000 Maximum thinking time Maximum time (in milliseconds) Computer A is allowed to think. 25 Maximum search-depth Maximum search-depth in the game tree for Computer A. 1.0 Evaluation weight for material Evaluation weight for material (number of pieces left, relative to the pieces left of the opponent). 0.2 Evaluation weight for freedom Evaluation weight for freedom (number of possible moves, relative to the possible moves of the opponent). 0.8 Evaluation weight for mills Evaluation weight for complete mills (number of completed mills, relative to the number of the opponent's mills). 1.0 Evaluation weight for experience Evaluation weight for the experience gained during previous games. Positions that lead to winning a game get a bonus, while positions that lead to a lost game are down-rated. 1000 Maximum thinking time Maximum time (in milliseconds) Computer A is allowed to think. 25 Maximum search-depth Maximum search-depth in the game tree for Computer A. 1.0 Evaluation weight for material Evaluation weight for material (number of pieces left, relative to the pieces left of the opponent). 0.2 Evaluation weight for freedom Evaluation weight for freedom (number of possible moves, relative to the possible moves of the opponent). 0.8 Evaluation weight for mills Evaluation weight for complete mills (number of completed mills, relative to the number of the opponent's mills). 1.0 Evaluation weight for experience Evaluation weight for the experience gained during previous games. Positions that lead to winning a game get a bonus, while positions that lead to a lost game are down-rated. morris-0.3/pixmaps/000077500000000000000000000000001373406602200143535ustar00rootroot00000000000000morris-0.3/pixmaps/Makefile.am000066400000000000000000000002651373406602200164120ustar00rootroot00000000000000 EXTRA_DIST = morris.png # board.png pieces.png #pixmapdir = $(datadir)/pixmaps/$(PACKAGE) #pixmap_DATA = board.png pieces.png icondir = $(datadir)/pixmaps icon_DATA = morris.png morris-0.3/pixmaps/morris.png000066400000000000000000000052301373406602200163740ustar00rootroot00000000000000‰PNG  IHDR00Ø`nÐgAMA± üabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÒ,‰ï. IDATxœÍXëÕ?÷5sgÆöú±ÎæI6„G!èBIBÚ†BU•  µ*j¿ôªÔ•*U­ZQ å©H¥@‹ ‚ ïìzñkwçu§l¯í±³Nó¥=²dû7¿¹ç̽çwνCÞxþø2ú¿ k¼ó¥H š¤n­@ÕF Þ%X‹Ø9ç¤" ¥YÑu\-€EDDJ©Ñšm0AÆ !¸Zš÷¤OÔr? ØH­SLçœQªÑF!¢A ” €² Ñ©×M‘²”À.ˆˆ¼ÃRD :U–;Àp† ùF2êåÝ™ë]7£ÃÆÖ“hüÁ«l,s,¥—u¸ ï; ”1FpÜ “J)¹¶{€PÂI/’΢ÕZ]󈈨´¾æÛ1U]ïݸ¡½üëÛúº¦j¢¯lrINͦ©ŠZŸn\¢Œ~7‡H§—-^^Íù2ðÄàgϯº.½~w“,4EJ‰$‰Lp·"IkƒXc5D å¼ì?‡”.¬Ê®ÛØÉ>Lº¬¥ïLdFkóJ›Âð“»ÂIéüî-‚e"„0šù0Ô„‚'‡pÎ;íi² ‚‹ È8sX/’ΗµÖ’iþÖZCào÷Ñûï¬Eaø“Ç÷=pbW–É'ïz­p¨‡L–ýX°^O^~e¾ÕnMò/>W[\£ÔÄ©I´Õ¤Hå–Tcªm¬LœšTÛÈÈË›9 vRZ%išái¥“¤&‰ŒçËí¶Öf-D4V¸*KeœõÄÄ ±Âv¨"DFfÇ4& “ h £¸ó»»dŽŽÈ¦ \ðþÜnÛ¿gïÌÇÆÜ{¨:ÛQŸÛ©5€`p& 6C«ÃãA6‡(gnaQ_ºÃéEñ$ˆ>ø‹_í9{®"Ùw}&¥”Ždzœ$”2ßqÁ$IhàfeŸQJ7 ìÞ ^U-@D­µ~H×qtOá}ð*eßlÇ%¹LÍð*„X0­‰5©Ìß.ý2! ÌP m·uª± d­µtŒÂÃ0üÙûÛÑ+»Nä«shauñÕú››Dó‡?{ëõf…>6ûЮë€åG 3GÐÂúÊ+½}ÁŸÿòé©Wëa>üÈžÿho7┑—RqjâÔ|úy«£ðR!ÿ×§æÍ4QÅt®rPº~­Nïz²+ÖåV+}ᥠÍV«˜ÏŸ|a±¶Æ©±´˜ßr¯ëøq¼VÜvx1Qæ›KkÏ>÷u£Õ,æó/Ÿ\ CÝ›Zˆ”ÛZOb…©¥K—cÁ2¾Ônkmê-)`Nw;¡F“®gIª9eDðÅVKkÝ\µ©¥Ô)­Ã\nŠ1–Z)Xi¤”ê8µfS­5ö cüe@«S²ð‚$‡ïž¹ï®=eOJ!ªÎîŠ>³ëç9¶8—ˆ4j~lM¶œlØ–ªÿý#ûJR®{ðÎÊM³¹‚$ITMp&k_8v¹è³ƒ·–xüÆ)ÇÉKï¶[‹…‚èö d?áíwr9÷[7 UÛÐV8/_)š {ïý%Æéí·N‚1Vˆ$+ƒàé3ËÊâ]·o!Ù!pó͕ѳ„Žk† ãMnìûo,Ù‘F¡“š1VCîfo(©«‘=‚´Ú6Œ“¼7R悵CÍÇ *@H¦@pÆÙ¨#ÎȘnO'wûßÿñìÛ§Úaþô‰ý÷÷jAyçý…êwÉêâ+õ…·ºàö£…™Ãˆdm韗çOmŒ€ˆqÄÑØn?Ò†3¹ÑH^:y±S ž}ja¹%Ê ¯ä«sRQ¼ZÙõ°\¢ ²Raæ^)ƒ(^+ïïâåRÀ úŒ˜:ç€&kŸ 9cïeQοsŽ€+Ê–꫾'{",/Å”ÁôôàF‡¹ Ðbrqðv!Ëh­N›ƒ`½RÊŠ¹¡‡o¬†´4¸ÉpÝ1µ`ËLvÏ€ëí¯¬µ¹á¶ŠÇœ¬G“Ý,8ÂÉÊ^Œ“}«RbÀ®Ž›±VSŠ™€Æšç—Øö È9#t’ìË;¿[¨ÞƒHZó'›KïmâãOOž?õZ#S ÆZiÛ¡©­ÇFkµhm·Œ—½p‹ùê·¥ÌEQ{ËÞ‡5º‰2©²Ê`œje°óIµýú›ÕgŸÿº[ ž^h4ÓTÛT™Ón0‘§¶Þ'eÇkå'ë/=B¿ôÞ1Ÿí—h™Ra¡P&„(ðm´ÖÑzïä.Ö"F)²Ônç¥W[If8D¥Óa&–rÝ‘ËMQÆ€ô÷ÚVœí!„è3âõEA#ÆJÖbÔ:瑦çQ ÝŸžÛòñݳ§O_J¬½ãŽÒÍûò³œ]°ø bê\nSÚ¨ð‚ÑëW7ù›Èž8rÚ¢ÖÉ„;"¼ónM8ìàêæL"dÑêdH€W){LãåI:û‚[*cZϸàU¼2Š:ÂQzXöAnš GÙWcah …‚mwÈ~Cá͋ϷVÎü·Ã=ùô§ÿúG= ßÿòÆ£G¶_C@ƒ²çŽ,ªsRæ.×¶Î>Z_>gL@!ÖZFiw% v^# .ÔÂgþö•ƒX-—ŸyrþÀmÓAÀÇ2:TໞXN™g,Q*œ*”H‚~šÆº«pë(#€`-Ž‚æCF(²®ìç—â™m> *­­µŽ„2‚ÝZÐ)"v@îϸ,ßy‰ËãpÁešRi‘ÄíO|Úôýñ €QðÈÜ–îžýðÌ¥ÄÚJ·ÜP¸sSp ôRçOGöÄñªhµJ&¿h5D¨Õ"BpëÖkÍêûÖÛèŽQØÁIEND®B`‚morris-0.3/po/000077500000000000000000000000001373406602200133105ustar00rootroot00000000000000morris-0.3/po/ChangeLog000066400000000000000000000016021373406602200150610ustar00rootroot000000000000002009-08-02 gettextize * Makefile.in.in: New file, from gettext-0.17. * boldquot.sed: New file, from gettext-0.17. * en@boldquot.header: New file, from gettext-0.17. * en@quot.header: New file, from gettext-0.17. * insert-header.sin: New file, from gettext-0.17. * quot.sed: New file, from gettext-0.17. * remove-potcdate.sin: New file, from gettext-0.17. * Rules-quot: New file, from gettext-0.17. 2009-08-02 gettextize * Makefile.in.in: New file, from gettext-0.17. * boldquot.sed: New file, from gettext-0.17. * en@boldquot.header: New file, from gettext-0.17. * en@quot.header: New file, from gettext-0.17. * insert-header.sin: New file, from gettext-0.17. * quot.sed: New file, from gettext-0.17. * remove-potcdate.sin: New file, from gettext-0.17. * Rules-quot: New file, from gettext-0.17. * POTFILES.in: New file. morris-0.3/po/LINGUAS000066400000000000000000000000111373406602200143250ustar00rootroot00000000000000de zh es morris-0.3/po/Makefile.in.in000066400000000000000000000153631373406602200157720ustar00rootroot00000000000000# Makefile for program source directory in GNU NLS utilities package. # Copyright (C) 1995, 1996, 1997 by Ulrich Drepper # Copyright (C) 2004-2008 Rodney Dawes # # This file may be copied and used freely without restrictions. It may # be used in projects which are not available under a GNU Public License, # but which still want to provide support for the GNU gettext functionality. # # - Modified by Owen Taylor to use GETTEXT_PACKAGE # instead of PACKAGE and to look for po2tbl in ./ not in intl/ # # - Modified by jacob berkman to install # Makefile.in.in and po2tbl.sed.in for use with glib-gettextize # # - Modified by Rodney Dawes for use with intltool # # We have the following line for use by intltoolize: # INTLTOOL_MAKEFILE GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ PACKAGE = @PACKAGE@ VERSION = @VERSION@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datadir = @datadir@ datarootdir = @datarootdir@ libdir = @libdir@ DATADIRNAME = @DATADIRNAME@ itlocaledir = $(prefix)/$(DATADIRNAME)/locale subdir = po install_sh = @install_sh@ # Automake >= 1.8 provides @mkdir_p@. # Until it can be supposed, use the safe fallback: mkdir_p = $(install_sh) -d INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ GMSGFMT = @GMSGFMT@ MSGFMT = @MSGFMT@ XGETTEXT = @XGETTEXT@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot ALL_LINGUAS = @ALL_LINGUAS@ PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; else echo "$(ALL_LINGUAS)"; fi) USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep \^$$lang$$ $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep \^$$lang$$`"; then printf "$$lang "; fi; done; fi) USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)" -o -n "$(LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done) POFILES=$(shell LINGUAS="$(PO_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.po "; done) DISTFILES = Makefile.in.in POTFILES.in $(POFILES) EXTRA_DISTFILES = ChangeLog POTFILES.skip Makevars LINGUAS POTFILES = \ # This comment gets stripped out CATALOGS=$(shell LINGUAS="$(USE_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.gmo "; done) .SUFFIXES: .SUFFIXES: .po .pox .gmo .mo .msg .cat .po.pox: $(MAKE) $(GETTEXT_PACKAGE).pot $(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox .po.mo: $(MSGFMT) -o $@ $< .po.gmo: file=`echo $* | sed 's,.*/,,'`.gmo \ && rm -f $$file && $(GMSGFMT) -o $$file $< .po.cat: sed -f ../intl/po2msg.sed < $< > $*.msg \ && rm -f $@ && gencat $@ $*.msg all: all-@USE_NLS@ all-yes: $(CATALOGS) all-no: $(GETTEXT_PACKAGE).pot: $(POTFILES) $(GENPOT) install: install-data install-data: install-data-@USE_NLS@ install-data-no: all install-data-yes: all linguas="$(USE_LINGUAS)"; \ for lang in $$linguas; do \ dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $$dir; \ if test -r $$lang.gmo; then \ $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \ else \ $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ echo "installing $(srcdir)/$$lang.gmo as" \ "$$dir/$(GETTEXT_PACKAGE).mo"; \ fi; \ if test -r $$lang.gmo.m; then \ $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \ echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \ else \ if test -r $(srcdir)/$$lang.gmo.m ; then \ $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \ $$dir/$(GETTEXT_PACKAGE).mo.m; \ echo "installing $(srcdir)/$$lang.gmo.m as" \ "$$dir/$(GETTEXT_PACKAGE).mo.m"; \ else \ true; \ fi; \ fi; \ done # Empty stubs to satisfy archaic automake needs dvi info tags TAGS ID: # Define this as empty until I found a useful application. install-exec installcheck: uninstall: linguas="$(USE_LINGUAS)"; \ for lang in $$linguas; do \ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ done check: all $(GETTEXT_PACKAGE).pot rm -f missing notexist srcdir=$(srcdir) $(INTLTOOL_UPDATE) -m if [ -r missing -o -r notexist ]; then \ exit 1; \ fi mostlyclean: rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp rm -f .intltool-merge-cache clean: mostlyclean distclean: clean rm -f Makefile Makefile.in POTFILES stamp-it rm -f *.mo *.msg *.cat *.cat.m *.gmo maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f Makefile.in.in distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: $(DISTFILES) dists="$(DISTFILES)"; \ extra_dists="$(EXTRA_DISTFILES)"; \ for file in $$extra_dists; do \ test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \ done; \ for file in $$dists; do \ test -f $$file || file="$(srcdir)/$$file"; \ ln $$file $(distdir) 2> /dev/null \ || cp -p $$file $(distdir); \ done update-po: Makefile $(MAKE) $(GETTEXT_PACKAGE).pot tmpdir=`pwd`; \ linguas="$(USE_LINGUAS)"; \ for lang in $$linguas; do \ echo "$$lang:"; \ result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \ if $$result; then \ if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.gmo failed!"; \ rm -f $$tmpdir/$$lang.new.po; \ fi; \ done Makefile POTFILES: stamp-it @if test ! -f $@; then \ rm -f stamp-it; \ $(MAKE) stamp-it; \ fi stamp-it: Makefile.in.in $(top_builddir)/config.status POTFILES.in cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \ $(SHELL) ./config.status # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: morris-0.3/po/Makevars000066400000000000000000000034171373406602200150110ustar00rootroot00000000000000# Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = $(PACKAGE) # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Dirk Farin # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = $(PACKAGE_BUGREPORT) # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = morris-0.3/po/POTFILES.in000066400000000000000000000004511373406602200150650ustar00rootroot00000000000000# List of source files which contain translatable strings. src/algo_alphabeta.cc src/boardgui.cc src/gtk_appgui.cc src/gtk_menutoolbar.cc src/gtk_movelog.cc src/gtk_prefAI.cc src/gtk_prefDisplay.cc src/gtk_prefRules.cc src/mainapp.cc src/util.hh morris.desktop.in net.nine-mens-morris.gschema.xml morris-0.3/po/de.po000066400000000000000000000345501373406602200142470ustar00rootroot00000000000000# German translations for Morris package. # Copyright (C) 2009 Dirk Farin # This file is distributed under the same license as the Morris package. # Dirk Farin , 2009. # msgid "" msgstr "" "Project-Id-Version: Morris 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-10-25 22:31+0100\n" "PO-Revision-Date: 2009-10-25 22:31+0100\n" "Last-Translator: Dirk Farin \n" "Language-Team: German\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" #: ../src/algo_alphabeta.cc:590 msgid "white" msgstr "weiß" #: ../src/algo_alphabeta.cc:591 msgid "black" msgstr "schwarz" #: ../src/algo_alphabeta.cc:600 #, c-format msgid "%s wins in %d moves)" msgstr "%s gewinnt in %d Zügen)" #: ../src/algo_alphabeta.cc:601 #, c-format msgid "%s wins the next move)" msgstr "%s gewinnt im nächsten Zug)" #: ../src/boardgui.cc:104 #, c-format msgid "You make take %d opponent piece(s)." msgstr "Du darfst %d gegnerische Steine entfernen." #: ../src/gtk_appgui.cc:200 msgid "White has won." msgstr "Weiß hat gewonnen." #: ../src/gtk_appgui.cc:201 msgid "Black has won." msgstr "Schwarz hat gewonnen." #: ../src/gtk_appgui.cc:202 msgid "Tie between both players." msgstr "Unentschieden." #: ../src/gtk_appgui.cc:209 msgid "Game over" msgstr "Spiel ist zu Ende" #: ../src/gtk_appgui.cc:231 msgid "" "A computer adaptation of the Nine-Mens-Morris board game and its variants." msgstr "Eine Computerimplementierung des Mühlespiels und seiner Varianten." #: ../src/gtk_menutoolbar.cc:173 msgid "Game" msgstr "Spiel" #: ../src/gtk_menutoolbar.cc:173 msgid "menu for game-related functions." msgstr "Menü für Funktionen zur Spielsteuerung" #: ../src/gtk_menutoolbar.cc:174 msgid "New game" msgstr "Neues Spiel" #: ../src/gtk_menutoolbar.cc:174 msgid "Start a new game." msgstr "Neues Spiel starten." #: ../src/gtk_menutoolbar.cc:175 msgid "Continue game" msgstr "Spiel fortsetzen" #: ../src/gtk_menutoolbar.cc:175 msgid "Continue a paused game." msgstr "Ein angehaltenes Spiel fortsetzen." #: ../src/gtk_menutoolbar.cc:176 msgid "Force move" msgstr "Zug erzwingen" #: ../src/gtk_menutoolbar.cc:176 msgid "Force computer move (immediately stop calculation)." msgstr "Zug erzwingen (Berechnung unterbrechen)." #: ../src/gtk_menutoolbar.cc:177 msgid "Undo move" msgstr "Zug zurücknehmen" #: ../src/gtk_menutoolbar.cc:177 msgid "Undo last move." msgstr "Letzten Zug zurücknehmen." #: ../src/gtk_menutoolbar.cc:178 msgid "Redo move" msgstr "Zug vorwärts" #: ../src/gtk_menutoolbar.cc:178 msgid "Redo last move." msgstr "Einen Zug vorwärts ziehen." #: ../src/gtk_menutoolbar.cc:179 msgid "Hint" msgstr "Vorschlag" #: ../src/gtk_menutoolbar.cc:179 msgid "Give a hint for the next move." msgstr "Vorschlag für den nächsten Zug geben." #: ../src/gtk_menutoolbar.cc:182 msgid "Options" msgstr "Optionen" #: ../src/gtk_menutoolbar.cc:183 ../src/mainapp.cc:348 msgid "White player" msgstr "Weißer Spieler" #: ../src/gtk_menutoolbar.cc:184 ../src/mainapp.cc:350 msgid "Black player" msgstr "Schwarzer Spieler" #: ../src/gtk_menutoolbar.cc:185 msgid "Swap players" msgstr "Spieler tauschen" #: ../src/gtk_menutoolbar.cc:186 msgid "Configure AI ..." msgstr "KI konfigurieren ..." #: ../src/gtk_menutoolbar.cc:187 msgid "Configure display ..." msgstr "Darstellung konfigurieren ..." #: ../src/gtk_menutoolbar.cc:188 msgid "Configure custom rules ..." msgstr "Eigene Regeln definieren ..." #: ../src/gtk_menutoolbar.cc:189 msgid "Help" msgstr "Hilfe" #: ../src/gtk_menutoolbar.cc:190 msgid "About Morris..." msgstr "Über Morris..." #: ../src/gtk_menutoolbar.cc:191 msgid "Preferences" msgstr "Einstellungen" #: ../src/gtk_menutoolbar.cc:196 ../src/gtk_menutoolbar.cc:204 msgid "Human" msgstr "Mensch" #: ../src/gtk_menutoolbar.cc:197 ../src/gtk_menutoolbar.cc:205 #: ../src/gtk_prefAI.cc:88 msgid "Computer A" msgstr "Computer A" #: ../src/gtk_menutoolbar.cc:198 ../src/gtk_menutoolbar.cc:206 #: ../src/gtk_prefAI.cc:88 msgid "Computer B" msgstr "Computer B" #: ../src/gtk_menutoolbar.cc:199 ../src/gtk_menutoolbar.cc:207 msgid "Network" msgstr "Netzwerk" #: ../src/gtk_menutoolbar.cc:212 msgid "Standard rules" msgstr "Standard Mühleregeln" #: ../src/gtk_menutoolbar.cc:213 ../src/gtk_prefRules.cc:113 msgid "Lasker variant" msgstr "Laskervariante" #: ../src/gtk_menutoolbar.cc:214 ../src/gtk_prefRules.cc:60 msgid "Moebius board" msgstr "Möbiusbrett" #: ../src/gtk_menutoolbar.cc:215 ../src/gtk_prefRules.cc:61 msgid "Morabaraba" msgstr "Morabaraba" #: ../src/gtk_menutoolbar.cc:216 ../src/gtk_prefRules.cc:62 msgid "Windmill" msgstr "Windmühle" #: ../src/gtk_menutoolbar.cc:217 ../src/gtk_prefRules.cc:63 msgid "Sunmill" msgstr "Sonnenmühle" #: ../src/gtk_menutoolbar.cc:218 ../src/gtk_prefRules.cc:68 msgid "Six Men's Morris" msgstr "6-Stein Mühle" #: ../src/gtk_menutoolbar.cc:219 ../src/gtk_prefRules.cc:67 msgid "Seven Men's Morris" msgstr "7-Stein Mühle" #: ../src/gtk_menutoolbar.cc:220 msgid "Triangle board" msgstr "Dreiecksmühle" #: ../src/gtk_menutoolbar.cc:221 msgid "Pentagon board" msgstr "Fünfecksmühle" #: ../src/gtk_menutoolbar.cc:222 msgid "Hexagon board" msgstr "Sechseckmühle" #: ../src/gtk_menutoolbar.cc:223 msgid "Tapatan" msgstr "Tapatan" #: ../src/gtk_menutoolbar.cc:224 msgid "Achi" msgstr "Achi" #: ../src/gtk_menutoolbar.cc:225 ../src/gtk_prefRules.cc:71 msgid "Small triangle" msgstr "Kleines Dreieck" #: ../src/gtk_menutoolbar.cc:226 msgid "Nine Holes" msgstr "Neun Löcher" #: ../src/gtk_menutoolbar.cc:227 msgid "Custom rules" msgstr "Eigene Regeln" #: ../src/gtk_menutoolbar.cc:232 msgid "Pause on AI-player" msgstr "Vor KI-Spieler pausieren" #: ../src/gtk_menutoolbar.cc:232 msgid "Pause before each AI move." msgstr "Vor jedem Computerzug anhalten." #. default #: ../src/gtk_menutoolbar.cc:234 msgid "Show log of moves" msgstr "Zugliste zeigen" #: ../src/gtk_movelog.cc:47 msgid "Move List" msgstr "Zugliste" #: ../src/gtk_movelog.cc:63 msgid "Move" msgstr "Zug" #: ../src/gtk_movelog.cc:71 msgid "White" msgstr "weiß" #: ../src/gtk_movelog.cc:79 msgid "Black" msgstr "schwarz" #: ../src/gtk_movelog.cc:154 msgid "tie" msgstr "unentschieden" #: ../src/gtk_prefAI.cc:76 msgid "AI Preferences" msgstr "KI Einstellungen" #: ../src/gtk_prefAI.cc:119 msgid "thinking process" msgstr "Zugberechnung" #: ../src/gtk_prefAI.cc:122 msgid "max. time" msgstr "max. Zeit" #: ../src/gtk_prefAI.cc:123 msgid "max. depth" msgstr "max. Suchtiefe" #: ../src/gtk_prefAI.cc:135 msgid "evaluation weights" msgstr "Bewertungsgewichte" #: ../src/gtk_prefAI.cc:141 msgid "material" msgstr "Material" #: ../src/gtk_prefAI.cc:142 msgid "freedom" msgstr "Bewegungsfreiheit" #: ../src/gtk_prefAI.cc:143 msgid "mills" msgstr "Mühlen" #: ../src/gtk_prefAI.cc:144 msgid "experience" msgstr "Erfahrung" #: ../src/gtk_prefAI.cc:184 msgid "share transposition table" msgstr "Brettcache gemeinsam benutzen" #: ../src/gtk_prefDisplay.cc:36 msgid "Display Preferences" msgstr "Darstellungseinstellungen" #: ../src/gtk_prefDisplay.cc:48 msgid "animate computer moves" msgstr "Züge des Computers animieren" #: ../src/gtk_prefDisplay.cc:49 msgid "animate setting of pieces" msgstr "Setzen der Steine animieren" #: ../src/gtk_prefDisplay.cc:50 msgid "animate takes" msgstr "Schlagen der Steine animieren" #: ../src/gtk_prefDisplay.cc:51 msgid "colored crossings while dragging" msgstr "Farbige Kreuzungspunkte während dem Ziehen" #: ../src/gtk_prefDisplay.cc:52 msgid "show game-over message box" msgstr "Mitteilungsbox am Ende des Spiels anzeigen" #: ../src/gtk_prefDisplay.cc:53 msgid "show coordinates" msgstr "Brettkoordinaten anzeigen" #: ../src/gtk_prefDisplay.cc:76 msgid "animation speed" msgstr "Animationsgeschwindigkeit" #: ../src/gtk_prefDisplay.cc:96 msgid "take piece delay" msgstr "Verzögerung beim Schlagen" #: ../src/gtk_prefRules.cc:59 msgid "Nine Men's Morris" msgstr "Standardbrett" #: ../src/gtk_prefRules.cc:64 msgid "Triangle" msgstr "Dreieck" #: ../src/gtk_prefRules.cc:65 msgid "Pentagon" msgstr "Fünfeck" #: ../src/gtk_prefRules.cc:66 msgid "Hexagon" msgstr "Sechseck" #: ../src/gtk_prefRules.cc:69 msgid "Small square" msgstr "Kleines Quadrat" #: ../src/gtk_prefRules.cc:70 msgid "Small square with diagonals" msgstr "Kleines Quadrat mit Diagonale" #: ../src/gtk_prefRules.cc:80 msgid "Rule Preferences" msgstr "Regeleinstellungen" #. board selection #: ../src/gtk_prefRules.cc:90 msgid "Board Type" msgstr "Bretttyp" #. #. setup the rule variations #. #: ../src/gtk_prefRules.cc:110 msgid "Rule Variations" msgstr "Regelvariationen" #: ../src/gtk_prefRules.cc:114 msgid "May jump with three pieces" msgstr "Springen mit 3 Steinen" #: ../src/gtk_prefRules.cc:115 msgid "May take from mills always" msgstr "Schlagen von Steinen in einer Mühle" #: ../src/gtk_prefRules.cc:116 msgid "May take multiple pieces" msgstr "Schlagen von mehreren Steinen" #: ../src/gtk_prefRules.cc:125 msgid "Number of pieces" msgstr "Anzahl der Steine" #: ../src/gtk_prefRules.cc:145 msgid "Declare tie after how many repeats" msgstr "Unentschieden nach wievielen Wiederholungen" #: ../src/gtk_prefRules.cc:221 msgid "Your changes require to end the currently running game." msgstr "" "Deine Änderungen machen es notwendig, dass das Spiel neu gestartet wird." #: ../src/gtk_prefRules.cc:222 msgid "Do you want to restart with the changed rules?" msgstr "Willst Du ein neues Spiel mit den geänderten Regeln starten?" #: ../src/mainapp.cc:324 msgid "Game over: white has won!" msgstr "Spielende: weiß hat gewonnen!" #: ../src/mainapp.cc:328 msgid "Game over: black has won!" msgstr "Spielende: Schwarz hat gewonnen!" #: ../src/mainapp.cc:332 msgid "Game ended in a tie between both players." msgstr "Das Spiel ist unentschieden." #: ../src/mainapp.cc:338 msgid "Game paused. Click continue to proceed." msgstr "Spiel angehalten, drücke \"Spiel fortsetzen\" um weiterzuspielen." #: ../src/mainapp.cc:356 msgid "set or move a piece." msgstr "setze oder ziehe einen Stein." #: ../src/mainapp.cc:357 msgid "set a piece." msgstr "setze einen Stein." #: ../src/mainapp.cc:358 msgid "move a piece." msgstr "ziehe einen Stein." #: ../src/mainapp.cc:362 msgid "computer is taking his turn... " msgstr "Computer berechnet seinen Zug... " #: ../morris.desktop.in.h:1 msgid "Morris" msgstr "Mühle" #: ../morris.desktop.in.h:2 msgid "Nine Mens Morris game" msgstr "Mühlespiel" #: ../morris.schemas.in.h:1 msgid "Animate setting new pieces" msgstr "Setzen der Steine animieren" #: ../morris.schemas.in.h:2 msgid "Animate takes" msgstr "Schlagen der Steine animieren" #: ../morris.schemas.in.h:3 msgid "Animate the computer moves" msgstr "Züge des Computers animieren" #: ../morris.schemas.in.h:4 msgid "Animation speed" msgstr "Animationsgeschwindigkeit" #: ../morris.schemas.in.h:5 msgid "Color the board crossing while dragging" msgstr "Farbige Kreuzungspunkte während dem Ziehen" #: ../morris.schemas.in.h:6 msgid "Delay between animations of takes" msgstr "" #: ../morris.schemas.in.h:7 msgid "" "Delay between the animation of takes and between the move-animation and the " "first take (in milliseconds)." msgstr "" #: ../morris.schemas.in.h:8 msgid "" "Evaluation weight for complete mills (number of completed mills, relative to " "the number of the opponent's mills)." msgstr "" #: ../morris.schemas.in.h:9 msgid "Evaluation weight for experience" msgstr "" #: ../morris.schemas.in.h:10 msgid "Evaluation weight for freedom" msgstr "" #: ../morris.schemas.in.h:11 msgid "" "Evaluation weight for freedom (number of possible moves, relative to the " "possible moves of the opponent)." msgstr "" #: ../morris.schemas.in.h:12 msgid "Evaluation weight for material" msgstr "" #: ../morris.schemas.in.h:13 msgid "" "Evaluation weight for material (number of pieces left, relative to the " "pieces left of the opponent)." msgstr "" #: ../morris.schemas.in.h:14 #, fuzzy msgid "Evaluation weight for mills" msgstr "Bewertungsgewichte" #: ../morris.schemas.in.h:15 msgid "" "Evaluation weight for the experience gained during previous games. Positions " "that lead to winning a game get a bonus, while positions that lead to a lost " "game are down-rated." msgstr "" #: ../morris.schemas.in.h:16 msgid "If enabled, setting new pieces by the computer will be animated." msgstr "" #: ../morris.schemas.in.h:17 msgid "If enabled, taking of opponent stones by the computer will be animated." msgstr "" #: ../morris.schemas.in.h:18 msgid "If enabled, the program will pause before an AI-player makes a move." msgstr "" #: ../morris.schemas.in.h:19 msgid "" "If this is enabled, the crossings of the board are colored while the user " "drags a piece to show the valid moves." msgstr "" #: ../morris.schemas.in.h:20 msgid "Maximum search-depth" msgstr "" #: ../morris.schemas.in.h:21 msgid "Maximum search-depth in the game tree for Computer A." msgstr "" #: ../morris.schemas.in.h:22 msgid "Maximum thinking time" msgstr "" #: ../morris.schemas.in.h:23 msgid "Maximum time (in milliseconds) Computer A is allowed to think." msgstr "" #: ../morris.schemas.in.h:24 #, fuzzy msgid "Pause on AI players" msgstr "Vor KI-Spieler pausieren" #: ../morris.schemas.in.h:25 #, fuzzy msgid "Share transposition tables between Computer A and B" msgstr "Brettcache gemeinsam benutzen" #: ../morris.schemas.in.h:26 msgid "Show a game log" msgstr "" #: ../morris.schemas.in.h:27 msgid "Show a message box with the winner at the end of the game." msgstr "" #: ../morris.schemas.in.h:28 msgid "Show a separate window with the history of the moves played in a game." msgstr "" #: ../morris.schemas.in.h:29 #, fuzzy msgid "Show board coordinates" msgstr "Brettkoordinaten anzeigen" #: ../morris.schemas.in.h:30 #, fuzzy msgid "Show game-over message-box" msgstr "Mitteilungsbox am Ende des Spiels anzeigen" #: ../morris.schemas.in.h:31 msgid "Show the alpha-numeric board coordinates." msgstr "" #: ../morris.schemas.in.h:32 msgid "" "Speed of pieces in the animation. Actually, the value is the number of " "milliseconds it takes to move a piece across the whole board." msgstr "" #: ../morris.schemas.in.h:33 msgid "" "Whether both AI players (Computer A and B) should use the same transposition " "table. If enables, one AI player will benefit from the calculations of the " "other. Note that if this is enabled, the evaluation weights of both players " "have to be set to identical values." msgstr "" #: ../morris.schemas.in.h:34 msgid "Whether the computer moves should be shown as small animations." msgstr "" morris-0.3/po/es.po000066400000000000000000000423621373406602200142660ustar00rootroot00000000000000# Spanish translations for Morris package. # Copyright (C) 2013 Miriam Ruiz # This file is distributed under the same license as the Morris package. # Dirk Farin , 2009. # msgid "" msgstr "" "Project-Id-Version: Morris 0.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-07-20 22:30+0100\n" "PO-Revision-Date: 2013-08-13 09:02+0100\n" "Last-Translator: Miriam Ruiz \n" "Language-Team: Spanish\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" "X-Generator: Poedit 1.5.4\n" #: ../src/algo_alphabeta.cc:590 msgid "white" msgstr "blancas" #: ../src/algo_alphabeta.cc:591 msgid "black" msgstr "negras" #: ../src/algo_alphabeta.cc:600 #, c-format msgid "%s wins in %d moves)" msgstr "%s gana en %d movimientos)" #: ../src/algo_alphabeta.cc:601 #, c-format msgid "%s wins the next move)" msgstr "%s gana en el siguiente movimiento)" #: ../src/boardgui.cc:104 #, c-format msgid "You make take %d opponent piece(s)." msgstr "Puedes capturar %d ficha(s) de tu oponente." #: ../src/gtk_appgui.cc:200 msgid "White has won." msgstr "Han ganado las blancas." #: ../src/gtk_appgui.cc:201 msgid "Black has won." msgstr "Han ganado las negras." #: ../src/gtk_appgui.cc:202 msgid "Tie between both players." msgstr "Tablas entre ambos participantes." #: ../src/gtk_appgui.cc:209 msgid "Game over" msgstr "Fin de la partida" #: ../src/gtk_appgui.cc:231 msgid "" "A computer adaptation of the Nine-Mens-Morris board game and its variants." msgstr "Una adaptación del juego de tablero del Molino y sus variantes." #: ../src/gtk_menutoolbar.cc:173 msgid "Game" msgstr "Juego" #: ../src/gtk_menutoolbar.cc:173 msgid "menu for game-related functions." msgstr "Menú de funciones para la partida" #: ../src/gtk_menutoolbar.cc:174 msgid "New game" msgstr "Partida nueva" #: ../src/gtk_menutoolbar.cc:174 msgid "Start a new game." msgstr "Comenzar una nueva partida." #: ../src/gtk_menutoolbar.cc:175 msgid "Continue game" msgstr "Continuar la partida" #: ../src/gtk_menutoolbar.cc:175 msgid "Continue a paused game." msgstr "Continuar una partida pausada." #: ../src/gtk_menutoolbar.cc:176 msgid "Force move" msgstr "Forzar movimiento" #: ../src/gtk_menutoolbar.cc:176 msgid "Force computer move (immediately stop calculation)." msgstr "" "Forzar un movimiento del ordenador (detener inmediatamente los cálculos)." #: ../src/gtk_menutoolbar.cc:177 msgid "Undo move" msgstr "Deshacer movimiento" #: ../src/gtk_menutoolbar.cc:177 msgid "Undo last move." msgstr "Deshacer el último movimiento." #: ../src/gtk_menutoolbar.cc:178 msgid "Redo move" msgstr "Rehacer movimiento" #: ../src/gtk_menutoolbar.cc:178 msgid "Redo last move." msgstr "Rehacer el último movimiento." #: ../src/gtk_menutoolbar.cc:179 msgid "Hint" msgstr "Pista" #: ../src/gtk_menutoolbar.cc:179 msgid "Give a hint for the next move." msgstr "Obtener una pista para el siguiente movimiento" #: ../src/gtk_menutoolbar.cc:182 msgid "Options" msgstr "Opciones" #: ../src/gtk_menutoolbar.cc:183 ../src/mainapp.cc:348 msgid "White player" msgstr "Jugador/a con blancas" #: ../src/gtk_menutoolbar.cc:184 ../src/mainapp.cc:350 msgid "Black player" msgstr "Jugador/a con negras" #: ../src/gtk_menutoolbar.cc:185 msgid "Swap players" msgstr "Intercambiar jugadores/as" #: ../src/gtk_menutoolbar.cc:186 msgid "Configure AI ..." msgstr "Configurar Inteligencia Artificial ..." #: ../src/gtk_menutoolbar.cc:187 msgid "Configure display ..." msgstr "Configurar la visualización ..." #: ../src/gtk_menutoolbar.cc:188 msgid "Configure custom rules ..." msgstr "Configurar las reglas personalizadas ..." #: ../src/gtk_menutoolbar.cc:189 msgid "Help" msgstr "Ayuda" #: ../src/gtk_menutoolbar.cc:190 msgid "About Morris..." msgstr "Sobre el juego del Molino ..." #: ../src/gtk_menutoolbar.cc:191 msgid "Preferences" msgstr "Opciones" #: ../src/gtk_menutoolbar.cc:196 ../src/gtk_menutoolbar.cc:204 msgid "Human" msgstr "Humano/a" #: ../src/gtk_menutoolbar.cc:197 ../src/gtk_menutoolbar.cc:205 #: ../src/gtk_prefAI.cc:88 msgid "Computer A" msgstr "Ordenador A" #: ../src/gtk_menutoolbar.cc:198 ../src/gtk_menutoolbar.cc:206 #: ../src/gtk_prefAI.cc:88 msgid "Computer B" msgstr "Ordenador B" #: ../src/gtk_menutoolbar.cc:199 ../src/gtk_menutoolbar.cc:207 msgid "Network" msgstr "Red" #: ../src/gtk_menutoolbar.cc:212 msgid "Standard rules" msgstr "Reglas estándar" #: ../src/gtk_menutoolbar.cc:213 ../src/gtk_prefRules.cc:113 msgid "Lasker variant" msgstr "Variante Lasker" #: ../src/gtk_menutoolbar.cc:214 ../src/gtk_prefRules.cc:60 msgid "Moebius board" msgstr "Tablero de Moebius" #: ../src/gtk_menutoolbar.cc:215 ../src/gtk_prefRules.cc:61 msgid "Morabaraba" msgstr "Morabaraba" #: ../src/gtk_menutoolbar.cc:216 ../src/gtk_prefRules.cc:62 msgid "Windmill" msgstr "Molino de viento" #: ../src/gtk_menutoolbar.cc:217 ../src/gtk_prefRules.cc:63 msgid "Sunmill" msgstr "Molino solar" #: ../src/gtk_menutoolbar.cc:218 ../src/gtk_prefRules.cc:68 msgid "Six Men's Morris" msgstr "Molino de seis personas" #: ../src/gtk_menutoolbar.cc:219 ../src/gtk_prefRules.cc:67 msgid "Seven Men's Morris" msgstr "Molino de siete personas" #: ../src/gtk_menutoolbar.cc:220 msgid "Triangle board" msgstr "Tablero triangular" #: ../src/gtk_menutoolbar.cc:221 msgid "Pentagon board" msgstr "Tablero pentagonal" #: ../src/gtk_menutoolbar.cc:222 msgid "Hexagon board" msgstr "Tablero hexagonal" #: ../src/gtk_menutoolbar.cc:223 msgid "Tapatan" msgstr "Tapatan" #: ../src/gtk_menutoolbar.cc:224 msgid "Achi" msgstr "Achi" #: ../src/gtk_menutoolbar.cc:225 ../src/gtk_prefRules.cc:71 msgid "Small triangle" msgstr "Triángulo pequeño" #: ../src/gtk_menutoolbar.cc:226 msgid "Nine Holes" msgstr "Nueve agujeros" #: ../src/gtk_menutoolbar.cc:227 msgid "Custom rules" msgstr "Reglas personalizadas" #: ../src/gtk_menutoolbar.cc:232 msgid "Pause on AI-player" msgstr "Pausar al jugador con Inteligencia Artificial" #: ../src/gtk_menutoolbar.cc:232 msgid "Pause before each AI move." msgstr "Pausar la partida antes de cada movimiento de Inteligencia Artificial" #. default #: ../src/gtk_menutoolbar.cc:234 msgid "Show log of moves" msgstr "Mostrar historial de movimientos" #: ../src/gtk_movelog.cc:47 msgid "Move List" msgstr "Lista de movimientos" #: ../src/gtk_movelog.cc:63 msgid "Move" msgstr "Mover" #: ../src/gtk_movelog.cc:71 msgid "White" msgstr "Blancas" #: ../src/gtk_movelog.cc:79 msgid "Black" msgstr "Negras" #: ../src/gtk_movelog.cc:154 msgid "tie" msgstr "empate" #: ../src/gtk_prefAI.cc:76 msgid "AI Preferences" msgstr "Preferencias de Inteligencia Artificial" #: ../src/gtk_prefAI.cc:119 msgid "thinking process" msgstr "pensando/b>" #: ../src/gtk_prefAI.cc:122 msgid "max. time" msgstr "tiempo máx." #: ../src/gtk_prefAI.cc:123 msgid "max. depth" msgstr "Profundidad máx." #: ../src/gtk_prefAI.cc:135 msgid "evaluation weights" msgstr "pesos de evaluación" #: ../src/gtk_prefAI.cc:141 msgid "material" msgstr "material" #: ../src/gtk_prefAI.cc:142 msgid "freedom" msgstr "libertad" #: ../src/gtk_prefAI.cc:143 msgid "mills" msgstr "molinos" #: ../src/gtk_prefAI.cc:144 msgid "experience" msgstr "experiencia" #: ../src/gtk_prefAI.cc:184 msgid "share transposition table" msgstr "compartir la tabla de transposición" #: ../src/gtk_prefDisplay.cc:36 msgid "Display Preferences" msgstr "Mostrar preferencias" #: ../src/gtk_prefDisplay.cc:48 msgid "animate computer moves" msgstr "animar los movimientos del ordenador" #: ../src/gtk_prefDisplay.cc:49 msgid "animate setting of pieces" msgstr "animar el posicionamiento de las fichas" #: ../src/gtk_prefDisplay.cc:50 msgid "animate takes" msgstr "animar las capturas" #: ../src/gtk_prefDisplay.cc:51 msgid "colored crossings while dragging" msgstr "Cruces coloreadas al arrastrar" #: ../src/gtk_prefDisplay.cc:52 msgid "show game-over message box" msgstr "mostrar cuadro de mensaje de fin de partida" #: ../src/gtk_prefDisplay.cc:53 msgid "show coordinates" msgstr "mostrar coordenadas" #: ../src/gtk_prefDisplay.cc:76 msgid "animation speed" msgstr "velocidad de animación" #: ../src/gtk_prefDisplay.cc:96 msgid "take piece delay" msgstr "retraso en la captura de fichas" #: ../src/gtk_prefRules.cc:59 msgid "Nine Men's Morris" msgstr "Molino de nueve personas" #: ../src/gtk_prefRules.cc:64 msgid "Triangle" msgstr "Triángulo" #: ../src/gtk_prefRules.cc:65 msgid "Pentagon" msgstr "Pentágono" #: ../src/gtk_prefRules.cc:66 msgid "Hexagon" msgstr "Hexágono" #: ../src/gtk_prefRules.cc:69 msgid "Small square" msgstr "Cuadrado pequeño" #: ../src/gtk_prefRules.cc:70 msgid "Small square with diagonals" msgstr "Cuadrado pequeño con diagonales" #: ../src/gtk_prefRules.cc:80 msgid "Rule Preferences" msgstr "Preferencias de las reglas" #. board selection #: ../src/gtk_prefRules.cc:90 msgid "Board Type" msgstr "Tipo de tablero" #. #. setup the rule variations #. #: ../src/gtk_prefRules.cc:110 msgid "Rule Variations" msgstr "Variaciones de las reglas" #: ../src/gtk_prefRules.cc:114 msgid "May jump with three pieces" msgstr "Es posible saltar con tres fichas" #: ../src/gtk_prefRules.cc:115 msgid "May take from mills always" msgstr "Siempre se pueden capturar fichas de los molinos" #: ../src/gtk_prefRules.cc:116 msgid "May take multiple pieces" msgstr "Se pueden capturar múltiples fichas" #: ../src/gtk_prefRules.cc:125 msgid "Number of pieces" msgstr "Número de fichas" #: ../src/gtk_prefRules.cc:145 msgid "Declare tie after how many repeats" msgstr "Declarar empate tras cuántas repeticiones" #: ../src/gtk_prefRules.cc:221 msgid "Your changes require to end the currently running game." msgstr "" "Es necesario finalizar la partida actual para aplicar los cambios realizados." #: ../src/gtk_prefRules.cc:222 msgid "Do you want to restart with the changed rules?" msgstr "¿Quieres volver a empezar con las reglas modificadas?" #: ../src/mainapp.cc:324 msgid "Game over: white has won!" msgstr "La partida ha terminado: Han ganado las blancas" #: ../src/mainapp.cc:328 msgid "Game over: black has won!" msgstr "La partida ha terminado: Han ganado las negras" #: ../src/mainapp.cc:332 msgid "Game ended in a tie between both players." msgstr "La partida ha terminado con un empate." #: ../src/mainapp.cc:338 msgid "Game paused. Click continue to proceed." msgstr "Partida pausada. Pulse continuar para seguir." #: ../src/mainapp.cc:356 msgid "set or move a piece." msgstr "poner o mover una ficha." #: ../src/mainapp.cc:357 msgid "set a piece." msgstr "poner una ficha." #: ../src/mainapp.cc:358 msgid "move a piece." msgstr "mover una ficha." #: ../src/mainapp.cc:362 msgid "computer is taking his turn... " msgstr "el ordenador está usando su turno ..." #: ../morris.desktop.in.h:1 msgid "Morris" msgstr "Molino" #: ../morris.desktop.in.h:2 msgid "Nine Mens Morris game" msgstr "Juego del Molino" #: ../morris.schemas.in.h:1 msgid "Animate setting new pieces" msgstr "Animar el posicionamiento de nuevas fichas" #: ../morris.schemas.in.h:2 msgid "Animate takes" msgstr "Animar las capturas" #: ../morris.schemas.in.h:3 msgid "Animate the computer moves" msgstr "Animar los movimientos del ordenador" #: ../morris.schemas.in.h:4 msgid "Animation speed" msgstr "Velocidad de las animaciones" #: ../morris.schemas.in.h:5 msgid "Color the board crossing while dragging" msgstr "Colorea las cruces del tablero al arrastrar" #: ../morris.schemas.in.h:6 msgid "Delay between animations of takes" msgstr "Tiempo de espera entre animaciones de capturas" #: ../morris.schemas.in.h:7 msgid "" "Delay between the animation of takes and between the move-animation and the " "first take (in milliseconds)." msgstr "" "Tiempo de espera entre la animación de las capturas y entre la animación y " "la primera captura (en milisegundos)." #: ../morris.schemas.in.h:8 msgid "" "Evaluation weight for complete mills (number of completed mills, relative to " "the number of the opponent's mills)." msgstr "" "Peso en la evaluación de la finalización de molinos (número de molinos " "completados, relativos al número de molinos del oponente)." #: ../morris.schemas.in.h:9 msgid "Evaluation weight for experience" msgstr "Peso de la experiencia en la evaluación" #: ../morris.schemas.in.h:10 msgid "Evaluation weight for freedom" msgstr "Peso de la libertad en la evaluación" #: ../morris.schemas.in.h:11 msgid "" "Evaluation weight for freedom (number of possible moves, relative to the " "possible moves of the opponent)." msgstr "" "Peso en la evaluación de la libertad (número de movimientos posibles, " "relativos al número de movimientos posibles del oponente)." #: ../morris.schemas.in.h:12 msgid "Evaluation weight for material" msgstr "Peso del material en la evaluación" #: ../morris.schemas.in.h:13 msgid "" "Evaluation weight for material (number of pieces left, relative to the " "pieces left of the opponent)." msgstr "" "Peso en la evaluación del material (número de fichas restantes, relativas al " "número de fichas restantes del oponente)." #: ../morris.schemas.in.h:14 msgid "Evaluation weight for mills" msgstr "Peso de los molinos en la evaluación" #: ../morris.schemas.in.h:15 msgid "" "Evaluation weight for the experience gained during previous games. Positions " "that lead to winning a game get a bonus, while positions that lead to a lost " "game are down-rated." msgstr "" "Peso en la evaluación de la experiencia ganada en partidas anteriores. Las " "posiciones que conducen a una partida ganada obtienen un bono positivo, " "mientras que las que conducen a una partida perdida son infravaloradas." #: ../morris.schemas.in.h:16 msgid "If enabled, setting new pieces by the computer will be animated." msgstr "" "Si está activado, las piezas que se pongan por parte del ordenador estarán " "animadas." #: ../morris.schemas.in.h:17 msgid "If enabled, taking of opponent stones by the computer will be animated." msgstr "" "Si está activado, la captura de fichas de un oponente por parte del " "ordenador estarán animadas." #: ../morris.schemas.in.h:18 msgid "If enabled, the program will pause before an AI-player makes a move." msgstr "" "Si está activado, el programa se pausará antes de que un jugador con " "Inteligencia Artificial realice un movimiento." #: ../morris.schemas.in.h:19 msgid "" "If this is enabled, the crossings of the board are colored while the user " "drags a piece to show the valid moves." msgstr "" "Si está activado, las cruces del tablero serán coloreadas mientras el " "usuario o usuaria arrastre una ficha para mostrar los movimientos válidos." #: ../morris.schemas.in.h:20 msgid "Maximum search-depth" msgstr "Profundidad máxima de búsqueda" #: ../morris.schemas.in.h:21 msgid "Maximum search-depth in the game tree for Computer A." msgstr "" "Profundidad máxima en en las búsquedas en el árbol de la partida para el " "ordenador A." #: ../morris.schemas.in.h:22 msgid "Maximum thinking time" msgstr "Tiempo máximo para pensar" #: ../morris.schemas.in.h:23 msgid "Maximum time (in milliseconds) Computer A is allowed to think." msgstr "Tiempo máximo (en milisegundos) que se permite pensar al ordenador A" #: ../morris.schemas.in.h:24 msgid "Pause on AI players" msgstr "Pausar todos los jugadores con Inteligencia Artificial" #: ../morris.schemas.in.h:25 msgid "Share transposition tables between Computer A and B" msgstr "Compartir las tablas de transposición entre los ordenadores A y B" #: ../morris.schemas.in.h:26 msgid "Show a game log" msgstr "Mostrar el historial de la partida" #: ../morris.schemas.in.h:27 msgid "Show a message box with the winner at the end of the game." msgstr "" "Muestra un cuadro de mensaje con el ganador o ganadora al final de la " "partida." #: ../morris.schemas.in.h:28 msgid "Show a separate window with the history of the moves played in a game." msgstr "" "Mostrar una ventana separada con la historia de los movimientos usados en " "una partida." #: ../morris.schemas.in.h:29 msgid "Show board coordinates" msgstr "Mostrar las coordenadas" #: ../morris.schemas.in.h:30 msgid "Show game-over message-box" msgstr "Mostrar cuadro de mensaje de fin de partida" #: ../morris.schemas.in.h:31 msgid "Show the alpha-numeric board coordinates." msgstr "Mostrar las coordenadas alfanuméricas" #: ../morris.schemas.in.h:32 msgid "" "Speed of pieces in the animation. Actually, the value is the number of " "milliseconds it takes to move a piece across the whole board." msgstr "" "Velocidad de las fichas en la animación. En realidad, este valor define el " "número de milisegundos que es necesario para mover una ficha a lo largo de " "todo el tablero." #: ../morris.schemas.in.h:33 msgid "" "Whether both AI players (Computer A and B) should use the same transposition " "table. If enables, one AI player will benefit from the calculations of the " "other. Note that if this is enabled, the evaluation weights of both players " "have to be set to identical values." msgstr "" "Si los dos jugadores con Inteligencia Artificial (ordenadores A y B) " "deberían usar la misma tabla de transposiciones. Si está activado, cada " "jugador con Inteligencia Artificial se beneficiará de los cálculos del otro. " "Nota: Si está activado, los pesos de evaluación de ambos jugadores han de " "ser asignados con valores iguales." #: ../morris.schemas.in.h:34 msgid "Whether the computer moves should be shown as small animations." msgstr "" "Si los movimientos del ordenador deberían ser mostrados como pequeñas " "animaciones" morris-0.3/po/zh.po000066400000000000000000000336421373406602200143010ustar00rootroot00000000000000# Chinese translations for morris package. # Copyright (C) 2009 Dirk Farin # This file is distributed under the same license as the morris package. # Dirk Farin , 2009. # msgid "" msgstr "" "Project-Id-Version: morris 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-10-25 22:31+0100\n" "PO-Revision-Date: 2009-10-25 21:51+0100\n" "Last-Translator: Dirk Farin \n" "Language-Team: Chinese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../src/algo_alphabeta.cc:590 msgid "white" msgstr "白方" #: ../src/algo_alphabeta.cc:591 msgid "black" msgstr "黑方" #: ../src/algo_alphabeta.cc:600 #, c-format msgid "%s wins in %d moves)" msgstr "%s将在%d回åˆå†…胜出" #: ../src/algo_alphabeta.cc:601 #, c-format msgid "%s wins the next move)" msgstr "%s将在下一回åˆèƒœå‡º" #: ../src/boardgui.cc:104 #, c-format msgid "You make take %d opponent piece(s)." msgstr "ä½ å¯ä»¥åƒæŽ‰å¯¹æ–¹çš„%d颗棋å­" #: ../src/gtk_appgui.cc:200 msgid "White has won." msgstr "白方胜出" #: ../src/gtk_appgui.cc:201 msgid "Black has won." msgstr "黑方胜出" #: ../src/gtk_appgui.cc:202 msgid "Tie between both players." msgstr "和棋" #: ../src/gtk_appgui.cc:209 msgid "Game over" msgstr "游æˆç»“æŸ" #: ../src/gtk_appgui.cc:231 msgid "" "A computer adaptation of the Nine-Mens-Morris board game and its variants." msgstr "删棋åŠå…¶å˜ä½“的电å­ç‰ˆ" #: ../src/gtk_menutoolbar.cc:173 msgid "Game" msgstr "游æˆ" #: ../src/gtk_menutoolbar.cc:173 msgid "menu for game-related functions." msgstr "游æˆåŠŸèƒ½ç›¸å…³çš„èœå•" #: ../src/gtk_menutoolbar.cc:174 msgid "New game" msgstr "新游æˆ" #: ../src/gtk_menutoolbar.cc:174 msgid "Start a new game." msgstr "开始新游æˆ" #: ../src/gtk_menutoolbar.cc:175 msgid "Continue game" msgstr "继续游æˆ" #: ../src/gtk_menutoolbar.cc:175 msgid "Continue a paused game." msgstr "继续游æˆ" #: ../src/gtk_menutoolbar.cc:176 msgid "Force move" msgstr "ç«‹å³èµ°å­" #: ../src/gtk_menutoolbar.cc:176 msgid "Force computer move (immediately stop calculation)." msgstr "强令电脑中断è¿ç®—, ç«‹å³èµ°å­" #: ../src/gtk_menutoolbar.cc:177 msgid "Undo move" msgstr "悔棋" #: ../src/gtk_menutoolbar.cc:177 msgid "Undo last move." msgstr "åæ‚”上一步棋" #: ../src/gtk_menutoolbar.cc:178 msgid "Redo move" msgstr "é‡å¤å悔的步骤" #: ../src/gtk_menutoolbar.cc:178 msgid "Redo last move." msgstr "é‡å¤å悔了的步骤" #: ../src/gtk_menutoolbar.cc:179 msgid "Hint" msgstr "æç¤º" #: ../src/gtk_menutoolbar.cc:179 msgid "Give a hint for the next move." msgstr "æç¤ºä¸‹ä¸€æ­¥æ£‹" #: ../src/gtk_menutoolbar.cc:182 msgid "Options" msgstr "选项" #: ../src/gtk_menutoolbar.cc:183 ../src/mainapp.cc:348 msgid "White player" msgstr "白方" #: ../src/gtk_menutoolbar.cc:184 ../src/mainapp.cc:350 msgid "Black player" msgstr "黑方" #: ../src/gtk_menutoolbar.cc:185 msgid "Swap players" msgstr "æ¢æ£‹" #: ../src/gtk_menutoolbar.cc:186 msgid "Configure AI ..." msgstr "äººå·¥æ™ºèƒ½å‚æ•°è®¾å®š ..." #: ../src/gtk_menutoolbar.cc:187 msgid "Configure display ..." msgstr "棋盘外观设定 ..." #: ../src/gtk_menutoolbar.cc:188 msgid "Configure custom rules ..." msgstr "规则设定 ..." #: ../src/gtk_menutoolbar.cc:189 msgid "Help" msgstr "帮助" #: ../src/gtk_menutoolbar.cc:190 msgid "About Morris..." msgstr "关于德克的删棋" #: ../src/gtk_menutoolbar.cc:191 msgid "Preferences" msgstr "喜好设定" #: ../src/gtk_menutoolbar.cc:196 ../src/gtk_menutoolbar.cc:204 msgid "Human" msgstr "真人" #: ../src/gtk_menutoolbar.cc:197 ../src/gtk_menutoolbar.cc:205 #: ../src/gtk_prefAI.cc:88 msgid "Computer A" msgstr "电脑甲" #: ../src/gtk_menutoolbar.cc:198 ../src/gtk_menutoolbar.cc:206 #: ../src/gtk_prefAI.cc:88 msgid "Computer B" msgstr "电脑乙" #: ../src/gtk_menutoolbar.cc:199 ../src/gtk_menutoolbar.cc:207 msgid "Network" msgstr "è”网对弈" #: ../src/gtk_menutoolbar.cc:212 msgid "Standard rules" msgstr "标准规则" #: ../src/gtk_menutoolbar.cc:213 ../src/gtk_prefRules.cc:113 msgid "Lasker variant" msgstr "拉斯科å˜ä½“" #: ../src/gtk_menutoolbar.cc:214 ../src/gtk_prefRules.cc:60 msgid "Moebius board" msgstr "莫比乌斯棋盘" #: ../src/gtk_menutoolbar.cc:215 ../src/gtk_prefRules.cc:61 msgid "Morabaraba" msgstr "莫拉巴拉巴" #: ../src/gtk_menutoolbar.cc:216 ../src/gtk_prefRules.cc:62 msgid "Windmill" msgstr "风车" #: ../src/gtk_menutoolbar.cc:217 ../src/gtk_prefRules.cc:63 #, fuzzy msgid "Sunmill" msgstr "风车" #: ../src/gtk_menutoolbar.cc:218 ../src/gtk_prefRules.cc:68 msgid "Six Men's Morris" msgstr "å…­å­åˆ æ£‹" #: ../src/gtk_menutoolbar.cc:219 ../src/gtk_prefRules.cc:67 msgid "Seven Men's Morris" msgstr "七å­åˆ æ£‹" #: ../src/gtk_menutoolbar.cc:220 msgid "Triangle board" msgstr "三角形棋盘" #: ../src/gtk_menutoolbar.cc:221 msgid "Pentagon board" msgstr "五边形棋盘" #: ../src/gtk_menutoolbar.cc:222 msgid "Hexagon board" msgstr "六边形棋盘" #: ../src/gtk_menutoolbar.cc:223 msgid "Tapatan" msgstr "它帕滩" #: ../src/gtk_menutoolbar.cc:224 msgid "Achi" msgstr "阿赤" #: ../src/gtk_menutoolbar.cc:225 ../src/gtk_prefRules.cc:71 msgid "Small triangle" msgstr "å°ä¸‰è§’" #: ../src/gtk_menutoolbar.cc:226 msgid "Nine Holes" msgstr "乿´ž" #: ../src/gtk_menutoolbar.cc:227 msgid "Custom rules" msgstr "自定义规则" #: ../src/gtk_menutoolbar.cc:232 msgid "Pause on AI-player" msgstr "ç”µè„‘æ¯æ­¥ä¸€åœ" #: ../src/gtk_menutoolbar.cc:232 msgid "Pause before each AI move." msgstr "电脑æ¯ä¸‹ä¸€æ­¥åŽæ¸¸æˆæš‚åœ" #. default #: ../src/gtk_menutoolbar.cc:234 msgid "Show log of moves" msgstr "显示本局棋谱" #: ../src/gtk_movelog.cc:47 msgid "Move List" msgstr "显示本局棋谱" #: ../src/gtk_movelog.cc:63 msgid "Move" msgstr "回åˆ" #: ../src/gtk_movelog.cc:71 msgid "White" msgstr "白方" #: ../src/gtk_movelog.cc:79 msgid "Black" msgstr "黑方" #: ../src/gtk_movelog.cc:154 msgid "tie" msgstr "和棋" #: ../src/gtk_prefAI.cc:76 msgid "AI Preferences" msgstr "人工智能设定" #: ../src/gtk_prefAI.cc:119 msgid "thinking process" msgstr "æ€è€ƒé™åˆ¶" #: ../src/gtk_prefAI.cc:122 msgid "max. time" msgstr "æ€è€ƒæ—¶é—´ä¸Šé™" #: ../src/gtk_prefAI.cc:123 msgid "max. depth" msgstr "æ€è€ƒæ·±åº¦ä¸Šé™" #: ../src/gtk_prefAI.cc:135 msgid "evaluation weights" msgstr "å–èˆæ¡ä»¶æƒé‡" #: ../src/gtk_prefAI.cc:141 msgid "material" msgstr "æ£‹å­æ•°é‡" #: ../src/gtk_prefAI.cc:142 msgid "freedom" msgstr "棋å­è‡ªç”±åº¦" #: ../src/gtk_prefAI.cc:143 msgid "mills" msgstr "æˆä¸‰åº¦" #: ../src/gtk_prefAI.cc:144 msgid "experience" msgstr "ç»éªŒæ•™è®­" #: ../src/gtk_prefAI.cc:184 msgid "share transposition table" msgstr "共享置æ¢è¡¨" #: ../src/gtk_prefDisplay.cc:36 msgid "Display Preferences" msgstr "棋盘外观设定" #: ../src/gtk_prefDisplay.cc:48 msgid "animate computer moves" msgstr "电脑下å­åŠ¨ç”»æ•ˆæžœ" #: ../src/gtk_prefDisplay.cc:49 msgid "animate setting of pieces" msgstr "下å­åŠ¨ç”»æ•ˆæžœ" #: ../src/gtk_prefDisplay.cc:50 msgid "animate takes" msgstr "åƒå­åŠ¨ç”»æ•ˆæžœ" #: ../src/gtk_prefDisplay.cc:51 msgid "colored crossings while dragging" msgstr "èµ°å­æ—¶æ£‹ç›˜èŠ‚ç‚¹ç€è‰²" #: ../src/gtk_prefDisplay.cc:52 msgid "show game-over message box" msgstr "显示游æˆç»“æŸå‘Šç¤ºç‰Œ" #: ../src/gtk_prefDisplay.cc:53 msgid "show coordinates" msgstr "æ˜¾ç¤ºæ£‹ç›˜åæ ‡" #: ../src/gtk_prefDisplay.cc:76 msgid "animation speed" msgstr "动画速度" #: ../src/gtk_prefDisplay.cc:96 msgid "take piece delay" msgstr "åƒå­è¡ŒåŠ¨å»¶è¿Ÿ" #: ../src/gtk_prefRules.cc:59 msgid "Nine Men's Morris" msgstr "ä¹å­æ£‹ç›˜" #: ../src/gtk_prefRules.cc:64 msgid "Triangle" msgstr "三角棋盘" #: ../src/gtk_prefRules.cc:65 msgid "Pentagon" msgstr "五边形棋盘" #: ../src/gtk_prefRules.cc:66 msgid "Hexagon" msgstr "六角形棋盘" #: ../src/gtk_prefRules.cc:69 msgid "Small square" msgstr "田字格棋盘" #: ../src/gtk_prefRules.cc:70 msgid "Small square with diagonals" msgstr "米字格棋盘" #: ../src/gtk_prefRules.cc:80 msgid "Rule Preferences" msgstr "规则设定" #. board selection #: ../src/gtk_prefRules.cc:90 msgid "Board Type" msgstr "棋盘类型" #. #. setup the rule variations #. #: ../src/gtk_prefRules.cc:110 msgid "Rule Variations" msgstr "规则å˜ä½“" #: ../src/gtk_prefRules.cc:114 msgid "May jump with three pieces" msgstr "棋盘上仅剩三å­çš„一方å¯ä»»æ„安置己方棋å­" #: ../src/gtk_prefRules.cc:115 msgid "May take from mills always" msgstr "å…è®¸åƒæŽ‰å¯¹æ–¹å·±æˆä¸‰çš„æ£‹å­" #: ../src/gtk_prefRules.cc:116 msgid "May take multiple pieces" msgstr "å…è®¸ä¸€æ¬¡åƒæŽ‰å¯¹æ–¹å¤šä¸ªæ£‹å­" #: ../src/gtk_prefRules.cc:125 msgid "Number of pieces" msgstr "æ¯æ–¹æ£‹å­æ•°" #: ../src/gtk_prefRules.cc:145 msgid "Declare tie after how many repeats" msgstr "几次é‡å¤å›žåˆåŽå’Œæ£‹" #: ../src/gtk_prefRules.cc:221 msgid "Your changes require to end the currently running game." msgstr "正在进行的游æˆå¿…须终止。" #: ../src/gtk_prefRules.cc:222 msgid "Do you want to restart with the changed rules?" msgstr "在刚刚设定好的规则下开始新游æˆå—?" #: ../src/mainapp.cc:324 msgid "Game over: white has won!" msgstr "游æˆç»“æŸï¼š 白方胜出ï¼" #: ../src/mainapp.cc:328 msgid "Game over: black has won!" msgstr "游æˆç»“æŸï¼š 黑方胜出ï¼" #: ../src/mainapp.cc:332 msgid "Game ended in a tie between both players." msgstr "游æˆç»“æŸï¼šå’Œæ£‹ã€‚" #: ../src/mainapp.cc:338 msgid "Game paused. Click continue to proceed." msgstr "æ¸¸æˆæš‚åœä¸­ã€‚ 按工具æ¡ä¸Šçš„继续键或èœå•里的继续选项继续游æˆã€‚" #: ../src/mainapp.cc:356 msgid "set or move a piece." msgstr "䏋孿ˆ–移动一å­ã€‚" #: ../src/mainapp.cc:357 msgid "set a piece." msgstr "下一å­ã€‚" #: ../src/mainapp.cc:358 msgid "move a piece." msgstr "移动一å­ã€‚" #: ../src/mainapp.cc:362 msgid "computer is taking his turn... " msgstr "电脑æ€ç´¢ä¸­..." #: ../morris.desktop.in.h:1 msgid "Morris" msgstr "删棋" #: ../morris.desktop.in.h:2 msgid "Nine Mens Morris game" msgstr "删棋(æˆä¸‰æ£‹ï¼‰" #: ../morris.schemas.in.h:1 msgid "Animate setting new pieces" msgstr "下å­åŠ¨ç”»æ•ˆæžœ" #: ../morris.schemas.in.h:2 msgid "Animate takes" msgstr "åƒå­åŠ¨ç”»æ•ˆæžœ" #: ../morris.schemas.in.h:3 msgid "Animate the computer moves" msgstr "电脑下å­åŠ¨ç”»æ•ˆæžœ" #: ../morris.schemas.in.h:4 msgid "Animation speed" msgstr "动画速度" #: ../morris.schemas.in.h:5 msgid "Color the board crossing while dragging" msgstr "èµ°å­æ—¶æ£‹ç›˜èŠ‚ç‚¹ç€è‰²" #: ../morris.schemas.in.h:6 msgid "Delay between animations of takes" msgstr "" #: ../morris.schemas.in.h:7 msgid "" "Delay between the animation of takes and between the move-animation and the " "first take (in milliseconds)." msgstr "" #: ../morris.schemas.in.h:8 msgid "" "Evaluation weight for complete mills (number of completed mills, relative to " "the number of the opponent's mills)." msgstr "" #: ../morris.schemas.in.h:9 msgid "Evaluation weight for experience" msgstr "" #: ../morris.schemas.in.h:10 msgid "Evaluation weight for freedom" msgstr "" #: ../morris.schemas.in.h:11 msgid "" "Evaluation weight for freedom (number of possible moves, relative to the " "possible moves of the opponent)." msgstr "" #: ../morris.schemas.in.h:12 msgid "Evaluation weight for material" msgstr "" #: ../morris.schemas.in.h:13 msgid "" "Evaluation weight for material (number of pieces left, relative to the " "pieces left of the opponent)." msgstr "" #: ../morris.schemas.in.h:14 #, fuzzy msgid "Evaluation weight for mills" msgstr "å–èˆæ¡ä»¶æƒé‡" #: ../morris.schemas.in.h:15 msgid "" "Evaluation weight for the experience gained during previous games. Positions " "that lead to winning a game get a bonus, while positions that lead to a lost " "game are down-rated." msgstr "" #: ../morris.schemas.in.h:16 msgid "If enabled, setting new pieces by the computer will be animated." msgstr "" #: ../morris.schemas.in.h:17 msgid "If enabled, taking of opponent stones by the computer will be animated." msgstr "" #: ../morris.schemas.in.h:18 msgid "If enabled, the program will pause before an AI-player makes a move." msgstr "" #: ../morris.schemas.in.h:19 msgid "" "If this is enabled, the crossings of the board are colored while the user " "drags a piece to show the valid moves." msgstr "" #: ../morris.schemas.in.h:20 msgid "Maximum search-depth" msgstr "" #: ../morris.schemas.in.h:21 msgid "Maximum search-depth in the game tree for Computer A." msgstr "" #: ../morris.schemas.in.h:22 msgid "Maximum thinking time" msgstr "" #: ../morris.schemas.in.h:23 msgid "Maximum time (in milliseconds) Computer A is allowed to think." msgstr "" #: ../morris.schemas.in.h:24 #, fuzzy msgid "Pause on AI players" msgstr "ç”µè„‘æ¯æ­¥ä¸€åœ" #: ../morris.schemas.in.h:25 #, fuzzy msgid "Share transposition tables between Computer A and B" msgstr "共享置æ¢è¡¨" #: ../morris.schemas.in.h:26 msgid "Show a game log" msgstr "" #: ../morris.schemas.in.h:27 msgid "Show a message box with the winner at the end of the game." msgstr "" #: ../morris.schemas.in.h:28 msgid "Show a separate window with the history of the moves played in a game." msgstr "" #: ../morris.schemas.in.h:29 #, fuzzy msgid "Show board coordinates" msgstr "æ˜¾ç¤ºæ£‹ç›˜åæ ‡" #: ../morris.schemas.in.h:30 #, fuzzy msgid "Show game-over message-box" msgstr "显示游æˆç»“æŸå‘Šç¤ºç‰Œ" #: ../morris.schemas.in.h:31 msgid "Show the alpha-numeric board coordinates." msgstr "" #: ../morris.schemas.in.h:32 msgid "" "Speed of pieces in the animation. Actually, the value is the number of " "milliseconds it takes to move a piece across the whole board." msgstr "" #: ../morris.schemas.in.h:33 msgid "" "Whether both AI players (Computer A and B) should use the same transposition " "table. If enables, one AI player will benefit from the calculations of the " "other. Note that if this is enabled, the evaluation weights of both players " "have to be set to identical values." msgstr "" #: ../morris.schemas.in.h:34 msgid "Whether the computer moves should be shown as small animations." msgstr "" morris-0.3/src/000077500000000000000000000000001373406602200134615ustar00rootroot00000000000000morris-0.3/src/Makefile.am000066400000000000000000000024351373406602200155210ustar00rootroot00000000000000## Makefile.am for morris/src bin_PROGRAMS = morris morris_SOURCES = morris.cc morris.hh board.cc board.hh control.hh control.cc \ gtkcairo_boardgui.cc gtkcairo_boardgui.hh boardgui.cc boardgui.hh \ algo_random.hh algo_random.cc ttable.cc ttable.hh learn.hh \ algo_alphabeta.hh algo_alphabeta.cc threadtunnel.hh \ player.hh gtk_prefAI.cc gtk_prefRules.cc mainapp.hh mainapp.cc \ util.hh boardspec.hh rules.hh boardspec.cc rules.cc constants.hh \ appgui.hh gtk_appgui.hh gtk_appgui.cc gtk_appgui_interface.hh \ gtk_menutoolbar.cc gtk_menutoolbar.hh \ gtk_threadtunnel.hh gtk_threadtunnel.cc \ gtk_prefDisplay.cc gtk_prefDisplay.hh \ movelog.hh gtk_movelog.hh gtk_movelog.cc \ configmgr.hh configmgr.cc app_configmgr.hh app_configmgr.cc \ appgtk_configmgr.hh appgtk_configmgr.cc \ gettext.h # gnome_appgui.hh gnome_appgui.cc # gnome_menu.hh gnome_menu.cc if OS_WIN32 win32_ldflags = -mwindows # $(WIN32_LARGE_ADDRESS_AWARE) endif morris_LDFLAGS = $(BOOST_SIGNALS2_LDFLAGS) $(win32_ldflags) morris_LDADD = $(GTK_LIBS) $(GCONF_LIBS) $(BOOST_SIGNALS2_LIBS) $(LIBINTL) AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" \ $(GTK_CFLAGS) $(GCONF_CFLAGS) $(BOOST_CPPFLAGS) # -I$(top_srcdir) \ # -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ # -DGNOME_ICONDIR=\""$(datadir)/pixmaps"\" morris-0.3/src/algo_alphabeta.cc000066400000000000000000000335061373406602200167220ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "algo_alphabeta.hh" #include "ttable.hh" #include "threadtunnel.hh" #include "util.hh" #include "mainapp.hh" #include #include #include #include #include #define RANDOMIZE true #define LOGSEARCH false #define ALGOTRACE 0 const PlayerIF_AlgoAB::eval_t EVAL_INFTY=10000; const PlayerIF_AlgoAB::eval_t EVAL_WIN = 9000; inline void addPly(PlayerIF_AlgoAB::eval_t& e) { /**/ if (e> EVAL_WIN) e--; else if (e<-EVAL_WIN) e++; } inline void subPly(PlayerIF_AlgoAB::eval_t& e) { /**/ if (e> EVAL_WIN) e++; else if (e<-EVAL_WIN) e--; } int nPlysUntilEnd(PlayerIF_AlgoAB::eval_t e) { e=fabs(e); return EVAL_INFTY-e; } static int timeDiff_ms(const struct timeval& t1, const struct timeval& t2) { const int diffSec = t2.tv_sec - t1.tv_sec; const int diffUS = t2.tv_usec- t1.tv_usec; const int diffMS = diffSec*1000 + diffUS/1000; return diffMS; } PlayerIF_AlgoAB::PlayerIF_AlgoAB() : m_tunnel(NULL), thread(NULL) { moveCnt=0; m_maxMSecs = 1000; m_maxDepth = 25; m_weight[Weight_Material] = 1.0; m_weight[Weight_Freedom] = 0.2; m_weight[Weight_Mills] = 0.8; m_weight[Weight_Experience] = 1.0; } void PlayerIF_AlgoAB::resetGame() { /* We have to clear the t-table to prevent that the computer always plays the same game. */ m_ttable->clear(); } void startSearchThread(class PlayerIF_AlgoAB*); void PlayerIF_AlgoAB::startMove(const Board& curr, int moveID) { /* std::cout << "-------------------- "; if (curr.getCurrentPlayer()==PL_White) std::cout << "white"; else std::cout << "black"; std::cout << " (ply=" << curr.getPly() << ")\n"; */ moveCnt++; m_stopThread=false; m_ignoreMove=false; m_computedSomeMove=false; m_startBoard = curr; m_moveID = moveID; thread = g_thread_new(NULL, (GThreadFunc)startSearchThread, this); } // kicker void startSearchThread(class PlayerIF_AlgoAB* algo) { algo->doSearch(); } void PlayerIF_AlgoAB::doSearch() { gettimeofday(&m_startTime,NULL); m_move.reset(); m_ttable->resetStats(); float e; for (int depth=1; depth<=m_maxDepth;depth++) { m_nodesEvaluated=0; Variation var; e = NegaMax(m_startBoard, -EVAL_INFTY, EVAL_INFTY, 0, depth, var, true); // normalize evaluation for white if (m_startBoard.getCurrentPlayer()==PL_Black) { e = -e; } if (LOGSEARCH) std::cout << "STEP move " << m_move << " depth " << depth << " -> eval=" << e << " nodes evaluated= " << m_nodesEvaluated << "\n"; if (fabs(e) >= EVAL_WIN) { int overInPlys = nPlysUntilEnd(e); if (overInPlys <= depth+1) { // we won't find a better winning line break; } } } m_tunnel->doMove(m_move, m_moveID); installJoinThreadHandler(); } void PlayerIF_AlgoAB::installJoinThreadHandler() { class IdleFunc_JoinAlgoThread : public IdleFunc { public: IdleFunc_JoinAlgoThread(PlayerIF_AlgoAB* algo) : obj(algo) { } void operator()() { obj->joinThread(); } private: PlayerIF_AlgoAB* obj; }; IdleFunc::install(new IdleFunc_JoinAlgoThread(this)); } void PlayerIF_AlgoAB::forceMove() { m_stopThread=true; } void PlayerIF_AlgoAB::cancelMove() { m_ignoreMove=true; m_stopThread=true; joinThread(); } void PlayerIF_AlgoAB::joinThread() { if (thread) { g_thread_join(thread); thread=NULL; } } inline void PlayerIF_AlgoAB::checkTime() { struct timeval endTime; gettimeofday(&endTime,NULL); int timeDiffMS = timeDiff_ms(m_startTime, endTime); // thinking time is over if (timeDiffMS >= m_maxMSecs) { m_stopThread = true; } // update progress bar float perc = timeDiffMS; perc /= m_maxMSecs; if (perc>1.0) perc=1.0; m_tunnel->setProgress(perc); } // ---------------------------------------------------------------------------------------------------- #define INDENT std::cout << "-" << (&"| | | | | | | | | | "[20-currDepth*2]); float PlayerIF_AlgoAB::NegaMax(const Board& board,float alpha,float beta, int currDepth, int levels_to_go, Variation& variation, bool useTT) { if (ALGOTRACE) { INDENT; std::cout << "--- NEGAMAX (" << alpha << ";" << beta << ") ---\n"; } const bool atRoot = (currDepth==0); // check thinking time and stop if we were thinking too long if (levels_to_go>5 || atRoot) { if (useTT) checkTime(); } if (m_stopThread && m_computedSomeMove) { if (!m_ignoreMove) { m_tunnel->doMove(m_move, m_moveID); } installJoinThreadHandler(); g_thread_exit(NULL); } // check winning situations if (board.getNPiecesLeft( board.getCurrentPlayer() )<3) { return -EVAL_INFTY; } // check transposition-table const float oldAlpha = alpha; const TranspositionTable::Entry* entry = NULL; if (useTT) entry = m_ttable->lookup(board.getHash(), board); if (entry) { if (entry->depth >= levels_to_go) { if (ALGOTRACE) { INDENT; std::cout << "found table entry !\n"; } if (entry->getBoundType() == TranspositionTable::AccurateValue) { if (atRoot) { m_move = entry->bestMove; m_computedSomeMove=true; logBestMoveFromTable(board, m_move, entry->eval, entry->depth); } if (ALGOTRACE) { INDENT; std::cout << "entry = " << *entry << "\n"; } return entry->eval; } else if (entry->getBoundType() == TranspositionTable::LowerBound) { alpha = std::max(alpha, entry->eval); } else if (entry->getBoundType() == TranspositionTable::UpperBound) { beta = std::min(beta, entry->eval); } if (alpha >= beta) { if (atRoot) { m_move = entry->bestMove; m_computedSomeMove=true; } if (ALGOTRACE) { std::cout << " table-> " << entry->eval << "\n"; } return entry->eval; } } } // process leaves if (levels_to_go==0) { float eval = Eval(board, levels_to_go); /* float memeval = -m_posMemory.lookupHash(board); if (memeval!=0) { subPly(memeval); return memeval; } */ if (ALGOTRACE) { INDENT; std::cout << "leaf. Eval=" << eval << "\n"; } return eval; } // try previous best-move first Board tmpBoard; float bestEval = -EVAL_INFTY; Move bestMove; tmpBoard = board; // recurse std::vector moves; moves.reserve(100); // speed-up move generation m_ruleSpec->generateMoves(moves, board); if (moves.size()==0) { return -EVAL_INFTY; } // Move ordering: put most promising move to front if (entry) { for (int i=1;ibestMove) { std::swap(moves[0], moves[i]); break; } } // random move order to randomize play if (RANDOMIZE && atRoot) { for (int i=1;igetOffset( m_ruleSpec->getBoardID_Symmetric(tmpBoard), m_selfPlayer ); offset *= m_weight[Weight_Experience]; eval += offset; } } /* if (abs(eval)>EVAL_WIN) m_posMemory.storeBoard(tmpBoard,eval); */ tmpBoard.undoMove(moves[i]); if (eval>bestEval) { bestEval=eval; bestMove=moves[i]; variation.clear(); variation.push_back(moves[i]); variation.append(childVar); if (atRoot) { logBestMove(variation, bestEval, levels_to_go); m_move=bestMove; m_computedSomeMove=true; } if (ALGOTRACE) { INDENT; std::cout << "set best move to " << moves[i] << " @eval=" << eval << "\n"; } // alpha-beta pruning if (bestEval>=beta) { if (ALGOTRACE) { INDENT; std::cout << "beta cut-off\n"; } break; } } // MAX if (bestEval>alpha) { alpha = bestEval; if (ALGOTRACE) { INDENT; std::cout << "adjust alpha to " << alpha << "\n"; } } } // insert into transposition-table m_ttable->insert(board.getHash(), bestEval, TranspositionTable::boundType(bestEval, oldAlpha, beta), levels_to_go, bestMove, board); if (ALGOTRACE) { INDENT; std::cout << "bestEval= " << bestEval << "\n"; INDENT; std::cout << "bestMove= " << bestMove << "\n"; } return bestEval; } float PlayerIF_AlgoAB::Eval(const Board& board, int levelsToGo) const { m_nodesEvaluated++; float eval = 0.0; const Player me = board.getCurrentPlayer(); const Player other = opponent(me); const RuleSpec& ruleSpec = *m_ruleSpec; const BoardSpec& boardSpec = *ruleSpec.boardSpec; // ========== material ========== eval += m_weight[Weight_Material]*(board.getNPiecesLeft( board.getCurrentPlayer() ) - board.getNPiecesLeft( board.getOpponentPlayer() )); // ========== freedom ========== int myFreedom =0; int oppFreedom=0; for (int i=0;i no freedom. if (myFreedom==0 && board.getNPiecesOnBoard( board.getCurrentPlayer())>0) { if (ruleSpec.mayJump && board.getNPiecesLeft( board.getCurrentPlayer() )==3) { } else if (board.getNPiecesToSet( board.getCurrentPlayer() )>0) { } else { return -EVAL_INFTY; } } eval += m_weight[Weight_Freedom] * (myFreedom - oppFreedom); // ========== mills ========== int myMills=0; int otherMills=0; for (int i=0;i< boardSpec.nMills(); i++) { const MillPosVector& mill=boardSpec.getMill(i); Player p0 = board.getPosition(mill[0]); if (p0 != PL_None && p0 == board.getPosition(mill[1]) && p0 == board.getPosition(mill[2])) { if (p0 == me) myMills++; else otherMills++; } } eval += m_weight[Weight_Mills] * (myMills - otherMills); #if 0 // dummy weights for debugging ... for (int i=0;igetBoardSpec().nPositions();i++) { /**/ if (board.getPosition(i) == me) eval += 24-i; else if (board.getPosition(i) == other) eval -= 24-i; } #endif return eval; } void PlayerIF_AlgoAB::logBestMoveFromTable(const Board& b, const Move& m, eval_t e, int depth) const { Board board = b; Move move = m; Variation v; for (int i=0;i<=depth;i++) { v.push_back(move); board.doMove(move); const TranspositionTable::Entry* entry; entry = m_ttable->lookup(board.getHash(), board); if (entry) { move = entry->bestMove; } else break; } logBestMove(v,e,depth," <- from ttable"); } void PlayerIF_AlgoAB::logBestMove(const Move& m, eval_t e, int depth) const { Variation v; v.push_back(m); logBestMove(v,e,depth); } void PlayerIF_AlgoAB::logBestMove(const Variation& v, eval_t e, int depth, const char* suffix) const { std::stringstream strstr; Player p = m_startBoard.getCurrentPlayer(); for (int i=0;iboardSpec) << " "; if (p==PL_Black && i EVAL_WIN) { strstr << e << " "; Player winner; if (m_startBoard.getCurrentPlayer() == PL_White) winner=PL_White; else winner=PL_Black; if (e<0) winner= opponent(winner); char* player; if (winner==PL_White) player=_("white"); else player=_("black"); int eInt = e; int eAbs = (eInt < 0 ? -eInt : eInt); int iInt = EVAL_INFTY; int winInMoves = (iInt-1-eAbs)/2+1; char buf[100]; if (winInMoves>1) sprintf(buf, _("%s wins in %d moves)"), player, winInMoves); else sprintf(buf, _("%s wins the next move)"), player); strstr << buf; } else { if (m_startBoard.getCurrentPlayer() == PL_Black) e = -e; strstr << e << ')'; } strstr << " [" << depth << "]" << suffix; m_tunnel->showThinkingInfo(strstr.str()); } void PlayerIF_AlgoAB::notifyWinner(Player p) { if (p==PL_None) { return; } if (m_experience==NULL) { return; } const GameControl& control = MainApp::app().getControl(); for (int i=0;i board = control.getHistoryBoard(i); m_experience->addBoard( m_ruleSpec->getBoardID_Symmetric(*board), p); } } morris-0.3/src/algo_alphabeta.hh000066400000000000000000000073351373406602200167350ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef ALGO_ALPHABETA_HH #define ALGO_ALPHABETA_HH #include "control.hh" #include "ttable.hh" #include "learn.hh" #include #include #include #include /* A quite standard alpha-beta search algo with a quite basic evaluation function. Still, it is a quite competitive player. Features: - use of transposition table - PV display - learning of good/bad games and avoiding previous bad situations. */ class PlayerIF_AlgoAB : public PlayerIF { public: PlayerIF_AlgoAB(); typedef float eval_t; typedef SmallVec Variation; // --- configuration --- void registerTTable(ttable_ptr tt) { m_ttable=tt; } void registerThreadTunnel(ThreadTunnel& tunnel) { m_tunnel=&tunnel; } void registerExperience(experience_ptr e) { m_experience=e; } // --- AI parameters --- void setMaxTime_msec(int msecs) { m_maxMSecs=msecs; } void setMaxDepth(int d) { m_maxDepth=d; } int askMaxTime_msec() const { return m_maxMSecs; } int askMaxDepth() const { return m_maxDepth; } enum Weight { Weight_Material, Weight_Freedom, Weight_Mills, Weight_Experience, Weight_NWEIGHTS }; void setEvalWeight(Weight w, float val) { m_weight[w] = val; } float askEvalWeight(Weight w) const { return m_weight[w]; } // --- standard methods --- bool isInteractivePlayer() const { return false; } // start a new game void resetGame(); void startMove(const Board& curr, int moveID); // Carry out the move as soon as possible. void forceMove(); // Cancel the current move (do not send the currently computed move). void cancelMove(); void notifyWinner(Player p); private: void doSearch(); float NegaMax(const Board& board,float alpha,float beta, int currDepth, int levels_to_go,Variation&, bool useTT); float Eval(const Board& board, int levelsToGo) const; Board m_startBoard; Move m_move; // the move that is currently computed //PositionMemory m_posMemory; // TODO: disabled, because not as effective as Experience experience_ptr m_experience; // multi-threading management friend void startSearchThread(class PlayerIF_AlgoAB*); void installJoinThreadHandler(); void joinThread(); class ThreadTunnel* m_tunnel; GThread* thread; int m_moveID; bool m_stopThread; bool m_ignoreMove; bool m_computedSomeMove; // time management struct timeval m_startTime; // time when move was started void checkTime(); // configuration ttable_ptr m_ttable; int m_maxMSecs; int m_maxDepth; float m_weight[Weight_NWEIGHTS]; // visualization void logBestMove(const Variation&, eval_t, int depth, const char* suffix="") const; void logBestMove(const Move&, eval_t, int depth) const; void logBestMoveFromTable(const Board&, const Move&, eval_t, int depth) const; // statistics mutable int m_nodesEvaluated; // debug int moveCnt; }; #endif morris-0.3/src/algo_random.cc000066400000000000000000000022151373406602200162520ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "algo_random.hh" #include "mainapp.hh" void PlayerIF_AlgoRandom::startMove(const Board& current, int moveID) { std::vector moves; m_ruleSpec->generateMoves(moves, current); assert(moves.size()>0); int idx = rand()%moves.size(); m_tunnel->doMove(moves[idx], moveID); } morris-0.3/src/algo_random.hh000066400000000000000000000026721373406602200162730ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef ALGO_RANDOM_HH #define ALGO_RANDOM_HH #include "control.hh" #include /* A very dumb AI that just makes a random move. Was mainly used to test the move generation. Is not employed in the current program. */ class PlayerIF_AlgoRandom : public PlayerIF { public: PlayerIF_AlgoRandom() { } void registerThreadTunnel(ThreadTunnel& tunnel) { m_tunnel=&tunnel; } bool isInteractivePlayer() const { return false; } void startMove(const Board& current, int moveID); void forceMove() { } void cancelMove() { } private: class ThreadTunnel* m_tunnel; }; #endif morris-0.3/src/app_configmgr.cc000066400000000000000000000147511373406602200166130ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "app_configmgr.hh" #include "mainapp.hh" #include "gtk_menutoolbar.hh" // TODO: gtk is a special implementation ! #include "algo_alphabeta.hh" ConfigManager_Application::ConfigManager_Application() { } ConfigManager_Application::~ConfigManager_Application() { g_object_unref(settings); g_object_unref(disp_settings); g_object_unref(ai_settings); g_object_unref(compA_settings); g_object_unref(compB_settings); g_object_unref(weightsA_settings); g_object_unref(weightsB_settings); } void ConfigManager_Application::readInitialValues() { /* TODO: this should somehow be in the base class */ store(settings, itemPref_pauseOnAIPlayer, read_bool(settings, itemPref_pauseOnAIPlayer)); store(settings, itemPref_showLogOfMoves, read_bool(settings, itemPref_showLogOfMoves)); store(disp_settings, itemDisplay_showGameOverMessageBox, read_bool(disp_settings, itemDisplay_showGameOverMessageBox)); store(disp_settings, itemDisplayGtk_showCoordinates, read_bool(disp_settings, itemDisplayGtk_showCoordinates)); store(disp_settings, itemDisplayGtk_coloredCrossingsWhileDragging, read_bool(disp_settings, itemDisplayGtk_coloredCrossingsWhileDragging)); store(disp_settings, itemDisplayGtk_animateComputerMoves, read_bool(disp_settings, itemDisplayGtk_animateComputerMoves)); store(disp_settings, itemDisplayGtk_animateSettingOfPieces, read_bool(disp_settings, itemDisplayGtk_animateSettingOfPieces)); store(disp_settings, itemDisplayGtk_animateTakes, read_bool(disp_settings, itemDisplayGtk_animateTakes)); store(disp_settings, itemDisplayGtk_animationSpeed, read_float(disp_settings, itemDisplayGtk_animationSpeed)); store(disp_settings, itemDisplayGtk_takePieceDelay, read_float(disp_settings, itemDisplayGtk_takePieceDelay)); for (int i=0;i<2;i++) { GSettings* obj; if (i == 0) obj = compA_settings; else obj = compB_settings; store(obj, itemComputer_maxTime[i], read_int(obj, itemComputer_maxTime[i])); store(obj, itemComputer_maxDepth[i], read_int(obj, itemComputer_maxDepth[i])); if (i == 0) obj = weightsA_settings; else obj = weightsB_settings; store(obj, itemComputer_weightMaterial[i], read_float(obj, itemComputer_weightMaterial[i])); store(obj, itemComputer_weightFreedom[i], read_float(obj, itemComputer_weightFreedom[i])); store(obj, itemComputer_weightMills[i], read_float(obj, itemComputer_weightMills[i])); store(obj, itemComputer_weightExperience[i], read_float(obj, itemComputer_weightExperience[i])); } store(ai_settings, itemComputers_shareTTables, read_bool(ai_settings, itemComputers_shareTTables)); } void ConfigManager_Application::store(GSettings* settings, const char* key, int value) { if (read_int(settings,key)==value) return; g_settings_set_int(settings,key,value); { PlayerIF_AlgoAB* p; for (int i=0;i<2;i++) { p = dynamic_cast(MainApp::app().getAIPlayer(i).get()); if (cmp(key,itemComputer_maxTime[i])) { p->setMaxTime_msec(value); return; } else if (cmp(key,itemComputer_maxDepth[i])) { p->setMaxDepth(value); return; } } } if (m_delegate != NULL) { m_delegate->store(settings, key, value); } } void ConfigManager_Application::store(GSettings* settings, const char* key, bool value) { if (read_bool(settings,key)==value) return; g_settings_set_boolean(settings,key,value); if (cmp(key,itemPref_pauseOnAIPlayer)) { MainApp::app().options.alwaysPauseOnAIPlayer = value; menu_setPauseOnAI(value); } else if (cmp(key,itemComputers_shareTTables)) { MainApp::app().setShareTTables(value); } else if (m_delegate != NULL) { m_delegate->store(settings,key,value); } } void ConfigManager_Application::store(GSettings* settings, const char* key, float value) { if (read_float(settings,key)==value) return; g_settings_set_double(settings,key,value); for (int i=0;i<2;i++) { PlayerIF_AlgoAB* p = dynamic_cast(MainApp::app().getAIPlayer(i).get()); if (cmp(key,itemComputer_weightMaterial[i])) { p->setEvalWeight(PlayerIF_AlgoAB::Weight_Material, value); return; } else if (cmp(key,itemComputer_weightFreedom[i])) { p->setEvalWeight(PlayerIF_AlgoAB::Weight_Freedom, value); return; } else if (cmp(key,itemComputer_weightMills[i])) { p->setEvalWeight(PlayerIF_AlgoAB::Weight_Mills, value); return; } else if (cmp(key,itemComputer_weightExperience[i])) { p->setEvalWeight(PlayerIF_AlgoAB::Weight_Experience, value); return; } } // delegate if (m_delegate != NULL) { m_delegate->store(settings,key,value); } } void ConfigManager_Application::store(GSettings* settings, const char* key, const char* value) { if (strcmp(read_string(settings,key).c_str(),value)==0) return; if (m_delegate != NULL) { m_delegate->store(settings,key,value); } } int ConfigManager_Application::read_int(GSettings* settings, const char* key) { return g_settings_get_int(settings,key); } bool ConfigManager_Application::read_bool(GSettings* settings, const char* key) { return g_settings_get_boolean(settings,key); } float ConfigManager_Application::read_float(GSettings* settings, const char* key) { return g_settings_get_double(settings,key); } std::string ConfigManager_Application::read_string(GSettings* settings, const char* key) { if (m_delegate != NULL) { return m_delegate->read_string(settings,key); } } morris-0.3/src/app_configmgr.hh000066400000000000000000000035411373406602200166200ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef APP_CONFIGMGR_HH #define APP_CONFIGMGR_HH #include "configmgr.hh" // Helper class. class ConfigManager_Chained : public ConfigManager { public: void setDelegate(configmanager_ptr c) { m_delegate=c; } protected: configmanager_ptr m_delegate; }; class ConfigManager_Application : public ConfigManager_Chained { public: ConfigManager_Application(); ~ConfigManager_Application(); virtual void readInitialValues(); virtual void store(GSettings* settings, const char* key, int value); virtual void store(GSettings* settings, const char* key, bool value); virtual void store(GSettings* settings, const char* key, float value); virtual void store(GSettings* settings, const char* key, const char* value); virtual int read_int (GSettings* settings, const char* key); virtual bool read_bool (GSettings* settings, const char* key); virtual float read_float (GSettings* settings, const char* key); virtual std::string read_string(GSettings* settings, const char* key); }; #endif morris-0.3/src/appgtk_configmgr.cc000066400000000000000000000130261373406602200173130ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "appgtk_configmgr.hh" #include "mainapp.hh" #include "gtk_menutoolbar.hh" #include "gtk_appgui.hh" #include "gtkcairo_boardgui.hh" void ConfigManager_AppGtk::store(GSettings* settings, const char* key, int value) { if (m_delegate != NULL) { m_delegate->store(settings, key, value); } } void ConfigManager_AppGtk::store(GSettings* settings, const char* key, bool value) { if (cmp(key,itemPref_showLogOfMoves)) { MainApp::app().getApplicationGUI()->showMoveLog(value, false); } else if (cmp(key,itemDisplayGtk_showCoordinates)) { dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().showCoordinates = value; MainApp::app().getBoardGUI()->resetDisplay(); } else if (cmp(key,itemDisplayGtk_coloredCrossingsWhileDragging)) { dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().coloredCrossingWhileDragging = value; } else if (cmp(key,itemDisplayGtk_animateComputerMoves)) { dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().animateComputerMoves = value; } else if (cmp(key,itemDisplayGtk_animateSettingOfPieces)) { dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().set_moveIn = value; } else if (cmp(key,itemDisplayGtk_animateTakes)) { dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().take_moveOut = value; } else if (cmp(key,itemDisplay_showGameOverMessageBox)) { ApplicationGUI_Gtk* gui = dynamic_cast(MainApp::app().getApplicationGUI().get()); gui->enableGameOverDialog(value); } else if (m_delegate != NULL) { m_delegate->store(settings,key,value); } } void ConfigManager_AppGtk::store(GSettings* settings, const char* key, float value) { if (cmp(key,itemDisplayGtk_animationSpeed)) { dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().animationSpeed = value; } else if (cmp(key,itemDisplayGtk_takePieceDelay)) { dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().take_delay = value; } else if (m_delegate != NULL) { m_delegate->store(settings,key,value); } } void ConfigManager_AppGtk::store(GSettings* settings, const char* key, const char* value) { if (m_delegate != NULL) { m_delegate->store(settings,key,value); } } int ConfigManager_AppGtk::read_int(GSettings* settings, const char* key) { if (m_delegate != NULL) { return m_delegate->read_int(settings,key); } } bool ConfigManager_AppGtk::read_bool(GSettings* settings, const char* key) { if (cmp(key,itemPref_showLogOfMoves)) { return MainApp::app().getApplicationGUI()->isMoveLogShown(); } else if (cmp(key,itemDisplayGtk_showCoordinates)) { return dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().showCoordinates; } else if (cmp(key,itemDisplayGtk_coloredCrossingsWhileDragging)) { return dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().coloredCrossingWhileDragging; } else if (cmp(key,itemDisplayGtk_animateComputerMoves)) { return dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().animateComputerMoves; } else if (cmp(key,itemDisplayGtk_animateSettingOfPieces)) { return dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().set_moveIn; } else if (cmp(key,itemDisplayGtk_animateTakes)) { return dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().take_moveOut; } else if (cmp(key,itemDisplay_showGameOverMessageBox)) { ApplicationGUI_Gtk* gui = dynamic_cast(MainApp::app().getApplicationGUI().get()); return gui->getGameOverDialogFlag(); } if (m_delegate != NULL) { return m_delegate->read_bool(settings,key); } } float ConfigManager_AppGtk::read_float(GSettings* settings, const char* key) { if (cmp(key,itemDisplayGtk_animationSpeed)) { return dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().animationSpeed; } else if (cmp(key,itemDisplayGtk_takePieceDelay)) { return dynamic_cast(MainApp::app().getBoardGUI().get())->getOptions().take_delay; } if (m_delegate != NULL) { return m_delegate->read_float(settings,key); } } std::string ConfigManager_AppGtk::read_string(GSettings* settings, const char* key) { if (m_delegate != NULL) { return m_delegate->read_string(settings,key); } } morris-0.3/src/appgtk_configmgr.hh000066400000000000000000000031071373406602200173240ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef APPGTK_CONFIGMGR_HH #define APPGTK_CONFIGMGR_HH #include "app_configmgr.hh" class ConfigManager_AppGtk : public ConfigManager_Chained { public: virtual void store(GSettings* settings, const char* key, int value); virtual void store(GSettings* settings, const char* key, bool value); virtual void store(GSettings* settings, const char* key, float value); virtual void store(GSettings* settings, const char* key, const char* value); virtual int read_int (GSettings* settings, const char* key); virtual bool read_bool (GSettings* settings, const char* key); virtual float read_float (GSettings* settings, const char* key); virtual std::string read_string(GSettings* settings, const char* key); }; #endif morris-0.3/src/appgui.hh000066400000000000000000000031041373406602200152650ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef APP_HH #define APP_HH #include #include "boardgui.hh" #include "util.hh" class ApplicationGUI { public: virtual ~ApplicationGUI() { } virtual void setProgress(float) { } virtual void setStatusbar(const std::string&) { } virtual void showGameOverDialog(Player winner) { } virtual void preferencesDialog_Display() { } virtual void showAboutDialog() { } virtual void showMoveLog(bool enable=true, bool quitapp=false) { } virtual bool isMoveLogShown() const { return false; } virtual boardgui_ptr getBoardGUI() const = 0; // run main-loop virtual void startApplication() = 0; virtual void quitApplication() = 0; }; typedef boost::shared_ptr appgui_ptr; #endif morris-0.3/src/board.cc000066400000000000000000000162751373406602200150720ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "board.hh" #include #include #include bool Move::operator==(const Move& m) const { // note: the comparisons are ordered somehow in the order of decreasing probability if (newPos!=m.newPos) return false; if (mode==Mode_Move && oldPos!=m.oldPos) return false; if (mode != m.mode) return false; if (takes.size() != m.takes.size()) return false; for (int i=0;i" << m.newPos; if (m.takes.size()>0) { ostr << " ("; for (int i=0;i0) ostr << ","; ostr << m.takes[i]; } ostr << ")"; } ostr << "]"; return ostr; } // generate a random hash value static BoardHash randomHash() { return BoardHash(rand()) ^ (BoardHash(rand())<<16) ^ (BoardHash(rand())<<32) ^ (BoardHash(rand())<<48); } BoardHash Board::hash_pos[3][MAXPOSITIONS]; BoardHash Board::hash_nToSet[3][MAXPIECES]; BoardHash Board::hash_playerToggle; void Board::initHashValues() { for (int p=0 ; p<=2 ; p+=2 /* skip [1] */) { for (int i=0;i0); boardPos[m.newPos] = currentPlayer; hash ^= hash_pos [currentPlayer+1][m.newPos]; hash ^= hash_nToSet[currentPlayer+1][ nPiecesToSet[playerIndex] ]; hash ^= hash_nToSet[currentPlayer+1][ nPiecesToSet[playerIndex]-1]; nPiecesOnBoard[ playerIndex ]++; nPiecesToSet [ playerIndex ]--; } break; case Move::Mode_Move: { boardPos[m.oldPos] = PL_None; boardPos[m.newPos] = currentPlayer; hash ^= hash_pos[currentPlayer+1][m.oldPos]; hash ^= hash_pos[currentPlayer+1][m.newPos]; } break; } // optionally take away opponent piece(s) for (int i=0; i Morris 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 3 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, see . ***************************************************************************/ #ifndef BOARD_HH #define BOARD_HH #include #include #include #include #include "util.hh" #include "constants.hh" /* This class encodes a half-move of a player. The mode can either be setting a new piece onto the board, or moving an existing piece. For setting, the 'oldPos' remains undefined. */ class Move { public: enum { MAXTAKES=3 }; enum MoveMode { Mode_Set, Mode_Move } mode; Position oldPos; // old position of the piece (undefined in set-mode) Position newPos; // new position of the piece SmallVec takes; // the set of opponent pieces to remove from the board // methods for easier manipulation void reset() { takes.clear(); oldPos=newPos=-1; } void setMove_Set(Position p) { mode=Mode_Set; newPos=p; oldPos=-1; } void setMove_Move(Position from, Position to) { mode=Mode_Move; oldPos=from; newPos=to; } void addTake(Position p) { takes.push_back(p); } bool operator==(const Move& m) const; }; // move logging for debugging std::ostream& operator<<(std::ostream& ostr, const Move&); typedef unsigned long long BoardHash; /* The board class hold the current configuation of the players' pieces, as well as additional status information like the current player and the number of pieces each player can still set. The Board class also maintains a hash-code for the board using the Zobrist hashing algorithm. Additionally, the board can include a pointer to the previous board (in a running game). This is used to detect ties by repeated board positions. NOTE: you have to call reset() before the board is in a playable state. */ class Board { public: void reset(int nPiecesToSet); void doMove(const Move&); void undoMove(const Move&); // --- current player --- void togglePlayer() { ::togglePlayer(currentPlayer); hash ^= hash_playerToggle; } Player getCurrentPlayer() const { return currentPlayer; } Player getOpponentPlayer() const { return opponent(currentPlayer); } // --- querying the board --- Player getPosition(int p) const { return Player(boardPos[p]); } bool isPlayer (Position p) const { return boardPos[p]==currentPlayer; } bool isOpponent(Position p) const { return boardPos[p]==opponent(currentPlayer); } bool isEmpty (Position p) const { return boardPos[p]==PL_None; } // --- counting pieces --- short getNPiecesToSet(Player p) const { return nPiecesToSet[ player2Index(p) ]; } short getNPiecesToSet() const { return nPiecesToSet[ player2Index(currentPlayer) ]; } short getNPiecesOnBoard(Player p) const { return nPiecesOnBoard[ player2Index(p) ]; } short getNPiecesOnBoard() const { return nPiecesOnBoard[ player2Index(currentPlayer) ]; } short getNPiecesLeft(Player p) const { return getNPiecesToSet(p) + getNPiecesOnBoard(p); } short getNPiecesLeft() const { return getNPiecesLeft(currentPlayer); } // --- chaining --- void setPrevBoard(boost::shared_ptr b) { prev=b; } boost::shared_ptr getPrevBoard() const { return prev; } // --- hashes --- BoardHash getHash() const { return hash; } static void initHashValues(); // fill the hash tables with random values // --- hard board modification, not considering the hash value --- void setPosition_noHash(int p, Player pl) { boardPos[p]=pl; } // --- standard operators --- bool operator==(const Board& b) const; // --- debugging --- //void setNPiecesToSet(Player pl, int n) { nPiecesToSet[player2Index(pl)]=n; } //void setCurrentPlayer(Player pl) { currentPlayer=pl; } void displayOnConsole() const; private: signed char boardPos[MAXPOSITIONS]; Player currentPlayer; signed char nPiecesToSet[2]; signed char nPiecesOnBoard[2]; boost::shared_ptr prev; // --- hash --- BoardHash hash; /* The arrays are organized as follows: index [1] is unused, [0] and [2] is mapped to the two players. This makes it possible to access the arrays with simply 'player+1', since player is {-1;1}. */ static BoardHash hash_pos[3][MAXPOSITIONS]; // player, board-position static BoardHash hash_nToSet[3][MAXPIECES]; // player, number of pieces in stack static BoardHash hash_playerToggle; // xor'ed to hash if player is PL_Black BoardHash hashFromScratch() const; // for debugging only }; #endif morris-0.3/src/boardgui.cc000066400000000000000000000154431373406602200155730ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "boardgui.hh" #include "mainapp.hh" #include // this is usually overridden by the derived class void BoardGUI_Base::visualizeMove(const Move& move, int gameID) { GameControl& control = MainApp::app().getControl(); if (gameID == control.getCurrentMoveID() && control.getGameState().state == GameState::Moving) { MainApp::app().doMove(move); } redrawBoard(); } static std::ostream& operator<<(std::ostream& ostr, GfxState s) { switch (s) { case GS_Waiting: ostr << "GS_Waiting"; break; case GS_Inactive: ostr << "GS_Inactive"; break; case GS_DraggingPiece: ostr << "GS_DraggingPiece"; break; case GS_Take: ostr << "GS_Take"; break; case GS_NonInteractiveMove: ostr << "GS_NonInteractiveMove"; break; default: ostr << "GS_UNKNOWN"; break; } return ostr; } HoverState::HoverState() : hoverPosValid(false), hoverMode(Hover_None), hoverPos(-1) { } BoardGUI_Base::BoardGUI_Base() : m_gfxState(GS_Inactive) { } void BoardGUI_Base::setState(GfxState s) { m_gfxState=s; changeGfxState(m_gfxState); } void BoardGUI_Base::startInteractiveMove() { assert(m_gfxState==GS_Inactive); setState(GS_Waiting); } void BoardGUI_Base::cancelInteractiveMove() { setState(GS_Inactive); } void BoardGUI_Base::startNonInteractiveMove() { assert(m_gfxState==GS_Inactive); setState(GS_NonInteractiveMove); } void BoardGUI_Base::endNonInteractiveMove() { assert(m_gfxState==GS_NonInteractiveMove); setState(GS_Inactive); } void BoardGUI_Base::doMove() { int nTakes = MainApp::app().doMove(m_playermove); if (nTakes>0) { char buf[100]; sprintf(buf,_("You make take %d opponent piece(s)."),nTakes); MainApp::app().getApplicationGUI()->setStatusbar(buf); setState(GS_Take); } else { setState(GS_Inactive); m_playermove.reset(); } redrawBoard(); } void BoardGUI_Base::cb_buttonPress(Position p, Point2D pixelPos, MouseButton button) { GameControl& control = MainApp::app().getControl(); // if the left mouse button is pressed if (button == MB_Left) { if (p==-1) { return; } switch (m_gfxState) { case GS_Waiting: if (control.getCurrentBoard().getPosition(p) == PL_None && control.getGameState().SUBSTATE_PlayerSet) { m_playermove.setMove_Set(p); setHover(Hover_None); doMove(); } else if (control.getCurrentBoard().getPosition(p) == control.getCurrentPlayer() && control.getGameState().SUBSTATE_PlayerMove) { m_playermove.setMove_Move(p,-1); setHover(Hover_None); m_gfxState = GS_DraggingPiece; changeGfxState(m_gfxState); startPieceDrag(p,pixelPos); } break; case GS_Take: if (control.getCurrentBoard().isOpponent(p)) { bool mayTake = control.getRuleSpec()->mayTake( control.getCurrentBoard(), p ); if (mayTake) { m_playermove.addTake(p); setHover(Hover_None); doMove(); } } break; case GS_Inactive: break; } } } void BoardGUI_Base::cb_buttonRelease(Position p, MouseButton button) { const Board& board = MainApp::app().getControl().getCurrentBoard(); const RuleSpec& rules = *MainApp::app().getControl().getRuleSpec(); // if the left mouse button is pressed if (button == MB_Left) { if (m_gfxState==GS_DraggingPiece) { setHover(Hover_None); m_playermove.newPos = p; stopPieceDrag(); if (p == -1 || rules.isValidMove(board, m_playermove)==false) { // release at invalid position m_gfxState=GS_Waiting; changeGfxState(m_gfxState); redrawBoard(); } else { // check if position is a valid move if (rules.isValidMove(board, m_playermove)) { // release at valid position doMove(); } } } } } void BoardGUI_Base::cb_mouseMotion(Position pos, Point2D pixelPos) { const GameControl& control = MainApp::app().getControl(); const Board& board = MainApp::app().getControl().getCurrentBoard(); const RuleSpec& rules = *MainApp::app().getControl().getRuleSpec(); HoverMode hoverMode = Hover_None; bool hoverValid; switch (m_gfxState) { case GS_Waiting: if (pos != -1 && control.getGameState().SUBSTATE_PlayerSet && board.getPosition(pos) == PL_None) { hoverMode = Hover_Set; } else if (pos != -1 && control.getGameState().SUBSTATE_PlayerMove && board.getPosition(pos) == board.getCurrentPlayer()) { hoverMode = Hover_MoveStart; } break; case GS_DraggingPiece: if (pos != -1 && control.getGameState().SUBSTATE_PlayerMove && board.getPosition(pos) == PL_None) { // check if this is really a valid move m_playermove.newPos = pos; hoverMode = Hover_MoveEnd; hoverValid = rules.isValidMove(board, m_playermove); doPieceDrag(pixelPos, hoverValid); } else { doPieceDrag(pixelPos, false); } break; case GS_Take: if (pos != -1 && board.getPosition(pos) == opponent(board.getCurrentPlayer())) { // check for opponent mills hoverMode = Hover_Take; hoverValid = rules.mayTake( board, pos ); } break; } setHover(hoverMode, pos, hoverValid); } void BoardGUI_Base::setHover(HoverMode mode, Position pos, bool valid) { const HoverMode oldHoverMode = m_hoverState.hoverMode; const Position oldHoverPos = m_hoverState.hoverPos; m_hoverState.hoverMode = mode; m_hoverState.hoverPos = pos; m_hoverState.hoverPosValid = valid; if (m_hoverState.hoverMode != oldHoverMode || m_hoverState.hoverPos != oldHoverPos) { if (oldHoverPos>=0) invalidateHoverAtPos(oldHoverPos); if (pos>=0) invalidateHoverAtPos(pos); } } // --------------------------------------------------------------------------- void PlayerIF_Human::startMove(const Board& current, int moveID) { MainApp::app().getBoardGUI()->startInteractiveMove(); } void PlayerIF_Human::cancelMove() { MainApp::app().getBoardGUI()->cancelInteractiveMove(); } morris-0.3/src/boardgui.hh000066400000000000000000000075551373406602200156120ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef BOARDGUI_HH #define BOARDGUI_HH #include #include "control.hh" #include "board.hh" #include "player.hh" enum MouseButton { MB_Left, MB_Middle, MB_Right }; enum GfxState { GS_Inactive, // no game in progress GS_NonInteractiveMove, // AI is computing its move GS_Waiting, // interactive move: waiting for move input GS_DraggingPiece, // interactive move: dragging of piece in progress GS_Take // interactive move: taking of piece to progres }; enum HoverMode { Hover_None, Hover_Set, Hover_MoveStart, Hover_MoveEnd, Hover_Take }; struct HoverState { HoverState(); HoverMode hoverMode; Position hoverPos; bool hoverPosValid; }; /* This is an abstraction layer that helps implement the interactive board GUI. This layer implements the user interaction process, independent of the actual graphics output. This class has to be derived and the missing methods be filled in to obtain a fully functional implementation. */ class BoardGUI_Base { public: BoardGUI_Base(); virtual ~BoardGUI_Base() { } // recompute everything (e.g. layout for a changed board and new piece sizes) virtual void resetDisplay() { } // redraw everything virtual void redrawBoard() = 0; void startInteractiveMove(); void cancelInteractiveMove(); void startNonInteractiveMove(); void endNonInteractiveMove(); virtual void visualizeMove(const Move& move, int gameID); virtual void checkHover() { } // hints virtual void showHint(const Move&) { } virtual void removeHint() { } // preferences virtual void preferencesDialog_Display() { } protected: GfxState getGfxState() const { return m_gfxState; } const HoverState& getHoverState() const { return m_hoverState; } const Move& getPlayerMove() const { return m_playermove; } virtual void startPieceDrag(Position p, Point2D pixelPos) { } virtual void stopPieceDrag() { } virtual void doPieceDrag(Point2D pixelPos, bool valid) { } virtual void invalidateHoverAtPos(Position) { } virtual void changeGfxState(GfxState) { } // callback that you have to connect to void cb_buttonPress (Position p, Point2D pixelPos, MouseButton b); void cb_buttonRelease(Position p, MouseButton b); void cb_mouseMotion (Position p, Point2D pixelPos); private: void setState(GfxState s); void setHover(HoverMode mode, Position=-1, bool valid=true); void doMove(); GfxState m_gfxState; HoverState m_hoverState; Move m_playermove; // the successively built, interactive player move }; typedef boost::shared_ptr boardgui_ptr; /* The human player object. This closely interacts with the board-GUI. In fact, it is very simple and simply switches the interaction mode on and off. */ class PlayerIF_Human : public PlayerIF { public: PlayerIF_Human() { } bool isInteractivePlayer() const { return true; } void startMove(const Board& current, int moveID); void forceMove() { } void cancelMove(); }; #endif morris-0.3/src/boardspec.cc000066400000000000000000000567221373406602200157460ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "boardspec.hh" #include BoardSpec_Polygon::BoardSpec_Polygon(int nCorners) { m_nCorners = nCorners; assert(nCorners >= 3); assert(nCorners*2*3 <= MAXPOSITIONS); // --- generate positions --- double angleStep = 2*M_PI/nCorners; double angle = +M_PI/2 -angleStep/2; float maxX=0, minX=0; float maxY=0, minY=0; const float ringSpacing[] = { 0,0,0, /* 3 */ 2.25, /* 4 */ 1.57, /* 5 */ 1.35, /* 6 */ 1.30 }; // compute bounding box for (int c=0;cmaxX) { maxX=x; } if (xmaxY) { maxY=y; } if (ynMaxNeighbors;n++) { if (spec->neighbors[i][n]<0) break; v.push_back(spec->neighbors[i][n]); } neighbors[i] = v; } // convert mills-table int nMills=0; while (spec->mills[nMills][0] >= 0) { nMills++; } mills.resize(nMills); millsAtPos.resize(nPositions()); for (int i=0;imills[i][n]<0) { millSize=n; break; } v.push_back(spec->mills[i][n]); } mills[i] = v; // insert mill to position-indexed tables for (int n=0;ngeom_width; } switch (spec->geom_width) { case 5: return 0.32 / spec->geom_width; default: return 0.42 / spec->geom_width; } } int BoardSpec_Grid::nPositions() const { return spec->nPositions; } const NeighborVector& BoardSpec_Grid::getNeighbors(Position p) const { return neighbors[p]; } Point2D BoardSpec_Grid::getPositionLocation(Position pos) const { Point2D p; p.x = spec->geometry[pos][0]; p.y = spec->geometry[pos][1]; if (spec->geom_width != 0) { assert(spec->geom_height != 0); p.x = (p.x+0.5) / spec->geom_width; p.y = (p.y+0.5) / spec->geom_height; } return p; } std::string BoardSpec_Grid::getPositionName(Position p) const { short x = spec->geometry[p][0]; short y = spec->geometry[p][1]; std::string name; int i; for (i=0; spec->xcoords[i] != x; i++) { } int k; for (k=0; spec->ycoords[k] != y; k++) { } name += i+'a'; name += k+'1'; return name; } int BoardSpec_Grid::nMills() const { return mills.size(); } const MillPosVector& BoardSpec_Grid::getMill(int i) const { return mills[i]; } BoardSpec::BoardPreset BoardSpec_Grid::getBoardPresetID() const { return spec->preset; } std::vector BoardSpec_Grid::xCoords() const { std::vector coords; for (int i=0; spec->xcoords[i]>=0 ; i++) { double p = spec->xcoords[i]; p = (p+0.5) / spec->geom_width; coords.push_back(p); } return coords; } std::vector BoardSpec_Grid::yCoords() const { std::vector coords; for (int i=0; spec->ycoords[i]>=0 ; i++) { double p = spec->ycoords[i]; p = (p+0.5) / spec->geom_height; coords.push_back(p); } return coords; } boardspec_ptr BoardSpec::boardFactory(BoardSpec::BoardPreset preset) { BoardSpec* spec = NULL; switch (preset) { case Board_Standard9MM: case Board_Moebius: case Board_Morabaraba: case Board_Windmill: case Board_Sunmill: case Board_6MM: case Board_7MM: case Board_SmallSq: case Board_SmallSqWithDiag: case Board_SmallTri: spec = new BoardSpec_Grid(preset); break; case Board_Polygon3: spec = new BoardSpec_Polygon(3); break; case Board_Polygon5: spec = new BoardSpec_Polygon(5); break; case Board_Polygon6: spec = new BoardSpec_Polygon(6); break; case Board_Unknown: assert(0); } assert(spec != NULL); return boardspec_ptr(spec); } void BoardSpec::recursePermutation(Permutation& p, UsageVector& used, int pos) { // If permutation vector is complete, store it into the set. if (pos==nPositions()) { /* for (int i=0;i Morris 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 3 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, see . ***************************************************************************/ #ifndef BOARDSPEC_HH #define BOARDSPEC_HH #include "constants.hh" #include "util.hh" #include #include #include typedef SmallVec NeighborVector; typedef SmallVec MillPosVector; typedef boost::shared_ptr boardspec_ptr; /* The BoardSpec specifies the board geometry. This includes the graphical layout as well as logical topology. The base class comprises a complete list of board presets, which may be implemented in different derived classes. The main purpose of using a hierarchy of classes here is code reuse. */ class BoardSpec { public: virtual ~BoardSpec() { } // The number of positions on this board. virtual int nPositions() const = 0; // All neighbors to position p. virtual const NeighborVector& getNeighbors(Position p) const = 0; // The human-readable name of the position. virtual std::string getPositionName(Position) const = 0; /* The geometrical location of the position. This assumes that the board spans the area [0;1]x[0;1]. */ virtual Point2D getPositionLocation(Position) const = 0; // The radius of a piece in the same units as for the board position. virtual float getPieceRadius() const = 0; // The total number of mill configurations on this board. virtual int nMills() const = 0; // The positions for mill 'i'. virtual const MillPosVector& getMill(int i) const = 0; // All the mills through a fixed position. virtual const std::vector& getMillsThroughPos(Position) const = 0; /* Return a set of position-permutation vectors for this board configuration. Permuting the board positions according to these permutations results in symmetric situations. */ typedef SmallVec Permutation; const std::vector& getPermutations() const { return m_permutations; } enum BoardPreset { Board_Standard9MM, Board_Moebius, Board_Morabaraba, Board_Windmill, Board_Sunmill, Board_6MM, Board_7MM, Board_SmallSq, Board_SmallSqWithDiag, Board_SmallTri, Board_Polygon3, Board_Polygon5, Board_Polygon6, Board_Unknown }; // The ID of this board configuration. virtual BoardPreset getBoardPresetID() const { return Board_Unknown; } /* A board factory that can create any of the preset board configurations. */ static boardspec_ptr boardFactory(BoardPreset); protected: /* This initializes the set of permutations for symmetric boards. Call this method once in the constructor. */ void initPermutations(); private: typedef bool UsageVector[MAXPOSITIONS]; void recursePermutation(Permutation&, UsageVector& used, int pos); std::vector m_permutations; }; /* An implementation of the board-specification interface which makes it easy to generate polygonal boards (three rings of n-polygons). It is used currently for the triangular, pentagonal, and hexagonal boards. */ class BoardSpec_Polygon : public BoardSpec { public: virtual ~BoardSpec_Polygon() { } BoardSpec_Polygon(int nCorners); // --- standard interface --- virtual int nPositions() const; virtual const NeighborVector& getNeighbors(Position) const; virtual std::string getPositionName(Position) const; virtual Point2D getPositionLocation(Position) const; virtual float getPieceRadius() const; virtual int nMills() const; virtual const MillPosVector& getMill(int i) const; virtual const std::vector& getMillsThroughPos(Position p) const { return millsAtPos[p]; } virtual BoardPreset getBoardPresetID() const; // --- class specific methods --- // (none) private: int m_nCorners; std::vector neighbors; std::vector mills; std::vector > millsAtPos; std::vector positions; }; /* An implementation of the board-specification interface which arranges the positions on a regular grid (however also with some positions remaining empty). The neighborhood relationsships and mill structure is defined via tables. */ class BoardSpec_Grid : public BoardSpec { public: virtual ~BoardSpec_Grid() { } BoardSpec_Grid(BoardPreset); // --- standard interface --- virtual int nPositions() const; virtual const NeighborVector& getNeighbors(Position) const; virtual std::string getPositionName(Position) const; virtual Point2D getPositionLocation(Position) const; virtual float getPieceRadius() const; virtual int nMills() const; virtual const MillPosVector& getMill(int i) const; virtual const std::vector& getMillsThroughPos(Position p) const { return millsAtPos[p]; } virtual BoardPreset getBoardPresetID() const; // --- class specific methods --- /* A vector with the used geometric X- and Y-coordinates of all the positions. This can be used for displaying a coordinate frame around the board. */ std::vector xCoords() const; std::vector yCoords() const; private: const struct boardTable* spec; std::vector neighbors; std::vector mills; std::vector > millsAtPos; }; #endif morris-0.3/src/configmgr.cc000066400000000000000000000056241373406602200157520ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "configmgr.hh" #include const char* ConfigManager::itemComputer_maxTime[2] = { "max-time","max-time" }; const char* ConfigManager::itemComputer_maxDepth[2] = { "max-depth", "max-depth" }; const char* ConfigManager::itemComputer_weightMaterial[2] = { "material","material" }; const char* ConfigManager::itemComputer_weightFreedom[2] = { "freedom","freedom" }; const char* ConfigManager::itemComputer_weightMills[2] = { "mills","mills" }; const char* ConfigManager::itemComputer_weightExperience[2] = { "experience","experience" }; const char* ConfigManager::itemComputers_shareTTables = "share-transposition-tables"; const char* ConfigManager::itemDisplay_showGameOverMessageBox = "show-game-over-message-box"; const char* ConfigManager::itemDisplayGtk_showCoordinates = "show-board-coordinates"; const char* ConfigManager::itemDisplayGtk_coloredCrossingsWhileDragging = "colored-crossings-while-dragging"; const char* ConfigManager::itemDisplayGtk_animateComputerMoves = "animate-computer-moves"; const char* ConfigManager::itemDisplayGtk_animateSettingOfPieces = "animate-setting-of-pieces"; const char* ConfigManager::itemDisplayGtk_animateTakes = "animate-takes"; const char* ConfigManager::itemDisplayGtk_animationSpeed = "animation-speed"; const char* ConfigManager::itemDisplayGtk_takePieceDelay = "take-piece-delay"; const char* ConfigManager::itemPref_pauseOnAIPlayer = "pause-on-ai-player"; const char* ConfigManager::itemPref_showLogOfMoves = "show-log-of-moves"; ConfigManager::ConfigManager() { settings = g_settings_new("net.nine-mens-morris"); disp_settings = g_settings_get_child(settings, "display"); ai_settings = g_settings_get_child(settings, "ai"); compA_settings = g_settings_get_child(ai_settings, "computer-a"); compB_settings = g_settings_get_child(ai_settings, "computer-b"); weightsA_settings = g_settings_get_child(compA_settings, "weights"); weightsB_settings = g_settings_get_child(compB_settings, "weights"); } bool ConfigManager::cmp(const char* a, const char* b) { if (a==b) return true; return strcmp(a,b)==0; } morris-0.3/src/configmgr.hh000066400000000000000000000106001373406602200157520ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef CONFIGMGR_HH #define CONFIGMGR_HH #include #include #include /* The config manager organizes all the configurable options. The architecture is as follows: - An application config-manager establishes the connection between the config and the application (i.e. it knows how to read options out of the application and send changed values to it). - Application config-managers can be chained, so that a main manager can handle all the generic options, while a platform dependent manager can handle the additional specific options. - On top of the application config-manager, another config manager can handle saving and loading of the configuration (such as through gconf). Changed parameters are then forwarded via the application config-manager. The idea of this architecture is to employ gconf-like configuration if it is supported by the system and some other scheme if it is not. In the simplest case, the application config-manager can be used directly, which results in the default behaviour of not saving the configuration, but be otherwise fully functional. */ class ConfigManager { public: ConfigManager(); virtual ~ConfigManager() { } virtual void readInitialValues() { } virtual void store(GSettings* settings, const char* key, int value) = 0; virtual void store(GSettings* settings, const char* key, bool value) = 0; virtual void store(GSettings* settings, const char* key, float value) = 0; virtual void store(GSettings* settings, const char* key, const char* value) = 0; virtual int read_int (GSettings* settings, const char* key) = 0; virtual bool read_bool (GSettings* settings, const char* key) = 0; virtual float read_float (GSettings* settings, const char* key) = 0; virtual std::string read_string(GSettings* settings, const char* key) = 0; GSettings* main() { return settings; } GSettings* disp() { return disp_settings; } GSettings* ai() { return ai_settings; } GSettings* compA() { return compA_settings; } GSettings* compB() { return compB_settings; } GSettings* weightsA() { return weightsA_settings; } GSettings* weightsB() { return weightsB_settings; } // constant strings for the configurable items static const char* itemComputer_maxTime[2]; static const char* itemComputer_maxDepth[2]; static const char* itemComputer_weightMaterial[2]; static const char* itemComputer_weightFreedom[2]; static const char* itemComputer_weightMills[2]; static const char* itemComputer_weightExperience[2]; static const char* itemComputers_shareTTables; static const char* itemDisplay_showGameOverMessageBox; static const char* itemDisplayGtk_showCoordinates; static const char* itemDisplayGtk_coloredCrossingsWhileDragging; static const char* itemDisplayGtk_animateComputerMoves; static const char* itemDisplayGtk_animateSettingOfPieces; static const char* itemDisplayGtk_animateTakes; static const char* itemDisplayGtk_animationSpeed; static const char* itemDisplayGtk_takePieceDelay; static const char* itemPref_pauseOnAIPlayer; static const char* itemPref_showLogOfMoves; protected: GSettings* settings; GSettings* disp_settings; GSettings* ai_settings; GSettings* compA_settings; GSettings* compB_settings; GSettings* weightsA_settings; GSettings* weightsB_settings; // Compare two config-keys. This function is optimized for the comparisons of the keys. static bool cmp(const char*, const char*); }; typedef boost::shared_ptr configmanager_ptr; #endif morris-0.3/src/constants.hh000066400000000000000000000024361373406602200160230ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef CONSTANTS_HH #define CONSTANTS_HH enum { MAXPOSITIONS =36 }; // maximum number of positions on a board enum { MAXPIECES =15 }; // maximum number of pieces for a player enum { MAXNEIGHBORS =8 }; // maximum number of neighbors of a board position enum { MAXMILLSIZE =3 }; // maximum mill-size enum { MAXSEARCHDEPTH=50 }; enum { TRANSPOSITION_TABLE_SIZE=20 }; // significant bits for the transposition-table hash #endif morris-0.3/src/control.cc000066400000000000000000000153511373406602200154550ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "control.hh" #include "threadtunnel.hh" #include GameControl::GameControl() { m_partialMoveActive = false; // TODO: move the partial moves into board-gui ? m_history.push_back( boost::shared_ptr(new Board) ); m_currentHistoryPos=0; m_board=m_history[0].get(); m_moveID=0; // setup some game ... m_ruleSpec = RuleSpec::createPresetRule(RuleSpec::Preset_Standard); resetGame(); } GameControl::~GameControl() { } void GameControl::registerPlayerIF(Player p, player_ptr interf) { int idx = player2Index(p); // if a move is underway, stop it if (m_gameState.state == GameState::Moving && p==m_board->getCurrentPlayer()) { m_gameState.state = GameState::Idle; m_moveID++; m_player[idx]->cancelMove(); m_signal_endMove(getCurrentPlayerInterface()); } // replace the player m_player[idx] = interf; interf->setPlayer(p); interf->setRuleSpec( m_ruleSpec ); } void GameControl::registerRuleSpec(rulespec_ptr r) { m_ruleSpec=r; if (m_gameState.state == GameState::Moving && getCurrentPlayerInterface()) { getCurrentPlayerInterface()->cancelMove(); m_signal_endMove(getCurrentPlayerInterface()); } for (int i=0;i<2;i++) if (m_player[i]!=NULL) m_player[i]->setRuleSpec(r); m_gameState.state = GameState::Idle; } int GameControl::doMove(Move m) { assert(m_gameState.state == GameState::Moving); // check if there are still 'takes' to be added to the move int nTakes = m_ruleSpec->nPotentialMills(*m_board, m); if (nTakes > 0 && m_ruleSpec->mayTakeMultiple==false) nTakes=1; nTakes -= m.takes.size(); // subtract the number of takes we have already entered if (nTakes>0) { m_partialMoveActive= true; m_partialMoveBoard = *m_board; m_partialMoveBoard.doMove(m); m_partialMoveBoard.togglePlayer(); // stay with current player (toggle back) return nTakes; } // --- move is complete, carry out the move --- m_partialMoveActive=false; m_signal_endMove(getCurrentPlayerInterface()); // add copy of current board to history end m_history.resize(m_currentHistoryPos+1); // delete future history m_movelog.resize(m_currentHistoryPos); // delete future history m_history.push_back( boost::shared_ptr(new Board) ); m_movelog.push_back(m); m_currentHistoryPos++; *(m_history.back()) = *m_board; m_history.back()->setPrevBoard(*(m_history.end()-2)); m_board = m_history.back().get(); m_board->doMove(m); // check for end of game if (m_ruleSpec->currentPlayerHasLost(*m_board)) { m_gameState.state = GameState::Ended; m_gameState.SUBSTATE_Winner = m_board->getOpponentPlayer(); } /* We do not have to check for the current player having won, because in that case, the opponent would have been detected as loser in the previous move. */ else if (m_ruleSpec->tieBetweenBothPlayers(*m_board)) { m_gameState.state = GameState::Ended; m_gameState.SUBSTATE_Winner = PL_None; } else { m_gameState.state = GameState::Idle; } // announce winner if (m_gameState.state == GameState::Ended) { m_gameHasEnded=true; m_winner=m_gameState.SUBSTATE_Winner; for (int i=0;i<2;i++) { m_player[i]->notifyWinner(m_winner); } m_signal_gameOver(m_winner); m_signal_changeState(m_gameState); } m_signal_changeBoard(); return 0; // no more takes, move is complete } void GameControl::startNextMove() { assert(m_gameState.state == GameState::Idle); assert(getCurrentPlayerInterface() != NULL); m_gameState.state = GameState::Moving; // update game state const Player p = m_board->getCurrentPlayer(); m_gameState.SUBSTATE_PlayerSet = (m_board->getNPiecesToSet(p) > 0); m_gameState.SUBSTATE_PlayerMove = (m_board->getNPiecesToSet(p)==0 || m_ruleSpec->laskerVariant); // initiate next player's move m_moveID++; getCurrentPlayerInterface()->startMove(getCurrentBoard(), m_moveID); m_signal_startMove( getCurrentPlayerInterface() ); } void GameControl::undoMove() { if (m_currentHistoryPos>0) { m_moveID++; if (m_gameState.state == GameState::Moving) { getCurrentPlayerInterface()->cancelMove(); m_signal_endMove(getCurrentPlayerInterface()); } m_gameState.state = GameState::Idle; m_partialMoveActive=false; m_currentHistoryPos--; m_board = m_history[m_currentHistoryPos].get(); m_signal_changeState(m_gameState); m_signal_changeBoard(); } } void GameControl::redoMove() { if (m_currentHistoryPoscancelMove(); m_signal_endMove(getCurrentPlayerInterface()); } m_partialMoveActive=false; m_currentHistoryPos++; m_board = m_history[m_currentHistoryPos].get(); Player winner; if (m_ruleSpec->isGameOver(*m_board, &winner)) { m_gameState.state = GameState::Ended; m_gameState.SUBSTATE_Winner = winner; } else { m_gameState.state = GameState::Idle; } m_signal_changeState(m_gameState); m_signal_changeBoard(); } } void GameControl::resetGame() { if (m_gameState.state==GameState::Moving) { getCurrentPlayerInterface()->cancelMove(); m_signal_endMove(getCurrentPlayerInterface()); } for (int i=0;i<2;i++) if (m_player[i]) { m_player[i]->resetGame(); } m_moveID++; m_partialMoveActive = false; m_history.clear(); m_movelog.clear(); m_history.push_back( boost::shared_ptr(new Board) ); m_currentHistoryPos=0; m_board = m_history[0].get(); m_board->reset( m_ruleSpec->nPieces ); m_gameHasEnded=false; m_gameState.state = GameState::Idle; m_signal_changeState(m_gameState); m_signal_changeBoard(); } void GameControl::stopThreads() { for (int i=0;i<2;i++) if (m_player[i]) { m_player[i]->cancelMove(); } } morris-0.3/src/control.hh000066400000000000000000000162631373406602200154720ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef CONTROL_HH #define CONTROL_HH #include #include #include #include "board.hh" #include "player.hh" struct GameState { enum State { Idle, /* GameControl is waiting for the next move. */ Moving, /* A new move was started, but the player did not return a (complete) move yet. */ Ended /* The game is over. */ }; State state; bool SUBSTATE_PlayerSet; // whether the player may set a new stone bool SUBSTATE_PlayerMove; // whether the player may move a stone Player SUBSTATE_Winner; // for STATE_Ended }; /* The GameControl manages running a game and controls the players. Since some players may run in their own threads, the players probably will not return their moves directly, but via some other path. Process of conducting a move: - Call startNextMove(). The GameControl will then send a start command to the current player. - Once the move was given by the user or the AI finished thinking, the method 'doMove()' has to be called to actually carry out the move. - If the move was not complete (a human move closed a mill, but the move did not contain the take), the move is only partially carried out and the number of remaining takes is returned. 'doMove()' then has to be called again. This can be repeated until the move is complete. */ class GameControl { public: GameControl(); ~GameControl(); /* Call this only if the program wants to close and all threads have to be stopped before. */ void stopThreads(); // --- configuration --- void registerPlayerIF(Player p, boost::shared_ptr interf); void registerRuleSpec(rulespec_ptr); boardspec_ptr getBoardSpec() const { return m_ruleSpec->boardSpec; } rulespec_ptr getRuleSpec() const { return m_ruleSpec; } // --- global game control --- void resetGame(); /* Initiate the next move. Usually, this will not actually carry out the move, but simply e.g., start a background process for AI, or put the user-interface into a different state that allows inputting of moves. */ void startNextMove(); /* Returns the number of takes the player still has to perform. If this is != 0, the GUI has to send a new move with more takes. Only of the return value is 0, the move has been actually carried out. TODO: I now think that this design is bad, because it mixes a query (move complete) with a concrete action. This mixing introduces difficulties, e.g., when the GUI wants to enter the move, it cannot really end it before it calls doMove(), because it doesn't know, if it is really the end. Consequently, startNextMove() cannot immediately start the next move, because the GUI is not cleaned up yet. This requires the current work-arounds with starting the next move in an idle-function. */ int doMove(Move m); /* Force the current player (usually the AI) to carry out the move as soon as possible. */ void forceMove() { m_player[ player2Index(m_board->getCurrentPlayer()) ]->forceMove(); } GameState getGameState() const { return m_gameState; } Player getCurrentPlayer() const { return getCurrentBoard().getCurrentPlayer(); } player_ptr getCurrentPlayerInterface() const { return m_player[player2Index(m_board->getCurrentPlayer())]; } /* Get the current board. After conducting an incomplete move, this shows the situation after the incomplete move. */ const Board& getCurrentBoard() const { return m_partialMoveActive ? m_partialMoveBoard : *m_board; } /* Same as above, but will never return an intermediate board after a partial move, but the situation just before the move. */ const Board& getCurrentBoard_noTemporary() const { return *m_board; } bool hasGameEnded() const { return m_gameHasEnded; } Player getGameWinner() const { return m_winner; } /* The move-ID is a number that identifies the current move. It is used to solve nasty race-conditions, in which a separate AI-thread pushes its move into the main-loop while the user just starts a new game or performs an undo-operation. With the move-ID, the main thread can check if the move sent by the AI-thread is still the same game as the currently shown board. To this end, the AI-thread stores the move-ID at the time its move was started and forwards this stored ID together with its move to the main-thread. */ int getCurrentMoveID() const { return m_moveID; } // --- history / undo-buffer --- // TODO: extract history to external class (would allow e.g. variation analysis) void undoMove(); void redoMove(); int getHistoryPos() const { return m_currentHistoryPos; } int getHistorySize() const { return m_history.size(); } Move getHistoryMove(int ply) const { return m_movelog[ply]; } boost::shared_ptr getHistoryBoard(int ply) const { return m_history[ply]; } // --- signals --- boost::signals2::signal& getSignal_gameOver() { return m_signal_gameOver; } boost::signals2::signal& getSignal_changeState() { return m_signal_changeState; } boost::signals2::signal& getSignal_changeBoard() { return m_signal_changeBoard; } boost::signals2::signal& getSignal_startMove() { return m_signal_startMove; } boost::signals2::signal& getSignal_endMove() { return m_signal_endMove; } private: rulespec_ptr m_ruleSpec; player_ptr m_player[2]; Board* m_board; GameState m_gameState; int m_moveID; bool m_partialMoveActive; Board m_partialMoveBoard; bool m_gameHasEnded; /* Do not confuse with GameState::Ended. This flag tells if the game in the history is complete. */ Player m_winner; // Only valid if m_gameHasEnded==true. // Undo-Buffer std::vector m_movelog; std::vector< boost::shared_ptr > m_history; int m_currentHistoryPos; // signals boost::signals2::signal m_signal_gameOver; boost::signals2::signal m_signal_changeState; boost::signals2::signal m_signal_changeBoard; boost::signals2::signal m_signal_startMove; boost::signals2::signal m_signal_endMove; }; #endif morris-0.3/src/gconf_configmgr.cc000066400000000000000000000126511373406602200171240ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "gconf_configmgr.hh" #include "mainapp.hh" static const char* prefix = "/apps/morris"; static std::string gconfKey(const char* item) { std::string path = prefix; path += "/"; path += std::string(item); return path; } static const char* mapKey(const char* gconfpath) { return &gconfpath[ strlen(prefix)+1 ]; } void cb_gconf_change_notify(GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data) { // value was unset if (entry==NULL) { return; } ConfigManager_GConf* obj = (ConfigManager_GConf*)(user_data); //std::cout << "change notify: " << entry->key << "\n"; switch (entry->value->type) { case GCONF_VALUE_STRING: obj->appConfig.store(mapKey(entry->key), (const char*)(gconf_value_get_string(entry->value))); break; case GCONF_VALUE_INT: obj->appConfig.store(mapKey(entry->key), int(gconf_value_get_int(entry->value))); break; case GCONF_VALUE_FLOAT: obj->appConfig.store(mapKey(entry->key), float(gconf_value_get_float(entry->value))); break; case GCONF_VALUE_BOOL: obj->appConfig.store(mapKey(entry->key), bool(gconf_value_get_bool(entry->value))); break; } } ConfigManager_GConf::ConfigManager_GConf(int argc, char** argv) { gconf_init(argc, argv, NULL); client = gconf_client_get_default(); gconf_client_add_dir(client, prefix, GCONF_CLIENT_PRELOAD_NONE, NULL); gconf_client_notify_add(client, prefix, cb_gconf_change_notify, this, NULL, NULL); } ConfigManager_GConf::~ConfigManager_GConf() { g_object_unref(client); } void ConfigManager_GConf::readInitialBoolValue(const char* key) { appConfig.store(key, read_bool(key)); } void ConfigManager_GConf::readInitialFloatValue(const char* key) { appConfig.store(key, read_float(key)); } void ConfigManager_GConf::readInitialIntValue(const char* key) { appConfig.store(key, read_int(key)); } void ConfigManager_GConf::readInitialValues() { /* TODO: this should somehow be in the base class */ readInitialBoolValue(itemPref_pauseOnAIPlayer); readInitialBoolValue(itemPref_showLogOfMoves); readInitialBoolValue(itemDisplay_showGameOverMessageBox); readInitialBoolValue(itemDisplayGtk_showCoordinates); readInitialBoolValue(itemDisplayGtk_coloredCrossingsWhileDragging); readInitialBoolValue(itemDisplayGtk_animateComputerMoves); readInitialBoolValue(itemDisplayGtk_animateSettingOfPieces); readInitialBoolValue(itemDisplayGtk_animateTakes); readInitialFloatValue(itemDisplayGtk_animationSpeed); readInitialFloatValue(itemDisplayGtk_takePieceDelay); for (int i=0;i<2;i++) { readInitialIntValue(itemComputer_maxTime[i]); readInitialIntValue(itemComputer_maxDepth[i]); readInitialFloatValue(itemComputer_weightMaterial[i]); readInitialFloatValue(itemComputer_weightFreedom[i]); readInitialFloatValue(itemComputer_weightMills[i]); readInitialFloatValue(itemComputer_weightExperience[i]); } readInitialBoolValue(itemComputers_shareTTables); } void ConfigManager_GConf::store(const char* key, int value) { gconf_client_set_int(client, gconfKey(key).c_str(), value, NULL); } void ConfigManager_GConf::store(const char* key, bool value) { gconf_client_set_bool(client, gconfKey(key).c_str(), value, NULL); } void ConfigManager_GConf::store(const char* key, float value) { gconf_client_set_float(client, gconfKey(key).c_str(), value, NULL); } void ConfigManager_GConf::store(const char* key, const char* value) { assert(0); // TODO } int ConfigManager_GConf::read_int(const char* key) { GConfValue* value = gconf_client_get(client, gconfKey(key).c_str(), NULL); if (value==NULL || value->type != GCONF_VALUE_INT) { return appConfig.read_int(key); } int v = gconf_value_get_int(value); gconf_value_free(value); return v; } bool ConfigManager_GConf::read_bool(const char* key) { GConfValue* value = gconf_client_get(client, gconfKey(key).c_str(), NULL); if (value==NULL || value->type != GCONF_VALUE_BOOL) { return appConfig.read_bool(key); } bool v = gconf_value_get_bool(value); gconf_value_free(value); return v; } float ConfigManager_GConf::read_float(const char* key) { GConfValue* value = gconf_client_get(client, gconfKey(key).c_str(), NULL); if (value==NULL || value->type != GCONF_VALUE_FLOAT) { return appConfig.read_float(key); } float v = gconf_value_get_float(value); gconf_value_free(value); return v; } std::string ConfigManager_GConf::read_string(const char* key) { assert(0); // TODO /* if (str) g_free(str); */ } morris-0.3/src/gconf_configmgr.hh000066400000000000000000000037531373406602200171410ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef GCONF_CONFIGMGR_HH #define GCONF_CONFIGMGR_HH #include "configmgr.hh" #include "app_configmgr.hh" #include class ConfigManager_GConf : public ConfigManager { public: ConfigManager_GConf(int argc, char** argv); ~ConfigManager_GConf(); virtual void readInitialValues(); virtual void store(const char* key, int value); virtual void store(const char* key, bool value); virtual void store(const char* key, float value); virtual void store(const char* key, const char* value); virtual int read_int (const char* key); virtual bool read_bool (const char* key); virtual float read_float (const char* key); virtual std::string read_string(const char* key); void setAppConfigDelegate(configmanager_ptr c) { appConfig.setDelegate(c); } private: ConfigManager_Application appConfig; GConfClient* client; friend void cb_gconf_change_notify(GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data); void readInitialBoolValue(const char* key); void readInitialFloatValue(const char* key); void readInitialIntValue(const char* key); }; #endif morris-0.3/src/gettext.h000066400000000000000000000224211373406602200153170ustar00rootroot00000000000000/* Convenience header for conditional use of GNU . Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc. 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, 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 Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _LIBGETTEXT_H #define _LIBGETTEXT_H 1 /* NLS can be disabled through the configure --disable-nls option. */ #if ENABLE_NLS /* Get declarations of GNU message catalog functions. */ # include /* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by the gettext() and ngettext() macros. This is an alternative to calling textdomain(), and is useful for libraries. */ # ifdef DEFAULT_TEXT_DOMAIN # undef gettext # define gettext(Msgid) \ dgettext (DEFAULT_TEXT_DOMAIN, Msgid) # undef ngettext # define ngettext(Msgid1, Msgid2, N) \ dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) # endif #else /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which chokes if dcgettext is defined as a macro. So include it now, to make later inclusions of a NOP. We don't include as well because people using "gettext.h" will not include , and also including would fail on SunOS 4, whereas is OK. */ #if defined(__sun) # include #endif /* Many header files from the libstdc++ coming with g++ 3.3 or newer include , which chokes if dcgettext is defined as a macro. So include it now, to make later inclusions of a NOP. */ #if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) # include # if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H # include # endif #endif /* Disabled NLS. The casts to 'const char *' serve the purpose of producing warnings for invalid uses of the value returned from these functions. On pre-ANSI systems without 'const', the config.h file is supposed to contain "#define const". */ # define gettext(Msgid) ((const char *) (Msgid)) # define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) # define dcgettext(Domainname, Msgid, Category) \ ((void) (Category), dgettext (Domainname, Msgid)) # define ngettext(Msgid1, Msgid2, N) \ ((N) == 1 \ ? ((void) (Msgid2), (const char *) (Msgid1)) \ : ((void) (Msgid1), (const char *) (Msgid2))) # define dngettext(Domainname, Msgid1, Msgid2, N) \ ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ ((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N)) # define textdomain(Domainname) ((const char *) (Domainname)) # define bindtextdomain(Domainname, Dirname) \ ((void) (Domainname), (const char *) (Dirname)) # define bind_textdomain_codeset(Domainname, Codeset) \ ((void) (Domainname), (const char *) (Codeset)) #endif /* A pseudo function call that serves as a marker for the automated extraction of messages, but does not call gettext(). The run-time translation is done at a different place in the code. The argument, String, should be a literal string. Concatenated strings and other string expressions won't work. The macro's expansion is not parenthesized, so that it is suitable as initializer for static 'char[]' or 'const char[]' variables. */ #define gettext_noop(String) String /* The separator between msgctxt and msgid in a .mo file. */ #define GETTEXT_CONTEXT_GLUE "\004" /* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be short and rarely need to change. The letter 'p' stands for 'particular' or 'special'. */ #ifdef DEFAULT_TEXT_DOMAIN # define pgettext(Msgctxt, Msgid) \ pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) #else # define pgettext(Msgctxt, Msgid) \ pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) #endif #define dpgettext(Domainname, Msgctxt, Msgid) \ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) #define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) #ifdef DEFAULT_TEXT_DOMAIN # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) #else # define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) #endif #define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) #ifdef __GNUC__ __inline #else #ifdef __cplusplus inline #endif #endif static const char * pgettext_aux (const char *domain, const char *msg_ctxt_id, const char *msgid, int category) { const char *translation = dcgettext (domain, msg_ctxt_id, category); if (translation == msg_ctxt_id) return msgid; else return translation; } #ifdef __GNUC__ __inline #else #ifdef __cplusplus inline #endif #endif static const char * npgettext_aux (const char *domain, const char *msg_ctxt_id, const char *msgid, const char *msgid_plural, unsigned long int n, int category) { const char *translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); if (translation == msg_ctxt_id || translation == msgid_plural) return (n == 1 ? msgid : msgid_plural); else return translation; } /* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID can be arbitrary expressions. But for string literals these macros are less efficient than those above. */ #include #define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \ /* || __STDC_VERSION__ >= 199901L */ ) #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS #include #endif #define pgettext_expr(Msgctxt, Msgid) \ dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) #define dpgettext_expr(Domainname, Msgctxt, Msgid) \ dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) #ifdef __GNUC__ __inline #else #ifdef __cplusplus inline #endif #endif static const char * dcpgettext_expr (const char *domain, const char *msgctxt, const char *msgid, int category) { size_t msgctxt_len = strlen (msgctxt) + 1; size_t msgid_len = strlen (msgid) + 1; const char *translation; #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS char msg_ctxt_id[msgctxt_len + msgid_len]; #else char buf[1024]; char *msg_ctxt_id = (msgctxt_len + msgid_len <= sizeof (buf) ? buf : (char *) malloc (msgctxt_len + msgid_len)); if (msg_ctxt_id != NULL) #endif { memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); msg_ctxt_id[msgctxt_len - 1] = '\004'; memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); translation = dcgettext (domain, msg_ctxt_id, category); #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS if (msg_ctxt_id != buf) free (msg_ctxt_id); #endif if (translation != msg_ctxt_id) return translation; } return msgid; } #define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) #ifdef __GNUC__ __inline #else #ifdef __cplusplus inline #endif #endif static const char * dcnpgettext_expr (const char *domain, const char *msgctxt, const char *msgid, const char *msgid_plural, unsigned long int n, int category) { size_t msgctxt_len = strlen (msgctxt) + 1; size_t msgid_len = strlen (msgid) + 1; const char *translation; #if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS char msg_ctxt_id[msgctxt_len + msgid_len]; #else char buf[1024]; char *msg_ctxt_id = (msgctxt_len + msgid_len <= sizeof (buf) ? buf : (char *) malloc (msgctxt_len + msgid_len)); if (msg_ctxt_id != NULL) #endif { memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); msg_ctxt_id[msgctxt_len - 1] = '\004'; memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); #if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS if (msg_ctxt_id != buf) free (msg_ctxt_id); #endif if (!(translation == msg_ctxt_id || translation == msgid_plural)) return translation; } return (n == 1 ? msgid : msgid_plural); } #endif /* _LIBGETTEXT_H */ morris-0.3/src/gtk_appgui.cc000066400000000000000000000137501373406602200161300ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "config.h" #include "gtkcairo_boardgui.hh" #include "gtk_menutoolbar.hh" #include "gtk_appgui.hh" #include "mainapp.hh" #include "gtk_threadtunnel.hh" #include "gtk_prefDisplay.hh" #include "appgtk_configmgr.hh" #include #include #include #include static gboolean delete_callback(GtkWidget *widget, GdkEvent* event, gpointer data) { return FALSE; } static void cb_destroy(GtkWidget *widget, gpointer data) { ((ApplicationGUI_Gtk*)(data))->quitApplication(); } /* This function should also work if MainApp is not fully functional yet. */ ApplicationGUI_Gtk::ApplicationGUI_Gtk() { window = gtk_window_new(GTK_WINDOW_TOPLEVEL); main_vbox = gtk_vbox_new(false,0); gtk_container_add (GTK_CONTAINER (window), main_vbox); gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE); gtk_widget_realize(window); // statusbar statusbar = gtk_statusbar_new(); statusbar_context = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), "mainapp"); gtk_box_pack_end(GTK_BOX(main_vbox), statusbar, false,true,0); progressbar = gtk_progress_bar_new(); gtk_box_pack_start(GTK_BOX(statusbar), progressbar, false,true,0); gtk_box_reorder_child(GTK_BOX(statusbar), progressbar, 0); // signals gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(cb_destroy), this); gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_callback), this); } ApplicationGUI_Gtk::~ApplicationGUI_Gtk() { } void ApplicationGUI_Gtk::initApplicationGUI(int& argc, char**& argv) { gdk_threads_init(); gtk_init(&argc,&argv); // attach app-GUI and board-GUI to main application ApplicationGUI_Gtk* appgui = new ApplicationGUI_Gtk; MainApp::app().setApplicationGUI( appgui_ptr(appgui) ); MainApp::app().setThreadTunnel( getThreadTunnel_Gtk() ); BoardGUI_GtkCairo* boardgui = new BoardGUI_GtkCairo; appgui->setBoardGUI( boardgui_ptr(boardgui)); gtk_box_pack_end(GTK_BOX(appgui->getMainWindowVBox()), boardgui->getBoardWidget(), true,true,0); ConfigManager_Chained* config = new ConfigManager_Application(); config->setDelegate(configmanager_ptr(new ConfigManager_AppGtk)); MainApp::app().registerConfigManager(configmanager_ptr(config)); } void ApplicationGUI_Gtk::startApplication() { GameControl& control = MainApp::app().getControl(); control.getSignal_changeState().connect(boost::bind(&ApplicationGUI_Gtk::changeState, this, _1)); control.getSignal_changeBoard().connect(boost::bind(&ApplicationGUI_Gtk::changeBoard, this)); control.getSignal_startMove() .connect(boost::bind(&ApplicationGUI_Gtk::startMove, this)); gtk_initMainMenu(main_vbox, window); gtk_connectMenuSignals(); showWindow(); MainApp::app().getConfigManager()->readInitialValues(); // TODO: this should probably be in MainApp.init() control.startNextMove(); // === main loop === gdk_threads_enter(); gtk_main(); gdk_threads_leave(); } void ApplicationGUI_Gtk::quitApplication() { showMoveLog(false, true); MainApp::app().getControl().stopThreads(); gtk_main_quit(); } void ApplicationGUI_Gtk::changeState(const GameState& state) { } void ApplicationGUI_Gtk::changeBoard() { } void ApplicationGUI_Gtk::startMove() { } void ApplicationGUI_Gtk::preferencesDialog_Display() { ::preferencesDialog_Display(); gui_board->resetDisplay(); } void ApplicationGUI_Gtk::showMoveLog(bool enable, bool quitApp) { if (enable) { gui_movelog = boost::shared_ptr(new MoveLog_Gtk); gui_movelog->getSignal_windowClosed().connect(boost::bind(&ApplicationGUI_Gtk::showMoveLog, this,false,false)); gui_movelog->getSignal_windowClosed().connect(boost::bind(menu_closedMoveLog, false)); } else { gui_movelog.reset(); } if (!quitApp) { configmanager_ptr config = MainApp::app().getConfigManager(); config->store(config->main(), ConfigManager::itemPref_showLogOfMoves, enable); } } void ApplicationGUI_Gtk::showGameOverDialog(Player winner) { if (!options.showGameOverRequester) { return; } const char* text; switch (winner) { case PL_White: text=_("White has won."); break; case PL_Black: text=_("Black has won."); break; case PL_None: text=_("Tie between both players."); break; } GtkWidget* dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, _("Game over")); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", text); gtk_dialog_run(GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } void ApplicationGUI_Gtk::showAboutDialog() { const char* authors[] = { "Dirk Farin ", NULL }; gtk_show_about_dialog (GTK_WINDOW(window), "program-name", PACKAGE_NAME, //"logo", example_logo, //"title", _("About Gnome Nine-Mens-Morris"), // tag does not exist ? "authors", authors, "version", VERSION, "comments", _("A computer adaptation of the Nine-Mens-Morris board game and its variants."), "copyright", "Copyright (c) 2009 Dirk Farin", //"website", "morris.org", NULL); } morris-0.3/src/gtk_appgui.hh000066400000000000000000000052571373406602200161450ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef GTK_APP_HH #define GTK_APP_HH #include "gtk_appgui_interface.hh" #include "gtk_movelog.hh" #include #include class ApplicationGUI_Gtk : public ApplicationGUI_GtkIF { public: ApplicationGUI_Gtk(); ~ApplicationGUI_Gtk(); static void initApplicationGUI(int& argc, char**& argv); virtual void startApplication(); virtual void quitApplication(); virtual void setProgress(float p) { gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), p); } virtual void setStatusbar(const std::string& str) { gtk_statusbar_pop (GTK_STATUSBAR(statusbar), statusbar_context); gtk_statusbar_push(GTK_STATUSBAR(statusbar), statusbar_context, str.c_str()); } void showGameOverDialog(Player winner); void enableGameOverDialog(bool flag) { options.showGameOverRequester = flag; } bool getGameOverDialogFlag() const { return options.showGameOverRequester; } void preferencesDialog_Display(); void showMoveLog(bool enable=true, bool quitApp=false); bool isMoveLogShown() const { return gui_movelog != NULL; } GtkWidget* getMainWindow() { return window; } GtkWidget* getMainWindowVBox() { return main_vbox; } void showWindow() { gtk_widget_show_all(window); } void setBoardGUI(boardgui_ptr gui) { gui_board=gui; } boardgui_ptr getBoardGUI() const { return gui_board; } void showAboutDialog(); private: GtkWidget* window; GtkWidget* main_vbox; GtkWidget* statusbar; gint statusbar_context; GtkWidget* progressbar; boardgui_ptr gui_board; boost::shared_ptr gui_movelog; struct Options { Options() : showGameOverRequester(true) { } bool showGameOverRequester; } options; friend void gtk_initMainMenu(GtkWidget* vbox, GtkWidget* window); void changeState(const struct GameState& state); void changeBoard(); void startMove(); }; #endif morris-0.3/src/gtk_appgui_interface.hh000066400000000000000000000022371373406602200201600ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef APPLICATIONGUI_GTKIF #define APPLICATIONGUI_GTKIF #include #include "appgui.hh" // Trivial helper class in case we want to easily support both Gtk-only // and Gnome applications. class ApplicationGUI_GtkIF : public ApplicationGUI { public: virtual GtkWidget* getMainWindow() = 0; }; #endif morris-0.3/src/gtk_menutoolbar.cc000066400000000000000000000374471373406602200172030ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "gtk_menutoolbar.hh" #include "boardgui.hh" #include "mainapp.hh" static void quit_callback(gpointer) { MainApp::app().getApplicationGUI()->quitApplication(); } static void new_game_callback(gpointer) { MainApp::app().resetGame(); } static void undo_move_callback(gpointer) { MainApp::app().undo(); } static void redo_move_callback(gpointer) { MainApp::app().redo(); } static void cb_continue_game(gpointer) { MainApp::app().continueGame(); } static void cb_forceMove(gpointer) { MainApp::app().getControl().forceMove(); } static void hint_callback(gpointer) { MainApp::app().computeHint(); } void cb_gtk_select_player(GtkAction*); void gtk_swap_players(gpointer spec); void cb_config_customRules(); void cb_gtk_setBoard(GtkAction*); extern bool preferencesDialog_ruleSpec(); extern void preferencesDialog_AI(); static void cb_showAboutDialog() { MainApp::app().getApplicationGUI()->showAboutDialog(); } static void preferencesDialog_Display() { appgui_ptr gui = MainApp::app().getApplicationGUI(); gui->preferencesDialog_Display(); } static void cb_pauseOnAI(GtkToggleAction* a) { bool active = bool(gtk_toggle_action_get_active(a)); configmanager_ptr config = MainApp::app().getConfigManager(); config->store(config->main(), ConfigManager::itemPref_pauseOnAIPlayer, active); } static void cb_showMoveLog(GtkToggleAction* a) { bool active = bool(gtk_toggle_action_get_active(a)); configmanager_ptr config = MainApp::app().getConfigManager(); config->store(config->main(), ConfigManager::itemPref_showLogOfMoves, active); MainApp::app().getApplicationGUI()->showMoveLog(active, false); } static void cb_animated_moves(GtkWidget* w, gpointer spec) { } static const char* menu_toolbar_spec = "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " //" " " " " " " " " " " " //" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ""; static const char* toolbar_spec = "" " " " " " " " " " " " " " " " " " " ""; static GtkActionEntry actions[] = { { "GameMenu", NULL, N_("Game"), NULL, N_("menu for game-related functions."), NULL }, { "NewGame", GTK_STOCK_REFRESH, N_("New game"), "n", N_("Start a new game."), (GCallback)new_game_callback }, { "ContinueGame", GTK_STOCK_MEDIA_PLAY,N_("Continue game"), "c", N_("Continue a paused game."), (GCallback)cb_continue_game }, { "ForceMove", GTK_STOCK_STOP, N_("Force move"), "f", N_("Force computer move (immediately stop calculation)."), (GCallback)cb_forceMove }, { "UndoMove", GTK_STOCK_UNDO, N_("Undo move"), "z", N_("Undo last move."), (GCallback)undo_move_callback }, { "RedoMove", GTK_STOCK_REDO, N_("Redo move"), "z", N_("Redo last move."), (GCallback)redo_move_callback }, { "Hint", GTK_STOCK_HELP, N_("Hint"), "h", N_("Give a hint for the next move."), (GCallback)hint_callback }, { "QuitPrg", GTK_STOCK_QUIT, NULL, NULL, NULL, (GCallback)quit_callback }, { "PropertiesMenu", NULL, N_("Options"), NULL, NULL, NULL }, { "whtPlayer", NULL, N_("White player"), 0,0,0 }, { "blkPlayer", NULL, N_("Black player"), 0,0,0 }, { "swap", NULL, N_("Swap players"), "s",0,(GCallback)gtk_swap_players }, { "confAI", NULL, N_("Configure AI ..."), 0,0,(GCallback)preferencesDialog_AI }, { "prefDisplay",NULL, N_("Configure display ..."), 0,0,(GCallback)preferencesDialog_Display }, { "configure-rules",NULL, N_("Configure custom rules ..."), 0,0,(GCallback)cb_config_customRules }, { "HelpMenu", NULL, N_("Help"), 0,0,0 }, { "aboutDialog", GTK_STOCK_ABOUT, N_("About Morris..."), 0,0,(GCallback)cb_showAboutDialog }, { "PreferencesMenu", NULL, N_("Preferences"), NULL, NULL, NULL } }; static GtkRadioActionEntry whtPlayerRadio[] = { { "whtPlayer-human", NULL, N_("Human"), 0,0,1+256 }, { "whtPlayer-compA", NULL, N_("Computer A"), 0,0,2+256 }, { "whtPlayer-compB", NULL, N_("Computer B"), 0,0,4+256 }, { "whtPlayer-network", NULL, N_("Network"), 0,0,8+256 } }; static GtkRadioActionEntry blkPlayerRadio[] = { { "blkPlayer-human", NULL, N_("Human"), 0,0,1 }, { "blkPlayer-compA", NULL, N_("Computer A"), 0,0,2 }, { "blkPlayer-compB", NULL, N_("Computer B"), 0,0,4 }, { "blkPlayer-network", NULL, N_("Network"), 0,0,8 }, }; static GtkRadioActionEntry rulesRadio[] = { { "rule-std", NULL, N_("Standard rules"), 0,0,RuleSpec::Preset_Standard }, { "rule-lasker", NULL, N_("Lasker variant"), 0,0,RuleSpec::Preset_Lasker }, { "rule-moebius", NULL, N_("Moebius board"), 0,0,RuleSpec::Preset_Moebius }, { "rule-morabaraba",NULL, N_("Morabaraba"), 0,0,RuleSpec::Preset_Morabaraba }, { "rule-windmill", NULL, N_("Windmill"), 0,0,RuleSpec::Preset_Windmill }, { "rule-sunmill", NULL, N_("Sunmill"), 0,0,RuleSpec::Preset_Sunmill }, { "rule-6mm", NULL, N_("Six Men's Morris"), 0,0,RuleSpec::Preset_6MM }, { "rule-7mm", NULL, N_("Seven Men's Morris"),0,0,RuleSpec::Preset_7MM }, { "rule-poly3", NULL, N_("Triangle board"), 0,0,RuleSpec::Preset_Polygon3 }, { "rule-poly5", NULL, N_("Pentagon board"), 0,0,RuleSpec::Preset_Polygon5 }, { "rule-poly6", NULL, N_("Hexagon board"), 0,0,RuleSpec::Preset_Polygon6 }, { "rule-tapatan", NULL, N_("Tapatan"), 0,0,RuleSpec::Preset_Tapatan }, { "rule-achi", NULL, N_("Achi"), 0,0,RuleSpec::Preset_Achi }, { "rule-minitri", NULL, N_("Small triangle"), 0,0,RuleSpec::Preset_SmallTri }, { "rule-9holes", NULL, N_("Nine Holes"), 0,0,RuleSpec::Preset_NineHoles }, { "rule-custom", NULL, N_("Custom rules"), 0,0,1000 } }; static GtkToggleActionEntry toggleActions[] = { { "pauseOnAI", NULL, N_("Pause on AI-player"), 0,N_("Pause before each AI move."), (GCallback)cb_pauseOnAI, FALSE /* default */ }, { "moveLog", NULL, N_("Show log of moves"), 0,0, (GCallback)cb_showMoveLog, FALSE /* default */ } }; static GtkUIManager* uiManager; static GtkActionGroup* actiongroup; void gtk_initMainMenu(GtkWidget* vbox, GtkWidget* window) { actiongroup = gtk_action_group_new("morrisActions"); gtk_action_group_set_translation_domain(actiongroup, PACKAGE); gtk_action_group_add_actions(actiongroup, actions, G_N_ELEMENTS(actions), NULL /*user-data*/); gtk_action_group_add_radio_actions(actiongroup, whtPlayerRadio, G_N_ELEMENTS(whtPlayerRadio), 1, (GCallback)cb_gtk_select_player /*cb*/, 0/*data*/); gtk_action_group_add_radio_actions(actiongroup, blkPlayerRadio, G_N_ELEMENTS(blkPlayerRadio), 4, (GCallback)cb_gtk_select_player /*cb*/, 0/*data*/); gtk_action_group_add_radio_actions(actiongroup, rulesRadio, G_N_ELEMENTS(rulesRadio), 0, (GCallback)cb_gtk_setBoard /*cb*/, 0/*data*/); gtk_action_group_add_toggle_actions(actiongroup, toggleActions, G_N_ELEMENTS(toggleActions), 0); uiManager = gtk_ui_manager_new(); gtk_ui_manager_insert_action_group (uiManager, actiongroup, 0); GError* error = NULL; gtk_ui_manager_add_ui_from_string(uiManager, menu_toolbar_spec, -1, &error); if (error) std::cout << "ERROR: " << error->message << "\n"; gtk_ui_manager_add_ui_from_string(uiManager, toolbar_spec, -1, &error); if (error) std::cout << "ERROR: " << error->message << "\n"; gtk_window_add_accel_group (GTK_WINDOW (window), gtk_ui_manager_get_accel_group (uiManager)); // menu GtkWidget* menu = gtk_ui_manager_get_widget(uiManager, "/menubar"); gtk_box_pack_start(GTK_BOX(vbox), menu, false,true,0); // toolbar GtkWidget* toolbar = gtk_ui_manager_get_widget(uiManager, "/toolbar1"); gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_BOTH); gtk_box_pack_start(GTK_BOX(vbox), toolbar, false,true,0); // set defaults configmanager_ptr config = MainApp::app().getConfigManager(); if (config->read_bool(config->main(), ConfigManager::itemPref_pauseOnAIPlayer)) gtk_action_activate(gtk_action_group_get_action(actiongroup, "pauseOnAI")); if (config->read_bool(config->main(), ConfigManager::itemPref_showLogOfMoves)) gtk_action_activate(gtk_action_group_get_action(actiongroup, "moveLog")); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "ContinueGame"), false); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "ForceMove"), false); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "UndoMove"), false); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "RedoMove"), false); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "Hint"), true); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "whtPlayer-compB"), false); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "rule-custom"), false); } void cb_gtk_select_player(GtkAction* a) { int idx = gtk_radio_action_get_current_value(GTK_RADIO_ACTION(a)); Player player = ((idx & 256) ? PL_White : PL_Black); idx &= 255; if (player==PL_White) { gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "blkPlayer-compA"), !(idx==2)); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "blkPlayer-compB"), !(idx==4)); } else { gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "whtPlayer-compA"), !(idx==2)); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "whtPlayer-compB"), !(idx==4)); } MainApp& app = MainApp::app(); /**/ if (idx==1) { app.setPlayer(player, player_ptr(new PlayerIF_Human)); } else if (idx==2) { app.setPlayer(player, app.getAIPlayer(0)); } else if (idx==4) { app.setPlayer(player, app.getAIPlayer(1)); } else { assert(0); } } void gtk_swap_players(gpointer spec) { GtkAction* whtAction = gtk_action_group_get_action(actiongroup, "whtPlayer-human"); GtkAction* blkAction = gtk_action_group_get_action(actiongroup, "blkPlayer-human"); int whtIdx = gtk_radio_action_get_current_value(GTK_RADIO_ACTION(whtAction)) & 0xFF; int blkIdx = gtk_radio_action_get_current_value(GTK_RADIO_ACTION(blkAction)) & 0xFF; gtk_radio_action_set_current_value(GTK_RADIO_ACTION(whtAction), blkIdx + 256); gtk_radio_action_set_current_value(GTK_RADIO_ACTION(blkAction), whtIdx); } void cb_gtk_setBoard(GtkAction* a) { int idx = gtk_radio_action_get_current_value(GTK_RADIO_ACTION(a)); if (idx==1000) { } else { rulespec_ptr rule; rule=RuleSpec::createPresetRule(RuleSpec::RulePreset(idx)); MainApp::app().setRules(rule,true); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "rule-custom"), false); } } void cb_config_customRules() { if (preferencesDialog_ruleSpec()) { GtkAction* action = gtk_action_group_get_action(actiongroup, "rule-custom"); gtk_action_set_sensitive( action, true ); gtk_radio_action_set_current_value(GTK_RADIO_ACTION(action), 1000); } } static void cb_menu_pause(bool pause) { gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "ContinueGame"), pause); } static void menu_changeState(const GameState& state) { gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "Hint"), state.state!=GameState::Ended); } static void menu_changeBoard() { gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "UndoMove"), MainApp::app().getControl().getHistoryPos()>0); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "RedoMove"), MainApp::app().getControl().getHistoryPos()isInteractivePlayer()==false); gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "ForceMove"), computerMove); } static void menu_endMove(player_ptr p) { gtk_action_set_sensitive( gtk_action_group_get_action(actiongroup, "ForceMove"), false); } void menu_closedMoveLog(bool active) { gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(gtk_action_group_get_action(actiongroup, "moveLog")), active); } void menu_setPauseOnAI(bool active) { gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(gtk_action_group_get_action(actiongroup, "pauseOnAI")), active); } void gtk_connectMenuSignals() { // connect signals GameControl& control = MainApp::app().getControl(); control.getSignal_changeState().connect(menu_changeState); control.getSignal_changeBoard().connect(menu_changeBoard); control.getSignal_startMove() .connect(menu_startMove); control.getSignal_endMove() .connect(menu_endMove); MainApp::app().getSignal_pauseChanged().connect(cb_menu_pause); } morris-0.3/src/gtk_menutoolbar.hh000066400000000000000000000021451373406602200172000ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef GTK_MENUTOOLBAR_HH #define GTK_MENUTOOLBAR_HH #include void gtk_initMainMenu(GtkWidget* appWindow, GtkWidget* window); void gtk_connectMenuSignals(); void menu_closedMoveLog(bool active); void menu_setPauseOnAI (bool active); #endif morris-0.3/src/gtk_movelog.cc000066400000000000000000000131431373406602200163070ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "gtk_movelog.hh" #include "util.hh" #include "rules.hh" #include "mainapp.hh" #include #include const int PADDING=10; static gboolean quit_callback(GtkWidget *widget, gpointer data) { return FALSE; } gboolean cbMoveLog_gtk_destroy(GtkWidget *widget, gpointer data) { ((MoveLog_Gtk*)(data))->cbDestroy(); return FALSE; } MoveLog_Gtk::MoveLog_Gtk() { window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), _("Move List")); gtk_container_set_border_width(GTK_CONTAINER(window), PADDING); gtk_window_set_default_size(GTK_WINDOW(window), 210,400); scrolledWindow = gtk_scrolled_window_new(NULL,NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); treeview = gtk_tree_view_new(); gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), GTK_SELECTION_NONE); { GtkCellRenderer* renderer; GtkTreeViewColumn* column; renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Move"), renderer, "text", 0, //"foreground", COLOR_COLUMN, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("White"), renderer, "text", 1, "background-gdk", 4, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Black"), renderer, "text", 2, "background-gdk", 6, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); } liststore = gtk_list_store_new(7, G_TYPE_INT, // move number G_TYPE_STRING, G_TYPE_STRING, // white move, black move GDK_TYPE_COLOR, GDK_TYPE_COLOR, // white fgr, bkg GDK_TYPE_COLOR, GDK_TYPE_COLOR // black fgr, bkg ); { refresh(); } gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(liststore)); // do not g_object_unref(liststore); -> keep lock on liststore g_object_ref(window); gtk_container_add(GTK_CONTAINER(scrolledWindow), treeview); gtk_container_add(GTK_CONTAINER(window), scrolledWindow); gtk_widget_show_all(window); g_signal_connect(window, "delete_event", G_CALLBACK(quit_callback), NULL); destroyHandler = g_signal_connect(window, "destroy", G_CALLBACK(cbMoveLog_gtk_destroy), this); GameControl& control = MainApp::app().getControl(); refreshConnection = control.getSignal_changeBoard().connect(boost::bind(&MoveLog_Gtk::refresh, this)); } MoveLog_Gtk::~MoveLog_Gtk() { refreshConnection.disconnect(); g_signal_handler_disconnect(window, destroyHandler); // avoid endless recursive destroying loop gtk_widget_destroy(window); g_object_unref(liststore); g_object_unref(window); } void MoveLog_Gtk::cbDestroy() { m_signal_windowClosed(); } /* TODO: the refresh is really inefficient, because the complete list is rebuilt, adding the content line by line. Since gtk seems to make a refresh for each line, this is very slow. */ void MoveLog_Gtk::refresh() { if (!liststore) { return; } gtk_list_store_clear(liststore); const GameControl& control = MainApp::app().getControl(); boardspec_ptr boardspec = control.getBoardSpec(); GdkColor activeColor, passiveColor; gdk_color_parse("#c0c0ff", &activeColor); gdk_color_parse("#ffffff", &passiveColor); const bool ended = (control.hasGameEnded()); std::string winner; if (ended) { if (control.getGameWinner()==PL_None) winner=_("tie"); else winner="+++"; } else winner="..."; for (int ply=0;ply Morris 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 3 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, see . ***************************************************************************/ #ifndef GTK_MOVELOG_HH #define GTK_MOVELOG_HH #include "movelog.hh" #include class MoveLog_Gtk : public MoveLog { public: MoveLog_Gtk(); ~MoveLog_Gtk(); void refresh(); private: GtkWidget* window; GtkWidget* scrolledWindow; GtkWidget* treeview; GtkListStore* liststore; gulong destroyHandler; boost::signals2::connection refreshConnection; void cbDestroy(); friend gboolean cbMoveLog_gtk_destroy(GtkWidget *widget, gpointer data); }; #endif morris-0.3/src/gtk_prefAI.cc000066400000000000000000000237411373406602200160120ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "util.hh" #include "algo_alphabeta.hh" #include "mainapp.hh" #include "gtk_appgui_interface.hh" #include static const int PADDING=8; static GtkWidget* new_label_left(const char* txt) { GtkWidget* label = gtk_label_new(txt); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); return label; } struct aiWidgets { GtkWidget *vbox, *frame; GtkWidget *spin_time, *spin_depth; GtkWidget *scale_material, *scale_freedom, *scale_mills, *scale_experience; }; static void enableDualEvalWeights(const aiWidgets* ai, bool enable) { gtk_widget_set_sensitive(GTK_WIDGET(ai->scale_material), enable); gtk_widget_set_sensitive(GTK_WIDGET(ai->scale_freedom), enable); gtk_widget_set_sensitive(GTK_WIDGET(ai->scale_mills), enable); gtk_widget_set_sensitive(GTK_WIDGET(ai->scale_experience), enable); } static void cb_aiPref_shareTT(GtkToggleButton *togglebutton, gpointer user_data) { const aiWidgets* aiWidg = (aiWidgets*)(user_data); bool share = gtk_toggle_button_get_active(togglebutton); //std::cout << (on ? "ON" : "OFF") << "\n"; enableDualEvalWeights(aiWidg, !share); } void preferencesDialog_AI() { ApplicationGUI_GtkIF* appgui = dynamic_cast(MainApp::app().getApplicationGUI().get()); GtkWidget* window = appgui->getMainWindow(); configmanager_ptr config = MainApp::app().getConfigManager(); GtkWidget* pref_dialog; GSettings* obj; struct aiWidgets ai[2]; pref_dialog = gtk_dialog_new_with_buttons(_("AI Preferences"), GTK_WINDOW(window), GtkDialogFlags(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); gtk_window_set_resizable(GTK_WINDOW(pref_dialog), FALSE); // same widgets for both computer AIs for (int c=0;c<2;c++) { static const char* frameName[2] = { N_("Computer A"), N_("Computer B") }; ai[c].frame = gtk_frame_new( gettext(frameName[c]) ); ai[c].vbox = gtk_vbox_new(FALSE,0); ai[c].spin_depth = gtk_spin_button_new_with_range(1.0, 50.0, 1.0); ai[c].spin_time = gtk_spin_button_new_with_range(0.0, 999.0, 1.0); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(ai[c].spin_time), 1); ai[c].scale_material = gtk_hscale_new_with_range(0.0, 1.0, 0.1); ai[c].scale_freedom = gtk_hscale_new_with_range(0.0, 1.0, 0.1); ai[c].scale_mills = gtk_hscale_new_with_range(0.0, 1.0, 0.1); ai[c].scale_experience = gtk_hscale_new_with_range(0.0, 1.0, 0.1); gtk_scale_set_value_pos(GTK_SCALE(ai[c].scale_material ), GTK_POS_RIGHT); gtk_scale_set_value_pos(GTK_SCALE(ai[c].scale_freedom ), GTK_POS_RIGHT); gtk_scale_set_value_pos(GTK_SCALE(ai[c].scale_mills ), GTK_POS_RIGHT); gtk_scale_set_value_pos(GTK_SCALE(ai[c].scale_experience), GTK_POS_RIGHT); gtk_widget_set_size_request(ai[c].scale_freedom, 75, -1); // set a minimum width GtkWidget* label; GtkWidget* hbox; GtkWidget* table; // --- table = gtk_table_new(3,3,FALSE); gtk_table_set_row_spacing(GTK_TABLE(table), 1, PADDING); label = new_label_left(NULL); gtk_label_set_markup(GTK_LABEL(label), _("thinking process")); gtk_box_pack_start(GTK_BOX(ai[c].vbox), label, FALSE, TRUE, PADDING/2); gtk_table_attach(GTK_TABLE(table), new_label_left(_("max. time" )), 1,2,0,1, GTK_FILL, GTK_FILL, 0,0); gtk_table_attach(GTK_TABLE(table), new_label_left(_("max. depth")), 1,2,1,2, GTK_FILL, GTK_FILL, 0,0); gtk_table_attach_defaults(GTK_TABLE(table), ai[c].spin_time, 2,3,0,1); gtk_table_attach_defaults(GTK_TABLE(table), ai[c].spin_depth, 2,3,1,2); gtk_table_set_col_spacings(GTK_TABLE(table), PADDING); //gtk_container_set_border_width(GTK_CONTAINER(table), PADDING); gtk_box_pack_start(GTK_BOX(ai[c].vbox), table, FALSE, TRUE, PADDING/2); // --- label = new_label_left(NULL); gtk_label_set_markup(GTK_LABEL(label), _("evaluation weights")); gtk_box_pack_start(GTK_BOX(ai[c].vbox), label, FALSE, TRUE, PADDING/2); table = gtk_table_new(3,4,FALSE); gtk_table_attach(GTK_TABLE(table), new_label_left(_("material")), 1,2,0,1, GTK_FILL, GTK_FILL, 0,0); gtk_table_attach(GTK_TABLE(table), new_label_left(_("freedom")), 1,2,1,2, GTK_FILL, GTK_FILL, 0,0); gtk_table_attach(GTK_TABLE(table), new_label_left(_("mills")), 1,2,2,3, GTK_FILL, GTK_FILL, 0,0); gtk_table_attach(GTK_TABLE(table), new_label_left(_("experience")),1,2,3,4, GTK_FILL, GTK_FILL, 0,0); gtk_table_attach_defaults(GTK_TABLE(table), ai[c].scale_material, 2,3,0,1); gtk_table_attach_defaults(GTK_TABLE(table), ai[c].scale_freedom, 2,3,1,2); gtk_table_attach_defaults(GTK_TABLE(table), ai[c].scale_mills, 2,3,2,3); gtk_table_attach_defaults(GTK_TABLE(table), ai[c].scale_experience, 2,3,3,4); gtk_table_set_col_spacings(GTK_TABLE(table), PADDING); //gtk_container_set_border_width(GTK_CONTAINER(table), PADDING); gtk_box_pack_start(GTK_BOX(ai[c].vbox), table, FALSE, TRUE, PADDING/2); //gtk_box_pack_start(GTK_BOX(ai[c].vbox), ai[c].scale_material, FALSE, TRUE, PADDING/2); gtk_container_add(GTK_CONTAINER(ai[c].frame), ai[c].vbox); gtk_container_set_border_width(GTK_CONTAINER(ai[c].vbox), PADDING/2); // set default values if (c == 0) obj = config->compA(); else obj = config->compB(); gtk_spin_button_set_value(GTK_SPIN_BUTTON(ai[c].spin_depth), config->read_int(obj,ConfigManager::itemComputer_maxDepth[c])); gtk_spin_button_set_value(GTK_SPIN_BUTTON(ai[c].spin_time), config->read_int(obj,ConfigManager::itemComputer_maxTime[c])/1000.0); if (c == 0) obj = config->weightsA(); else obj = config->weightsB(); gtk_range_set_value(GTK_RANGE(ai[c].scale_material), config->read_float(obj,ConfigManager::itemComputer_weightMaterial[c])); gtk_range_set_value(GTK_RANGE(ai[c].scale_freedom), config->read_float(obj,ConfigManager::itemComputer_weightFreedom[c])); gtk_range_set_value(GTK_RANGE(ai[c].scale_mills), config->read_float(obj,ConfigManager::itemComputer_weightMills[c])); gtk_range_set_value(GTK_RANGE(ai[c].scale_experience), config->read_float(obj,ConfigManager::itemComputer_weightExperience[c])); } GtkWidget* big_hbox = gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(big_hbox), ai[0].frame, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(big_hbox), ai[1].frame, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pref_dialog)->vbox), big_hbox, FALSE, TRUE, PADDING); GtkWidget* check_shareTT= gtk_check_button_new_with_label(_("share transposition table")); bool share_TT = config->read_bool(config->ai(), ConfigManager::itemComputers_shareTTables); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_shareTT), share_TT); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pref_dialog)->vbox), check_shareTT, FALSE, TRUE, PADDING); gtk_signal_connect(GTK_OBJECT(check_shareTT), "toggled", GTK_SIGNAL_FUNC(cb_aiPref_shareTT), &ai[1]); enableDualEvalWeights(&ai[1], !share_TT); gtk_widget_show_all(pref_dialog); // can run it gint button = gtk_dialog_run(GTK_DIALOG(pref_dialog)); switch (button) { case GTK_RESPONSE_ACCEPT: { share_TT=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_shareTT)); config->store(config->ai(), ConfigManager::itemComputers_shareTTables, share_TT); for (int c=0;c<2;c++) { MainApp::app().getTTable(c)->clear(); // TODO: in fact, we only have to clear the table, if we changed a crucial parameter if (c == 0) obj = config->compA(); else obj = config->compB(); config->store(obj,ConfigManager::itemComputer_maxTime[c], int( gtk_spin_button_get_value(GTK_SPIN_BUTTON(ai[c].spin_time)) * 1000.0 )); config->store(obj,ConfigManager::itemComputer_maxDepth[c], int(gtk_spin_button_get_value(GTK_SPIN_BUTTON(ai[c].spin_depth)))); // Read evaluation weights. If a shared transposition-table is used, both evaluation weights will be // taken from computer-A to ensure that they are the same. int c2 = c; if (share_TT) { c2=0; } if (c == 0) obj = config->weightsA(); else obj = config->weightsB(); config->store(obj,ConfigManager::itemComputer_weightMaterial[c], float(gtk_range_get_value(GTK_RANGE(ai[c2].scale_material)))); config->store(obj,ConfigManager::itemComputer_weightFreedom[c], float(gtk_range_get_value(GTK_RANGE(ai[c2].scale_freedom)))); config->store(obj,ConfigManager::itemComputer_weightMills[c], float(gtk_range_get_value(GTK_RANGE(ai[c2].scale_mills)))); config->store(obj,ConfigManager::itemComputer_weightExperience[c], float(gtk_range_get_value(GTK_RANGE(ai[c2].scale_experience)))); } } break; default: /* do no changes */ break; } gtk_widget_destroy (pref_dialog); } morris-0.3/src/gtk_prefDisplay.cc000066400000000000000000000160361373406602200171250ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "util.hh" #include "mainapp.hh" #include "gtk_appgui_interface.hh" #include "gtk_prefDisplay.hh" #include static const int PADDING=8; bool preferencesDialog_Display() { ApplicationGUI_GtkIF* appgui = dynamic_cast(MainApp::app().getApplicationGUI().get()); GtkWidget* window = appgui->getMainWindow(); configmanager_ptr config = MainApp::app().getConfigManager(); GtkWidget *pref_dialog, *vbox; pref_dialog = gtk_dialog_new_with_buttons(_("Display Preferences"), GTK_WINDOW(window), GtkDialogFlags(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); gtk_window_set_resizable(GTK_WINDOW(pref_dialog), FALSE); // board selection vbox = gtk_vbox_new(FALSE,0); GtkWidget* check_animComp = gtk_check_button_new_with_label(_("animate computer moves")); GtkWidget* check_animSet = gtk_check_button_new_with_label(_("animate setting of pieces")); GtkWidget* check_animTake = gtk_check_button_new_with_label(_("animate takes")); GtkWidget* check_colCross = gtk_check_button_new_with_label(_("colored crossings while dragging")); GtkWidget* check_gameOverReq = gtk_check_button_new_with_label(_("show game-over message box")); GtkWidget* check_showCoords = gtk_check_button_new_with_label(_("show coordinates")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_gameOverReq), config->read_bool(config->disp(), ConfigManager::itemDisplay_showGameOverMessageBox)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_animComp), config->read_bool(config->disp(), ConfigManager::itemDisplayGtk_animateComputerMoves)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_animSet), config->read_bool(config->disp(), ConfigManager::itemDisplayGtk_animateSettingOfPieces)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_animTake), config->read_bool(config->disp(), ConfigManager::itemDisplayGtk_animateTakes)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_showCoords), config->read_bool(config->disp(), ConfigManager::itemDisplayGtk_showCoordinates)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_colCross), config->read_bool(config->disp(), ConfigManager::itemDisplayGtk_coloredCrossingsWhileDragging)); gtk_box_pack_start(GTK_BOX(vbox), check_gameOverReq, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(vbox), check_showCoords, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(vbox), check_colCross, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(vbox), check_animComp, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(vbox), check_animSet, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(vbox), check_animTake, FALSE, TRUE, PADDING/2); GtkWidget* hbox = gtk_hbox_new(FALSE,0); GtkWidget* label = gtk_label_new(_("animation speed")); float animSpeed = config->read_float(config->disp(), ConfigManager::itemDisplayGtk_animationSpeed); animSpeed = 100-animSpeed/20; GtkObject* adj_animSpeed = gtk_adjustment_new(animSpeed, 0.0, // lower 100.0, // upper 1.0, // step_increment 10.0, // page_increment 0.0); // page_size GtkWidget* scale_animSpeed = gtk_hscale_new( GTK_ADJUSTMENT(adj_animSpeed) ); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(hbox), scale_animSpeed, TRUE, TRUE, PADDING); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, PADDING/2); hbox = gtk_hbox_new(FALSE,0); label = gtk_label_new(_("take piece delay")); float takeDelay = config->read_float(config->disp(), ConfigManager::itemDisplayGtk_takePieceDelay); takeDelay = takeDelay/10; GtkObject* adj_takeDelay = gtk_adjustment_new(takeDelay, // initial value 0.0, // lower 100.0, // upper 1.0, // step_increment 10.0, // page_increment 0.0); // page_size GtkWidget* scale_takeDelay = gtk_hscale_new(GTK_ADJUSTMENT(adj_takeDelay)); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(hbox), scale_takeDelay, TRUE, TRUE, PADDING); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pref_dialog)->vbox), vbox, FALSE, TRUE, PADDING); gtk_scale_set_value_pos(GTK_SCALE(scale_animSpeed), GTK_POS_RIGHT); gtk_scale_set_value_pos(GTK_SCALE(scale_takeDelay), GTK_POS_RIGHT); gtk_widget_show_all(pref_dialog); // can run it gint button = gtk_dialog_run(GTK_DIALOG(pref_dialog)); bool newValues = false; switch (button) { case GTK_RESPONSE_ACCEPT: { config->store(config->disp(), ConfigManager::itemDisplay_showGameOverMessageBox, bool(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_gameOverReq)))); config->store(config->disp(), ConfigManager::itemDisplayGtk_coloredCrossingsWhileDragging, bool(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_colCross)))); config->store(config->disp(), ConfigManager::itemDisplayGtk_animateComputerMoves, bool(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_animComp)))); config->store(config->disp(), ConfigManager::itemDisplayGtk_animateSettingOfPieces, bool(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_animSet)))); config->store(config->disp(), ConfigManager::itemDisplayGtk_animateTakes, bool(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_animTake)))); config->store(config->disp(), ConfigManager::itemDisplayGtk_showCoordinates, bool(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_showCoords)))); config->store(config->disp(), ConfigManager::itemDisplayGtk_animationSpeed, float( 20*(100-gtk_range_get_value(GTK_RANGE(scale_animSpeed))) )); config->store(config->disp(), ConfigManager::itemDisplayGtk_takePieceDelay, float( 10* gtk_range_get_value(GTK_RANGE(scale_takeDelay)) )); newValues = true; } break; default: /* do no changes */ break; } gtk_widget_destroy (pref_dialog); return newValues; } morris-0.3/src/gtk_prefDisplay.hh000066400000000000000000000017051373406602200171340ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef GTK_PREFDISPLAY_HH #define GTK_PREFDISPLAY_HH bool preferencesDialog_Display(); #endif morris-0.3/src/gtk_prefRules.cc000066400000000000000000000217721373406602200166150ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "util.hh" #include "mainapp.hh" #include "gtk_appgui_interface.hh" #include static const int PADDING=8; bool confirmationRequester(GtkWindow* parent, const char* primaryText, const char* secondaryText) { GtkWidget* dialog = gtk_message_dialog_new(GTK_WINDOW(parent), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "%s", primaryText); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", secondaryText); gint button = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy (dialog); switch (button) { case GTK_RESPONSE_YES: return true; case GTK_RESPONSE_NO: return false; default: assert(0); } } bool preferencesDialog_ruleSpec() { ApplicationGUI_GtkIF* appgui = dynamic_cast(MainApp::app().getApplicationGUI().get()); GtkWidget* window = appgui->getMainWindow(); struct BoardOption { const char* name; BoardSpec::BoardPreset boardSpec; GtkWidget* radioButton; } boardSpec_radio[] = { { N_("Nine Men's Morris"), BoardSpec::Board_Standard9MM }, { N_("Moebius board"), BoardSpec::Board_Moebius }, { N_("Morabaraba"), BoardSpec::Board_Morabaraba }, { N_("Windmill"), BoardSpec::Board_Windmill }, { N_("Sunmill"), BoardSpec::Board_Sunmill }, { N_("Triangle"), BoardSpec::Board_Polygon3 }, { N_("Pentagon"), BoardSpec::Board_Polygon5 }, { N_("Hexagon"), BoardSpec::Board_Polygon6 }, { N_("Seven Men's Morris"),BoardSpec::Board_7MM }, { N_("Six Men's Morris"), BoardSpec::Board_6MM }, { N_("Small square"), BoardSpec::Board_SmallSq }, { N_("Small square with diagonals"), BoardSpec::Board_SmallSqWithDiag }, { N_("Small triangle"), BoardSpec::Board_SmallTri }, { NULL } }; GtkWidget *pref_dialog, *vbox1, *vbox2; GtkWidget *frame1, *frame2; rulespec_ptr oldRuleSpec = MainApp::app().getControl().getRuleSpec(); pref_dialog = gtk_dialog_new_with_buttons(_("Rule Preferences"), GTK_WINDOW(window), GtkDialogFlags(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); gtk_window_set_resizable(GTK_WINDOW(pref_dialog), FALSE); // board selection frame1 = gtk_frame_new(_("Board Type")); vbox1 = gtk_vbox_new(FALSE,0); GtkWidget* radioButton=NULL; for (int i=0; boardSpec_radio[i].name != NULL; i++) { radioButton = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioButton), gettext(boardSpec_radio[i].name)); gtk_box_pack_start(GTK_BOX(vbox1), radioButton, FALSE, TRUE, PADDING*0/2); if (oldRuleSpec->boardSpec->getBoardPresetID() == boardSpec_radio[i].boardSpec) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radioButton), TRUE); } boardSpec_radio[i].radioButton = radioButton; } // // setup the rule variations // frame2 = gtk_frame_new(_("Rule Variations")); vbox2 = gtk_vbox_new(FALSE,0); GtkWidget* check_lasker = gtk_check_button_new_with_label(_("Lasker variant")); GtkWidget* check_mayjump = gtk_check_button_new_with_label(_("May jump with three pieces")); GtkWidget* check_takemills= gtk_check_button_new_with_label(_("May take from mills always")); GtkWidget* check_takemulti= gtk_check_button_new_with_label(_("May take multiple pieces")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_lasker), oldRuleSpec->laskerVariant); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_mayjump), oldRuleSpec->mayJump); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_takemills),oldRuleSpec->mayTakeFromMillsAlways); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_takemulti),oldRuleSpec->mayTakeMultiple); GtkWidget* hbox_pieces = gtk_hbox_new(FALSE,0); GtkWidget* label_pieces = gtk_label_new(_("Number of pieces")); GtkObject* adj_pieces = gtk_adjustment_new(oldRuleSpec->nPieces, // initial value 3.0, // lower 20.0, // upper 1.0, // step_increment 1.0, // page_increment 0.0); // page_size GtkWidget* spin_pieces = gtk_spin_button_new(GTK_ADJUSTMENT(adj_pieces),0.0,0); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON(spin_pieces),TRUE); gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(spin_pieces),TRUE); gtk_box_pack_start(GTK_BOX(hbox_pieces), label_pieces,FALSE, TRUE, PADDING*0); gtk_box_pack_start(GTK_BOX(hbox_pieces), spin_pieces, FALSE, TRUE, PADDING); GtkWidget* hbox_tie = gtk_hbox_new(FALSE,0); GtkWidget* label_tie = gtk_label_new(_("Declare tie after how many repeats")); GtkObject* adj_tie = gtk_adjustment_new(oldRuleSpec->tieAfterNRepeats, // initial value 0.0, // lower 5.0, // upper 1.0, // step_increment 1.0, // page_increment 0.0); // page_size GtkWidget* spin_tie = gtk_spin_button_new(GTK_ADJUSTMENT(adj_tie),0.0,0); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON(spin_tie),TRUE); gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(spin_tie),TRUE); gtk_box_pack_start(GTK_BOX(hbox_tie), label_tie,FALSE, TRUE, PADDING*0); gtk_box_pack_start(GTK_BOX(hbox_tie), spin_tie, FALSE, TRUE, PADDING); gtk_box_pack_start(GTK_BOX(vbox2), hbox_pieces, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(vbox2), check_lasker, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(vbox2), check_mayjump, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(vbox2), check_takemills, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(vbox2), check_takemulti, FALSE, TRUE, PADDING/2); gtk_box_pack_start(GTK_BOX(vbox2), hbox_tie, FALSE, TRUE, PADDING/2); gtk_container_add(GTK_CONTAINER(frame1),vbox1); gtk_container_add(GTK_CONTAINER(frame2),vbox2); GtkWidget* hbox = gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(hbox), frame1, FALSE, TRUE, PADDING); gtk_box_pack_start(GTK_BOX(hbox), frame2, FALSE, TRUE, PADDING); gtk_container_set_border_width(GTK_CONTAINER(vbox1), PADDING/2); gtk_container_set_border_width(GTK_CONTAINER(vbox2), PADDING/2); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(pref_dialog)->vbox), hbox, FALSE, TRUE, PADDING); gtk_widget_show_all(pref_dialog); // can run it bool replaceRules=false; bool runDialog=true; while (runDialog) { gint button = gtk_dialog_run(GTK_DIALOG(pref_dialog)); switch (button) { case GTK_RESPONSE_ACCEPT: { rulespec_ptr newRuleSpec = rulespec_ptr(new RuleSpec); *newRuleSpec = *oldRuleSpec; newRuleSpec->laskerVariant = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_lasker)); newRuleSpec->mayJump = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_mayjump)); newRuleSpec->mayTakeMultiple = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_takemulti)); newRuleSpec->mayTakeFromMillsAlways = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check_takemills)); newRuleSpec->tieAfterNRepeats = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_tie)); newRuleSpec->nPieces = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_pieces)); for (int i=0; boardSpec_radio[i].name != NULL; i++) { GtkWidget* button = boardSpec_radio[i].radioButton; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) { newRuleSpec->boardSpec = BoardSpec::boardFactory( boardSpec_radio[i].boardSpec ); } } bool significantChange=false; if (oldRuleSpec->nPieces != newRuleSpec->nPieces) significantChange=true; if (oldRuleSpec->boardSpec->getBoardPresetID() != newRuleSpec->boardSpec->getBoardPresetID()) { significantChange=true; } bool sure = true; if (significantChange) { sure = confirmationRequester(GTK_WINDOW(pref_dialog), _("Your changes require to end the currently running game."), _("Do you want to restart with the changed rules?")); } if (sure) { MainApp::app().setRules(newRuleSpec, significantChange); replaceRules = true; runDialog=false; } } break; default: /* do no changes */ runDialog=false; break; } } gtk_widget_destroy (pref_dialog); return replaceRules; } morris-0.3/src/gtk_threadtunnel.cc000066400000000000000000000055231373406602200173370ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "mainapp.hh" #include "gtk_threadtunnel.hh" #include #include #include static gboolean cb_setProgress(gpointer p) { float* progress = (float*)p; MainApp::app().getApplicationGUI()->setProgress(*progress); delete progress; return FALSE; } static gboolean cb_setStatusbar(gpointer p) { std::string* str = (std::string*)p; MainApp::app().getApplicationGUI()->setStatusbar(*str); delete str; return FALSE; } struct MoveData { Move move; int gameID; }; static gboolean cb_doMove(gpointer p) { MoveData* m = (MoveData*)p; gdk_threads_enter(); // see gtk_boardgui.cc for why this is needed MainApp::app().visualizeMove(m->move, m->gameID); gdk_threads_leave(); delete m; return FALSE; } // --------------------------------------------------------------------------- class ThreadTunnel_Gtk : public ThreadTunnel { public: void setStatusbar(const char* buf) { g_idle_add( cb_setStatusbar, new std::string(buf) ); } void setProgress(float progress) { float* p = new float; *p = progress; g_idle_add( cb_setProgress, p ); } void doMove(Move m, int gameID) { MoveData* md = new MoveData; md->move = m; md->gameID = gameID; g_idle_add( cb_doMove, md ); } void showThinkingInfo(const std::string& str) { class IdleFunc_showThinking : public IdleFunc { public: IdleFunc_showThinking(const std::string& s) : m_string(s) { } void operator()() { MainApp::app().setThinkingInfo(m_string); } std::string m_string; }; IdleFunc::install(new IdleFunc_showThinking(str)); } }; static ThreadTunnel_Gtk guicb_gtk; ThreadTunnel& getThreadTunnel_Gtk() { return guicb_gtk; } // --------------------------------------------------------------------------- static gboolean cb_idlefunc(gpointer p) { IdleFunc* func = (IdleFunc*)p; (*func)(); delete func; return FALSE; } void IdleFunc::install(IdleFunc* func) { g_idle_add( cb_idlefunc, func ); } morris-0.3/src/gtk_threadtunnel.hh000066400000000000000000000017461373406602200173540ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef GTK_THREADTUNNEL_HH #define GTK_THREADTUNNEL_HH #include "threadtunnel.hh" ThreadTunnel& getThreadTunnel_Gtk(); #endif morris-0.3/src/gtkcairo_boardgui.cc000066400000000000000000000732701373406602200174600ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "config.h" #include "control.hh" #include "gtkcairo_boardgui.hh" #include "mainapp.hh" #include #include #include #include extern gint animation_timer(gpointer obj); void BoardGUI_GtkCairo::expose_area_rect(int x0,int y0,int w,int h) { if (offscreenBuffer==NULL) { return; } if (boardGfxInvalid) { draw_board(x0,y0,w,h); boardGfxInvalid=false; } gdk_draw_drawable( drawingArea->window, drawingArea->style->fg_gc[GTK_WIDGET_STATE(drawingArea)], offscreenBuffer, x0,y0, x0,y0, w,h ); } void BoardGUI_GtkCairo::redrawBoard() { boardGfxInvalid=true; gdk_window_invalidate_rect(drawingArea->window, NULL, false); } // this func is used when an area of the window is uncovered void BoardGUI_GtkCairo::cb_expose_area(GtkWidget *widget, GdkEventExpose *event) { expose_area_rect(event->area.x, event->area.y, event->area.width, event->area.height); } // this func is used when an area of the window is reconfigured void BoardGUI_GtkCairo::cb_configure_area(GtkWidget *widget, GdkEventConfigure *event) { cb_realize_area(widget); } void BoardGUI_GtkCairo::cb_realize_area(GtkWidget *widget) { if (offscreenBuffer) { gdk_pixmap_unref(offscreenBuffer); } offscreenBuffer = gdk_pixmap_new(drawingArea->window, drawingArea->allocation.width, drawingArea->allocation.height, -1); resetDisplay(); draw_board(0,0, drawingArea->allocation.width, drawingArea->allocation.height); } void BoardGUI_GtkCairo::resetDisplay() { geom.fitInto(drawingArea->allocation.width, drawingArea->allocation.height, options); changeGfxState(getGfxState()); redrawBoard(); } void BoardGUI_GtkCairo::invalidatePiecePos(Point2D pos_inUnits, float extraRadius) { GdkRectangle rect; Point2D pos = geom.board2Pixel(pos_inUnits); float radius= geom.getPieceRadiusInPixels() + extraRadius*geom.scale_units2pixels; rect.x = pos.x-radius -2; rect.y = pos.y-radius -2; rect.width = 2*radius+5; rect.height = 2*radius+5; /* std::cout << "invalidate " << rect.x << ";" << rect.y << ";" << rect.width << ";" << rect.height << "\n"; */ gdk_window_invalidate_rect(drawingArea->window, &rect, false); boardGfxInvalid=true; } void BoardGUI_GtkCairo::invalidateHoverAtPos(Position p) { GameControl& control = MainApp::app().getControl(); boardspec_ptr board = control.getBoardSpec(); Point2D pt = board->getPositionLocation(p); invalidatePiecePos(pt, 1.0/7/2); } void BoardGUI_GtkCairo::showHint(const Move& hint) { m_hint = hint; m_showHint = true; redrawBoard(); } void BoardGUI_GtkCairo::removeHint() { m_showHint = false; redrawBoard(); } // ===== drawing the board ==== int Animation::elapsedTimeMS() const { struct timeval tv; gettimeofday(&tv,NULL); int diffMS = (tv.tv_sec-startTime.tv_sec)*1000 + (tv.tv_usec-startTime.tv_usec)/1000; return diffMS; } bool Animation_RemovePiece::action(BoardGUI_GtkCairo& gui) { if (elapsedTimeMS() >= durationMS) { gui.hidePos.push_back(pos); gui.boardGfxInvalid=true; gdk_window_invalidate_rect(gui.drawingArea->window, NULL, false); return true; } else return false; } bool Animation_RemoveStack::action(BoardGUI_GtkCairo& gui) { const int piecesOnStack = MainApp::app().getControl().getCurrentBoard().getNPiecesToSet(player); Point2D piecePos = gui.geom.getStackPiecePos(player, piecesOnStack-1); gui.invalidatePiecePos( piecePos ); gui.removeStackPiece = player; return true; } bool Animation_MoveOverlay::action(BoardGUI_GtkCairo& gui) { if (overlayIdx<0) { overlayIdx = gui.overlay.size(); BoardGUI_GtkCairo::OverlayPiece o; o.player = player; gui.overlay.push_back(o); } else { gui.invalidatePiecePos(gui.overlay[overlayIdx].coordinate); } int elapsed = elapsedTimeMS(); if (elapsed>=durationMS) { gui.overlay[overlayIdx].coordinate = endPos; gui.invalidatePiecePos(endPos); gui.boardGfxInvalid=true; return true; } else { const float f = float(elapsed)/durationMS; Point2D c; c.x = (1.0-f)*startPos.x + f*endPos.x; c.y = (1.0-f)*startPos.y + f*endPos.y; gui.overlay[overlayIdx].coordinate = c; gui.invalidatePiecePos(c); gui.boardGfxInvalid=true; return false; } } bool Animation_DoMove::action(BoardGUI_GtkCairo& gui) { /* We are in a g_idle callback, which does not lock. This will cause problems in recursive main-loops when, e.g., gtk_dialog_run() is called from within doMove(). gtk_dialog_run() will first call unlock() on a mutex, which is not locked, and at the end again call lock(). This will cause the main-loop to lock, because it assumes that the thread will come back in the unlocked state in which it left the main-loop. */ gdk_threads_enter(); gui.overlay.clear(); gui.hidePos.clear(); gui.removeStackPiece = PL_None; GameControl& control = MainApp::app().getControl(); if (gameID == control.getCurrentMoveID() && control.getGameState().state == GameState::Moving) { MainApp::app().doMove(move); } else { // If the move turned out to come too late (did not match the moveID), // the gfx-state at the end of the animation does not match the board state. // Hence, we have to redraw the board. gui.redrawBoard(); } gdk_threads_leave(); return true; } gint BoardGUI_GtkCairo::cb_animation_timer() { while (!animation.empty()) { bool stop = animation[0]->action(*this); if (stop) { for (int i=1;ipos = m.oldPos; anim0->durationMS = 0; animation.push_back( animation_ptr(anim0) ); Animation_MoveOverlay* anim = new Animation_MoveOverlay; anim->player = control.getCurrentBoard().getPosition(m.oldPos); anim->startPos = board->getPositionLocation(m.oldPos); anim->endPos = board->getPositionLocation(m.newPos); float dist = hypot(anim->startPos.x-anim->endPos.x, anim->startPos.y-anim->endPos.y); anim->durationMS = dist*move_unitTime; animation.push_back( animation_ptr(anim) ); } else if (m.mode == Move::Mode_Set) { if (set_moveIn) { Animation_RemoveStack* anim0 = new Animation_RemoveStack; anim0->player = control.getCurrentPlayer(); anim0->durationMS = 0; animation.push_back( animation_ptr(anim0) ); } Animation_MoveOverlay* anim = new Animation_MoveOverlay; anim->player = control.getCurrentPlayer(); anim->startPos = geom.getStackPiecePos(anim->player, control.getCurrentBoard().getNPiecesToSet(anim->player)-1); anim->endPos = board->getPositionLocation(m.newPos); float dist = hypot(anim->startPos.x-anim->endPos.x, anim->startPos.y-anim->endPos.y); if (set_moveIn) anim->durationMS = dist*move_unitTime; else anim->durationMS = 0; animation.push_back( animation_ptr(anim) ); } for (int i=0;ipos = m.takes[i]; anim0->durationMS = take_delay; animation.push_back( animation_ptr(anim0) ); if (take_moveOut) { Animation_MoveOverlay* anim = new Animation_MoveOverlay; anim->player = control.getCurrentBoard().getPosition(m.takes[i]); anim->startPos = board->getPositionLocation(m.takes[i]); anim->endPos.x = ((anim->player==PL_White) ? geom.windowWidth_inUnits + geom.piece_radius_inUnits : -geom.piece_radius_inUnits); anim->endPos.y = geom.windowHeight_inUnits/2; anim->endPos.x -= geom.xoffset_board_inUnits; anim->endPos.y -= geom.yoffset_board_inUnits; float dist = hypot(anim->startPos.x-anim->endPos.x, anim->startPos.y-anim->endPos.y); anim->durationMS = dist*move_unitTime; animation.push_back( animation_ptr(anim) ); } } } { Animation_DoMove* anim = new Animation_DoMove; anim->move = m; anim->gameID = gameID; anim->durationMS = 0; animation.push_back( animation_ptr(anim) ); } // set start times struct timeval startTime; gettimeofday(&startTime,NULL); for (int i=0;istartTime = startTime; startTime.tv_usec += animation[i]->durationMS*1000; while (startTime.tv_usec > 1000000) { startTime.tv_usec -= 1000000; startTime.tv_sec++; } } // start animation g_timeout_add(20 /* ms */, animation_timer, this); } void BoardGUI_GtkCairo::checkHover() { // emit a dummy mouse-motion event gint mx,my; gdk_window_get_pointer(drawingArea->window,&mx,&my,NULL); Position pos = geom.pixel2Pos(mx,my); cb_mouseMotion( pos, Point2D(mx,my) ); } void BoardGUI_GtkCairo::draw_piece(cairo_t* cr, Point2D pos_inUnits, Player player, bool transparent) { draw_piece_inPixels(cr, geom.board2Pixel(pos_inUnits), player, transparent); } void BoardGUI_GtkCairo::draw_piece_inPixels(cairo_t* cr, Point2D pos_inPixels, Player player, bool transparent) { float col_main = 0.0; float col_med = 0.5; float col_high = 1.0; float radius = geom.getPieceRadiusInPixels(); if (player==PL_White) { std::swap(col_main,col_high); } cairo_save(cr); cairo_translate(cr, pos_inPixels.x, pos_inPixels.y); const float alpha = (transparent ? 0.5 : 1.0); cairo_set_source_rgba(cr, col_main,col_main,col_main, alpha); cairo_arc (cr, 0,0, radius, 0., 2 * M_PI); cairo_fill(cr); cairo_set_line_width (cr, 0.75); cairo_set_source_rgba(cr, col_high,col_high,col_high, alpha); cairo_arc (cr, 0,0, radius, 0., 2 * M_PI); cairo_stroke (cr); cairo_set_source_rgba(cr, col_med,col_med,col_med, alpha); cairo_arc (cr, 0,0, 0.8*radius, 0., 2 * M_PI); cairo_stroke (cr); cairo_arc (cr, 0,0, 0.37*radius, 0., 2 * M_PI); cairo_stroke (cr); cairo_restore(cr); } Point2D BoardGUI_GtkCairo::Geometry::getStackPiecePos(Player p, int n) const { int maxPieces = MainApp::app().getControl().getRuleSpec()->nPieces; Point2D pt; float ySpacing = 0.8/(maxPieces-1); if (ySpacing>1.5*piece_radius_inUnits) { ySpacing = 1.5*piece_radius_inUnits; pt.y = 0.5 -((maxPieces-1)/2.0-n)*ySpacing; } else { pt.y = ySpacing*n; pt.y += 0.1; } if (p==PL_White) pt.x = stackX_white_inUnits; else pt.x = stackX_black_inUnits; return pt; } BoardGUI_GtkCairo::Options::Options() { coloredCrossingWhileDragging = true; animateComputerMoves = true; animationSpeed = 1000; // 1sec set_moveIn = true; take_moveOut = true; take_delay = 250; showCoordinates = true; } void BoardGUI_GtkCairo::drawRect(cairo_t* cr, Point2D tl, Point2D br, bool fill) { tl = geom.board2Pixel(tl); br = geom.board2Pixel(br); cairo_move_to (cr, tl.x, tl.y); cairo_line_to (cr, tl.x, br.y); cairo_line_to (cr, br.x, br.y); cairo_line_to (cr, br.x, tl.y); cairo_line_to (cr, tl.x, tl.y); if (fill) cairo_fill(cr); else cairo_stroke (cr); } void BoardGUI_GtkCairo::drawCoordinates(cairo_t* cr) { GameControl& control = MainApp::app().getControl(); boardspec_ptr board = control.getBoardSpec(); BoardSpec_Grid* boardGrid = dynamic_cast(board.get()); { const float bkggrey=0.7; cairo_set_line_width (cr, 1); Point2D tl; tl.x = -geom.boardBorderLeft_inUnits; tl.y = -geom.boardBorderTop_inUnits; Point2D br; br.x = 1+ geom.boardBorderRight_inUnits; br.y = 1+ geom.boardBorderBottom_inUnits; cairo_set_source_rgb (cr, 0.9, 0.9, 0.9); drawRect(cr,tl,br,true); tl.x = 0; tl.y = 0; br.x = tl.x+1; br.y = tl.y+1; cairo_set_source_rgb (cr, bkggrey+0.05, bkggrey+0.05, bkggrey+0.05); drawRect(cr,tl,br,true); } if (boardGrid) { cairo_text_extents_t extents; cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, geom.scale_units2pixels*geom.textSize_inUnits); cairo_set_source_rgb (cr, 0, 0, 0); double maxUp=0; double maxDown=0; std::vector coords = boardGrid->xCoords(); for (int i=0; iyCoords(); for (int b=0; b<2; b++) for (int i=0; inPositions(); i++) { const NeighborVector& neighbors = board->getNeighbors(i); for (int n=0;ni) { continue; } Point2D p1 = board->getPositionLocation(i); Point2D p2 = board->getPositionLocation(p); p1 = geom.board2Pixel(p1); p2 = geom.board2Pixel(p2); cairo_set_source_rgb (cr, 0, 0, 0); cairo_set_line_width (cr, geom.scale_units2pixels*1/64); cairo_move_to (cr, p1.x, p1.y); cairo_line_to (cr, p2.x, p2.y); cairo_stroke (cr); } } // draw crossings for (int i=0;inPositions(); i++) { Point2D p = board->getPositionLocation(i); p = geom.board2Pixel(p); cairo_set_source_rgb (cr, 0, 0, 0); cairo_arc (cr, p.x,p.y, geom.scale_units2pixels*1/64, 0., 2 * M_PI); cairo_fill(cr); if (getGfxState()==GS_DraggingPiece && options.coloredCrossingWhileDragging) { // colored crossings Move m = getPlayerMove(); m.newPos = i; if (control.getRuleSpec()->isValidMove( control.getCurrentBoard(), m)) { cairo_set_source_rgb (cr, 0, 1, 0); } else { cairo_set_source_rgb (cr, 1, 0, 0); } } else { cairo_set_source_rgb (cr, 1, 1, 1); } cairo_arc (cr, p.x,p.y, geom.scale_units2pixels*5/(7*64), 0., 2 * M_PI); cairo_fill(cr); } // draw pieces stacks int maxPieces = control.getRuleSpec()->nPieces; int nPieces; const Board& b = control.getCurrentBoard(); nPieces = b.getNPiecesToSet(PL_White); if (removeStackPiece==PL_White) nPieces--; for (int i=0;inPositions();p++) if ((pl = control.getCurrentBoard().getPosition(p)) != PL_None) { bool hide=false; for (int i=0;!hide && igetPositionLocation(p); draw_piece(cr, pt, pl); } // draw overlays for (int i=0;igetPositionLocation(hoverState.hoverPos); pt=geom.board2Pixel(pt); cairo_save(cr); cairo_translate(cr, pt.x,pt.y); cairo_set_source_rgb(cr, 0.0, 0.75, 0.0); cairo_set_line_width (cr, 3); cairo_arc (cr, 0,0, pieceSize, 0., 2 * M_PI); cairo_stroke(cr); cairo_restore(cr); } break; // hover move case Hover_MoveStart: { Point2D pt = board->getPositionLocation(hoverState.hoverPos); pt=geom.board2Pixel(pt); cairo_save(cr); cairo_translate(cr, pt.x,pt.y); cairo_set_source_rgb (cr, 0.0, 0.8, 0.0); cairo_set_line_width (cr, 5.0); cairo_arc (cr, 0,0, pieceSize, 0., 2 * M_PI); cairo_stroke(cr); cairo_restore(cr); } break; // hover dest case Hover_MoveEnd: { Point2D pt = board->getPositionLocation(hoverState.hoverPos); pt=geom.board2Pixel(pt); cairo_save(cr); cairo_translate(cr, pt.x,pt.y); if (hoverState.hoverPosValid) cairo_set_source_rgb (cr, 0.0, 0.8, 0.0); else cairo_set_source_rgb (cr, 0.8, 0.0, 0.0); cairo_set_line_width (cr, 5.0); cairo_arc (cr, 0,0, pieceSize, 0., 2 * M_PI); cairo_stroke(cr); cairo_restore(cr); } break; // hover take case Hover_Take: { Point2D pt = board->getPositionLocation(hoverState.hoverPos); pt=geom.board2Pixel(pt); cairo_save(cr); cairo_translate(cr, pt.x,pt.y); if (hoverState.hoverPosValid) cairo_set_source_rgb (cr, 0.0, 0.8, 0.0); else cairo_set_source_rgb (cr, 0.8, 0.0, 0.0); cairo_set_line_width (cr, 5.0); const float crossSize = pieceSize*0.8; cairo_move_to (cr, -crossSize, -crossSize); cairo_line_to (cr, crossSize, crossSize); cairo_move_to (cr, crossSize, -crossSize); cairo_line_to (cr, -crossSize, crossSize); cairo_stroke(cr); cairo_restore(cr); } break; } // show hint if (m_showHint) { Player pl = control.getCurrentPlayer(); //if (m_hint.mode == Move::Mode_Set) { Point2D pt = board->getPositionLocation(m_hint.newPos); draw_piece(cr, pt, pl, true); } if (m_hint.mode == Move::Mode_Move) { Point2D p1 = board->getPositionLocation(m_hint.oldPos); Point2D p2 = board->getPositionLocation(m_hint.newPos); p1=geom.board2Pixel(p1); p2=geom.board2Pixel(p2); const float width = pieceSize*0.1; const float arrowW = 3*width; const float arrowL = 6*width; const float len = hypot(p1.x-p2.x, p1.y-p2.y); const float angle = atan2(p2.y-p1.y, p2.x-p1.x); cairo_save(cr); cairo_set_line_width (cr, 1.0); cairo_translate(cr, p1.x,p1.y); cairo_rotate(cr, angle); cairo_set_source_rgba(cr, 0.8, 0.6, 0.2, 1.0); cairo_move_to (cr, 0, -width); cairo_line_to (cr, len-arrowL,-width); cairo_line_to (cr, len-arrowL,-arrowW); cairo_line_to (cr, len, 0); cairo_line_to (cr, len-arrowL, arrowW); cairo_line_to (cr, len-arrowL, width); cairo_line_to (cr, 0, width); cairo_fill(cr); cairo_restore(cr); } for (int i=0;igetPositionLocation(m_hint.takes[i]); pt=geom.board2Pixel(pt); cairo_save(cr); cairo_translate(cr, pt.x,pt.y); cairo_set_source_rgba(cr, 0.0, 0.8, 0.0, 0.75); cairo_set_line_width (cr, 5.0); const float crossSize = pieceSize*0.8; cairo_move_to (cr, -crossSize, -crossSize); cairo_line_to (cr, crossSize, crossSize); cairo_move_to (cr, crossSize, -crossSize); cairo_line_to (cr, -crossSize, crossSize); cairo_stroke(cr); cairo_restore(cr); } } // draw dragged piece if (drag_active) { draw_piece_inPixels(cr, Point2D(drag_position.x + drag_offset_x, drag_position.y + drag_offset_y), drag_player); } cairo_destroy(cr); } void BoardGUI_GtkCairo::startPieceDrag(Position p, Point2D pixelPos) { GameControl& control = MainApp::app().getControl(); const Board& board = control.getCurrentBoard(); OverlayPiece o; o.player = board.getCurrentPlayer(); o.coordinate = control.getBoardSpec()->getPositionLocation(p); Point2D piecePos_inPixels = geom.board2Pixel(o.coordinate); drag_active = true; drag_player = board.getCurrentPlayer(); drag_offset_x = (piecePos_inPixels.x - pixelPos.x); drag_offset_y = (piecePos_inPixels.y - pixelPos.y); drag_position = pixelPos; hidePos.push_back(p); if (options.coloredCrossingWhileDragging) redrawBoard(); } void BoardGUI_GtkCairo::stopPieceDrag() { drag_active = false; hidePos.clear(); } void BoardGUI_GtkCairo::doPieceDrag(Point2D pixelPos, bool valid) { Point2D oldpos = drag_position; oldpos.x += drag_offset_x; oldpos.y += drag_offset_y; invalidatePiecePos(geom.pixel2Board(oldpos)); drag_position = pixelPos; boardGfxInvalid=true; Point2D newpos = pixelPos; newpos.x += drag_offset_x; newpos.y += drag_offset_y; invalidatePiecePos(geom.pixel2Board(newpos)); } BoardGUI_GtkCairo::Geometry::Geometry() { textSize_inUnits = 0.25/7; } void BoardGUI_GtkCairo::Geometry::fitInto(int w,int h, const BoardGUI_GtkCairo::Options& options) { piece_radius_inUnits = MainApp::app().getControl().getBoardSpec()->getPieceRadius(); float coordBorder = 0; if (options.showCoordinates) coordBorder = piece_radius_inUnits*0.8; boardBorderLeft_inUnits = coordBorder; boardBorderRight_inUnits = coordBorder; boardBorderTop_inUnits = coordBorder; boardBorderBottom_inUnits = coordBorder; float borderLR = boardBorderLeft_inUnits + boardBorderRight_inUnits; float borderTB = boardBorderTop_inUnits + boardBorderBottom_inUnits; width_inUnits =(7+1.5+1.5)/7 + borderLR; height_inUnits=1.0 + borderTB; float scaleH = w/width_inUnits; float scaleV = h/height_inUnits; scale_units2pixels = std::min(scaleH,scaleV); windowWidth_inUnits = w/scale_units2pixels; windowHeight_inUnits = h/scale_units2pixels; float boardWidth_inPixels = (1.0+borderLR)*scale_units2pixels; float boardHeight_inPixels = (1.0+borderTB)*scale_units2pixels; xoffset_board_inUnits = (w-boardWidth_inPixels )/ scale_units2pixels/2 + boardBorderLeft_inUnits; yoffset_board_inUnits = (h-boardHeight_inPixels)/ scale_units2pixels/2 + boardBorderTop_inUnits; stackX_white_inUnits = ( -0.75/7) - boardBorderLeft_inUnits; stackX_black_inUnits = (1.0+0.75/7) + boardBorderRight_inUnits; } Point2D BoardGUI_GtkCairo::Geometry::board2Pixel(Point2D boardCoord) const { Point2D p; p.x = (boardCoord.x + xoffset_board_inUnits) * scale_units2pixels; p.y = (boardCoord.y + yoffset_board_inUnits) * scale_units2pixels; return p; } Point2D BoardGUI_GtkCairo::Geometry::pixel2Board(Point2D pixelCoord) const { Point2D p; p.x = pixelCoord.x / scale_units2pixels - xoffset_board_inUnits; p.y = pixelCoord.y / scale_units2pixels - yoffset_board_inUnits; return p; } Position BoardGUI_GtkCairo::Geometry::pixel2Pos(int mx,int my) const { const float distThreshold = 0.055; float x = mx/scale_units2pixels - xoffset_board_inUnits; float y = my/scale_units2pixels - yoffset_board_inUnits; boardspec_ptr spec = MainApp::app().getControl().getBoardSpec(); float dist=100; Position pos; for (int i=0;inPositions();i++) { Point2D p = spec->getPositionLocation(i); float d = hypot(p.x-x, p.y-y); if (ddistThreshold) { return -1; } return pos; } static MouseButton convertGtkMouseButton(guint button) { switch (button) { case 1: return MB_Left; case 2: return MB_Middle; case 3: return MB_Right; } assert(false); } gint button_press_area(GtkWidget *widget, GdkEventButton *event, gpointer obj) { BoardGUI_GtkCairo* self = (BoardGUI_GtkCairo*)(obj); Position p = self->geom.pixel2Pos(event->x, event->y); self->cb_buttonPress( p, Point2D(event->x, event->y), convertGtkMouseButton(event->button) ); return FALSE; } gint button_release_area(GtkWidget *widget, GdkEventButton *event, gpointer obj) { BoardGUI_GtkCairo* self = (BoardGUI_GtkCairo*)(obj); Position p = self->geom.pixel2Pos(event->x, event->y); self->cb_buttonRelease( p, convertGtkMouseButton(event->button) ); return FALSE; } gint mouse_motion_area(GtkWidget *widget, GdkEventButton *event, gpointer obj) { BoardGUI_GtkCairo* self = (BoardGUI_GtkCairo*)(obj); gint mx,my; gdk_window_get_pointer(self->drawingArea->window,&mx,&my,NULL); Position pos = self->geom.pixel2Pos(mx,my); self->cb_mouseMotion( pos, Point2D(mx,my) ); return FALSE; } gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer obj) { BoardGUI_GtkCairo* self = (BoardGUI_GtkCairo*)(obj); self->cb_expose_area(widget, event); return FALSE; } gint configure_area(GtkWidget *widget, GdkEventConfigure *event, gpointer obj) { BoardGUI_GtkCairo* self = (BoardGUI_GtkCairo*)(obj); self->cb_configure_area(widget,event); return TRUE; } gint realize_area(GtkWidget *widget, gpointer obj) { BoardGUI_GtkCairo* self = (BoardGUI_GtkCairo*)(obj); self->cb_realize_area(widget); return TRUE; } gint animation_timer(gpointer obj) { BoardGUI_GtkCairo* self = (BoardGUI_GtkCairo*)(obj); return self->cb_animation_timer(); } BoardGUI_GtkCairo::BoardGUI_GtkCairo() : drawingArea(NULL), offscreenBuffer(NULL), boardGfxInvalid(true), removeStackPiece(PL_None), drag_active(false), m_showHint(false) { drawingArea = gtk_drawing_area_new(); gtk_drawing_area_size(GTK_DRAWING_AREA(drawingArea), 10*64, 7*64); gtk_widget_set_events(drawingArea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_RELEASE_MASK); g_signal_connect(GTK_OBJECT(drawingArea),"expose_event", G_CALLBACK(expose_area), this); g_signal_connect(GTK_OBJECT(drawingArea),"configure_event", G_CALLBACK(configure_area), this); g_signal_connect_after(GTK_OBJECT(drawingArea),"realize",G_CALLBACK(realize_area),this); g_signal_connect(GTK_OBJECT(drawingArea),"button_press_event", G_CALLBACK(button_press_area), this); g_signal_connect(GTK_OBJECT(drawingArea),"button_release_event", G_CALLBACK(button_release_area),this); g_signal_connect(GTK_OBJECT(drawingArea),"motion_notify_event", G_CALLBACK(mouse_motion_area), this); ////boardpic = gdk_pixbuf_new_from_file(GTK_ICONDIR"/morris/board.png", NULL); // TODO: proper error handling ////piecespic = gdk_pixbuf_new_from_file(GTK_ICONDIR"/morris/pieces.png",NULL); // TODO: proper error handling } BoardGUI_GtkCairo::~BoardGUI_GtkCairo() { if (offscreenBuffer) { gdk_pixmap_unref(offscreenBuffer); offscreenBuffer=NULL; } } void BoardGUI_GtkCairo::changeGfxState(GfxState gfx) { if (!drawingArea->window) return; GdkCursor* cursor = NULL; switch (gfx) { case GS_Inactive: cursor = NULL; break; case GS_NonInteractiveMove: cursor = gdk_cursor_new(GDK_WATCH); break; case GS_Waiting: cursor = gdk_cursor_new(GDK_TCROSS); break; case GS_DraggingPiece: cursor = gdk_cursor_new(GDK_CIRCLE); break; case GS_Take: cursor = gdk_cursor_new(GDK_X_CURSOR); break; } gdk_window_set_cursor(drawingArea->window, cursor); if (cursor) gdk_cursor_destroy(cursor); } morris-0.3/src/gtkcairo_boardgui.hh000066400000000000000000000134061373406602200174650ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef GTKCAIRO_BOARDGUI_HH #define GTKCAIRO_BOARDGUI_HH #include #include "board.hh" #include "boardgui.hh" #include struct Animation { virtual ~Animation() { } virtual bool action(class BoardGUI_GtkCairo&) = 0; // return true when effect ended int elapsedTimeMS() const; struct timeval startTime; int durationMS; }; struct Animation_RemovePiece : public Animation { virtual bool action(class BoardGUI_GtkCairo&); Position pos; }; struct Animation_RemoveStack : public Animation { virtual bool action(class BoardGUI_GtkCairo&); Player player; }; struct Animation_MoveOverlay : public Animation { Animation_MoveOverlay() : overlayIdx(-1) { } virtual bool action(class BoardGUI_GtkCairo&); Player player; Point2D startPos; Point2D endPos; private: int overlayIdx; }; // Carry out the move and remove the overlays and hidden pieces. struct Animation_DoMove : public Animation { virtual bool action(class BoardGUI_GtkCairo&); Move move; int gameID; }; typedef boost::shared_ptr animation_ptr; class BoardGUI_GtkCairo : public BoardGUI_Base { public: BoardGUI_GtkCairo(); ~BoardGUI_GtkCairo(); void resetDisplay(); void redrawBoard(); void visualizeMove(const Move&, int gameID); void checkHover(); void showHint(const Move&); void removeHint(); GtkWidget* getBoardWidget() { return drawingArea; } struct Options { Options(); bool coloredCrossingWhileDragging; bool animateComputerMoves; float animationSpeed; // time in [ms] for moving across whole board bool set_moveIn; bool take_moveOut; float take_delay; bool showCoordinates; }; Options& getOptions() { return options; } private: GtkWidget* drawingArea; GdkPixmap* offscreenBuffer; bool boardGfxInvalid; struct OverlayPiece { Player player; Point2D coordinate; }; SmallVec overlay; SmallVec hidePos; Player removeStackPiece; std::vector animation; void draw_board_complete(); void draw_board(int x0,int y0,int w,int h); void expose_area_rect(int x0,int y0,int w,int h); void invalidatePiecePos(Point2D pos_inUnits, float extraRadius=0); virtual void invalidateHoverAtPos(Position); virtual void changeGfxState(GfxState); void draw_piece (cairo_t* cr, Point2D pos_inUnits, Player player, bool halfTransparent=false); void draw_piece_inPixels(cairo_t* cr, Point2D pos_inPixels, Player player, bool halfTransparent=false); // geometric layout struct Geometry { Geometry(); void fitInto(int w,int h, const Options&); Point2D board2Pixel(Point2D boardCoord) const; Point2D pixel2Board(Point2D boardCoord) const; Point2D getStackPiecePos(Player, int n) const; float getPieceRadiusInPixels() const { return piece_radius_inUnits*scale_units2pixels; } Position pixel2Pos(int mx,int my) const; float width_inUnits; float height_inUnits; float windowWidth_inUnits; float windowHeight_inUnits; float scale_units2pixels; float xoffset_board_inUnits; float yoffset_board_inUnits; float boardBorderLeft_inUnits; float boardBorderRight_inUnits; float boardBorderTop_inUnits; float boardBorderBottom_inUnits; float stackX_white_inUnits; float stackX_black_inUnits; float piece_radius_inUnits; float textSize_inUnits; } geom; // display options Options options; // manual piece dragging virtual void startPieceDrag(Position p, Point2D pixelPos); virtual void stopPieceDrag(); virtual void doPieceDrag(Point2D pixelPos, bool valid); bool drag_active; Player drag_player; Point2D drag_position; float drag_offset_x; float drag_offset_y; // hint display Move m_hint; bool m_showHint; // utility functions void drawRect(cairo_t*, Point2D topleft, Point2D bottomright, bool fill); void drawCoordinates(cairo_t*); // additional Gtk callbacks void cb_expose_area(GtkWidget *widget, GdkEventExpose *event); void cb_configure_area(GtkWidget *widget, GdkEventConfigure *event); void cb_realize_area(GtkWidget *widget); gint cb_animation_timer(); // kicker functions friend gint button_press_area(GtkWidget *widget, GdkEventButton *event, gpointer obj); friend gint button_release_area(GtkWidget *widget, GdkEventButton *event, gpointer obj); friend gint mouse_motion_area(GtkWidget *widget, GdkEventButton *event, gpointer obj); friend gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer obj); friend gint configure_area(GtkWidget *widget, GdkEventConfigure *event, gpointer obj); friend gint realize_area(GtkWidget *widget, gpointer obj); friend gint animation_timer(gpointer obj); // animation classes are friends friend class Animation_RemovePiece; friend class Animation_RemoveStack; friend class Animation_MoveOverlay; friend class Animation_DoMove; }; #endif morris-0.3/src/learn.hh000066400000000000000000000060121373406602200151020ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef LEARN_HH #define LEARN_HH #include "board.hh" #include class Experience { public: enum { SIGNIFICANT_BITS=8 }; void reset() { for (int i=0;i< (1< memory[1< experience_ptr; // --------------------------------------------------------------------------- class PositionMemory { public: enum { SIGNIFICANT_BITS=12 }; PositionMemory() { nEntries=0; } void storeBoard(const Board& b, float e) { return; int list = b.getHash() & ((1< memory[1< Morris 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 3 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, see . ***************************************************************************/ #include "mainapp.hh" #include "algo_alphabeta.hh" #include "algo_random.hh" #include #include #include "util.hh" AppState::AppState() { gamePaused = false; networkConnected = false; } MainApp::Options::Options() { alwaysPauseOnAIPlayer=false; } static boost::shared_ptr mainapp_singleton; void MainApp::createMainAppSingleton() { // init tables Board::initHashValues(); // create main application mainapp_singleton = boost::shared_ptr(new MainApp); } MainApp& MainApp::app() { assert(mainapp_singleton != NULL); return *(mainapp_singleton.get()); } MainApp::MainApp() : threadTunnel(NULL), hintID(-100000) // set to a large negative number to avoid collision with gameID { experience = experience_ptr(new Experience); // initialize the two AI players for (int c=0;c<2;c++) { TranspositionTable* tt = new TranspositionTable(TRANSPOSITION_TABLE_SIZE); ttable[c] = ttable_ptr(tt); PlayerIF_AlgoAB* algo = new PlayerIF_AlgoAB(); player_computer[c] = player_ptr(algo); algo->registerExperience(experience); } setShareTTables(true); // initialize hint algorithm { PlayerIF_AlgoAB* hintAlgo = new PlayerIF_AlgoAB; hint_computer = player_ptr(hintAlgo); hint_computer->setRuleSpec( control.getRuleSpec() ); hint_ttable = ttable_ptr(new TranspositionTable(TRANSPOSITION_TABLE_SIZE-1)); hintAlgo->registerTTable(hint_ttable); hintAlgo->registerExperience(experience); } // set the default players control.registerPlayerIF(PL_White, player_ptr(new PlayerIF_Human)); control.registerPlayerIF(PL_Black, player_computer[1]); control.resetGame(); } void MainApp::init() { control.getSignal_changeState().connect(boost::bind(&MainApp::setStatusbarText, this)); control.getSignal_gameOver() .connect(boost::bind(&MainApp::setStatusbarText, this)); control.getSignal_startMove() .connect(boost::bind(&MainApp::setStatusbarText, this)); control.getSignal_startMove().connect(boost::bind(&MainApp::startMove, this, _1)); control.getSignal_endMove() .connect(boost::bind(&MainApp::endMove, this, _1)); control.getSignal_gameOver() .connect(boost::bind(&ApplicationGUI::showGameOverDialog, gui_application, _1)); setStatusbarText(); } void MainApp::setThreadTunnel(ThreadTunnel& tt) { threadTunnel=&tt; for (int i=0;i<2;i++) player_computer[i]->registerThreadTunnel(tt); hint_computer->registerThreadTunnel(*threadTunnel); } void MainApp::setRules(rulespec_ptr rules, bool significantChange) { getBoardGUI()->removeHint(); hint_computer->cancelMove(); hint_computer->setRuleSpec( rules ); control.registerRuleSpec(rules); experience->reset(); if (significantChange) { control.resetGame(); } getBoardGUI()->resetDisplay(); nextMove_butPauseIfAIPlayer(); } void MainApp::setPlayer(Player pl, player_ptr player) { control.registerPlayerIF(pl, player); if (control.getGameState().state == GameState::Idle && pl == control.getCurrentPlayer()) { nextMove_butPauseIfAIPlayer(); } } void MainApp::resetGame() { getBoardGUI()->removeHint(); control.resetGame(); hint_computer->resetGame(); getBoardGUI()->redrawBoard(); nextMove_butPauseIfAIPlayer(); } void MainApp::undo() { getBoardGUI()->removeHint(); control.undoMove(); getBoardGUI()->redrawBoard(); nextMove_butPauseIfAIPlayer(); } void MainApp::redo() { getBoardGUI()->removeHint(); control.redoMove(); getBoardGUI()->redrawBoard(); nextMove_butPauseIfAIPlayer(); } void MainApp::startNextMove() { assert(appState.gamePaused==false); /* NOTE: it is essential that the new move is started in an idle function at a later time, because this allows the initiator of the current move to clean up after the doMove() function returns. This cannot always be done beforehand, because the doMove() routine may also indicate that the move was not complete yet. */ class IdleFunc_StartNextMove : public IdleFunc { public: void operator()() { MainApp::app().getControl().startNextMove(); } }; IdleFunc::install(new IdleFunc_StartNextMove); } void MainApp::visualizeMove(const Move& move, int gameID) { // Only carry out the move, if we are still in the same game. // (The user could have started a new game, while the thread was still computing on the old one.) if (gameID == control.getCurrentMoveID() && control.getGameState().state == GameState::Moving) { getBoardGUI()->visualizeMove(move, gameID); } else if (gameID == hintID && hint_gameID == control.getCurrentMoveID()) { getBoardGUI()->showHint(move); } else { // std::cout << "did not consider move, because it was too old...\n"; } } int MainApp::doMove(Move m) { // TODO: here, we could add more things, like logging getBoardGUI()->removeHint(); int nTakes = control.doMove(m); if (nTakes==0) { if (control.getGameState().state != GameState::Ended) { if (options.alwaysPauseOnAIPlayer) nextMove_butPauseIfAIPlayer(); else startNextMove(); } } // TODO: it is not quite logical to do this here getBoardGUI()->checkHover(); return nTakes; } void MainApp::computeHint() { hintID++; hint_gameID = control.getCurrentMoveID(); hint_computer->startMove(control.getCurrentBoard_noTemporary(), hintID); } // ------------------------- pause ------------------------- void MainApp::setPause(bool flag) { bool changed = (appState.gamePaused!=flag); appState.gamePaused=flag; if (changed) m_signal_pauseChanged(appState.gamePaused); } void MainApp::continueGame() { assert(appState.gamePaused); assert(control.getGameState().state != GameState::Ended); setPause(false); startNextMove(); } void MainApp::nextMove_butPauseIfAIPlayer() { bool ended = (control.getGameState().state == GameState::Ended); bool nonInteractive = (control.getCurrentPlayerInterface()->isInteractivePlayer() == false); setPause(nonInteractive && !ended); if (appState.gamePaused==false && !ended) // && control.getGameState().state==GameState::Idle) { assert(control.getGameState().state==GameState::Idle); startNextMove(); } } void MainApp::setShareTTables(bool share) { share_TT = share; for (int c=0;c<2;c++) { PlayerIF_AlgoAB* algo = dynamic_cast(player_computer[c].get()); algo->registerTTable(share_TT ? ttable[0] : ttable[c]); } } void MainApp::setThinkingInfo(const std::string& thinking) { setStatusbarText_withThinking(thinking); } void MainApp::setStatusbarText() { setStatusbarText_withThinking(""); } void MainApp::setStatusbarText_withThinking(const std::string& thinkingSuffix) { GameState state = control.getGameState(); switch (state.state) { case GameState::Ended: if (state.SUBSTATE_Winner==PL_White) { gui_application->setStatusbar(_("Game over: white has won!")); } else if (state.SUBSTATE_Winner==PL_Black) { gui_application->setStatusbar(_("Game over: black has won!")); } else { gui_application->setStatusbar(_("Game ended in a tie between both players.")); } break; // TODO: this has to be handled in another way case GameState::Idle: gui_application->setStatusbar(_("Game paused. Click continue to proceed.")); break; case GameState::Moving: { bool set = state.SUBSTATE_PlayerSet; bool move = state.SUBSTATE_PlayerMove; std::string str; if (control.getCurrentPlayer()==PL_White) { str = _("White player"); } else { str = _("Black player"); } str += ": "; if (control.getCurrentPlayerInterface()->isInteractivePlayer()) { if (set && move) { str += _("set or move a piece."); } else if (set) { str += _("set a piece."); } else if (move) { str += _("move a piece."); } } else { str += _("computer is taking his turn... "); str += thinkingSuffix; } gui_application->setStatusbar(str.c_str()); } break; } } void MainApp::startMove(player_ptr p) { if (!p->isInteractivePlayer()) gui_application->getBoardGUI()->startNonInteractiveMove(); } void MainApp::endMove(player_ptr p) { if (!p->isInteractivePlayer()) gui_application->getBoardGUI()->endNonInteractiveMove(); } morris-0.3/src/mainapp.hh000066400000000000000000000115621373406602200154340ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef MAINAPP_HH #define MAINAPP_HH #include "ttable.hh" #include "control.hh" #include "player.hh" #include "boardgui.hh" #include "appgui.hh" #include "learn.hh" #include "configmgr.hh" /* The general state of the main application. This is not at the granularity of the state in GameControl, but rather extends it with an higher-level application state. */ struct AppState { AppState(); bool gamePaused; // whether the game is paused and has to be explicitly continued bool networkConnected; // CURRENTLY UNUSED }; /* The MainApp is a singleton class that is the central entity of the application. This is where all the modules are instantiated and connected together. */ class MainApp { public: // --- initialization --- static void createMainAppSingleton(); // this initialized the global MainApp static MainApp& app(); // the main application singleton (without GUI) void init(); // call after the GUI has been initialized void setThreadTunnel(ThreadTunnel& tt); /* Replace the rules. If significant changes are indicated, the game is also restarted. */ void setRules(rulespec_ptr, bool significantChange); void setPlayer(Player, player_ptr); // --- application and game control --- void resetGame(); void undo(); void redo(); void setPause(bool flag=true); void continueGame(); // resume from pause GameControl& getControl() { return control; } /* Start the next move. Note that the next move is not started immediately, but simply marked down that it should be started. It will be started the next time the program gets idle. */ void startNextMove(); /* Graphically visualize the move and then forward it to the GameControl via the doMove() below. This method is usually used for non-interactive players. */ void visualizeMove(const Move& m, int gameID); // called from the player algorithm /* Immediately perform the move without any graphical feedback. This the usual way interactive moves are executed. */ int doMove(Move m); // returns the number of takes that still have to be carried out (see GameControl) // --- options --- void registerConfigManager(configmanager_ptr p) { m_configManager=p; } configmanager_ptr getConfigManager() { return m_configManager; } struct Options { Options(); bool alwaysPauseOnAIPlayer; }; Options options; // --- AI players --- player_ptr& getAIPlayer(int p) { return player_computer[p]; } ttable_ptr& getTTable(int p) { return ttable[p]; } bool getShareTTables() { return share_TT; } void setShareTTables(bool share); // --- hint AI --- void computeHint(); // --- network --- // ... TODO ... // --- GUI --- void setApplicationGUI(appgui_ptr gui) { gui_application=gui; } appgui_ptr getApplicationGUI() const { return gui_application; } boardgui_ptr getBoardGUI() const { return gui_application->getBoardGUI(); } void setThinkingInfo(const std::string&); // --- thread-tunnel --- // ThreadTunnel* getThreadTunnel() { return threadTunnel; } // currently unused // --- signals --- boost::signals2::signal& getSignal_pauseChanged() { return m_signal_pauseChanged; } private: MainApp(); // game control AppState appState; GameControl control; // players player_ptr player_computer[2]; // A and B bool share_TT; ttable_ptr ttable[2]; experience_ptr experience; // hint player_ptr hint_computer; int hintID, hint_gameID; ttable_ptr hint_ttable; // configuration configmanager_ptr m_configManager; // GUI appgui_ptr gui_application; ThreadTunnel* threadTunnel; void nextMove_butPauseIfAIPlayer(); // callbacks void setStatusbarText(); // check game state and set statusbar text accordingly void setStatusbarText_withThinking(const std::string& suffix); // check game state and set statusbar text accordingly void startMove(player_ptr); void endMove(player_ptr); boost::signals2::signal m_signal_pauseChanged; }; #endif morris-0.3/src/morris.cc000066400000000000000000000027511373406602200153100ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "config.h" #include "gtk_appgui.hh" #include "morris.hh" #include "mainapp.hh" #include #include int main(int argc, char **argv) { srand(time(NULL)); // init internationalization setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); // start main application control MainApp::createMainAppSingleton(); // init GUI //ApplicationGUI_Gnome::initApplicationGUI(argc, argv); ApplicationGUI_Gtk::initApplicationGUI(argc, argv); // set default state MainApp::app().init(); // start GUI MainApp::app().getApplicationGUI()->startApplication(); return 0; } morris-0.3/src/morris.hh000066400000000000000000000016201373406602200153140ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef MORRIS_HH #define MORRIS_HH #endif morris-0.3/src/movelog.hh000066400000000000000000000023541373406602200154560ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef MOVELOG_HH #define MOVELOG_HH #include /* A window showing a log of all moves in the current game. */ class MoveLog { public: virtual ~MoveLog() { } virtual void refresh() = 0; boost::signals2::signal& getSignal_windowClosed() { return m_signal_windowClosed; } protected: boost::signals2::signal m_signal_windowClosed; }; #endif morris-0.3/src/player.hh000066400000000000000000000047211373406602200153020ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef PLAYER_HH #define PLAYER_HH #include "board.hh" #include "rules.hh" #include "threadtunnel.hh" /* The main interface for all kinds of players. Communication of the player to the outside world is usually through the ThreadTunnel interface. This is because some players will run as separate threads and have to send their messages to the main application thread. This inter-thread-communication is performed by the thread-tunnel. NOTE: player do not have to use the thread-tunnel, if they do not need. But it can be convenient to use this interface even if it is not strictly required. The main operation is that GameControl initiates a new move by calling startMove(). Once the move is computed, entered, or received, it is sent to the main application with the doMove() method of the thread-tunnel. */ class PlayerIF { public: PlayerIF() { m_selfPlayer=PL_None; } virtual ~PlayerIF() { } void setPlayer(Player p) { m_selfPlayer=p; } void setRuleSpec(rulespec_ptr rs) { m_ruleSpec = rs; } virtual void registerThreadTunnel(ThreadTunnel& tunnel) { } virtual bool isInteractivePlayer() const { return false; } virtual void resetGame() { } virtual void startMove(const Board& current, int moveID) = 0; // start this player's move virtual void forceMove() { } // stop thinking process and move as soon as possible virtual void cancelMove() { } // stop thinking and do not move, will join the algo-thread virtual void notifyWinner(Player p) { } protected: Player m_selfPlayer; rulespec_ptr m_ruleSpec; }; typedef boost::shared_ptr player_ptr; #endif morris-0.3/src/rules.cc000066400000000000000000000302321373406602200151220ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "rules.hh" std::string writeMove(const Move& m, boardspec_ptr spec) { std::string str; if (m.mode == Move::Mode_Move) { str = spec->getPositionName(m.oldPos); str += '-'; } str += spec->getPositionName(m.newPos); for (int i=0;igetPositionName(m.takes[i]); } return str; } RuleSpec::RuleSpec() { laskerVariant=false; mayJump=true; mayTakeMultiple=false; mayTakeFromMillsAlways=false; tieAfterNRepeats=3; nPieces=9; } int RuleSpec::nPotentialMills(const Board& currentBoard, const Move& move) const { const Player pl = currentBoard.getCurrentPlayer(); int cnt=0; // get set of all mills through this position const std::vector& mills = boardSpec->getMillsThroughPos(move.newPos); // iterate through all mills for (size_t i=0;i& mills = boardSpec->getMillsThroughPos(pos); const Player pl = currBoard.getPosition(pos); for (size_t m=0;mnPositions();i++) if (currBoard.getPosition(i) == opponent(currBoard.getCurrentPlayer())) if (!isInMill(currBoard,i)) { onlyMills = false; break; } if (onlyMills) return true; else return false; } // generate all possible takes for the set/move-part of the partial move 'm' void RuleSpec::generateTakes(std::vector& output, const Move& m, const Board& currBoard, int n) const { assert(n>0); const Player other = currBoard.getOpponentPlayer(); // First try to generate takes assuming that not all opponent pieces are within mills // (or that it is irrelevant, because we may take any piece). bool takesGenerated = false; for (int i=0;inPositions();i++) if (currBoard.getPosition(i) == other) { if (mayTakeFromMillsAlways || isInMill(currBoard, i) == false) { Move move = m; move.addTake(i); takesGenerated=true; if (n==1) { // move complete, add to set output.push_back(move); } else { // we may add more takes, continue recursively Board tmpBoard = currBoard; tmpBoard.setPosition_noHash(i, PL_None); generateTakes(output, move, tmpBoard, n-1); } } } // If we could not take any opponent pieces (because all are in mills), // we are allowed to take any opponent piece we want (from mills). if (!takesGenerated) { for (int i=0;inPositions();i++) if (currBoard.getPosition(i) == other) { Move move = m; move.addTake(i); if (n==1) { output.push_back(move); } else { Board tmpBoard = currBoard; tmpBoard.setPosition_noHash(i, PL_None); generateTakes(output, move, tmpBoard, n-1); } } } } void RuleSpec::addTakesToMoveIfMillClosed(std::vector& output, const Move& m, const class Board& currBoard) const { int nMills = nPotentialMills(currBoard, m); if (nMills==0) { // no mills closed, do not add takes output.push_back(m); } else { // add takes if (mayTakeMultiple==false) { nMills=1; } generateTakes(output, m, currBoard, nMills); } } void RuleSpec::generateMoves(std::vector& output, const Board& currBoard) const { const bool maySet = (currBoard.getNPiecesToSet()>0); const bool mayMove = (currBoard.getNPiecesToSet()==0) || laskerVariant; const bool mayFly = mayJump && (currBoard.getNPiecesLeft()==3); // generate set-moves if (maySet) { for (int i=0;inPositions();i++) if (currBoard.getPosition(i) == PL_None) { Move m; m.setMove_Set(i); addTakesToMoveIfMillClosed(output,m,currBoard); } } // generate moves if (mayMove) { for (int i=0;inPositions();i++) if (currBoard.getPosition(i) == currBoard.getCurrentPlayer()) { if (mayFly) { for (int k=0;knPositions();k++) { if (k!=i && currBoard.getPosition(k) == PL_None) { Move m; m.setMove_Move(i,k); addTakesToMoveIfMillClosed(output,m,currBoard); } } } else { const NeighborVector& v = boardSpec->getNeighbors(i); for (int n=0;ngetNeighbors(m.oldPos); for (int i=0;inPositions();i++) if (b.isPlayer(i)) { freedom=freedomAtPosition(b,i); if (freedom>0) break; } if (freedom==0 && b.getNPiecesToSet()==0 && (b.getNPiecesOnBoard()>3 || !mayJump)) { return true; } // have to set a piece, but the board is completely filled if (b.getNPiecesToSet()>0 && b.getNPiecesOnBoard(PL_White) + b.getNPiecesOnBoard(PL_Black) == boardSpec->nPositions()) { return true; } return false; } bool RuleSpec::tieBetweenBothPlayers(const Board& b) const { if (tieAfterNRepeats==0) { return false; } int repeatCnt = 0; const Board* curr = &b; const Board* prev; for (;;) { prev = curr->getPrevBoard().get(); if (prev==NULL) break; if (*prev==b) { repeatCnt++; } if (repeatCnt==tieAfterNRepeats) return true; curr=prev; } return false; } rulespec_ptr RuleSpec::createPresetRule(enum RulePreset p) { rulespec_ptr rule = rulespec_ptr(new RuleSpec); switch (p) { case Preset_Standard: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_Standard9MM)); rule->nPieces = 9; break; case Preset_Lasker: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_Standard9MM)); rule->nPieces = 10; rule->laskerVariant=true; rule->mayJump=false; break; case Preset_Morabaraba: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_Morabaraba)); rule->nPieces = 12; break; case Preset_Moebius: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_Moebius)); rule->nPieces = 9; break; case Preset_Windmill: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_Windmill)); rule->nPieces = 12; rule->mayTakeMultiple=true; break; case Preset_Sunmill: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_Sunmill)); rule->nPieces = 12; rule->mayTakeMultiple=true; break; case Preset_6MM: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_6MM)); rule->nPieces = 6; rule->mayJump = false; rule->mayTakeMultiple=false; break; case Preset_7MM: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_7MM)); rule->nPieces = 7; rule->mayJump = false; rule->mayTakeMultiple=false; break; case Preset_Tapatan: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_SmallSqWithDiag)); rule->nPieces = 3; rule->mayJump = false; break; case Preset_NineHoles: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_SmallSq)); rule->nPieces = 3; rule->mayJump = true; break; case Preset_Achi: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_SmallSqWithDiag)); rule->nPieces = 4; rule->mayJump = false; break; case Preset_SmallTri: rule->boardSpec = boardspec_ptr(new BoardSpec_Grid(BoardSpec::Board_SmallTri)); rule->nPieces = 3; rule->mayJump = false; break; case Preset_Polygon3: rule->boardSpec = boardspec_ptr(new BoardSpec_Polygon(3)); rule->nPieces = 7; break; case Preset_Polygon5: rule->boardSpec = boardspec_ptr(new BoardSpec_Polygon(5)); rule->nPieces = 11; break; case Preset_Polygon6: rule->boardSpec = boardspec_ptr(new BoardSpec_Polygon(6)); rule->nPieces = 12; break; } return rule; } BoardID RuleSpec::getBoardID(const Board& board) const { BoardID id=0; id += board.getNPiecesToSet(PL_White); id *= nPieces+1; id += board.getNPiecesToSet(PL_Black); const int nPos = boardSpec->nPositions(); for (int p=0;p& permutations = boardSpec->getPermutations(); // Compute all symmetric permutations of the board position and determine the board ID for each. // Return the lowest ID. Board b = board; // TODO: setting only the meta-information would be faster (next player, pieces to set) BoardID id; for (int i=0;inPositions();p++) b.setPosition_noHash( permutations[i][p], board.getPosition(p) ); BoardID newid = getBoardID(b); if (i==0 || newid Morris 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 3 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, see . ***************************************************************************/ #ifndef RULES_HH #define RULES_HH #include "boardspec.hh" #include "board.hh" /* Write the move in human-readable notation. */ std::string writeMove(const Move& m, boardspec_ptr spec); typedef unsigned long long BoardID; // a unique ID for a specific board-configuration typedef boost::shared_ptr rulespec_ptr; /* The rule-specification class manages the various variants of the rules. It also carries out checks for rule-conforming moves, and it comprises the move-generator for AI players. */ class RuleSpec { public: RuleSpec(); boardspec_ptr boardSpec; // The board that is played on. bool laskerVariant; // Player may either set a new piece or move an existing piece. bool mayJump; // Player may jump if he is down to three pieces. bool mayTakeMultiple; // When closing more than one mill at once, may also take several opponent pieces. bool mayTakeFromMillsAlways;// May take from mills even if there are other pieces available. int tieAfterNRepeats; // Number of board-repetitions to declare a tie. NOTE: set to zero to turn off. int nPieces; // Number of pieces each player has at the beginning. // int movesBetweenReformingMill; // number of turns before mills may reform // --- checking for valid moves --- // The number of mills that would be closed by the given move. int nPotentialMills(const Board&, const Move&) const; /* Whether the specified piece may be taken. This depends on whether it is part of a mill and whether there are other pieces, not part of a mill. */ bool mayTake(const Board&, Position) const; /* Check whether the given move is valid. NOTE: the takes in this move are ignored ! */ bool isValidMove(const Board&, const Move&) const; /* The number of empty direct neighbors to the specified piece. */ int freedomAtPosition(const Board&, Position) const; // Whether the specified piece is part of a mill. bool isInMill(const Board&, Position) const; // --- game state --- // Whether the current situation is a game-over. bool isGameOver(const Board&, Player* winner=NULL) const; bool currentPlayerHasWon(const Board&) const; bool currentPlayerHasLost(const Board&) const; /* This checks for the current game history for board repetitions, if ties are enabled. For this to work, the chain of previous boards has to be set correctly. */ bool tieBetweenBothPlayers(const Board&) const; // Get a unique ID for the current board. BoardID getBoardID(const Board& board) const; // Get a unique ID for the current board, considering symmetries. I.e. a similar situation, // in which the board is just rotated, mirrored, or otherwise permuted receives the same ID. BoardID getBoardID_Symmetric(const Board& board) const; // --- move generator --- // Generate a set of valid moves for the current board. // NOTE: the 'output' set is not cleared in this function. void generateMoves(std::vector& output, const class Board& currentBoard) const; // --- rule factory --- enum RulePreset { Preset_Standard, Preset_Lasker, Preset_Moebius, Preset_Morabaraba, Preset_Windmill, Preset_Sunmill, Preset_6MM, Preset_7MM, Preset_Tapatan, Preset_Achi, Preset_SmallTri, Preset_NineHoles, Preset_Polygon3, Preset_Polygon5, Preset_Polygon6 }; // Initialize the rules to one of the preset. static rulespec_ptr createPresetRule(enum RulePreset); private: // Take the specified move as template and add all possible takes of 'n' opponent pieces. void generateTakes(std::vector& output, const Move&, const class Board& currentBoard, int n) const; /* Check is a mill will be closed by the specified move and if yes, extend the move with all possible takes and add to the set. Otherwise (if no mill was closed), simply add the move to the set (without takes). */ void addTakesToMoveIfMillClosed(std::vector& output, const Move& m,const class Board& currentBoard) const; }; /* NOTE: this function is defined inline, because it is used in the time critical board evaluation function. */ inline int RuleSpec::freedomAtPosition(const Board& b, Position p) const { const NeighborVector& v = boardSpec->getNeighbors(p); int cnt=0; for (int i=0;i Morris 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 3 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, see . ***************************************************************************/ #ifndef THREADTUNNEL_HH #define THREADTUNNEL_HH #include "board.hh" /* The thread-tunnel provides the interface through which the players communicate to the main application. The thread-tunnel object is required, because many players will run in separate threads and have to send their messages as inter-thread messages. The thread-tunnel performs this inter-thread message forwarding. */ class ThreadTunnel { public: ThreadTunnel() {} virtual ~ThreadTunnel() { } // --- thread tunnels --- // Set the progress bar in the status-line (value is in [0;1]). virtual void setProgress(float progress) { } // Show some additional information about the AI thinking-process in the statusbar. virtual void showThinkingInfo(const std::string&) { } // Send move to main application. virtual void doMove(Move m, int moveID) = 0; // currently unused // virtual void setStatusbar(const char*) { } }; /* Define and install a run-once function that is executed once when the program is idle. This is an alternative way of inter-thread communication. */ class IdleFunc { public: virtual ~IdleFunc() { } // The idle function... virtual void operator() () = 0; /* The install function is defined in one of the GUI-framework specific modules (e.g., gtk_threadtunnel.cc). */ static void install(IdleFunc*); }; #endif morris-0.3/src/ttable.cc000066400000000000000000000054401373406602200152460ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #include "ttable.hh" #include // 16 - 65536 // 17 - 131072 // 18 - 262144 // 19 - 524288 // 20 - 1048576 TranspositionTable::TranspositionTable(int nBits) { tableSize = 1< table[h].depth) { replaceEntry=true; } else { /* NOP */ } } if (replaceEntry) { table[h].hash = hash; table[h].eval = eval; table[h].depth = depth; table[h].bound = bound; table[h].bestMove = bestMove; #if SAFE_HASH table[h].board = b; #endif } } float TranspositionTable::getFillStatus() const { int nFilled=0; for (int i=0;i Morris 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 3 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, see . ***************************************************************************/ #ifndef TTABLE_HH #define TTABLE_HH #include "board.hh" #define SAFE_HASH 0 class TranspositionTable { public: TranspositionTable(int nBits); ~TranspositionTable(); void clear(); enum BoundType { LowerBound, AccurateValue, UpperBound }; struct Entry { BoardHash hash; float eval; signed char depth; // depth to which this node was calculated signed char bound; Move bestMove; #if SAFE_HASH Board board; // TMP #endif BoundType getBoundType() const { return (BoundType)(bound); } }; const Entry* lookup(BoardHash h, const Board&) const; void insert(BoardHash h, float eval, BoundType, int depth, const Move& bestMove, const Board&); static inline BoundType boundType(float eval, float alpha, float beta) { if (eval<=alpha) return UpperBound; if (eval>=beta) return LowerBound; return AccurateValue; } void resetStats() { lookups=hits=collisions=misses=0; } int nHits() const { return hits; } int nCollisions() const { return collisions; } int nLookups() const { return lookups; } float getFillStatus() const; private: Entry* table; int tableSize; BoardHash mask; mutable int lookups,hits,collisions,misses; }; typedef boost::shared_ptr ttable_ptr; #include #include inline std::ostream& operator<<(std::ostream& ostr, const TranspositionTable::BoundType& t) { switch (t) { case TranspositionTable::LowerBound: ostr << "lower"; break; case TranspositionTable::UpperBound: ostr << "upper"; break; case TranspositionTable::AccurateValue: ostr << "accurate"; break; } return ostr; } inline std::ostream& operator<<(std::ostream& ostr, const TranspositionTable::Entry& e) { ostr << "hash=" << std::hex << e.hash << " eval=" << e.eval << " depth=" << ((int)e.depth) << " bound=" << e.getBoundType() << " bestMove=" << e.bestMove; return ostr; } #endif morris-0.3/src/util.hh000066400000000000000000000043761373406602200147710ustar00rootroot00000000000000/*************************************************************************** This file is part of Morris. Copyright (C) 2009 Dirk Farin Morris 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 3 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, see . ***************************************************************************/ #ifndef UTIL_HH #define UTIL_HH #include #include "config.h" #include "gettext.h" #define _(String) gettext (String) #define N_(String) (String) /* Simple, computationally efficient vector-class with a fixed, maximum size. */ template class SmallVec { public: SmallVec() { nElements=0; } void push_back(const T& t) { assert(nElements& v) { for (int i=0;i>1; } #endif