[llvm-commits] CVS: llvm/test/Programs/MultiSource/Applications/obsequi/COPYRIGHT GPL LICENSE.TXT Makefile README consts.h cppflags.h display.c does_x_win.c globals.h hash.c init.c interface.h macros.h move_gen.c move_sort.c negamax.c obsequi.c position_values.c structs.h tables.c toggle_move.c traits.c utils.c utils.h
John Criswell
criswell at cs.uiuc.edu
Tue May 11 14:35:03 PDT 2004
Changes in directory llvm/test/Programs/MultiSource/Applications/obsequi:
COPYRIGHT added (r1.1)
GPL added (r1.1)
LICENSE.TXT added (r1.1)
Makefile added (r1.1)
README added (r1.1)
consts.h added (r1.1)
cppflags.h added (r1.1)
display.c added (r1.1)
does_x_win.c added (r1.1)
globals.h added (r1.1)
hash.c added (r1.1)
init.c added (r1.1)
interface.h added (r1.1)
macros.h added (r1.1)
move_gen.c added (r1.1)
move_sort.c added (r1.1)
negamax.c added (r1.1)
obsequi.c added (r1.1)
position_values.c added (r1.1)
structs.h added (r1.1)
tables.c added (r1.1)
toggle_move.c added (r1.1)
traits.c added (r1.1)
utils.c added (r1.1)
utils.h added (r1.1)
---
Log message:
Addition of the obsequi program. This program solves domineering boards.
---
Diffs of the changes: (+4819 -0)
Index: llvm/test/Programs/MultiSource/Applications/obsequi/COPYRIGHT
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/COPYRIGHT:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/COPYRIGHT Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,21 ----
+ Obsequi is a program which is able to solve the game of domineering
+ for various board sizes.
+
+ Copyright (C) 2002 Nathan Bullock
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ bullock at cs.ualberta.ca
+ jonathan at cs.ualberta.ca
Index: llvm/test/Programs/MultiSource/Applications/obsequi/GPL
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/GPL:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/GPL Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,340 ----
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+ freedom to share and change it. By contrast, the GNU General Public
+ License is intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users. This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it. (Some other Free Software Foundation software is covered by
+ the GNU Library General Public License instead.) You can apply it to
+ your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it
+ in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+ (2) offer you this license which gives you legal permission to copy,
+ distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+ modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+ a notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The "Program", below,
+ refers to any such program or work, and a "work based on the Program"
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term "modification".) Each licensee is addressed as "you".
+
+ Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of
+ running the Program is not restricted, and the output from the Program
+ is covered only if its contents constitute a work based on the
+ Program (independent of having been made by running the Program).
+ Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+ source code as you receive it, in any medium, provided that you
+ conspicuously and appropriately publish on each copy an appropriate
+ copyright notice and disclaimer of warranty; keep intact all the
+ notices that refer to this License and to the absence of any warranty;
+ and give any other recipients of the Program a copy of this License
+ along with the Program.
+
+ You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+ of it, thus forming a work based on the Program, and copy and
+ distribute such modifications or work under the terms of Section 1
+ above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+ These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote it.
+
+ Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.
+
+ In addition, mere aggregation of another work not based on the Program
+ with the Program (or with a work based on the Program) on a volume of
+ a storage or distribution medium does not bring the other work under
+ the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+ The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to
+ control compilation and installation of the executable. However, as a
+ special exception, the source code distributed need not include
+ anything that is normally distributed (in either source or binary
+ form) with the major components (compiler, kernel, and so on) of the
+ operating system on which the executable runs, unless that component
+ itself accompanies the executable.
+
+ If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent
+ access to copy the source code from the same place counts as
+ distribution of the source code, even though third parties are not
+ compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt
+ otherwise to copy, modify, sublicense or distribute the Program is
+ void, and will automatically terminate your rights under this License.
+ However, parties who have received copies, or rights, from you under
+ this License will not have their licenses terminated so long as such
+ parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying
+ the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further
+ restrictions on the recipients' exercise of the rights granted herein.
+ You are not responsible for enforcing compliance by third parties to
+ this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent
+ license would not permit royalty-free redistribution of the Program by
+ all those who receive copies directly or indirectly through you, then
+ the only way you could satisfy both it and this License would be to
+ refrain entirely from distribution of the Program.
+
+ If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.
+
+ It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made
+ generous contributions to the wide range of software distributed
+ through that system in reliance on consistent application of that
+ system; it is up to the author/donor to decide if he or she is willing
+ to distribute software through any other system and a licensee cannot
+ impose that choice.
+
+ This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License
+ may add an explicit geographical distribution limitation excluding
+ those countries, so that distribution is permitted only in or among
+ countries not thus excluded. In such case, this License incorporates
+ the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time. Such new versions will
+ be similar in spirit to the present version, but may differ in detail to
+ address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and "any
+ later version", you have the option of following the terms and conditions
+ either of that version or of any later version published by the Free
+ Software Foundation. If the Program does not specify a version number of
+ this License, you may choose any version ever published by the Free Software
+ Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the author
+ to ask for permission. For software which is copyrighted by the Free
+ Software Foundation, write to the Free Software Foundation; we sometimes
+ make exceptions for this. Our decision will be guided by the two goals
+ of preserving the free status of all derivatives of our free software and
+ of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+ REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+ possible use to the public, the best way to achieve this is to make it
+ free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+ to attach them to the start of each source file to most effectively
+ convey the exclusion of warranty; and each file should have at least
+ the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ Also add information on how to contact you by electronic and paper mail.
+
+ If the program is interactive, make it output a short notice like this
+ when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+ The hypothetical commands `show w' and `show c' should show the appropriate
+ parts of the General Public License. Of course, the commands you use may
+ be called something other than `show w' and `show c'; they could even be
+ mouse-clicks or menu items--whatever suits your program.
+
+ You should also get your employer (if you work as a programmer) or your
+ school, if any, to sign a "copyright disclaimer" for the program, if
+ necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+ This General Public License does not permit incorporating your program into
+ proprietary programs. If your program is a subroutine library, you may
+ consider it more useful to permit linking proprietary applications with the
+ library. If this is what you want to do, use the GNU Library General
+ Public License instead of this License.
Index: llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,5 ----
+ Obsequi
+ ------------------------------------------------------------------------------
+ Obsequi is licensed under the GNU General Public License. Please see the file
+ COPYRIGHT and GPL for more information.
+
Index: llvm/test/Programs/MultiSource/Applications/obsequi/Makefile
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/Makefile:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/Makefile Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,8 ----
+ LEVEL = ../../../../..
+ PROG = Obsequi
+ CPPFLAGS += -DCOUNTBITS16 -DLASTBIT16 -DCOUNTMOVES_TABLE -DHASHCODEBITS=23
+ CPPFLAGS += -DTWO_STAGE_GENERATION
+ LDFLAGS = -lsupc++
+ LIBS += -lsupc++
+ STDIN_FILENAME=$(BUILD_SRC_DIR)/input
+ include ../../Makefile.multisrc
Index: llvm/test/Programs/MultiSource/Applications/obsequi/README
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/README:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/README Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,23 ----
+ obsequi - latin for compliance, indulgence, submission, pliancy.
+
+ This program is able to play and solve domineering boards.
+ Currently it can solve 9x9 and larger boards with a single processor.
+
+ To compile cd to the directory "obsequi", type make.
+
+ Should work, if not, you must be using a different compiler or
+ libraries. (I use gcc and glibc).
+
+ There isn't really any documentation for obsequi (sorry).
+
+ To get it to solve an 8x8 board use:
+ echo "solve rows 8 cols 8 V" | ./Obsequi
+
+ You can also pre-place blocks on the board.
+ The V says it is verticals turn first.
+ There are a number of run time options and compile time options, the
+ compile time options are in cppflags.raw (don't change the other cppflags*
+ files they are automatically changed.)
+
+
+
Index: llvm/test/Programs/MultiSource/Applications/obsequi/consts.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/consts.h:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/consts.h Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,48 ----
+
+
+ //########################################################
+ // Constants which we use.
+ // Any constants which we commonly change or try to tweak
+ // should be in cppflags.raw.
+ //########################################################
+
+ // max number of empty squares which should ever exist is 256
+ // therefore we could possible get close to this number of moves.
+ #define MAXMOVES 256
+
+ // Player stuff. (Used for example with g_board to get the current player).
+ #define HORIZONTAL 0
+ #define VERTICAL 1
+ #define PLAYER_MASK 1
+
+ // Used with g_board_size (to get num of rows and num of cols).
+ #define ROW_INDEX HORIZONTAL
+ #define COL_INDEX VERTICAL
+
+
+ #define LOWER 0
+ #define EXACT 1
+ #define UPPER 2
+
+
+ // blah
+ #define ERASE_NEXT_BIT 0x80000000;
+ #define NEXT_BIT 0x00010000;
+
+ //########################################################
+ // Constants used in conjuction with the transposition table
+ // and the zobrist values.
+ //########################################################
+
+ // HASHCODEBITS should already be defined.
+ #ifndef HASHCODEBITS
+ #error "HASHCODEBITS must be defined.\n"
+ #endif
+
+ // It should have a value of between 0 and 31.
+ #if ! (HASHCODEBITS > 0 && HASHCODEBITS < 31)
+ #error "Invalid value for HASHCODEBITS, it should be a value from 1 - 30."
+ #endif
+
+ #define HASHSIZE (1 << HASHCODEBITS)
+ #define HASHMASK (HASHSIZE - 1)
Index: llvm/test/Programs/MultiSource/Applications/obsequi/cppflags.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/cppflags.h:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/cppflags.h Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,10 ----
+ // This file is automatically generated from CPPFLAGS_raw
+
+ char option_string[] =
+ "-Wall -O2\n"
+ "-DCOUNTBITS16\n"
+ "-DLASTBIT16\n"
+ "-DCOUNTMOVES_TABLE\n"
+ "-DHASHCODEBITS=23\n"
+ "-DTWO_STAGE_GENERATION\n"
+ ;
Index: llvm/test/Programs/MultiSource/Applications/obsequi/display.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/display.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/display.c Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,333 ----
+
+
+ #include "globals.h"
+
+
+ //########################################################
+ // Sanity check functions.
+ // These functions try to do a quick check of some set of
+ // information. They crash and burn if the check fails.
+ //########################################################
+
+ static void
+ check_hashkey_bit_set(Hash_Key key, s32bit index)
+ {
+ if(! (key.key[index/32] & NTH_BIT(index%32)) ){
+
+ printf("%d", index);
+
+ print_bitboard(HORIZONTAL);
+
+ print_hashkey(key);
+
+ fatal_error(1, "HashKey Incorrect.\n");
+ }
+ }
+
+ static void
+ check_hashkey_bit_not_set(Hash_Key key, s32bit index)
+ {
+ if( (key.key[index/32] & NTH_BIT(index%32)) ){
+
+ printf("%d", index);
+
+ print_bitboard(HORIZONTAL);
+
+ print_hashkey(key);
+
+ fatal_error(1, "HashKey Incorrect.\n");
+ }
+ }
+
+ static void
+ check_hashkey_code(Hash_Key key)
+ {
+ s32bit i, j, index, n_rows, n_cols, code;
+
+ n_rows = g_board_size[HORIZONTAL], n_cols = g_board_size[VERTICAL];
+
+ code = key.code;
+
+ for(i = 0; i < n_rows; i++)
+ for(j = 0; j < n_cols; j++){
+ index = (i*n_cols) + j;
+ if(key.key[index/32] & NTH_BIT(index%32))
+ code ^= g_zobrist[i+1][j+1];
+ }
+
+ if(code != 0){
+ fatal_error(1, "Invalid hash code.\n");
+ }
+ }
+
+
+
+ //========================================================
+ // This function checks to make sure hash codes
+ // and keys are correct.
+ //========================================================
+ extern void
+ check_hash_code_sanity()
+ {
+ s32bit i, j, index, n_rows, n_cols;
+
+ n_rows = g_board_size[HORIZONTAL], n_cols = g_board_size[VERTICAL];
+
+ for(i = 0; i < n_rows; i++)
+ for(j = 0; j < n_cols; j++)
+ if(g_board[HORIZONTAL][i+1] & NTH_BIT(j+1)) {
+
+ index = (i*n_cols)+j;
+ check_hashkey_bit_set(g_norm_hashkey, index);
+
+ index = (i*n_cols) + (n_cols - j - 1);
+ check_hashkey_bit_set(g_flipV_hashkey, index);
+
+ index = ( (n_rows - i - 1) *n_cols) + j;
+ check_hashkey_bit_set(g_flipH_hashkey, index);
+
+ index = ( (n_rows - i - 1) *n_cols) + (n_cols - j - 1);
+ check_hashkey_bit_set(g_flipVH_hashkey, index);
+ } else {
+ index = (i*n_cols)+j;
+ check_hashkey_bit_not_set(g_norm_hashkey, index);
+
+ index = (i*n_cols) + (n_cols - j - 1);
+ check_hashkey_bit_not_set(g_flipV_hashkey, index);
+
+ index = ( (n_rows - i - 1) *n_cols) + j;
+ check_hashkey_bit_not_set(g_flipH_hashkey, index);
+
+ index = ( (n_rows - i - 1) *n_cols) + (n_cols - j - 1);
+ check_hashkey_bit_not_set(g_flipVH_hashkey, index);
+ }
+
+ check_hashkey_code(g_norm_hashkey);
+ check_hashkey_code(g_flipV_hashkey);
+ check_hashkey_code(g_flipH_hashkey);
+ check_hashkey_code(g_flipVH_hashkey);
+ }
+
+
+
+ //========================================================
+ // This function compares the Horizontal board info to
+ // the vertical board info.
+ //========================================================
+ extern void
+ check_board_sanity()
+ {
+ s32bit i, j;
+ s32bit count;
+
+ for(j = 0; j < g_board_size[HORIZONTAL] + 2; j++)
+ for(i = 0; i < g_board_size[VERTICAL] + 2; i++){
+ count = 0;
+
+ if(g_board[VERTICAL][i] & NTH_BIT(j)) count++;
+ if(g_board[HORIZONTAL][j] & NTH_BIT(i)) count++;
+
+ if(count == 1){
+ print_board(VERTICAL);
+ print_board(HORIZONTAL);
+
+ printf("%d %d - %d.\n", j, i, count);
+
+ fatal_error(1, "Board is inconsistent.\n");
+ }
+ }
+ }
+
+ //========================================================
+ // Check the board info which we have to make sure that it
+ // is accurate.
+ //========================================================
+ /*
+ extern void
+ check_info_sanity()
+ {
+ }*/
+
+
+
+ //########################################################
+ // Display functions.
+ // These functions print out some set of information in what
+ // is hopefully a fairly readable format.
+ //########################################################
+ extern void
+ print_hashentry(s32bit index)
+ {
+ Hash_Entry entry = g_trans_table[index];
+
+ printf("Hash entry: %d.\n", index);
+ printf(" Key:%8X:%8X:%8X:%8X, n:%u, d:%d, w:%d"
+ ", v:%d, t:%d, int:%d.\n",
+ entry.key[0], entry.key[1], entry.key[2], entry.key[3],
+ entry.nodes, entry.depth, entry.whos_turn,
+ entry.value, entry.type, entry.best_move);
+ }
+
+
+ extern void
+ print_board(s32bit player)
+ {
+ s32bit player_index;
+ s32bit row, col, i, j;
+
+ player_index = player&PLAYER_MASK;
+
+ row = g_board_size[player_index];
+ col = g_board_size[player_index^PLAYER_MASK];
+
+ for(i = 0; i < row; i++){
+ for(j = 0; j < col; j++){
+ if(g_board[player_index][i+1] & NTH_BIT(j+1))
+ printf(" #");
+ else
+ printf(" 0");
+ }
+ printf("\n");
+ }
+ }
+
+ extern void
+ print_board_info(s32bit player)
+ {
+ s32bit num_rows, num_cols, max_dim, i;
+ char str[32][80], null_str[1] = "";
+
+ num_rows = g_board_size[HORIZONTAL];
+ num_cols = g_board_size[VERTICAL];
+ max_dim = MAX_TWO(num_rows, num_cols);
+
+ sprintf(str[1], "Number of rows = %d", g_board_size[HORIZONTAL]);
+ sprintf(str[2], "Number of columns = %d", g_board_size[VERTICAL]);
+
+ printf("%7s %15s %15s\n",
+ null_str, "Vertical", "Horizontal");
+ printf("%7s %7s %7s %7s %7s\n",
+ null_str, "Real", "Safe", "Real", "Safe");
+
+ for(i = 0; i < max_dim; i++){
+ printf("%6d) %7d %7d %7d %7d %s\n", i + 1,
+ g_info[VERTICAL][i+1].real, g_info[VERTICAL][i+1].safe,
+ g_info[HORIZONTAL][i+1].real, g_info[HORIZONTAL][i+1].safe,
+ (i < 2) ? str[i+1] : null_str);
+ }
+
+ printf("Totals: %7d %7d %7d %7d\n",
+ g_info_totals[VERTICAL].real, g_info_totals[VERTICAL].safe,
+ g_info_totals[HORIZONTAL].real, g_info_totals[HORIZONTAL].safe);
+ }
+
+ extern void
+ print_bitboard(s32bit player)
+ {
+ s32bit player_index;
+ s32bit i;
+
+ player_index = player&PLAYER_MASK;
+
+ for(i = 0; i < g_board_size[player_index] + 2; i++)
+ printf("%X\n", g_board[player_index][i]);
+ }
+
+ extern void
+ print_hashkey(Hash_Key key)
+ {
+ printf("Key: %8X:%8X:%8X:%8X, Code: %8X.\n",
+ key.key[0], key.key[1], key.key[2], key.key[3], key.code);
+ }
+
+ extern void
+ print_u64bit(u64bit val)
+ {
+ s32bit vals[10];
+ s32bit i = 0;
+
+ do {
+ vals[i] = val % 1000;
+ val = val / 1000;
+ i++;
+ } while(val != 0);
+
+ if(i > 10) fatal_error(1, "Too large???\n");
+
+ printf("%d", vals[--i]);
+
+ while(i != 0)
+ printf(",%3d", vals[--i]);
+ }
+
+ extern void
+ print_keyinfo(KeyInfo_s info, s32bit with)
+ {
+ if(info.bit1_index == -1) fatal_error(1, "bit1_index equal to -1");
+
+ if(with)
+ printf("%3d:%3d %8X ",
+ info.bit1_index, info.bit2_index, info.hash_code);
+ else
+ printf("%3d:%3d ",
+ info.bit1_index, info.bit2_index);
+ }
+
+
+ extern void
+ print_keyinfo_table(s32bit player, s32bit with_hashcode)
+ {
+ s32bit r, c;
+
+ for(r = 0; r < 32; r++)
+ for(c = 0; c < 32; c++){
+ if(g_keyinfo[player][r][c].norm.bit1_index != -1){
+
+ printf("(%2d,%2d)>> ", r, c);
+
+ print_keyinfo(g_keyinfo[player][r][c].norm, with_hashcode);
+ print_keyinfo(g_keyinfo[player][r][c].flipV, with_hashcode);
+ print_keyinfo(g_keyinfo[player][r][c].flipH, with_hashcode);
+ print_keyinfo(g_keyinfo[player][r][c].flipVH, with_hashcode);
+ putchar('\n');
+ }
+ }
+ }
+
+
+ extern void
+ print_external()
+ {
+ // print_keyinfo_table(HORIZONTAL, 1);
+ print_keyinfo_table(VERTICAL, 1);
+ }
+
+ extern s32bit g_print;
+
+ extern void
+ print_current_state()
+ {
+ print_board(HORIZONTAL);
+ printf("\n");
+ print_board_info(HORIZONTAL);
+ g_print = 0;
+ }
+
+
+ extern const char*
+ current_search_state()
+ {
+ static char* str = NULL;
+
+ g_print = 1;
+
+ if(str != NULL) free(str);
+
+ asprintf(&str, "Nodes: %s.\n%d %d %d %d %d %d %d %d %d.",
+ u64bit_to_string(g_num_nodes),
+ g_move_number[1], g_move_number[2], g_move_number[3],
+ g_move_number[4], g_move_number[5], g_move_number[6],
+ g_move_number[7], g_move_number[8], g_move_number[9]);
+
+ return str;
+ }
Index: llvm/test/Programs/MultiSource/Applications/obsequi/does_x_win.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/does_x_win.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/does_x_win.c Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,641 ----
+
+ #include "globals.h"
+
+ #define PRINT_DOES_X_WIN_INFO
+
+ // If defined we just immediately return from each function with
+ // a value of -1. (In other words no winner yet.)
+ //#define NOTHING
+
+ // If defined don't pack any protected moves onto the board.
+ //#define NO_PROT
+
+ // If defined pretend all (unpacked) squares are available to opponent.
+ //#define NO_UNUSED
+
+ // If defined pretend we didn't find any vulnerable moves with a prot square.
+ //#define NO_VULN_W_PROT
+
+ // If defined pretend we didn't find any vulnerable moves with a prot square.
+ //#define NO_VULN_TYPE_1
+
+ // If defined pretend there were no vulnerable moves (note this also
+ // means NO_VULN_W_PROT).
+ //#define NO_VULN
+
+ // If defined don't look for safe options.
+ //#define NO_SAFE_OPT
+
+ //#################################################################
+ // This function tries to pack as many 'protective' areas onto
+ // the board as it can. (no guarantee of optimality).
+ //#################################################################
+ static inline void
+ pack_prot(u32bit tmp_board[32], s32bit player, s32bit *prot)
+ {
+ s32bit r = 0, p = 0; //row, and number of prot. areas we have placed.
+
+ u32bit tmp, inter, walls;
+
+ for(r = 0; r < g_board_size[player]; r++){
+ // set bit at each position where there is interference.
+ inter = (tmp_board[r] | tmp_board[r+1] | tmp_board[r+2] | tmp_board[r+3]
+ | g_board[player][r+1] | g_board[player][r+2]);
+ inter = (inter >> 1) | inter;
+
+ // set bit at each position which there is a wall.
+ walls = ( ((g_board[player][r] >> 1) & g_board[player][r])
+ | ((g_board[player][r+3] >> 1) & g_board[player][r+3]) );
+
+ // combine (bit set at each position which we can place a prot. area).
+ inter = walls & ~inter;
+
+ // process the positions.
+ while(inter){
+ tmp = (inter & -inter); // least sig bit of m
+ inter &= ~(tmp | (tmp << 1)); // remove bit and next bit.
+
+ tmp_board[r+1] |= tmp | (tmp << 1); //record where we put
+ tmp_board[r+2] |= tmp | (tmp << 1); // the protective square.
+
+ p++; // count it.
+ }
+ }
+
+ *prot = p;
+ }
+
+
+ //#################################################################
+ // This function tries to pack as many 'vuln. type 1 and 2' areas
+ // onto the board as it can. (no guarantee of optimality).
+ // It also counts the number of unused squares.
+ //#################################################################
+ static void
+ pack_vuln(u32bit tmp_board[32], s32bit player,
+ s32bit *vuln2, s32bit *vuln2_w_prot,
+ s32bit *vuln1, s32bit *vuln1_w_prot,
+ s32bit *unused) //, s32bit print)
+ {
+ u32bit curr_row, adj_rows, next_prev_row;
+ u32bit tmp = 0, tmp_;
+
+ s32bit v2 = 0, v2_p = 0, v1 = 0, v1_p = 0, u = 0;
+
+ s32bit r, state;
+ u32bit s_v = 0; //start of vulnerable
+
+ for(r = 0; r < g_board_size[player]; r++){
+ next_prev_row = tmp_board[r];
+ next_prev_row |= ~(g_board[player][r+2] | (g_board[player][r+2] << 1));
+ next_prev_row |= ~(g_board[player][r+2] | (g_board[player][r+2] >> 1));
+
+ curr_row = ~(g_board[player][r+1] | tmp_board[r+1]);
+ adj_rows = g_board[player][r] & g_board[player][r+2];
+ state = 0;
+
+ //========================================================
+ // Three types of squares, prot, empty, occ.
+ //
+ // state = 0
+ // if(prot) -> state = 1
+ // if(empty) -> state = 2, c_t = c,
+ // if(occ) -> state = 0
+ //
+ // state = 1
+ // if(prot) -> state = 0, safe++
+ // if(empty) -> state = 0, v_p++, mark(c-1)
+ // if(occ) -> state = 0, unu++
+ //
+ // state = 2
+ // if(prot) -> state = 3,
+ // if(empty) -> state = 0, vuln++, mark(c_t)
+ // if(occ) -> state = 0,
+ //
+ // state = 3
+ // if(prot) -> state = 4, safe++
+ // if(empty) -> state = 2, v_p++, mark(c_t), c_t = c
+ // if(occ) -> state = 0, v_p++, mark(c_t)
+ //
+ // state = 4
+ // if(prot) -> state = 3
+ // if(empty) -> state = 2, c_t = c
+ // if(occ) -> state = 0
+ //========================================================
+
+ while(curr_row){
+ tmp_ = (curr_row & -curr_row); //get least sig bit of curr_row
+ curr_row ^= tmp_; //remove least sig bit of curr_row.
+
+ // if true then this iteration and last iteration are not contiguous.
+ // Which means there was an occupied square.
+ if ( ((tmp_ >> 1) & tmp) == 0 ) {
+ if(state == 1) {
+ u++;
+ tmp_board[r+1] |= tmp;
+ } else if(state == 3) {
+ tmp_board[r+1] |= (s_v | (s_v << 1));
+ if((s_v & next_prev_row) || ((s_v << 1) & next_prev_row))
+ v2_p++;
+ else
+ v1_p++;
+ }
+ state = 0;
+ }
+ tmp = tmp_;
+
+ // empty and protected
+ if( tmp & adj_rows ){
+ if(state == 0) {
+ state = 1;
+ } else if(state == 1) {
+ state = 0;
+ //safe
+ } else if(state == 2) {
+ state = 3;
+ } else if(state == 3) {
+ state = 4;
+ //safe
+ } else if(state == 4) {
+ state = 3;
+ }
+ }
+
+ // unprotected
+ else {
+ if(state == 0) {
+ state = 2;
+ s_v = tmp;
+ } else if(state == 1){
+ state = 0;
+
+ // Check tmp >> 1
+
+ tmp_board[r+1] |= (tmp | (tmp >> 1));
+ if((tmp & next_prev_row) || ((tmp >> 1) & next_prev_row))
+ v2_p++;
+ else
+ v1_p++;
+ } else if(state == 2){
+ state = 0;
+ tmp_board[r+1] |= (s_v | (s_v << 1));
+ if((s_v & next_prev_row) || ((s_v << 1) & next_prev_row))
+ v2++;
+ else
+ v1++;
+ } else if(state == 3){
+ state = 2;
+ tmp_board[r+1] |= (s_v | (s_v << 1));
+ if((s_v & next_prev_row) || ((s_v << 1) & next_prev_row))
+ v2_p++;
+ else
+ v1_p++;
+ s_v = tmp;
+ } else if(state == 4){
+ state = 2;
+ s_v = tmp;
+ }
+ }
+ }
+
+ if(state == 1) {
+ u++;
+ tmp_board[r+1] |= tmp;
+ } else if(state == 3) {
+ tmp_board[r+1] |= (s_v | (s_v << 1));
+ if((s_v & next_prev_row) || ((s_v << 1) & next_prev_row))
+ v2_p++;
+ else
+ v1_p++;
+ }
+
+ // if(print)
+ // printf("%d %d %d %d %d - %X\n", v2, v2_p, v1, v1_p, u,
+ // tmp_board[r+1]);
+
+ }
+ // if(print) printf("\n");
+
+ *vuln2 = v2 + v2_p;
+ *vuln2_w_prot = v2_p;
+ *vuln1 = v1 + v1_p;
+ *vuln1_w_prot = v1_p;
+ *unused = u;
+ }
+
+
+ //#################################################################
+ // This function tries to pack as many 'option of vulnerability' areas
+ // onto the board as it can. (no guarantee of optimality).
+ //#################################################################
+ static inline void
+ pack_safe(u32bit tmp_board[32], s32bit player,
+ s32bit *safe_op2, s32bit *safe_op1, s32bit *safe_op0)
+ {
+ u32bit guard, mask, curr, tmp;
+
+ s32bit r; //row
+ s32bit s2 = 0, s1 = 0, s0 = 0;
+
+ for(r = 0; r < g_board_size[player]; r++){
+ guard = g_board[player][r] & g_board[player][r+2];
+ curr = g_board[player][r+1] | tmp_board[r+1];
+
+ // mask contains a bit for each safe move.
+ mask = ( (~(curr | (curr >> 1))) & (guard & (guard >> 1)) );
+
+ while(mask){
+ tmp = (mask & -mask); // least sig bit of m
+ mask &= ~(tmp | (tmp << 1)); // remove bit and next bit.
+
+ // add these bits to current.
+ curr |= (tmp | (tmp << 1));
+
+ if( ! ( (curr | tmp_board[r] | tmp_board[r+2]) & (tmp >> 1) ) ){
+ // we have an option to move vulnerably. (which option is it).
+ curr |= (tmp >> 1);
+ tmp_board[r+1] |= (tmp >> 1);
+
+ // check up.
+ if( (!(g_board[player][r] & (tmp >> 1)))
+ && (g_board[player][r-1] & (tmp >> 1)) ){
+ // up is good now check down.
+ if( (!(g_board[player][r+2] & (tmp >> 1)))
+ && (g_board[player][r+3] & (tmp >> 1)) ){
+ s2++;
+ } else {
+ s1++;
+ }
+ } else if( (!(g_board[player][r+2] & (tmp >> 1)))
+ && (g_board[player][r+3] & (tmp >> 1)) ){
+ s1++;
+ } else {
+ s0++;
+ }
+ } else
+ if( ! ( (mask | curr | tmp_board[r] | tmp_board[r+2]) & (tmp << 2) ) ){
+ // we have an option to move vulnerably. (which option is it).
+ curr |= (tmp << 2);
+ tmp_board[r+1] |= (tmp << 2);
+
+ // check up.
+ if( (!(g_board[player][r] & (tmp << 2)))
+ && (g_board[player][r-1] & (tmp << 2)) ){
+ // up is good now check down.
+ if( (!(g_board[player][r+2] & (tmp << 2)))
+ && (g_board[player][r+3] & (tmp << 2)) ){
+ s2++;
+ } else {
+ s1++;
+ }
+ } else if( (!(g_board[player][r+2] & (tmp << 2)))
+ && (g_board[player][r+3] & (tmp << 2)) ){
+ s1++;
+ } else {
+ s0++;
+ }
+ }
+ }
+ // if(debug) printf("(%d,%d) ", s0, s1);
+ }
+ // if(debug) printf("\n");
+
+ *safe_op2 = s2;
+ *safe_op1 = s1;
+ *safe_op0 = s0;
+ }
+
+ //#################################################################
+ //
+ //#################################################################
+ extern s32bit
+ #ifdef PRINT_DOES_X_WIN_INFO
+ does_next_player_win(s32bit next_player, s32bit print)
+ #else
+ does_next_player_win(s32bit next_player)
+ #endif
+ {
+ // info we directly get from the board.
+ s32bit prot; // This is the number of protective regions.
+
+ s32bit vuln2; // Total number of vulnerable moves (includes vuln_w_prot).
+ // Num of vuln moves which contain a square unavailable to the opponent.
+ s32bit vuln2_w_prot;
+ s32bit vuln1; // Total number of vulnerable moves (includes vuln_w_prot).
+ // Num of vuln moves which contain a square unavailable to the opponent.
+ s32bit vuln1_w_prot;
+
+ s32bit safe; // Number of safe moves horizontal has.
+ // Number of squares unused in our packing and unavailable for opponent.
+ s32bit unused;
+ s32bit empty; // Number of empty squares on board.
+ s32bit safe_op2, safe_op1, safe_op0; //safe moves with options.
+
+ // value we return and other variables.
+ s32bit r_value = 0, i;
+
+ // temporary board to store which positions have already been packed.
+ u32bit tmp_board[32];
+
+ #ifdef NOTHING
+ return -1;
+ #endif
+
+ //========================================================
+ // Initialize all of the values.
+ //========================================================
+ for(i = 0; i < 32; i++) tmp_board[i] = 0;
+ safe = g_info_totals[next_player].safe;
+ empty = g_empty_squares;
+
+ // Determine the number of protective regions that we have.
+ #ifdef NO_PROT
+ prot = 0;
+ #else
+ pack_prot(tmp_board, next_player, &prot);
+ #endif
+
+ // Determine the number of vuln, vuln_w_prot, and unused.
+ pack_vuln(tmp_board, next_player, &vuln2, &vuln2_w_prot,
+ &vuln1, &vuln1_w_prot, &unused); //, print);
+
+ #ifdef NO_VULN_W_PROT
+ vuln1_w_prot = vuln2_w_prot = 0;
+ #endif
+
+ #ifdef NO_VULN_TYPE_1
+ vuln2 += vuln1;
+ vuln2_w_prot += vuln1_w_prot;
+ vuln1 = vuln1_w_prot = 0;
+ #endif
+
+ #ifdef NO_UNUSED
+ unused = 0;
+ #endif
+
+ #ifdef NO_VULN
+ vuln2 = vuln1 = vuln2_w_prot = vuln1_w_prot = 0;
+ #endif
+
+ // Determine the number of safe moves with options we have.
+ #ifdef NO_SAFE_OPT
+ safe_op2 = safe_op1 = safe_op0 = 0;
+ #else
+ pack_safe(tmp_board, next_player, &safe_op2, &safe_op1, &safe_op0);
+ #endif
+
+ #ifdef PRINT_DOES_X_WIN_INFO
+ if(print){
+ fprintf(stderr, "%d moves next, do they win?\n", next_player);
+ fprintf(stderr, "prot %d, vuln2 %d(%d), vuln1 %d(%d), "
+ "safe %d, unused %d, empty %d.\n",
+ prot, vuln2, vuln2_w_prot, vuln1, vuln1_w_prot,
+ safe, unused, empty);
+ fprintf(stderr, "safe_op2 %d, safe_op1 %d, safe_op0 %d.\n",
+ safe_op2, safe_op1, safe_op0);
+ }
+ #endif
+
+ {
+ s32bit moves, opp_moves, x = 0;
+
+ if(prot % 2 == 1){
+ prot--;
+ safe += 2;
+ } else if(vuln2 % 3 != 0){
+ vuln2--;
+ safe++;
+ if(vuln2_w_prot > vuln2) vuln2_w_prot--;
+ } else if(vuln1 % 2 != 0){
+ vuln1--;
+ safe++;
+ if(vuln1_w_prot > vuln1) vuln1_w_prot--;
+ } else if(safe_op2 % 2 != 0){
+ safe_op2--;
+ unused+=3;
+ } else if(safe_op1 % 2 != 0){
+ safe_op1--;
+ unused+=2;
+ } else if(safe_op0 % 2 != 0){
+ safe_op0--;
+ unused+=1;
+ } else if(vuln2 > 0){
+ vuln2--;
+ safe++;
+ if(vuln2_w_prot > vuln2) vuln2_w_prot--;
+ } else if(vuln1 > 0){
+ vuln1--;
+ safe++;
+ if(vuln1_w_prot > vuln1) vuln1_w_prot--;
+ } else if(prot > 0){
+ prot--;
+ safe += 2;
+ } else {
+ return -1;
+ }
+
+ if(prot % 2 == 1){
+ prot--;
+ vuln2 += 2;
+ }
+
+ moves = (prot) + (vuln2/3) + (vuln1/2) + safe;
+
+ if(vuln2 % 3 != 0 && vuln1 % 2 != 0){
+ moves++, unused--, x=1;
+ // if(vuln2 > 0 || vuln1 > 0) unused--;
+ } else if(vuln2 % 3 == 0 && vuln1 % 2 == 0) x=1;
+
+ if(x == 1){
+ if(safe_op2%2 == 1) safe_op2--, safe_op1++;
+ if(safe_op1%2 == 1) safe_op1--, safe_op0++;
+ } else {
+ if(safe_op2%2 == 1){
+ unused += 3;
+ if(safe_op1%2==1) safe_op1--, safe_op0++;
+ } else if(safe_op1%2 == 1) { unused += 2; }
+ else if(safe_op0%2 == 1) { unused += 1; }
+ }
+
+ unused += vuln2_w_prot - ( (vuln2)/3 - (vuln2-vuln2_w_prot)/3 );
+ unused += vuln1_w_prot - ( (vuln1)/2 - (vuln1-vuln1_w_prot)/2 );
+
+ unused += (safe_op2/2) * 3;
+ unused += (safe_op1/2) * 2;
+ unused += (safe_op0/2) * 1;
+
+ opp_moves = (empty - (moves*2) - unused)/2;
+
+ //========================================================
+ // If r_value > 0 then next_player wins.
+ //========================================================
+ r_value = moves - opp_moves;
+
+ #ifdef PRINT_DOES_X_WIN_INFO
+ if(print){
+ printf("moves:%d, opp:%d.\n", moves, opp_moves);
+ if(moves - opp_moves >= 0) printf("H WINS\n");
+ }
+ #endif
+ }
+
+ return r_value;
+ }
+
+
+ //#################################################################
+ //
+ //#################################################################
+ extern s32bit
+ #ifdef PRINT_DOES_X_WIN_INFO
+ does_who_just_moved_win(s32bit who_just_moved, s32bit print)
+ #else
+ does_who_just_moved_win(s32bit who_just_moved)
+ #endif
+ {
+ // info we directly get from the board.
+ s32bit prot; // This is the number of protective regions.
+
+ s32bit vuln2; // Total number of vulnerable moves (includes vuln_w_prot).
+ // Num of vuln moves which contain a square unavailable to the opponent.
+ s32bit vuln2_w_prot;
+ s32bit vuln1; // Total number of vulnerable moves (includes vuln_w_prot).
+ // Num of vuln moves which contain a square unavailable to the opponent.
+ s32bit vuln1_w_prot;
+
+ s32bit safe; // Number of safe moves horizontal has.
+ // Number of squares unused in our packing and unavailable for opponent.
+ s32bit unused;
+ s32bit empty; // Number of empty squares on board.
+ s32bit safe_op2, safe_op1, safe_op0; //safe moves with options.
+
+ // value we return and other variables.
+ s32bit r_value = 0, i;
+
+ // temporary board to store which positions have already been packed.
+ u32bit tmp_board[32];
+
+ #ifdef NOTHING
+ return -1;
+ #endif
+
+ //========================================================
+ // Initialize all of the values.
+ //========================================================
+ for(i = 0; i < 32; i++) tmp_board[i] = 0;
+ safe = g_info_totals[who_just_moved].safe;
+ empty = g_empty_squares;
+
+ // Determine the number of protective regions that we have.
+ #ifdef NO_PROT
+ prot = 0;
+ #else
+ pack_prot(tmp_board, who_just_moved, &prot);
+ #endif
+
+ // Determine the number of vuln, vuln_w_prot, and unused.
+ pack_vuln(tmp_board, who_just_moved, &vuln2, &vuln2_w_prot,
+ &vuln1, &vuln1_w_prot, &unused);
+
+ #ifdef NO_VULN_W_PROT
+ vuln1_w_prot = vuln2_w_prot = 0;
+ #endif
+
+ #ifdef NO_VULN_TYPE_1
+ vuln2 += vuln1;
+ vuln2_w_prot += vuln1_w_prot;
+ vuln1 = vuln1_w_prot = 0;
+ #endif
+
+ #ifdef NO_UNUSED
+ unused = 0;
+ #endif
+
+ #ifdef NO_VULN
+ vuln2 = vuln1 = vuln2_w_prot = vuln1_w_prot = 0;
+ #endif
+
+ // Determine the number of safe moves with options we have.
+ #ifdef NO_SAFE_OPT
+ safe_op2 = safe_op1 = safe_op0 = 0;
+ #else
+ pack_safe(tmp_board, who_just_moved, &safe_op2, &safe_op1, &safe_op0);
+ #endif
+
+ /*
+ if(prot % 2 == 1){
+ prot--;
+ vuln2 += 2;
+ }
+
+ if(print == 1 && unused > 0
+ && prot >= 2 // && (vuln2%3 != 0 || vuln1%2 != 0)
+ && vuln2 >= 3 && vuln1 >= 2
+ && safe_op1 + safe_op0 >= 2){
+ print_board(who_just_moved);
+ } else {
+ print = 0;
+ }
+ */
+ #ifdef PRINT_DOES_X_WIN_INFO
+ if(print){
+ fprintf(stderr, "%d just moved, do they win?\n", who_just_moved);
+ fprintf(stderr, "prot %d, vuln2 %d(%d), vuln1 %d(%d), "
+ "safe %d, unused %d, empty %d.\n",
+ prot, vuln2, vuln2_w_prot, vuln1, vuln1_w_prot,
+ safe, unused, empty);
+ fprintf(stderr, "safe_op2 %d, safe_op1 %d, safe_op0 %d.\n",
+ safe_op2, safe_op1, safe_op0);
+ }
+ #endif
+
+ {
+ s32bit moves, opp_moves, x = 0;
+
+ if(prot % 2 == 1){
+ prot--;
+ vuln2 += 2;
+ }
+
+ moves = (prot) + (vuln2/3) + (vuln1/2) + safe;
+
+ if(vuln2 % 3 != 0 && vuln1 % 2 != 0){
+ moves++, unused--, x=1;
+ // if(vuln2 > 0 || vuln1 > 0) unused--;
+ } else if(vuln2 % 3 == 0 && vuln1 % 2 == 0) x=1;
+
+ if(x == 1){
+ if(safe_op2%2 == 1) safe_op2--, safe_op1++;
+ if(safe_op1%2 == 1) safe_op1--, safe_op0++;
+ } else {
+ if(safe_op2%2 == 1){
+ unused += 3;
+ if(safe_op1%2==1) safe_op1--, safe_op0++;
+ } else if(safe_op1%2 == 1) { unused += 2; }
+ else if(safe_op0%2 == 1) { unused += 1; }
+ }
+
+ unused += vuln2_w_prot - ( (vuln2)/3 - (vuln2-vuln2_w_prot)/3 );
+ unused += vuln1_w_prot - ( (vuln1)/2 - (vuln1-vuln1_w_prot)/2 );
+
+ unused += (safe_op2/2) * 3;
+ unused += (safe_op1/2) * 2;
+ unused += (safe_op0/2) * 1;
+
+ opp_moves = (empty - (moves*2) - unused)/2;
+
+ //========================================================
+ // If r_value >= 0 then who_just_moved wins.
+ //========================================================
+ r_value = moves - opp_moves;
+
+ #ifdef PRINT_DOES_X_WIN_INFO
+ if(print){
+ printf("moves:%d, opp:%d.\n", moves, opp_moves);
+ if(moves - opp_moves >= 0) printf("H WINS\n");
+ }
+ #endif
+ }
+
+ return r_value;
+ }
Index: llvm/test/Programs/MultiSource/Applications/obsequi/globals.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/globals.h:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/globals.h Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,224 ----
+
+ #ifndef GLOBALS_H
+ #define GLOBALS_H
+
+ #include "utils.h"
+
+ #include "interface.h"
+
+ #include "structs.h"
+ #include "consts.h"
+
+
+ //########################################################
+ // Function prototypes.
+ //########################################################
+
+ //========================================================
+ // Generate a list of moves that 'player'
+ // can make in the given position. (excluding safe moves).
+ //
+ // The moves are places in the movelist array.
+ // Returns the number of moves that were placed in movelist.
+ //========================================================
+ s32bit move_generator (Move movelist[MAXMOVES], s32bit player);
+
+ s32bit move_generator_stage1 (Move movelist[MAXMOVES], s32bit player);
+
+ s32bit move_generator_stage2 (Move movelist[MAXMOVES],
+ s32bit start, s32bit player);
+
+ //=================================================================
+ // Move ordering uses a simple evaluation function as well as
+ // a value associated with each position.
+ // The first two function set these values in a dynamic way.
+ // The 'set_position_values' function does it statically.
+ //=================================================================
+ #ifdef DYNAMIC_POSITION_VALUES
+ void init_move_value ();
+ s32bit set_move_value (Move movelist, s32bit player);
+ void unset_move_value (Move movelist, s32bit player);
+ #else
+ void set_position_values ();
+ #endif
+
+ //========================================================
+ // Toggle a move, if a move hasn't been played then play it, if
+ // it has then undo it.
+ //========================================================
+ void toggle_move (Move move, s32bit player);
+
+ //========================================================
+ // Give score of move relative to current position.
+ //========================================================
+ //s32bit score_move(Move move, s32bit player);
+ void
+ score_and_get_first(Move movelist[MAXMOVES], s32bit num_moves,
+ s32bit player, Move first);
+
+ //========================================================
+ // Use the value of movelist[i].info to sort the moves in
+ // descending order.
+ //========================================================
+ void sort_moves(Move movelist[MAXMOVES], s32bit start, s32bit num_moves);
+
+
+ void
+ update_safe(s32bit player, s32bit row);
+
+ void
+ update_real(s32bit player, s32bit row);
+
+
+ void init_less_static_tables();
+
+
+ void init_static_tables();
+
+
+
+ // make the bitboard consistent with the info past into this function.
+ void init__board(s32bit num_rows, s32bit num_cols, s32bit board[30][30]);
+
+ void initialize_tables();
+
+
+
+ //########################################################
+ // Functions for interacting with the hashtable.
+ //========================================================
+ // Store the current search value into the hashtable if there
+ // is a position available.
+ //========================================================
+ void hashstore (s32bit value, s32bit alpha, s32bit beta,
+ u32bit nodes, s32bit depth_remaining,
+ Move best, s32bit player);
+
+
+ //========================================================
+ // Check the hashtable to see if we have already seen the current
+ // position before.
+ //========================================================
+ s32bit hashlookup (s32bit *value, s32bit *alpha, s32bit *beta,
+ s32bit depth_remaining,
+ Move *force_first, s32bit player);
+
+
+ //########################################################
+ // Functions for information display or sanity checks.
+ //========================================================
+ // Functions which varify pieces of information.
+ //========================================================
+ void check_board();
+ void check_board_info();
+
+ void check_hash_code_sanity();
+
+
+ //========================================================
+ // Functions which print various pieces of information in a
+ // readable format.
+ //========================================================
+ void print_board(s32bit player);
+ void print_board_info();
+ void print_bitboard(s32bit player);
+ void print_hashkey(Hash_Key key);
+ void print_u64bit(u64bit val);
+ void print_hashentry(s32bit index);
+
+
+
+ //########################################################
+ // Global variables.
+ //########################################################
+
+ extern u64bit g_num_nodes;
+
+
+ // two bitboard arrays [0] is horizontals, [1] is verticals.
+ extern u32bit g_board[2][32];
+
+ // number of rows and cols in the board.
+ // [0] is the num of rows, [1] is the num of cols.
+ extern s32bit g_board_size[2];
+
+ // keep track of simple info such as real and safe moves.
+ extern Basic_Info g_info[2][32];
+ extern Basic_Info g_info_totals[2];
+ extern s32bit g_empty_squares;
+
+ // zobrist value for each position on the board.
+ extern s32bit g_zobrist[32][32];
+
+ // Transposition table.
+ extern Hash_Entry *g_trans_table;
+
+ // Current boards hash key and code (flipped in various ways).
+ extern Hash_Key g_norm_hashkey;
+ extern Hash_Key g_flipV_hashkey;
+ extern Hash_Key g_flipH_hashkey;
+ extern Hash_Key g_flipVH_hashkey;
+
+ extern s32bit g_first_move[2][32][32];
+
+ extern s32bit g_move_number[128];
+
+
+
+ //########################################################
+ // Tables of precalculated information.
+ //
+ // Calling initialize_board should initialize the information in
+ // all these tables.
+ //########################################################
+
+
+ //========================================================
+ // Declare the table we use for updating our hashkey after each move.
+ //========================================================
+ extern KeyInfo g_keyinfo[2][32][32];
+
+
+ //========================================================
+ // Declare the table we use in countmoves.
+ //========================================================
+ #ifdef COUNTMOVES_TABLE
+ extern s32bit move_table16[65536];
+ #endif
+
+
+ //========================================================
+ // Declare the table we use in countbits32.
+ //========================================================
+ #if defined COUNTBITS16
+ extern s32bit countbits16[65536];
+
+ #if defined COUNTBITS8
+ #error "Both COUNTBITS8 and COUNTBITS16 are defined."
+ #endif
+
+ #elif defined COUNTBITS8
+ extern s32bit countbits8[256];
+ #else
+ #error "Neither COUNTBITS8 or COUNTBITS16 are defined."
+ #endif
+
+
+ //========================================================
+ // Declare the table we use in lastbit32.
+ //========================================================
+ #if defined LASTBIT16
+ extern s32bit lastbit16[65536];
+
+ #if defined LASTBIT8
+ #error "Both LASTBIT8 and LASTBIT16 are defined."
+ #endif
+
+ #elif defined LASTBIT8
+ extern s32bit lastbit8[256];
+ #else
+ #error "Neither LASTBIT8 and LASTBIT16 are defined."
+ #endif
+
+
+ #endif //ifndef GLOBALS_H
Index: llvm/test/Programs/MultiSource/Applications/obsequi/hash.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/hash.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/hash.c Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,109 ----
+
+ #include "globals.h"
+
+ #define MOVE_TO_INT(mv, player) \
+ ((mv).mask_index-1)*g_board_size[(player)]+((mv).array_index-1)
+
+ #define TABLE_SET_KEY(table,index,k) \
+ table[index].key[0] = k[0], table[index].key[1] = k[1], \
+ table[index].key[2] = k[2], table[index].key[3] = k[3];
+
+ #define TABLE_CMP_KEY(table,index,k) \
+ (table[index].key[0] == k[0] && table[index].key[1] == k[1] && \
+ table[index].key[2] == k[2] && table[index].key[3] == k[3])
+
+
+ #define STORE_ENTRY(x) \
+ index = (x).code; \
+ \
+ if(TABLE_CMP_KEY(g_trans_table, index, (x).key) \
+ || g_trans_table[index].nodes <= nodes){ \
+ TABLE_SET_KEY(g_trans_table, index, (x).key); \
+ g_trans_table[index].nodes =nodes; \
+ g_trans_table[index].best_move =MOVE_TO_INT(best,player); \
+ g_trans_table[index].depth =depth; \
+ g_trans_table[index].whos_turn =player; \
+ g_trans_table[index].value =value; \
+ if (value>=beta) g_trans_table[index].type =LOWER; \
+ else if(value>alpha) g_trans_table[index].type =EXACT; \
+ else g_trans_table[index].type =UPPER; \
+ return; \
+ }
+
+
+ extern void
+ hashstore(s32bit value, s32bit alpha, s32bit beta,
+ u32bit nodes, s32bit depth, Move best, s32bit player)
+ {
+ s32bit index;
+
+ STORE_ENTRY(g_norm_hashkey);
+ STORE_ENTRY(g_flipV_hashkey);
+ STORE_ENTRY(g_flipH_hashkey);
+ STORE_ENTRY(g_flipVH_hashkey);
+ }
+
+
+ #define INT_TO_MOVE(mv, int, player) \
+ (mv).mask_index = ((int)/g_board_size[(player)])+1; \
+ (mv).array_index = ((int)%g_board_size[(player)])+1
+
+ #define LOOKUP_ENTRY(x) \
+ index = (x).code; \
+ if(TABLE_CMP_KEY(g_trans_table, index, (x).key) \
+ && g_trans_table[index].whos_turn == player ) { \
+ /* found matching entry.*/ \
+ \
+ /* If nothing else we can use this entry to give us a good move. */ \
+ INT_TO_MOVE(*force_first, g_trans_table[index].best_move, player); \
+ \
+ /* use value if depth >= than the depth remaining in our search. */ \
+ if(g_trans_table[index].depth >= depth_remaining) { \
+ \
+ /* if the value is exact we can use it. */ \
+ if(g_trans_table[index].type == EXACT) { \
+ *value=g_trans_table[index].value; \
+ return 1; \
+ } \
+ \
+ /* if value is a lower bound we can possibly use it. */ \
+ if(g_trans_table[index].type == LOWER) { \
+ if(g_trans_table[index].value>=(*beta)){ \
+ *value=g_trans_table[index].value; \
+ return 1; \
+ } \
+ if(g_trans_table[index].value>(*alpha)){ \
+ *alpha=g_trans_table[index].value; \
+ } \
+ return 0; \
+ } \
+ \
+ /* if value is a upper bound we can possibly use it. */ \
+ if(g_trans_table[index].type == UPPER) { \
+ if(g_trans_table[index].value<=(*alpha)){ \
+ *value=g_trans_table[index].value; \
+ return 1; \
+ } \
+ if(g_trans_table[index].value<(*beta)){ \
+ *beta=g_trans_table[index].value; \
+ } \
+ return 0; \
+ } \
+ } \
+ }
+
+
+
+ extern s32bit
+ hashlookup(s32bit *value, s32bit *alpha, s32bit *beta,
+ s32bit depth_remaining, Move *force_first, s32bit player)
+ {
+ s32bit index;
+
+ LOOKUP_ENTRY(g_norm_hashkey);
+ LOOKUP_ENTRY(g_flipV_hashkey);
+ LOOKUP_ENTRY(g_flipH_hashkey);
+ LOOKUP_ENTRY(g_flipVH_hashkey);
+
+ return 0;
+ }
Index: llvm/test/Programs/MultiSource/Applications/obsequi/init.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/init.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/init.c Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,172 ----
+
+ #include "globals.h"
+
+
+ u32bit g_board[2][32];
+ s32bit g_board_size[2] = {-1,-1};
+
+ Basic_Info g_info[2][32];
+ Basic_Info g_info_totals[2];
+
+ // zobrist value for each position on the board.
+ s32bit g_zobrist[32][32];
+
+ // Transposition table.
+ Hash_Entry *g_trans_table = 0;
+
+ // Current boards hash key and code (flipped in various ways).
+ Hash_Key norm_hashkey;
+ Hash_Key flipV_hashkey;
+ Hash_Key flipH_hashkey;
+ Hash_Key flipVH_hashkey;
+
+
+ extern void
+ init__safe_count(s32bit player)
+ {
+ s32bit i;
+
+ g_info_totals[player].safe = 0;
+
+ for(i = 0; i < g_board_size[player]; i++){
+ g_info[player][i+1].safe = 0;
+
+ update_safe(player, i+1);
+ }
+ }
+
+ extern void
+ init__real_count(s32bit player)
+ {
+ s32bit i;
+
+ g_info_totals[player].real = 0;
+
+ for(i = 0; i < g_board_size[player]; i++){
+ g_info[player][i+1].real = 0;
+
+ update_real(player, i+1);
+ }
+ }
+
+ extern void
+ initialize_solver()
+ {
+ s32bit i, j;
+
+ if(g_trans_table == NULL){
+
+ // first time initialization stuff.
+ g_trans_table = malloc(HASHSIZE*sizeof(Hash_Entry));
+
+ // initialize zobrist values
+ srandom(1);
+ for(i=1; i<31; i++) {
+ for(j=1; j<31; j++) {
+ g_zobrist[i][j] = random() & HASHMASK;
+ }
+ }
+
+ init_static_tables();
+ }
+
+ init_less_static_tables();
+ }
+
+
+
+ static void
+ init_hashkey_code(Hash_Key* key)
+ {
+ s32bit i, j, index, n_rows, n_cols;
+
+ n_rows = g_board_size[HORIZONTAL], n_cols = g_board_size[VERTICAL];
+
+ key->code = 0;
+
+ for(i = 0; i < n_rows; i++)
+ for(j = 0; j < n_cols; j++){
+ index = (i*n_cols) + j;
+ if(key->key[index/32] & NTH_BIT(index%32))
+ key->code ^= g_zobrist[i+1][j+1];
+ }
+ }
+
+ extern void
+ initialize_board(s32bit num_rows, s32bit num_cols, s32bit board[30][30])
+ {
+ s32bit i, j;
+ s32bit init = 0;
+
+ if(num_rows > 30 || num_rows < 1 || num_cols > 30 || num_cols < 1)
+ fatal_error(1, "Invalid board size %dX%d.\n", num_rows, num_cols);
+
+ if(num_rows * num_cols >= 128)
+ fatal_error(1, "Invalid board size %dX%d.\n", num_rows, num_cols);
+
+ // Check if we need to re-initialize the solver.
+ if(g_trans_table == NULL || g_board_size[HORIZONTAL] != num_rows
+ || g_board_size[VERTICAL] != num_cols) init = 1;
+
+ g_board_size[HORIZONTAL] = num_rows;
+ g_board_size[VERTICAL] = num_cols;
+
+ if(init) initialize_solver();
+
+ // Fill all positions on the board.
+ for(i = 0; i < 32; i++){
+ g_board[0][i] = ALL_BITS;
+ g_board[1][i] = ALL_BITS;
+ }
+
+ // Clear positions where there isn't a piece.
+ for(i = 0; i < num_rows; i++)
+ for(j = 0; j < num_cols; j++)
+ if(board[i][j] == 0){
+ g_board[HORIZONTAL][i+1] &= ~(NTH_BIT(j+1));
+ g_board[VERTICAL][j+1] &= ~(NTH_BIT(i+1));
+ }
+
+ init__real_count(VERTICAL);
+ init__real_count(HORIZONTAL);
+
+ init__safe_count(VERTICAL);
+ init__safe_count(HORIZONTAL);
+
+ for(i = 0; i < 4; i++){
+ g_norm_hashkey.key[i] = 0;
+ g_flipV_hashkey.key[i] = 0;
+ g_flipH_hashkey.key[i] = 0;
+ g_flipVH_hashkey.key[i] = 0;
+ }
+
+ // Modify hashkeys to deal with positions which are already occupied.
+ for(i = 0; i < num_rows; i++)
+ for(j = 0; j < num_cols; j++)
+ if(board[i][j] != 0){
+ s32bit index;
+
+ index = (i*num_cols)+j;
+ g_norm_hashkey.key[index/32] |= NTH_BIT(index%32);
+
+ index = (i*num_cols) + (num_cols - j - 1);
+ g_flipV_hashkey.key[index/32] |= NTH_BIT(index%32);
+
+ index = ( (num_rows - i - 1) *num_cols) + j;
+ g_flipH_hashkey.key[index/32] |= NTH_BIT(index%32);
+
+ index = ( (num_rows - i - 1) *num_cols) + (num_cols - j - 1);
+ g_flipVH_hashkey.key[index/32] |= NTH_BIT(index%32);
+ }
+
+ init_hashkey_code(&g_norm_hashkey);
+ init_hashkey_code(&g_flipV_hashkey);
+ init_hashkey_code(&g_flipH_hashkey);
+ init_hashkey_code(&g_flipVH_hashkey);
+
+ print_board(HORIZONTAL);
+ printf("\n");
+ print_board_info(HORIZONTAL);
+
+ check_hash_code_sanity();
+ }
Index: llvm/test/Programs/MultiSource/Applications/obsequi/interface.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/interface.h:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/interface.h Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,45 ----
+
+ #ifndef OBSEQUI_INTERFACE_H
+ #define OBSEQUI_INTERFACE_H
+
+ //########################################################
+ //
+ //########################################################
+ void print_external();
+
+ //########################################################
+ // This function initializes the solver.
+ //
+ // This includes things like allocating and zeroing data
+ // for the hashtable.
+ //
+ // If it is called a second time it will re-zero all the
+ // data, (restart from scratch).
+ //########################################################
+ void initialize_solver ();
+
+
+ //########################################################
+ // This function gives the solver the current board that
+ // we want to work with.
+ //########################################################
+ void initialize_board (s32bit row, s32bit col,
+ s32bit board[30][30]);
+
+
+ //########################################################
+ // This function tries to find the best move for 'player'.
+ //
+ // - player is either 'V' or 'H'.
+ //########################################################
+ s32bit search_for_move (char player,
+ s32bit *row, s32bit *col, u64bit *nodes);
+
+
+ //########################################################
+ // This function returns a string about the current
+ // state of the search.
+ //########################################################
+ const char* current_search_state();
+
+ #endif
Index: llvm/test/Programs/MultiSource/Applications/obsequi/macros.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/macros.h:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/macros.h Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,138 ----
+
+
+ #ifndef MACROS_H
+ #define MACROS_H
+
+ #include "globals.h"
+
+
+ //########################################################
+ // We use tables to count how many bits are set in a bitmask.
+ //########################################################
+ #ifdef COUNTBITS8
+ #define countbits32(x) (countbits8[x&0x000000FF] \
+ +countbits8[(x>>8)&0x000000FF]\
+ +countbits8[(x>>16)&0x000000FF]\
+ +countbits8[(x>>24)&0x000000FF])
+ #endif
+
+ #ifdef COUNTBITS16
+ #define countbits32(x) (countbits16[x&0x0000FFFF] \
+ +countbits16[(x>>16)&0x0000FFFF])
+ #endif
+
+
+ //########################################################
+ // Assume we have a mask with only one bit set -
+ // we use tables to determine the index of this bit.
+ //########################################################
+ static inline u32bit
+ lastbit32(u32bit x)
+ {
+ #ifdef LASTBIT8
+ /* returns the position of the last bit in x */
+ if(x&0x000000FF)
+ return(lastbit8[x&0x000000FF]);
+ if(x&0x0000FF00)
+ return(lastbit8[(x>>8)&0x000000FF]+8);
+ if(x&0x00FF0000)
+ return(lastbit8[(x>>16)&0x000000FF]+16);
+ if(x&0xFF000000)
+ return(lastbit8[(x>>24)&0x000000FF]+24);
+ return 100;
+ #endif
+
+ #ifdef LASTBIT16
+ /* returns the position of the last bit in x */
+ if(x&0x0000FFFF)
+ return(lastbit16[x&0x0000FFFF]);
+ if(x&0xFFFF0000)
+ return(lastbit16[(x>>16)&0x0000FFFF]+16);
+ return 100;
+ #endif
+ }
+
+
+ //########################################################
+ // Define the function COUNTMOVES.
+ // This is either a macro or an inline function.
+ //########################################################
+ static inline s32bit
+ COUNTMOVES_DYN(u32bit mask)
+ {
+ s32bit count = 0;
+ u32bit tmp;
+
+ while(mask){
+ tmp = (mask&-mask); // least sig bit of m
+ mask &= ~(tmp | (tmp << 1)); // remove bit and next bit.
+ count++;
+ }
+ return count;
+ }
+
+ #ifdef COUNTMOVES_TABLE
+ #ifdef BOARD_SIZE_LT_16
+ //========================================================
+ // count moves (assuming small board).
+ //========================================================
+ #define COUNTMOVES(mask) move_table16[(mask)]
+
+ #else
+ //========================================================
+ // count moves (assuming large board).
+ //========================================================
+ static inline s32bit
+ COUNTMOVES(u32bit mask)
+ {
+ s32bit count = 0;
+ count = move_table16[mask & 0x0000FFFF];
+
+ if(count&0xF0000000)
+ count = ((count & 0x0000FFFF) + move_table16[mask >> 16]) & 0x0000FFFE;
+ else
+ count = (count + move_table16[mask >> 16]) & 0x0000FFFF;
+
+ return count;
+
+ /*
+ if(count&ERASE_NEXT_BIT) mask &= ~(NEXT_BIT);
+ return (count + move_table16[mask >> 16]) & 0x0000FFFF;
+ */
+ }
+
+ #endif
+ #else
+ //========================================================
+ // count moves (move_table doesn't exist).
+ //========================================================
+ #define COUNTMOVES(mask) COUNTMOVES_DYN(mask)
+
+ #endif
+
+
+
+
+ #define HASHKEY_UPDATE(key,index) key[index/32] ^= NTH_BIT(index%32)
+
+
+ #define toggle_hash_code(info) \
+ \
+ HASHKEY_UPDATE(g_norm_hashkey.key, info.norm.bit1_index); \
+ HASHKEY_UPDATE(g_norm_hashkey.key, info.norm.bit2_index); \
+ g_norm_hashkey.code ^= info.norm.hash_code; \
+ \
+ HASHKEY_UPDATE(g_flipV_hashkey.key, info.flipV.bit1_index); \
+ HASHKEY_UPDATE(g_flipV_hashkey.key, info.flipV.bit2_index); \
+ g_flipV_hashkey.code ^= info.flipV.hash_code; \
+ \
+ HASHKEY_UPDATE(g_flipH_hashkey.key, info.flipH.bit1_index); \
+ HASHKEY_UPDATE(g_flipH_hashkey.key, info.flipH.bit2_index); \
+ g_flipH_hashkey.code ^= info.flipH.hash_code; \
+ \
+ HASHKEY_UPDATE(g_flipVH_hashkey.key, info.flipVH.bit1_index); \
+ HASHKEY_UPDATE(g_flipVH_hashkey.key, info.flipVH.bit2_index); \
+ g_flipVH_hashkey.code ^= info.flipVH.hash_code;
+
+
+ #endif //MACROS_H
Index: llvm/test/Programs/MultiSource/Applications/obsequi/move_gen.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/move_gen.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/move_gen.c Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,127 ----
+
+ #include "globals.h"
+ #include "macros.h"
+
+ //#################################################################
+ // The following functions are used to generate all the possible
+ // moves which could be made, for a certain player, given
+ // the current board position.
+ //#################################################################
+
+ //=================================================================
+ // This function generates all the moves in one pass.
+ //=================================================================
+ extern s32bit
+ move_generator(Move movelist[MAXMOVES], s32bit player)
+ {
+ s32bit i, count = 0, player_index;
+ u32bit prot_rows, curr_row, m, tmp;
+
+ // Will be 0 if horizontal, 1 if vertical.
+ // Appears to be redundant but seems to help the compiler optimize.
+ player_index = player&PLAYER_MASK;
+
+ for(i = 0; i < g_board_size[player_index]; i++){
+ prot_rows = g_board[player_index][i] & g_board[player_index][i+2];
+ curr_row = g_board[player_index][i+1];
+
+ #ifndef PLAY_SAFE_MOVES
+ // m contains a 1 at each position where there is valid move.
+ // (except safe moves, there is no need to play them)
+ m = ~((curr_row|(curr_row>>1)) | (prot_rows&(prot_rows>>1)));
+ #else
+ // if you uncomment this it will also play safe moves.
+ m = ~(curr_row|(curr_row>>1));
+ #endif
+
+ while(m){
+ tmp = (m&-m); // least sig bit of m
+ m ^= tmp; // remove least sig bit of m.
+ movelist[count].mask_index = lastbit32(tmp);
+ movelist[count].array_index = i+1;
+ movelist[count].info = 0;
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ //=================================================================
+ // The following functions use a two pass system. This means possibly
+ // less cost in evaluating (because if we find a cutoff quickly
+ // we will not have to evaluate the second half) and in sorting the
+ // moves.
+ //=================================================================
+ extern s32bit
+ move_generator_stage1(Move movelist[MAXMOVES], s32bit player)
+ {
+ s32bit i, count = 0;
+ s32bit player_index;
+
+ u32bit prot_rows, curr_row, m, tmp;
+
+ // will be 0 if horizontal, 1 if vertical.
+ // This appears to be redundant but it seems to helps the compiler
+ // optimize.
+ player_index = player&PLAYER_MASK;
+
+ for(i = 0; i < g_board_size[player_index]; i++){
+ prot_rows = g_board[player_index][i] & g_board[player_index][i+2];
+ curr_row = g_board[player_index][i+1];
+
+ // m will contain a 1 at each position that there is a move
+ // which is a vulnerable move with no protected squares.
+ m = ~((curr_row|(curr_row>>1)) | (prot_rows|(prot_rows>>1)));
+
+ while(m){
+ tmp = (m&-m); // least sig bit of m
+ m ^= tmp; // remove least sig bit of m.
+ movelist[count].mask_index = lastbit32(tmp);
+ movelist[count].array_index = i+1;
+ movelist[count].info = 0;
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ extern s32bit
+ move_generator_stage2(Move movelist[MAXMOVES], s32bit count, s32bit player)
+ {
+ s32bit i, player_index;
+ u32bit prot_rows, curr_row, m, tmp;
+
+ // will be 0 if horizontal, 1 if vertical.
+ // This appears to be redundant but it seems to helps the compiler
+ // optimize.
+ player_index = player&PLAYER_MASK;
+
+ for(i = 0; i < g_board_size[player_index]; i++){
+ prot_rows = g_board[player_index][i] & g_board[player_index][i+2];
+ curr_row = g_board[player_index][i+1];
+
+ #ifndef PLAY_SAFE_MOVES
+ // m will contain a 1 at each position that there is a move
+ // which is a vulnerable move with a protected squares.
+ m = ~((curr_row|(curr_row>>1)) | (~(prot_rows^(prot_rows>>1))) );
+ #else
+ // m will contain a 1 at each position that there is a move
+ // which is a vulnerable move with a protected squares.
+ m = ((~((curr_row|(curr_row>>1)) | (prot_rows|(prot_rows>>1))))
+ ^ (~(curr_row|(curr_row>>1))));
+ #endif
+
+ while(m){
+ tmp = (m&-m); // least sig bit of m
+ m ^= tmp; // remove least sig bit of m.
+ movelist[count].mask_index = lastbit32(tmp);
+ movelist[count].array_index = i+1;
+ movelist[count].info = 0;
+ count++;
+ }
+ }
+
+ return count;
+ }
Index: llvm/test/Programs/MultiSource/Applications/obsequi/move_sort.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/move_sort.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/move_sort.c Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,63 ----
+
+ #include "globals.h"
+
+ //********************************************************
+ // Move sorting function.
+ //
+ // This is where the program spends some of the larger
+ // portions of its time. Sometime it should be sped up.
+ //********************************************************
+
+ #define NUM_BUCKETS 128
+
+ //=================================================================
+ // This is a stable sort algorithm (uses a bucket sort algorithm).
+ //=================================================================
+ extern void
+ sort_moves(Move movelist[MAXMOVES], s32bit start, s32bit num_moves)
+ {
+ Move bucket[NUM_BUCKETS][MAXMOVES];
+ s32bit buck_val[NUM_BUCKETS];
+ s32bit buck_size[NUM_BUCKETS];
+
+ s32bit num_buckets = 0, i, j;
+
+ // place each move in it's proper bucket.
+ for(i = start; i < num_moves; i++){
+ for(j = 0; j < num_buckets; j++){
+ if(movelist[i].info == buck_val[j]){
+ bucket[j][buck_size[j]++] = movelist[i];
+ break;
+ }
+ }
+ if(j == num_buckets){
+ if(j == NUM_BUCKETS) fatal_error(1, "Not enough buckets.\n");
+ bucket[j][0] = movelist[i];
+ buck_val[j] = movelist[i].info;
+ buck_size[j] = 1;
+ num_buckets++;
+ }
+ }
+
+ // remove the moves from their buckets in the proper order.
+ {
+ s32bit best, index, count = start;
+
+ while(count != num_moves){
+
+ best = buck_val[0];
+ index = 0;
+
+ for(i = 1; i < num_buckets; i++)
+ if(buck_val[i] > best) index = i, best = buck_val[i];
+
+ // every bucket must have at least one move.
+ i = 0;
+ do {
+ movelist[count++] = bucket[index][i++];
+ } while(i < buck_size[index]);
+
+ buck_val[index] = -5000;
+ }
+ }
+ }
Index: llvm/test/Programs/MultiSource/Applications/obsequi/negamax.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/negamax.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/negamax.c Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,552 ----
+
+ #include "globals.h"
+ #include "macros.h"
+
+ #include <time.h>
+ #include <ctype.h>
+
+
+ //#################################################################
+ // Statistics gathering variables and functions.
+ //#################################################################
+
+ //Determines if we should collect this data.
+ #define COLLECT_STATS
+
+ //=================================================================
+ // Variables used for statistics gathering.
+ //=================================================================
+ #ifdef COLLECT_STATS
+ static s32bit cut1 = 0, cut2 = 0, cut3 = 0, cut4 = 0;
+ static s32bit stat_cutoffs[40];
+ static s32bit stat_nodes[40];
+ static s32bit stat_nth_try[40][10];
+ #endif
+
+ //=================================================================
+ // Print the statistics which we have gathered.
+ //=================================================================
+ static void
+ print_stats()
+ {
+ #ifdef COLLECT_STATS
+ s32bit i, j;
+
+ printf("%d %d %d %d.\n\n", cut1, cut2, cut3, cut4);
+
+ for(i = 0; i < 40; i++){
+ if(stat_cutoffs[i] != 0 || stat_nodes[i] != 0){
+ printf("cutoffs depth %d: (%d) %d -",
+ i, stat_nodes[i], stat_cutoffs[i]);
+ for(j = 0; j < 5; j++)
+ printf(" %d", stat_nth_try[i][j]);
+ printf(" >%d.\n", stat_nth_try[i][5]);
+ }
+ }
+ #else
+ printf("\n");
+ #endif
+ }
+
+ //=================================================================
+ // Initialize the statistical variables.
+ //=================================================================
+ static void
+ init_stats()
+ {
+ #ifdef COLLECT_STATS
+ s32bit i, j;
+
+ // zero all data.
+ for(i = 0; i < 40; i++){
+ for(j = 0; j < 6; j++)
+ stat_nth_try[i][j] = 0;
+ stat_cutoffs[i] = 0;
+ stat_nodes[i] = 0;
+ }
+ #endif
+ }
+
+
+ //#################################################################
+ // Other variables.
+ //#################################################################
+
+ //#define RECORD_MOVES
+ //#define DEBUG_NEGAMAX
+
+
+ extern s32bit debug_score_move;
+
+ Hash_Key g_norm_hashkey;
+ Hash_Key g_flipV_hashkey;
+ Hash_Key g_flipH_hashkey;
+ Hash_Key g_flipVH_hashkey;
+
+ u64bit g_num_nodes;
+
+ s32bit g_first_move[2][32][32];
+ s32bit g_empty_squares = 0;
+
+ s32bit g_move_number[128];
+
+ #ifdef RECORD_MOVES
+ static s32bit g_move_player[128];
+ static Move g_move_position[128];
+ #endif
+
+ s32bit g_print = 0;
+
+
+ static s32bit starting_depth;
+
+
+ //#################################################################
+ // Negamax and driver functions. (and function prototype).
+ //#################################################################
+ static s32bit
+ negamax(s32bit depth_remaining, s32bit whos_turn_t, s32bit alpha, s32bit beta);
+
+
+ //=================================================================
+ // Search for move function. (Negamax Driver)
+ //=================================================================
+ extern s32bit
+ search_for_move(char dir, s32bit *row, s32bit *col, u64bit *nodes)
+ {
+ s32bit d, i, value = 0, num_moves;
+ Move movelist[MAXMOVES];
+ s32bit whos_turn;
+ Move forcefirst;
+
+ // Set who's turn it is.
+ if(toupper(dir) == 'V') whos_turn = VERTICAL;
+ else if(toupper(dir) == 'H') whos_turn = HORIZONTAL;
+ else { fatal_error(1, "Invalid player.\n"); exit(1); }
+
+ // initialize the number of empty squares.
+ g_empty_squares = 0;
+ for(i = 0; i < g_board_size[0]; i++)
+ g_empty_squares += countbits32( (~g_board[0][i+1]) );
+
+ // zero out all the statistics variables.
+ init_stats();
+
+ // Can we already determine a winner?
+ {
+ s32bit opponent = whos_turn ^ PLAYER_MASK;
+
+ // stop search if game over.
+ if(g_info_totals[whos_turn].safe > g_info_totals[opponent].real){
+ // current player wins.
+ *col = *row = -1;
+ *nodes = 0;
+ return 5000;
+ }
+
+ if(g_info_totals[opponent].safe >= g_info_totals[whos_turn].real){
+ // opponent wins.
+ *col = *row = -1;
+ *nodes = 0;
+ return -5000;
+ }
+ }
+
+ // generate all possible moves for current player given current position.
+ num_moves = move_generator(movelist, whos_turn);
+
+ // This should never happen.
+ if(num_moves == 0) fatal_error(1, "No moves");
+
+ // should possibly sort the whole list instead of just get first.
+ forcefirst.array_index = -1;
+ score_and_get_first(movelist, num_moves, whos_turn, forcefirst);
+ sort_moves(movelist, 1, num_moves);
+
+ // Really this is for iterative deepening.
+ for(d = 1; d < 50; d += 44){
+
+ // Initialize alpha and beta.
+ s32bit alpha = -5000, beta = 5000;
+
+ // Re-initialize the statistics for each iteration.
+ g_num_nodes = 0;
+ init_stats();
+
+ // set what the starting max depth is.
+ starting_depth = d;
+
+ // iterate through all the possible moves.
+ for(i = 0; i < num_moves; i++){
+
+ #ifdef DYNAMIC_POSITION_VALUES
+ init_move_value();
+ set_move_value(movelist[i], whos_turn);
+ #else
+ set_position_values();
+ #endif
+
+ g_move_number[0] = i;
+ #ifdef RECORD_MOVES
+ g_move_player[0] = whos_turn;
+ g_move_position[0] = movelist[i];
+ #endif
+
+ g_empty_squares -= 2;
+ toggle_move(movelist[i], whos_turn);
+ toggle_hash_code
+ (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]);
+ check_hash_code_sanity();
+
+ value = -negamax(d-1, whos_turn^PLAYER_MASK, -beta, -alpha);
+
+ #ifdef DYNAMIC_POSITION_VALUES
+ unset_move_value(movelist[i], whos_turn);
+ #endif
+
+ g_empty_squares += 2;
+ toggle_move(movelist[i], whos_turn);
+ toggle_hash_code
+ (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]);
+ check_hash_code_sanity();
+
+ printf("Move (%d,%d), value %d: %s.\n",
+ movelist[i].array_index, movelist[i].mask_index,
+ value, u64bit_to_string(g_num_nodes));
+ printf("alpha %d, beta %d.\n", alpha, beta);
+
+ movelist[i].info = value;
+
+ if(value >= beta){
+ alpha = value;
+ break;
+ }
+ if(value > alpha) {
+ alpha = value;
+ }
+ }
+
+ if(value >= 5000){
+ printf("Winner found: %d.\n", value);
+ if(whos_turn == HORIZONTAL){
+ *row = movelist[i].array_index;
+ *col = movelist[i].mask_index;
+ } else if(whos_turn == VERTICAL){
+ *col = movelist[i].array_index;
+ *row = movelist[i].mask_index;
+ } else {
+ fatal_error(1, "oops.");
+ }
+
+ *nodes = g_num_nodes;
+
+ print_stats();
+
+ return value;
+ }
+
+ // remove lossing moves from movelist.
+ {
+ s32bit rem = 0;
+ for(i = 0; i < num_moves; i++){
+ if(movelist[i].info <= -5000) rem++;
+ else if(rem > 0) movelist[i-rem] = movelist[i];
+ }
+ num_moves -= rem;
+ /*
+ for(i = 0; i < num_moves; i++){
+ printf("(%d,%d): %d.\n",
+ movelist[i].array_index, movelist[i].mask_index,
+ movelist[i].info);
+ }
+ */
+ }
+
+ print_stats();
+
+ if(num_moves == 0){
+ break;
+ }
+
+ // use a stable sort algorithm
+ {
+ Move swp;
+ s32bit max, index, j;
+
+ for(i=0; i<num_moves; i++) {
+ max = movelist[i].info;
+ index = i;
+
+ for(j=i+1; j < num_moves; j++)
+ if(movelist[j].info > max){
+ max = movelist[j].info;
+ index = j;
+ }
+
+ if(index != i){
+ swp = movelist[index];
+ // printf("%d %d\n", index, i);
+ for(j = index; j != i; j--){
+ movelist[j] = movelist[j-1];
+ }
+ movelist[i] = swp;
+ }
+ }
+ }
+
+ printf("The value is %d at a depth of %d.\n", value, d);
+ printf("Nodes: %u.\n", (u32bit)g_num_nodes);
+ }
+
+ *col = *row = -1;
+ *nodes = g_num_nodes;
+
+ return value;
+ }
+
+
+ //=================================================================
+ // Negamax Function.
+ //=================================================================
+ static s32bit
+ negamax(s32bit depth_remaining, s32bit whos_turn_t, s32bit alpha, s32bit beta)
+ {
+ Move movelist[MAXMOVES], best;
+ s32bit whos_turn = whos_turn_t & PLAYER_MASK;
+ s32bit opponent = whos_turn_t ^ PLAYER_MASK;
+ s32bit value;
+ s32bit init_alpha = alpha, init_beta = beta;
+ u32bit start_nodes = g_num_nodes;
+ Move forcefirst;
+ s32bit who_wins_value;
+
+ s32bit stage = 0, state = 0, true_count, i = 0, num_moves = 1;
+
+ #ifdef DYNAMIC_POSITION_VALUES
+ s32bit dyn_set;
+ #endif
+
+ // increment a couple of stats
+ g_num_nodes++;
+ #ifdef COLLECT_STATS
+ stat_nodes[starting_depth - depth_remaining]++;
+ #endif
+
+ // if no depth remaining stop search.
+ if( depth_remaining <= 0 ){
+ s32bit a = 0, b = 0;
+
+ if( (a = does_next_player_win(whos_turn, 0)) > 0 ) {
+ // current player wins.
+ return 5000;
+ }
+
+ if( (b = does_who_just_moved_win(opponent, 0)) >= 0 ) {
+ // opponent wins.
+ return -5000;
+ }
+
+ return a - b;
+ }
+
+
+ //------------------------------------------
+ // Can we determine a winner yet (simple check).
+ //------------------------------------------
+
+ // does current player win
+ if(g_info_totals[whos_turn].safe > g_info_totals[opponent].real){
+ #ifdef COLLECT_STATS
+ cut1++;
+ #endif
+ return 5000;
+ }
+
+ // does opponent win
+ if(g_info_totals[opponent].safe >= g_info_totals[whos_turn].real){
+ #ifdef COLLECT_STATS
+ cut2++;
+ #endif
+ return -5000;
+ }
+
+
+ //------------------------------------------
+ // check transposition table
+ //------------------------------------------
+
+ forcefirst.array_index = -1;
+ if(hashlookup(&value, &alpha, &beta, depth_remaining,
+ &forcefirst, whos_turn))
+ return value;
+ // since we aren't using iter deep not interested in forcefirst.
+ forcefirst.array_index = -1;
+
+
+ //------------------------------------------
+ // Can we determine a winner yet (look harder).
+ //------------------------------------------
+
+ // does current player win
+ if( (who_wins_value = does_next_player_win(whos_turn, 0)) > 0 ) {
+
+ #ifdef DEBUG_NEGAMAX
+ if(random() % 1000000 == -1){
+ does_next_player_win(whos_turn, 1);
+ print_board(whos_turn);
+ }
+ #endif
+
+ #ifdef COLLECT_STATS
+ cut3++;
+ #endif
+ return 5000;
+ }
+
+ // does opponent win
+ if( (who_wins_value = does_who_just_moved_win(opponent, 0)) >= 0 ) {
+
+ #ifdef DEBUG_NEGAMAX
+ if(who_wins_value < 3){ // && random() % 500 == -1){
+ does_who_just_moved_win(opponent, 1);
+ // print_board(opponent);
+ }
+ #endif
+
+ #ifdef COLLECT_STATS
+ cut4++;
+ #endif
+ return -5000;
+ }
+
+ #if 0
+ {
+ s32bit num;
+ num = move_generator_stage1(movelist, whos_turn);
+ num = move_generator_stage2(movelist, num, whos_turn);
+ if(move_generator(movelist, whos_turn) != num)
+ fatal_error(1, "NOPE\n");
+ }
+ #endif
+
+
+ //------------------------------------------
+ // Generate child nodes and examine them.
+ //------------------------------------------
+
+ // initialize a few variables. (some of them don't really need to be.)
+ stage = state = true_count = i = 0;
+ num_moves = 1;
+
+ #ifdef TWO_STAGE_GENERATION
+ true_count = move_generator_stage1(movelist, whos_turn);
+ if(true_count == 0){
+ true_count = move_generator_stage2(movelist, 0, whos_turn);
+ stage = 1;
+ if(true_count == 0) fatal_error(1, "Should always have a move.\n");
+ }
+ #else
+ true_count = move_generator(movelist, whos_turn);
+ stage = 1;
+ if(true_count == 0) fatal_error(1, "Should always have a move.\n");
+ #endif
+
+ // score all the moves and move the best to the front.
+ score_and_get_first(movelist, true_count, whos_turn, forcefirst);
+
+ best = movelist[0];
+
+ // need to sort moves and generate more moves in certain situations.
+ while(state < 3){
+ if(state == 0) {
+ state = 1;
+ } else if(state == 1){
+ sort_moves(movelist, 1, true_count);
+ num_moves = true_count;
+ if(stage == 0) state = 2;
+ else state = 3;
+ } else {
+ num_moves = move_generator_stage2(movelist, num_moves, whos_turn);
+ state = 3;
+ }
+
+ // Iterate through all the moves.
+ for(; i < num_moves; i++){
+
+ // A few statistics
+ g_move_number[starting_depth - depth_remaining] = i;
+ #ifdef RECORD_MOVES
+ g_move_player[starting_depth - depth_remaining] = whos_turn;
+ g_move_position[starting_depth - depth_remaining] = movelist[i];
+ #endif
+
+ // make move.
+ g_empty_squares -= 2;
+ toggle_move(movelist[i], whos_turn);
+ toggle_hash_code
+ (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]);
+ #ifdef DYNAMIC_POSITION_VALUES
+ dyn_set = set_move_value(movelist[i], whos_turn);
+ #endif
+
+ // recurse.
+ value = -negamax(depth_remaining-1,whos_turn^PLAYER_MASK,
+ -beta, -alpha);
+
+ // undo move.
+ g_empty_squares += 2;
+ toggle_move(movelist[i], whos_turn);
+ toggle_hash_code
+ (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]);
+ #ifdef DYNAMIC_POSITION_VALUES
+ if(dyn_set != 0) unset_move_value(movelist[i], whos_turn);
+ #endif
+
+ #if 0
+ if(starting_depth - depth_remaining == 8) {
+ s32bit g;
+
+ printf("goof:");
+
+ for(g = 0; g < 8; g++){
+ printf(" :%c:%d(%d,%d)",
+ (g_move_player[g] == VERTICAL) ? 'V' : 'H',
+ g_move_number[g],
+ g_move_position[g].array_index - 1,
+ g_move_position[g].mask_index - 1);
+ }
+ printf("\n");
+ }
+ #endif
+
+ // If this is a cutoff, break.
+ if(value >= beta){
+ alpha = value;
+ best = movelist[i];
+
+ #ifdef COLLECT_STATS
+ stat_cutoffs[starting_depth - depth_remaining]++;
+ if(i < 5) stat_nth_try[starting_depth - depth_remaining][i]++;
+ else stat_nth_try[starting_depth - depth_remaining][5]++;
+ #endif
+ break;
+ }
+
+ // If the current value is greater than alpha, increase alpha.
+ if(value > alpha) {
+ alpha = value;
+ best = movelist[i];
+ }
+ }
+
+ // If we have broken out of previous FOR loop make sure we break out
+ // of this loop as well.
+ if(value >= beta) break;
+ }
+
+ // save the position in the hashtable
+ hashstore(alpha, init_alpha, init_beta, (g_num_nodes - start_nodes) >> 5,
+ depth_remaining, best, whos_turn);
+
+ return alpha;
+ }
Index: llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c Tue May 11 14:34:12 2004
***************
*** 0 ****
--- 1,620 ----
+ //********************************************************
+ // This file part of my Obsequi front end.
+ //********************************************************
+ //
+ // Copyright (C) 2001 Nathan Bullock
+ //
+ // This program is free software; you can redistribute it and/or modify
+ // it under the terms of the GNU General Public License as published by
+ // the Free Software Foundation; either version 2 of the License, or
+ // (at your option) any later version.
+ //
+ // This program is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+ //
+ // You should have received a copy of the GNU General Public License
+ // along with this program; if not, write to the Free Software
+ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ //
+ //********************************************************
+ // Email address - bullock at cs.ualberta.ca
+ // Web address - www.cs.ualberta.ca/~bullock
+ //********************************************************
+
+ #include "utils.h"
+
+ #include <signal.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include <sys/time.h>
+ #include <ctype.h>
+
+ #include "cppflags.h"
+ #include "interface.h"
+
+
+ //########################################################
+ // Function templates.
+ //########################################################
+
+ // handle command line options.
+ static void decode_switches (int argc, char **argv);
+
+ // signal handlers.
+ static void sig_int_setup ();
+ static void sig_int_handler (int sig);
+ static void sig_alrm_setup ();
+ static void sig_alrm_handler (int sig);
+ static void sig_block ();
+ static void set_stop_alrm (long minutes);
+
+ // main command loop functions.
+ static void get_solve_command ();
+
+ // lock file stuff.
+ static void get_solve_command_from_lock_file();
+ static void write_to_lock_file(char winner, const char* num_nodes);
+
+
+ //########################################################
+ // Global variables.
+ //########################################################
+
+ // Determines if we will have an alarm checking the input every so often.
+ static s32bit main_batch = 1;
+
+ // Determines if we should be reading a lock file and what it's name is.
+ static char *lock_file = NULL;
+
+ // Determines if we should be stopping program after x minutes.
+ static long stop_minutes = 0;
+
+ static char main_whos_turn;
+
+
+ //########################################################
+ // Entry point to obsequi.
+ //########################################################
+ int
+ main(int argc, char** argv)
+ {
+ decode_switches(argc, argv);
+
+ if(lock_file){
+ get_solve_command_from_lock_file();
+ if(stop_minutes) set_stop_alrm(stop_minutes);
+ } else {
+ get_solve_command();
+ if(!main_batch) sig_alrm_setup();
+ }
+
+ sig_int_setup();
+
+ // start solver.
+ {
+ s32bit row, col;
+ u64bit nodes;
+ s32bit score;
+ const char* num_nodes;
+
+ score = search_for_move(main_whos_turn, &row, &col, &nodes);
+
+ sig_block();
+
+ num_nodes = u64bit_to_string(nodes);
+
+ // print results.
+ if(score >= 5000){
+ printf("winner %c, move (%d,%d), nodes %s.\n",
+ main_whos_turn, row, col, num_nodes);
+ } else if(score <= 5000){
+ printf("winner %c, move (%d,%d), nodes %s.\n",
+ (main_whos_turn == 'V') ? 'H' : 'V',
+ row, col, num_nodes);
+ } else {
+ printf("Undecided, Best score: %d, nodes %s.\n",
+ score, num_nodes);
+ }
+
+ fflush(stdout);
+
+ if(lock_file){
+ char winner = 0;
+
+ if(score >= 5000) winner = main_whos_turn;
+ else if(score <= -5000) winner = (main_whos_turn == 'V') ? 'H' : 'V';
+ else fatal_error(1, "Undecided.\n");
+
+ write_to_lock_file(winner, num_nodes);
+ }
+ }
+
+ // if not in batch mode don't exit until stdin has been closed.
+ fcntl(STDIN_FILENO, F_SETFL, 0);
+ if (!main_batch){
+ while(getchar() != EOF);
+ }
+
+ return 0;
+ }
+
+
+ //########################################################
+ // Main input - output commands.
+ //########################################################
+
+ //========================================================
+ // This function reads stdin one line at a time.
+ // It initializes the solver engine when it finds a line of the format:
+ //
+ // "solve rows m cols n bx0,y0;x1,y1;...;x,y f"
+ // where:
+ // - m is the number of rows.
+ // - n is the number of cols.
+ // - bx0,y0 is the position of a block on the board.
+ // - f is H if it is horizontals turn and V if verticals turn.
+ //
+ // It discards all input which does not match this format and
+ // writes an error message to stderr.
+ //========================================================
+ static void
+ get_solve_command()
+ {
+ char* line = NULL, *blocks = NULL;
+ size_t line_size = 0, len;
+
+ // Board info for the board which we are solving.
+ u32bit num_rows;
+ u32bit num_cols;
+ s32bit board[30][30];
+ char c1, c2;
+
+ s32bit r, c;
+
+ while( (len = getline(&line, &line_size, stdin)) != -1){
+ s32bit t;
+
+ if(len > 0){
+ if(blocks != NULL) blocks = realloc(blocks, line_size);
+ else blocks = malloc(line_size);
+ } else continue;
+ line[len - 1] = 0;
+
+ t = sscanf(line, "solve rows %u cols %u %c%s %c",
+ &num_rows, &num_cols, &c1, blocks, &c2);
+
+ if(t != 3 && t != 5){
+ fprintf(stderr, "Invalid command: '%s'.\n", line);
+ continue;
+ }
+
+ if(num_rows > 30){
+ fprintf(stderr, "Too many rows: %u > 30.\n", num_rows);
+ continue;
+ }
+
+ if(num_cols > 30){
+ fprintf(stderr, "Too many cols: %u > 30.\n", num_cols);
+ continue;
+ }
+
+ if(num_cols * num_rows > 256){
+ fprintf(stderr,
+ "Search space too large: %u > 256.\n", num_cols*num_rows);
+ continue;
+ }
+
+ for(r = 0; r < 30; r++)
+ for(c = 0; c < 30; c++) board[r][c] = 0;
+
+ if(t == 5) {
+ char *tok;
+
+ c1 = toupper(c1);
+ if(c1 != 'B') {
+ fprintf(stderr, "Invalid command: '%s'.\n", line);
+ continue;
+ }
+
+ tok = strtok(blocks, ";");
+ while(tok != NULL){
+ if(sscanf(tok, "%u,%u", &r, &c) != 2){
+ fprintf(stderr, "Invalid block string: '%s'.\n", tok);
+ c1 = 0;
+ break;
+ }
+ if(r >= num_rows || c >= num_cols){
+ fprintf(stderr, "Invalid block string: '%s'.\n", tok);
+ c1 = 0;
+ break;
+ }
+
+ board[r][c] = 1;
+
+ tok = strtok(NULL, ";");
+ }
+ if(c1 == 0) continue;
+ } else {
+ c2 = c1;
+ }
+
+ c2 = toupper(c2);
+ if(c2 != 'V' && c2 != 'H'){
+ fprintf(stderr, "Invalid players turn: %c.\n", c2);
+ continue;
+ }
+
+ // everything should be initialized properly at this point.
+ printf("Starting\n");
+ fflush(stdout);
+ break;
+ }
+
+ if(len == -1) fatal_error(1, "No valid command given.\n");
+
+ /*
+ main_num_rows = num_rows;
+ main_num_cols = num_cols;
+
+ for(r = 0; r < 30; r++)
+ for(c = 0; c < 30; c++)
+ main_board[r][c] = board[r][c];
+ */
+ main_whos_turn = c2;
+
+ initialize_board(num_rows, num_cols, board);
+
+ //print_external(); exit(0);
+
+ free(line);
+ free(blocks);
+ }
+
+
+ //========================================================
+ // Non blocking input loop.
+ //========================================================
+ static void
+ get_other_commands()
+ {
+ static size_t line_size;
+ static char *line;
+ char c1;
+
+ fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
+
+ // get next line of input, exit at end of input.
+ while (getline(&line, &line_size, stdin) > 0){
+
+ printf(line);
+
+ // stop the search.
+ if(sscanf(line, "stop%c", &c1) == 1){
+ exit(0);
+ }
+
+ /*
+ // print info (whatever that is).
+ else if(sscanf(line, "info%c", &c1) == 1){
+ stringify_stack(&line, &line_size);
+ fprintf(stderr, "%s", line);
+ }
+ */
+
+ else {
+ fprintf(stderr, "Invalid command.\n");
+ }
+ }
+
+ fflush(stderr);
+ clearerr(stdin);
+ }
+
+
+ //########################################################
+ // Obsequi takes a number of arguments
+ // -e print flags used at compile time.
+ // -h print out help message and exit.
+ // -l specify file which contains a position to solve.
+ // -t specify maximum time limit for solving position.
+ // only works when using a "lock file" -l.
+ // -v print version information.
+ // -w wait for standard in to be closed before exiting.
+ //########################################################
+ static void
+ decode_switches(int argc, char **argv)
+ {
+ int c;
+
+ while ((c = getopt(argc, argv, "wehl:t:v")) != -1){
+ switch(c){
+ case 'e':
+ printf(option_string);
+ exit(0);
+
+ case 'h':
+ printf("No help available in this version.\n");
+ exit(0);
+
+ case 'l':
+ lock_file = strdup(optarg);
+ break;
+
+ case 't':
+ stop_minutes = atoi(optarg);
+ break;
+
+ case 'v':
+ printf("No version info available.\n");
+ exit(0);
+
+ case 'w':
+ main_batch = 0;
+ break;
+
+ default:
+ fatal_error(1, "Invalid option: '-%c'.\n", c);
+ }
+ }
+
+ if(optind < argc)
+ fatal_error(1, "Extra unknown options on command line.\n");
+ }
+
+
+
+ //########################################################
+ // Signal handling stuff.
+ //########################################################
+
+ //========================================================
+ // sig int stuff
+ //========================================================
+ static void
+ sig_int_handler(int sig)
+ {
+ const char* str;
+
+ str = current_search_state();
+
+ fprintf(stderr, "%s\n", str);
+
+ fflush(stderr);
+ }
+
+ static void
+ sig_int_setup()
+ {
+ struct sigaction act;
+
+ // sigemptyset(&act.sa_mask);
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0;
+
+ act.sa_handler = sig_int_handler;
+ if ( sigaction(SIGINT, &act, NULL) )
+ fatal_error(1, "`sigaction' failed.");
+ }
+
+
+ //========================================================
+ // sig alarm stuff
+ //========================================================
+ static void
+ sig_alrm_handler(int sig)
+ {
+ get_other_commands();
+ }
+
+ static void
+ stop_alrm_handler(int sig)
+ {
+ exit(0);
+ }
+
+ static void
+ set_stop_alrm(long minutes)
+ {
+ struct sigaction act;
+ struct itimerval itime;
+
+ // sigemptyset(&act.sa_mask);
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0;
+
+ act.sa_handler = stop_alrm_handler;
+ if ( sigaction(SIGVTALRM, &act, NULL) )
+ fatal_error(1, "`sigaction' failed.");
+
+ itime.it_interval.tv_sec = minutes * 60;
+ itime.it_interval.tv_usec = 0;
+ itime.it_value.tv_sec = minutes * 60;
+ itime.it_value.tv_usec = 0;
+
+ if ( setitimer(ITIMER_VIRTUAL, &itime, NULL) )
+ fatal_error(1, "`setitimer' failed.\n");
+ }
+
+ static void
+ sig_alrm_setup()
+ {
+ struct sigaction act;
+ struct itimerval itime;
+
+ // sigemptyset(&act.sa_mask);
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0;
+
+ act.sa_handler = sig_alrm_handler;
+ if ( sigaction(SIGALRM, &act, NULL) )
+ fatal_error(1, "`sigaction' failed.");
+
+ itime.it_interval.tv_sec = 2;
+ itime.it_interval.tv_usec = 0;
+ itime.it_value.tv_sec = 1;
+ itime.it_value.tv_usec = 0;
+
+ if ( setitimer(ITIMER_REAL, &itime, NULL) )
+ fatal_error(1, "`setitimer' failed.\n");
+ }
+
+
+ //========================================================
+ // block all new signals stuff
+ //========================================================
+ static void
+ sig_block()
+ {
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+ sigaddset(&set, SIGINT);
+
+ sigprocmask(SIG_BLOCK, &set, NULL);
+ }
+
+
+ //########################################################
+ // Lock and read lock file.
+ //########################################################
+
+ //========================================================
+ // Some local variables for the lock file stuff.
+ //========================================================
+ static s32bit lock_file_offset;
+
+ static s32bit
+ next_valid_pos(const char *line, s32bit line_pos)
+ {
+ s32bit i, state = 0;
+ for(i = line_pos; line[i] != 0; i++){
+ if(line[i] == ' ') {
+ if(state != 0) state = 2;
+ } else {
+ if(state == 2) break;
+ state = 1;
+ }
+ }
+ return i;
+ }
+
+
+ static void
+ write_to_lock_file(char winner, const char* num_nodes)
+ {
+ FILE* file = NULL;
+
+ if( (file = fopen(lock_file, "r+")) == NULL )
+ fatal_error(1, "Can't open file.\n");
+
+ // if(lockf(fileno(file), F_LOCK, 0) != 0)
+ // fatal_error(1, "Lock failed.\n");
+
+ printf("%s\n", lock_file);
+
+ fseek(file, lock_file_offset, SEEK_SET);
+ fprintf(file, "%c %15s", winner, num_nodes);
+ fflush(file);
+
+ // lockf(fileno(file), F_ULOCK, 0);
+ fclose(file);
+ }
+
+
+ static void
+ get_solve_command_from_lock_file()
+ {
+ FILE* file = NULL;
+
+ char* line = NULL;
+ size_t line_size = 0, len, line_pos;
+
+ // Board info for the board which we are solving.
+ u32bit num_rows;
+ u32bit num_cols;
+ s32bit board[30][30];
+ char player = 0;
+
+ s32bit r, c;
+
+ if( (file = fopen(lock_file, "r+")) == NULL )
+ fatal_error(1, "Can't open file.\n");
+
+ // if(lockf(fileno(file), F_LOCK, 0) != 0)
+ // fatal_error(1, "Lock failed.\n");
+
+ printf("%s\n", lock_file);
+
+ while( lock_file_offset = ftell(file),
+ (len = getline(&line, &line_size, file)) != -1){
+ // if line has a length of 0 line[0] will be '\0'.
+ if(line[0] != 'A') continue;
+
+ printf("%s", line);
+
+ if(len <= 18) fatal_error(1, line);
+
+ if(sscanf(line + 18, "(%d,%d)", &num_rows, &num_cols) != 2)
+ fatal_error(1, "Invalid row and columns.\n%s\n", line);
+
+ if(num_rows > 30)
+ fatal_error(1, "Too many rows: %u > 30.\n", num_rows);
+ if(num_cols > 30)
+ fatal_error(1, "Too many cols: %u > 30.\n", num_cols);
+ if(num_cols * num_rows > 128)
+ fatal_error(1, "Search space too large: %u > 256.\n", num_cols*num_rows);
+
+ for(r = 0; r < 30; r++)
+ for(c = 0; c < 30; c++) board[r][c] = 0;
+
+ line_pos = 18;
+
+ while(1){
+ s32bit ignore;
+
+ line_pos = next_valid_pos(line, line_pos);
+
+ if(line_pos >= len) break;
+
+ if(sscanf(line + line_pos, ":%c:%d(%d,%d)", &player,
+ &ignore, &r, &c) != 4)
+ break;
+
+ printf("%c %d %d\n", player, r, c);
+
+ if(player == 'V'){
+ if(board[c][r] == 1 || board[c+1][r] == 1)
+ fatal_error(1, line);
+ board[c][r] = board[c+1][r] = 1;
+ } else if(player == 'H'){
+ if(board[r][c] == 1 || board[r][c+1] == 1)
+ fatal_error(1, line);
+ board[r][c] = board[r][c+1] = 1;
+ } else fatal_error(1, "Invalid player.\n");
+ }
+
+ // everything should be initialized properly at this point.
+ printf("Starting\n");
+ fflush(stdout);
+ break;
+ }
+
+ if(len == -1) fatal_error(1, "No valid command given.\n");
+
+ fseek(file, lock_file_offset, SEEK_SET);
+ fprintf(file, "W");
+ fflush(file);
+
+ if(player == 'V') main_whos_turn = 'H';
+ else if(player == 'H') main_whos_turn = 'V';
+ else fatal_error(1, "Invalid player.\n");
+
+ initialize_board(num_rows, num_cols, board);
+
+ free(line);
+
+ // lockf(fileno(file), F_ULOCK, 0);
+ fclose(file);
+ }
Index: llvm/test/Programs/MultiSource/Applications/obsequi/position_values.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/position_values.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/position_values.c Tue May 11 14:34:13 2004
***************
*** 0 ****
--- 1,178 ----
+
+
+ #include "globals.h"
+
+ //#################################################################
+ // Give all the positions for this PLAYER which are symmetrical
+ // to the position (ROW, COL) a value of VALUE.
+ //#################################################################
+ static void
+ set_position_value(s32bit player, s32bit row, s32bit col, s32bit value)
+ {
+ s32bit num_rows, num_cols;
+
+ num_rows = g_board_size[player] + 1;
+ num_cols = g_board_size[player^PLAYER_MASK];
+
+ //printf("1 - %d %d %d\n", player, row, col);
+ g_first_move[player][row][col] = value;
+ //printf("2 - %d %d %d\n", player, num_rows-row, col);
+ g_first_move[player][num_rows-row][col] = value;
+ //printf("3 - %d %d %d\n", player, num_rows-row, num_cols-col);
+ g_first_move[player][num_rows-row][num_cols-col] = value;
+ // printf("4 - %d %d %d\n", player, row, num_cols-col);
+ g_first_move[player][row][num_cols-col] = value;
+ }
+
+
+ #ifdef DYNAMIC_POSITION_VALUES
+ //#################################################################
+ // If we are using dynamic position values then these are the
+ // functions (and variables) which we use to set these values.
+ //#################################################################
+
+ //=================================================================
+ // Variable to keep track of value we will give to the next position.
+ //=================================================================
+ static s32bit set_move_value_current = 127;
+
+ //=================================================================
+ // Initialize all positions with a value of 0
+ //=================================================================
+ extern void
+ init_move_value ()
+ {
+ s32bit i, j, k;
+ set_move_value_current = 127;
+
+ for(i = 0; i < 2; i++)
+ for(j = 0; j < 32; j++)
+ for(k = 0; k < 32; k++)
+ g_first_move[i][j][k] = 0;
+ }
+
+ //=================================================================
+ // Set the value of the positions symetrical to MOVE.
+ // return 0 if these positions already have a value, otherwise 1.
+ //=================================================================
+ extern s32bit
+ set_move_value (Move move, s32bit player)
+ {
+ if(g_first_move[player][move.array_index][move.mask_index] != 0)
+ return 0;
+
+ set_position_value(player, move.array_index, move.mask_index,
+ set_move_value_current--);
+ return 1;
+ }
+
+ //=================================================================
+ // UnSet the value of the positions symetrical to MOVE.
+ // Shouldn't be called if when 'set' was called it returned a value of 0.
+ //=================================================================
+ extern void
+ unset_move_value (Move move, s32bit player)
+ {
+ set_move_value_current
+ = g_first_move[player][move.array_index][move.mask_index];
+
+ set_position_value(player, move.array_index, move.mask_index, 0);
+ }
+
+ #else
+ //#################################################################
+ // If we are using dynamic position values then these are the
+ // functions which we use to set these values.
+ //#################################################################
+
+ //=================================================================
+ // Set the value of all the positions on the board.
+ // We only do this once at the start of the search.
+ //=================================================================
+ extern void
+ set_position_values()
+ {
+ s32bit i, j, k, count;
+
+ // set them all to zero.
+ for(i = 0; i < 2; i++)
+ for(j = 0; j < 32; j++)
+ for(k = 0; k < 32; k++)
+ g_first_move[i][j][k] = 0;
+
+ #if 0
+ // Set values using very simple scheme.
+ for(i = 0; i < 2; i++){
+ count = 64;
+ for(j = 1; j < (g_board_size[i]+3)/2; j++){
+ for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k++){
+ if(g_first_move[i][j][k] == 0)
+ set_position_value(i, j, k, --count);
+ }
+ }
+ }
+ #elif 1
+ // Set values using a more complex (seems to be better) scheme.
+ for(i = 0; i < 2; i++){
+ count = 127;
+ for(j = 2; j < (g_board_size[i]+3)/2; j+=2){
+ for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k+=2){
+ set_position_value(i, j, k, --count);
+ }
+ }
+ }
+ for(i = 0; i < 2; i++){
+ count = 90;
+ for(j = 2; j < (g_board_size[i]+3)/2; j+=2){
+ for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k++){
+ if(g_first_move[i][j][k] == 0)
+ set_position_value(i, j, k, --count);
+ }
+ }
+ }
+ for(i = 0; i < 2; i++){
+ count = 70;
+ for(j = 3; j < (g_board_size[i]+3)/2; j++){
+ for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k+=2){
+ if(g_first_move[i][j][k] == 0)
+ set_position_value(i, j, k, --count);
+ }
+ }
+ }
+ for(i = 0; i < 2; i++){
+ count = 50;
+ for(j = 3; j < (g_board_size[i]+3)/2; j++){
+ for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k++){
+ if(g_first_move[i][j][k] == 0)
+ set_position_value(i, j, k, --count);
+ }
+ }
+ }
+ for(i = 0; i < 2; i++){
+ count = 30;
+ for(j = 1; j < (g_board_size[i]+3)/2; j++){
+ for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k++){
+ if(g_first_move[i][j][k] == 0)
+ set_position_value(i, j, k, --count);
+ }
+ }
+ }
+ #endif
+
+ // print the values. (mostly for debugging)
+ #if 0
+ for(i = 0; i < 2; i++){
+ for(j = 0; j < 32; j++){
+ for(k = 0; k < 32; k++){
+ printf("%d ", g_first_move[i][j][k]);
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+ exit(0);
+ #endif
+
+ }
+
+ #endif
Index: llvm/test/Programs/MultiSource/Applications/obsequi/structs.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/structs.h:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/structs.h Tue May 11 14:34:13 2004
***************
*** 0 ****
--- 1,266 ----
+
+
+ #ifndef STRUCTS_H
+ #define STRUCTS_H
+
+ #include "utils.h"
+
+ //########################################################
+ // Basic board info which we keep track of.
+ //########################################################
+ typedef struct
+ {
+ s32bit safe;
+ s32bit real;
+ s32bit mobility;
+ } Basic_Info;
+
+
+ //########################################################
+ // Info we need to describe a move.
+ //########################################################
+ typedef struct
+ {
+ s32bit array_index;
+ s32bit mask_index;
+ s32bit info;
+ } Move;
+
+
+ //########################################################
+ // Info we need for each entry in the hashtable.
+ //########################################################
+ typedef struct
+ {
+ // uniquely identifies a board position.
+ u32bit key[4];
+
+ // if real num of nodes exceeds ULONG_MAX set to ULONG_MAX.
+ // or maybe we could just shift the bits (larger granularity).
+ u32bit nodes;
+
+ // uniquely identifies the previous best move for this position.
+ u8bit best_move;
+
+ // depth of the search when this value was determined.
+ u8bit depth : 7;
+
+ // whos turn it is.
+ u8bit whos_turn : 1;
+
+ // value of node determined with a search to `depth`.
+ s16bit value : 14;
+
+ // value of node determined with a search to `depth`.
+ u16bit type : 2; //UPPER, LOWER, EXACT.
+ } Hash_Entry;
+
+
+ //########################################################
+ // structure used to store current key and it's hash code.
+ //########################################################
+ typedef struct
+ {
+ u32bit key[4];
+ s32bit code;
+ } Hash_Key;
+
+
+ //########################################################
+ // table_keyinfo
+ //########################################################
+ typedef struct
+ {
+ s32bit bit1_index;
+ s32bit bit2_index;
+ u32bit hash_code;
+ } KeyInfo_s;
+
+ typedef struct
+ {
+ KeyInfo_s norm;
+ KeyInfo_s flipV;
+ KeyInfo_s flipH;
+ KeyInfo_s flipVH;
+ } KeyInfo;
+
+ #endif
+
+ #ifndef STRUCTS_H
+
+ extern void
+ hashstore(s32bit value, s32bit alpha, s23bit beta,
+ u64bit nodes, int depth, struct move best, int color)
+ {
+ /* write the record anyway where the index is*/
+ int32 index, minindex;
+ int mindepth=1000,iter=0;
+ int from,to;
+
+ if(depth<0) return;
+ hashstores++;
+
+ if(realdepth < DEEPLEVEL) {
+ /* its in the "deep" hashtable: take care not to overwrite other entries */
+ index=Gkey&HASHMASKDEEP;
+ minindex=index;
+ while(iter<HASHITER) {
+ if(deep[index].lock==Glock || deep[index].lock==0) {
+ /* found an index where we can write the entry */
+ deep[index].lock=Glock;
+ deep[index].info=(int16) (depth&DEPTH);
+ if(color==BLACK) {
+ deep[index].best=best.bm|best.bk;
+ deep[index].info|=HASHBLACK;
+ } else
+ deep[index].best=best.wm|best.wk;
+
+ deep[index].value=(sint16)value;
+ /* determine valuetype */
+ if(value>=beta) {deep[index].info|=LOWER;return;}
+ if(value>alpha) {deep[index].info|=EXACT;return;}
+ deep[index].info|=UPPER;
+ return;
+ } else {
+ if( hashdepth(deep[index].info) < mindepth) {
+ minindex=index;
+ mindepth=hashdepth(deep[index].info);
+ }
+ }
+ iter++;
+ index++;
+ index=index&HASHMASKDEEP;
+ }
+ /* if we arrive here it means we have gone through all hashiter
+ entries and all were occupied. in this case, we write the entry
+ to minindex */
+ if(mindepth>(depth)) return;
+ deep[minindex].lock=Glock;
+ deep[minindex].info=(int16) (depth);
+ if(color==BLACK)
+ deep[minindex].best=best.bm|best.bk;
+ else
+ deep[minindex].best=best.wm|best.wk;
+ deep[minindex].info|=(int16)((color>>1)<<13);
+ deep[minindex].value=value;
+ /* determine valuetype */
+ if(value>=beta) {deep[minindex].info|=LOWER;return;}
+ if(value>alpha) {deep[minindex].info|=EXACT;return;}
+ deep[minindex].info|=UPPER;
+ return;
+ /* and return */
+ } else {
+ index=Gkey&HASHMASKSHALLOW;
+ if( hashdepth(shallow[index].info) <= depth )
+ /* replace the old entry if the new depth is larger */
+ {
+ shallow[index].lock=Glock;
+ shallow[index].info=(int16)depth;
+ shallow[index].value=(sint16)value;
+ if(color==BLACK)
+ {
+ shallow[index].best=best.bm|best.bk;
+ shallow[index].info|=HASHBLACK;
+ }
+ else
+ shallow[index].best=best.wm|best.wk;
+
+ /* determine valuetype */
+
+ if(value>=beta) {shallow[index].info|=LOWER;return;}
+ if(value>alpha) {shallow[index].info|=EXACT;return;}
+ shallow[index].info|=UPPER;
+ }
+ }
+ return;
+ }
+
+ int hashlookup(int *value, int *alpha, int *beta, int depth, int32 *forcefirst, int color)
+ {
+ int32 index;
+ int iter=0;
+
+ hashsearch++;
+
+ if(realdepth<DEEPLEVEL)
+ /* a position in the "deep" hashtable - it's important to find it since */
+ /* the effect is larger here! */
+ {
+ hashhit++;
+ index=Gkey&HASHMASKDEEP;
+ while(iter<HASHITER)
+ {
+ if(deep[index].lock==Glock && (hashcolor(deep[index].info)>>13)==(color>>1))
+ {
+ /* we have found the position */
+ hashhit++;
+ /* move ordering */
+ *forcefirst=deep[index].best;
+ /* use value if depth in hashtable >= current depth)*/
+ if(hashdepth(deep[index].info)>=depth)
+ {
+ /* if it's an exact value we can use it */
+ if(hashvaluetype(deep[index].info) == EXACT)
+ {
+ *value=deep[index].value;
+ return 1;
+ }
+ /* lower bound */
+ if(hashvaluetype(deep[index].info) == LOWER)
+ {
+ if(deep[index].value>=(*beta)) {*value=deep[index].value;return 1;}
+ if(deep[index].value>(*alpha)) {*alpha=deep[index].value;}
+ return 0;
+ }
+ /* upper bound */
+ if(hashvaluetype(deep[index].info) == UPPER)
+ {
+ if(deep[index].value<=*alpha) {*value=deep[index].value;return 1;}
+ if(deep[index].value<*beta) {*beta=deep[index].value;}
+ return 0;
+ }
+ }
+ }
+ iter++;
+ index++;
+ index&=HASHMASKDEEP;
+ }
+ return 0;
+ }
+ /* use shallow hashtable */
+ else
+ {
+ index=Gkey&HASHMASKSHALLOW;
+ if(shallow[index].lock==Glock && (hashcolor(shallow[index].info)>>13)==(color>>1))
+ {
+ hashhit++;
+ /*found the right entry!*/
+ *forcefirst=shallow[index].best;
+ if(hashdepth(shallow[index].info)>=depth)
+ {
+ if(hashvaluetype(shallow[index].info) == EXACT)
+ {
+ *value=shallow[index].value;
+ return 1;
+ }
+ /* lower bound */
+ if(hashvaluetype(shallow[index].info) == LOWER)
+ {
+ if(shallow[index].value>=*beta) {*value=shallow[index].value;return 1;}
+ if(shallow[index].value>*alpha) {*alpha=shallow[index].value;}
+ return 0;
+ }
+ /* upper bound */
+ if(hashvaluetype(shallow[index].info) == UPPER)
+ {
+ if(shallow[index].value<=*alpha) {*value=shallow[index].value;return 1;}
+ if(shallow[index].value<*beta) {*beta=shallow[index].value;}
+ return 0;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+ */
+ #endif
Index: llvm/test/Programs/MultiSource/Applications/obsequi/tables.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/tables.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/tables.c Tue May 11 14:34:13 2004
***************
*** 0 ****
--- 1,227 ----
+
+
+ #include "globals.h"
+
+ #ifdef COUNTBITS16
+ s32bit countbits16[65536];
+
+ static void
+ init_countbits()
+ {
+ s32bit i;
+
+ countbits16[0] = 0;
+
+ for(i = 1; i < 65536; i++){
+ countbits16[i] = (i & 1) + countbits16[i >> 1];
+ }
+ }
+ #endif
+
+ #ifdef COUNTBITS8
+ s32bit countbits8[256];
+
+ static void
+ init_countbits()
+ {
+ s32bit i;
+
+ countbits8[0] = 0;
+
+ for(i = 1; i < 256; i++){
+ countbits8[i] = (i & 1) + countbits8[i >> 1];
+ }
+ }
+ #endif
+
+ #ifdef LASTBIT16
+ s32bit lastbit16[65536];
+
+ static void
+ init_lastbit()
+ {
+ s32bit i;
+
+ for(i = 1; i < 65536; i++){
+ if(i&NTH_BIT(0)) {lastbit16[i] = 0; continue;}
+ if(i&NTH_BIT(1)) {lastbit16[i] = 1; continue;}
+ if(i&NTH_BIT(2)) {lastbit16[i] = 2; continue;}
+ if(i&NTH_BIT(3)) {lastbit16[i] = 3; continue;}
+ if(i&NTH_BIT(4)) {lastbit16[i] = 4; continue;}
+ if(i&NTH_BIT(5)) {lastbit16[i] = 5; continue;}
+ if(i&NTH_BIT(6)) {lastbit16[i] = 6; continue;}
+ if(i&NTH_BIT(7)) {lastbit16[i] = 7; continue;}
+ if(i&NTH_BIT(8)) {lastbit16[i] = 8; continue;}
+ if(i&NTH_BIT(9)) {lastbit16[i] = 9; continue;}
+ if(i&NTH_BIT(10)) {lastbit16[i] = 10; continue;}
+ if(i&NTH_BIT(11)) {lastbit16[i] = 11; continue;}
+ if(i&NTH_BIT(12)) {lastbit16[i] = 12; continue;}
+ if(i&NTH_BIT(13)) {lastbit16[i] = 13; continue;}
+ if(i&NTH_BIT(14)) {lastbit16[i] = 14; continue;}
+ if(i&NTH_BIT(15)) {lastbit16[i] = 15; continue;}
+ }
+
+ lastbit16[0] = 100;
+ }
+ #endif
+
+ #ifdef LASTBIT8
+ s32bit lastbit8[256];
+
+ static void
+ init_lastbit()
+ {
+ s32bit i;
+
+ for(i = 1; i < 256; i++){
+ if(i&NTH_BIT(0)) {lastbit8[i] = 0; continue;}
+ if(i&NTH_BIT(1)) {lastbit8[i] = 1; continue;}
+ if(i&NTH_BIT(2)) {lastbit8[i] = 2; continue;}
+ if(i&NTH_BIT(3)) {lastbit8[i] = 3; continue;}
+ if(i&NTH_BIT(4)) {lastbit8[i] = 4; continue;}
+ if(i&NTH_BIT(5)) {lastbit8[i] = 5; continue;}
+ if(i&NTH_BIT(6)) {lastbit8[i] = 6; continue;}
+ if(i&NTH_BIT(7)) {lastbit8[i] = 7; continue;}
+ }
+
+ lastbit8[0] = 100;
+ }
+ #endif
+
+ #ifdef COUNTMOVES_TABLE
+ s32bit move_table16[65536];
+
+ static void
+ init_movetable()
+ {
+ u32bit i = 0, mask, tmp = 0, count;
+
+ while(i < 65536){
+ mask = i;
+ count = 0;
+
+ while(mask){
+ tmp = (mask&-mask); // least sig bit of m
+ mask &= ~(tmp | (tmp << 1)); // remove bit and next bit.
+ count++;
+ }
+
+ #ifndef BOARD_SIZE_LT_16
+ if(tmp & 0x00008000) count |= 0xF0000000;
+ #endif
+
+ move_table16[i] = count;
+ i++;
+ }
+ }
+ #else
+ #define init_movetable() ;
+ #endif
+
+ extern void
+ init_static_tables()
+ {
+ init_countbits();
+ init_lastbit();
+ init_movetable();
+ }
+
+
+ KeyInfo g_keyinfo[2][32][32];
+
+ static void
+ negate_keyinfo(KeyInfo_s *keyinfo)
+ {
+ keyinfo->bit1_index = keyinfo->bit2_index = -1;
+ keyinfo->hash_code = 0;
+ }
+
+
+ static void
+ fill_in_hash_code(KeyInfo_s *info, s32bit num_cols)
+ {
+ s32bit r, c, hash = 0;
+
+ r = info->bit1_index/num_cols;
+ c = info->bit1_index%num_cols;
+
+ hash = g_zobrist[r+1][c+1];
+
+ r = info->bit2_index/num_cols;
+ c = info->bit2_index%num_cols;
+
+ hash ^= g_zobrist[r+1][c+1];
+
+ info->hash_code = hash;
+ }
+
+
+ static void
+ fill_in_key_entry(KeyInfo *keyinfo, s32bit num_rows, s32bit num_cols)
+ {
+ if(keyinfo->norm.bit1_index == -1){
+ negate_keyinfo( & keyinfo->norm);
+ negate_keyinfo( & keyinfo->flipV);
+ negate_keyinfo( & keyinfo->flipH);
+ negate_keyinfo( & keyinfo->flipVH);
+ } else {
+ s32bit r1, c1, r2, c2;
+
+ r1 = keyinfo->norm.bit1_index/num_cols;
+ c1 = keyinfo->norm.bit1_index%num_cols;
+ r2 = keyinfo->norm.bit2_index/num_cols;
+ c2 = keyinfo->norm.bit2_index%num_cols;
+
+ keyinfo->flipV.bit1_index = (r1*num_cols)+(num_cols - c1 - 1);
+ keyinfo->flipV.bit2_index = (r2*num_cols)+(num_cols - c2 - 1);
+
+ keyinfo->flipH.bit1_index = ((num_rows - r1 - 1) * num_cols) + c1;
+ keyinfo->flipH.bit2_index = ((num_rows - r2 - 1) * num_cols) + c2;
+
+ keyinfo->flipVH.bit1_index = ( ((num_rows - r1 - 1) * num_cols)
+ + (num_cols - c1 - 1) );
+ keyinfo->flipVH.bit2_index = ( ((num_rows - r2 - 1) * num_cols)
+ + (num_cols - c2 - 1) );
+
+ fill_in_hash_code( & keyinfo->norm, num_cols);
+ fill_in_hash_code( & keyinfo->flipV, num_cols);
+ fill_in_hash_code( & keyinfo->flipH, num_cols);
+ fill_in_hash_code( & keyinfo->flipVH, num_cols);
+ }
+ }
+
+
+ extern void
+ init_less_static_tables()
+ {
+ s32bit n_rows, n_cols, i, j, k;
+
+ n_rows = g_board_size[HORIZONTAL], n_cols = g_board_size[VERTICAL];
+
+ for(i = 0; i < 32; i++)
+ for(j = 0; j < 32; j++)
+ for(k = 0; k < 2; k++)
+ negate_keyinfo( & g_keyinfo[k][i][j].norm);
+
+ for(i = 0; i < n_rows; i++){
+ for(j = 0; j < n_cols; j++){
+ //Horizontal Entry
+ if(j + 1 < n_cols){
+ g_keyinfo[HORIZONTAL][i+1][j+1].norm.bit1_index = (i*n_cols)+j;
+ g_keyinfo[HORIZONTAL][i+1][j+1].norm.bit2_index = (i*n_cols)+(j+1);
+ }
+
+ //Vertical Entry
+ if(i + 1 < n_rows){
+ g_keyinfo[VERTICAL][j+1][i+1].norm.bit1_index = (i*n_cols)+j;
+ g_keyinfo[VERTICAL][j+1][i+1].norm.bit2_index = ((i+1)*n_cols)+j;
+ }
+ }
+ }
+
+ for(i = 0; i < 32; i++)
+ for(j = 0; j < 32; j++)
+ for(k = 0; k < 2; k++)
+ fill_in_key_entry(&g_keyinfo[k][i][j], n_rows, n_cols);
+ }
+
Index: llvm/test/Programs/MultiSource/Applications/obsequi/toggle_move.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/toggle_move.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/toggle_move.c Tue May 11 14:34:13 2004
***************
*** 0 ****
--- 1,189 ----
+
+ #include "globals.h"
+ #include "macros.h"
+
+ //########################################################
+ // This function counts the number of safe moves in a row.
+ //
+ // Never call this function for rows 0 or 31.
+ //########################################################
+ static inline s32bit
+ count_safe(s32bit player, s32bit row)
+ {
+ u32bit guard = g_board[player][row-1] & g_board[player][row+1];
+
+ // mask contains a bit for each safe move.
+ u32bit mask= ( (~(g_board[player][row] | (g_board[player][row] << 1)))
+ & (guard & (guard << 1)) );
+
+ return COUNTMOVES(mask);
+ }
+
+ //########################################################
+ // This function counts the number of real moves in a row.
+ //
+ // Never call this function for rows 0 or 31.
+ //########################################################
+ static inline s32bit
+ count_real(s32bit player, s32bit row)
+ {
+ // mask contains a bit for each real move.
+ u32bit mask= ~(g_board[player][row] | (g_board[player][row] << 1));
+
+ return COUNTMOVES(mask);
+ }
+
+
+ static inline void
+ _update_safe(s32bit player, s32bit row)
+ {
+ s32bit count = count_safe(player, row);
+
+ g_info_totals[player].safe += count - g_info[player][row].safe;
+ g_info[player][row].safe = count;
+ }
+
+ static inline void
+ _update_real(s32bit player, s32bit row)
+ {
+ s32bit count = count_real(player, row);
+
+ g_info_totals[player].real += count - g_info[player][row].real;
+ g_info[player][row].real = count;
+ }
+
+
+
+ extern void
+ update_safe(s32bit player, s32bit row)
+ { _update_safe(player, row); }
+
+ extern void
+ update_real(s32bit player, s32bit row)
+ { _update_real(player, row); }
+
+ extern void
+ toggle_move(Move move, s32bit player)
+ {
+ s32bit row, col, horz_play, vert_play;
+
+ row = (move).array_index, col = (move).mask_index;
+ horz_play = player & PLAYER_MASK;
+ vert_play = player ^ PLAYER_MASK;
+
+ g_board[horz_play][row] ^= (3<<col);
+ g_board[vert_play][col] ^= (1<<row);
+ g_board[vert_play][col+1] ^= (1<<row);
+
+ // update safe moves
+ if(row - 1 != 0)
+ _update_safe(horz_play, row - 1);
+ _update_safe(horz_play, row);
+ if(row != g_board_size[horz_play])
+ _update_safe(horz_play, row + 1);
+
+ if(col - 1 != 0)
+ _update_safe(vert_play, col - 1);
+ if(col + 1 != g_board_size[vert_play])
+ _update_safe(vert_play, col + 2);
+
+ // update real moves
+ _update_real(horz_play, row);
+
+ _update_real(vert_play, col);
+ _update_real(vert_play, col + 1);
+ }
+
+
+ //#define DEBUG_SCORE_MOVE
+
+ static inline s32bit
+ score_move(Move move, s32bit player)
+ {
+ s32bit row, col, horz_play, vert_play;
+ s32bit score;
+
+ row = move.array_index, col = move.mask_index;
+ horz_play = player & PLAYER_MASK;
+ vert_play = player ^ PLAYER_MASK;
+
+ g_board[horz_play][row] ^= (3<<col);
+ g_board[vert_play][col] ^= (1<<row);
+ g_board[vert_play][col+1] ^= (1<<row);
+
+ // update real moves
+ score = count_real(horz_play, row) - g_info[horz_play][row].real;
+
+ score -= count_real(vert_play, col) - g_info[vert_play][col].real;
+ score -= count_real(vert_play, col + 1) - g_info[vert_play][col+1].real;
+
+ // update safe moves
+ if(row - 1 != 0)
+ score += count_safe(horz_play, row - 1) - g_info[horz_play][row-1].safe;
+ score += count_safe(horz_play, row) - g_info[horz_play][row].safe;
+ if(row != g_board_size[horz_play])
+ score += count_safe(horz_play, row+1) - g_info[horz_play][row+1].safe;
+
+ if(col - 1 != 0)
+ score -= count_safe(vert_play, col - 1) - g_info[vert_play][col-1].safe;
+ if(col + 1 != g_board_size[vert_play])
+ score -= count_safe(vert_play, col + 2) - g_info[vert_play][col+2].safe;
+
+ g_board[horz_play][row] ^= (3<<col);
+ g_board[vert_play][col] ^= (1<<row);
+ g_board[vert_play][col+1] ^= (1<<row);
+
+ score *= 128;
+ score += g_first_move[player][row][col];
+
+ return score;
+ }
+
+ extern void
+ score_and_get_first(Move movelist[MAXMOVES], s32bit num_moves,
+ s32bit player, Move first)
+ {
+ s32bit i, max = -50000, max_index = -1;
+
+ //========================================================
+ // Give the move from the hashtable a large sorting value.
+ //========================================================
+ /*
+ {
+ int z = 0;
+ for (z = 0; z < num_moves; z++)
+ printf("> %d %d\n", movelist[z].array_index, movelist[z].mask_index);
+ }
+ */
+ if(first.array_index != -1){
+ for(i = 0; i < num_moves; i++){
+ if(first.array_index == movelist[i].array_index
+ && first.mask_index == movelist[i].mask_index){
+ movelist[i].info = 450000;
+ max_index = i;
+ } else {
+ movelist[i].info = score_move(movelist[i], player);
+ }
+ }
+ }
+
+ else {
+ for(i = 0; i < num_moves; i++){
+ movelist[i].info = score_move(movelist[i], player);
+ if(movelist[i].info > max){
+ max = movelist[i].info;
+ max_index = i;
+ }
+ }
+ }
+
+ if(max_index == -1) fatal_error(1, "No maximum\n");
+
+ // put biggest at front
+ if(num_moves > 1) {
+ Move tmp_move = movelist[max_index];
+ for(i = max_index; i > 0; i--)
+ movelist[i] = movelist[i - 1];
+ movelist[0] = tmp_move;
+ }
+ }
Index: llvm/test/Programs/MultiSource/Applications/obsequi/traits.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/traits.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/traits.c Tue May 11 14:34:13 2004
***************
*** 0 ****
--- 1,174 ----
+
+ #include "globals.h"
+ #include "macros.h"
+
+ static FILE *trait_file = NULL;
+
+
+ static s32bit
+ tr_total_non_safe_moves(s32bit player)
+ {
+ u32bit mask1, mask2;
+ s32bit num_rows = g_board_size[player];
+ s32bit count = 0, i;
+
+ for(i = 0; i < num_rows; i++){
+ mask1 = g_board[player][i] & g_board[player][i+2];
+ mask2 = ~g_board[player][i+1];
+
+ mask1 = (~((mask1 >> 1) & mask1)) & ((mask2 >> 1) & mask2);
+
+ // printf("%X\n", mask1);
+
+ count += countbits32(mask1);
+ }
+
+ return count;
+ }
+
+ static s32bit
+ tr_non_safe_moves_a_little_touchy(s32bit player)
+ {
+ u32bit mask1, mask2;
+ s32bit num_rows = g_board_size[player];
+ s32bit count = 0, i;
+
+ for(i = 0; i < num_rows; i++){
+ mask1 = g_board[player][i] | g_board[player][i+2];
+ mask2 = g_board[player][i+1];
+
+ mask1 = ( (mask1 << 1) | mask1
+ | (mask2 >> 1) | mask2 | (mask2 << 1) | (mask2 << 2) );
+
+ count += countbits32(~mask1);
+ }
+
+ if(count == -1){
+ print_board(player);
+ printf("%d %d\n", player, count);
+ exit(1);
+ }
+
+ return count;
+ }
+
+ static s32bit
+ tr_non_safe_moves_no_touchy(s32bit player)
+ {
+ return 1;
+ }
+
+ static s32bit
+ tr_total_empty_squares()
+ {
+ u32bit mask;
+ s32bit num_rows = g_board_size[0];
+ s32bit count = 0, i;
+
+ for(i = 0; i < num_rows; i++){
+ mask = ~(g_board[0][i+1]);
+
+ count += countbits32(mask);
+ }
+
+ return count;
+ }
+
+ static s32bit
+ tr_border_length_col(player)
+ {
+ u32bit mask;
+ s32bit num_rows = g_board_size[player];
+ s32bit count = 0, i;
+
+ for(i = 0; i <= num_rows; i++){
+ mask = g_board[player][i] ^ g_board[player][i+1];
+
+ count += countbits32(mask);
+ }
+
+ return count;
+ }
+
+ static s32bit
+ tr_border_length_row(player)
+ {
+ u32bit mask;
+ s32bit num_rows = g_board_size[player];
+ s32bit count = 0, i;
+
+ for(i = 0; i <= num_rows; i++){
+ mask = (g_board[player][i+1]>>1) ^ g_board[player][i+1];
+ mask &= 0x7FFFFFFF;
+
+ count += countbits32(mask);
+ }
+
+ return count;
+ }
+
+
+
+
+ extern void
+ write_node_info(u64bit num_nodes, s32bit winner)
+ {
+ s32bit num;
+
+ if(trait_file == NULL) {
+ trait_file = fopen("trait_file", "w");
+ if(trait_file == NULL)
+ fprintf(stderr, "Couldn't open \"trait_file\".\n");
+ }
+
+ fprintf(trait_file, "%c %15s :", (winner == VERTICAL) ? 'V' : 'H',
+ u64bit_to_string(num_nodes));
+
+ //========================================================
+ // number of non-safe moves.
+ //========================================================
+
+ // total number allowing overlapping of other non-safe moves
+ // and of safe moves.
+ num = tr_total_non_safe_moves(winner);
+ fprintf(trait_file, " %2d", num);
+
+ num = tr_total_non_safe_moves(winner^PLAYER_MASK);
+ fprintf(trait_file, " %2d :", num);
+
+
+ // non safe moves that don't touch a border, except diagonally.
+ num = tr_non_safe_moves_a_little_touchy(winner);
+ fprintf(trait_file, " %2d", num);
+
+ num = tr_non_safe_moves_a_little_touchy(winner^PLAYER_MASK);
+ fprintf(trait_file, " %2d :", num);
+
+
+ // non safe moves that don't touch a border, never.
+ num = tr_non_safe_moves_no_touchy(winner);
+ fprintf(trait_file, " %2d", num);
+
+ num = tr_non_safe_moves_no_touchy(winner^PLAYER_MASK);
+ fprintf(trait_file, " %2d :", num);
+
+
+ //========================================================
+ // Miscellaneous other info.
+ //========================================================
+
+ // empty squares.
+ num = tr_total_empty_squares();
+ fprintf(trait_file, " %2d :", num);
+
+ // border length.
+ num = tr_border_length_col(winner);
+ fprintf(trait_file, " %2d", num);
+
+ // border length.
+ num = tr_border_length_row(winner);
+ fprintf(trait_file, " %2d", num);
+
+ fprintf(trait_file, "\n");
+ }
+
Index: llvm/test/Programs/MultiSource/Applications/obsequi/utils.c
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/utils.c:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/utils.c Tue May 11 14:34:13 2004
***************
*** 0 ****
--- 1,163 ----
+
+ #include "utils.h"
+
+ #include <stdarg.h>
+ #include <ctype.h>
+ #include <sys/stat.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+ #include <unistd.h>
+ #include <stdarg.h>
+ #include <regex.h>
+
+
+ //########################################################
+ // This function prints a message to both stderr and
+ // to the file ".fatal_error".
+ //
+ // If ERR_NUM != 0 then exit is called with the value ERR_NUM.
+ //########################################################
+ extern void
+ _fatal_error_aux(const char *file, const s32bit line, const s32bit err_num,
+ const char *format, ... )
+ {
+ va_list ap;
+ static FILE* err_file = NULL;
+ char *msg_type = (err_num == 0) ? "WARNING: " : "ERROR: ";
+
+ // only need to open this if not already open.
+ if(err_file == NULL) err_file = fopen(".fatal_error", "w");
+ if(err_file == NULL) fprintf(stderr, "Couldn't open \".fatal_error\".\n");
+
+ if(err_num == 0) {
+ // Check size of file, we don't want to end up filling up the whole disk.
+ s32bit size = ftell(err_file);
+ if(size == -1)
+ fatal_error(1, "size == -1.\n");
+
+ else if(size > (2<<24) + 2000 ){
+ return;
+ }
+
+ else if(size > (2<<24)){
+ fprintf(stderr, "Log file getting too large.\n");
+ fprintf(err_file, "Log file getting too large.\n");
+ }
+ }
+
+ // start writing the real message.
+ fprintf(stderr, msg_type);
+ fprintf(err_file, msg_type);
+
+ va_start (ap, format);
+ vfprintf (stderr, format, ap);
+ vfprintf (err_file, format, ap);
+ va_end (ap);
+
+ fprintf(stderr, "> File: %s, Line: %d.\n", file, line);
+ fprintf(err_file, "> File: %s, Line: %d.\n", file, line);
+
+ fflush(stderr);
+ fflush(err_file);
+
+ if (err_num != 0) exit(err_num);
+ }
+
+
+ //########################################################
+ // These are dynamic sprintf function, they malloc space as needed.
+ //########################################################
+
+ //========================================================
+ // This function stores the string created from FORMAT and the
+ // following args to the string STR, starting at position OFFSET.
+ //========================================================
+ extern s32bit
+ Asprintf(char **str, s32bit *len, s32bit offset, const char *format, ... )
+ {
+ va_list ap;
+ s32bit nchars;
+
+ va_start (ap, format);
+
+ // if no space allocated yet, allocate some.
+ if(*len == 0){ *len = 128; *str = malloc(*len); }
+
+ while (1) {
+ // attempt printing in the allocated space
+ nchars = vsnprintf (*str + offset, *len - offset, format, ap);
+
+ if (nchars < *len - offset) break;
+
+ // if not enough space allocate some more.
+ *len += 128;
+ *str = realloc(*str, *len);
+ }
+
+ va_end (ap);
+ return nchars;
+ }
+
+ //========================================================
+ // This function stores the string created from FORMAT and the
+ // following args to the end of the string STR.
+ //========================================================
+ extern s32bit
+ asprintf_my(char **str, s32bit offset, const char *format, ... )
+ {
+ va_list ap;
+ s32bit nchars, len = ALLOCED(*str,char);
+
+ va_start (ap, format);
+
+ // if no space allocated yet, allocate some.
+ if(len == 0){ len = 128; *str = malloc(len); }
+
+ while (1) {
+ // attempt printing in the allocated space
+ nchars = vsnprintf (*str + offset, len - offset, format, ap);
+
+ if (nchars < len - offset) break;
+
+ // if not enough space allocate some more.
+ len += 128;
+ *str = realloc(*str, len);
+ }
+
+ va_end (ap);
+ return nchars;
+ }
+
+
+ //########################################################
+ // Return a string with the printed value of a 64 bit number.
+ //########################################################
+ extern const char*
+ u64bit_to_string(u64bit val)
+ {
+ static char big_num[80]; // plenty large
+ s32bit vals[10]; // plenty large
+ s32bit i = 0, offset;
+
+ do {
+ vals[i] = val % 1000;
+ val = val / 1000;
+ i++;
+ } while(val != 0);
+
+ offset = sprintf(big_num, "%d", vals[--i]);
+
+ while(i != 0)
+ offset += sprintf(big_num + offset, ",%03d", vals[--i]);
+
+ return big_num;
+ }
+
+
+ //########################################################
+ // I'm not sure why I have this function.
+ // I suppose it may come in useful for performance analysis.
+ //########################################################
+ extern void
+ null_command() {}
+
Index: llvm/test/Programs/MultiSource/Applications/obsequi/utils.h
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/utils.h:1.1
*** /dev/null Tue May 11 14:34:23 2004
--- llvm/test/Programs/MultiSource/Applications/obsequi/utils.h Tue May 11 14:34:13 2004
***************
*** 0 ****
--- 1,143 ----
+
+
+ #ifndef OBSEQUI_UTILS_H
+ #define OBSEQUI_UTILS_H
+
+ #define _GNU_SOURCE //Need this so that __USE_GNU is defined
+ #include <features.h>
+
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <malloc.h>
+ #include <string.h>
+
+
+ //#################################################################
+ // Define a couple of types which I like to use.
+ //#################################################################
+
+ typedef u_int8_t u8bit;
+ typedef u_int16_t u16bit;
+ typedef u_int32_t u32bit;
+ typedef u_int64_t u64bit;
+
+ typedef int16_t s16bit;
+ typedef int32_t s32bit;
+
+
+ //#################################################################
+ // Define a number of useful constants and macros.
+ //#################################################################
+
+ //=================================================================
+ // I think that DEFINED should always be defined.
+ // Also make sure NOT_DEFINED is not.
+ //=================================================================
+ #define DEFINED
+ #undef NOT_DEFINED
+
+ //=================================================================
+ // Determine the max value of two numbers.
+ //=================================================================
+ #define MAX_TWO(a,b) (((a) > (b)) ? (a) : (b))
+
+ //=================================================================
+ // Determine the min value of two numbers.
+ //=================================================================
+ #define MIN_TWO(a,b) (((a) > (b)) ? (b) : (a))
+
+ //=================================================================
+ // Constants and Macros for dealing with bit masks.
+ //=================================================================
+ #define ALL_BITS 0xFFFFFFFF
+ #define NTH_BIT(i) ( 1 << (i) )
+ #define FIRST_N_BITS(i) (~(ALL_BITS << (i)))
+ #define LAST_N_BITS(i) (~(ALL_BITS >> (i)))
+
+ //=================================================================
+ // Determine how many elements have been alloced for ptr.
+ // - this probably only works if using glibc.
+ //=================================================================
+ #define ALLOCED(ptr,type) (malloc_usable_size(ptr)/sizeof(type))
+
+
+ //########################################################
+ // The following functions print a message to both stderr and
+ // to the file ".fatal_error". These messages can be helpful
+ // for debugging since they contain both the file name and line number
+ // of where this function was called. (They all return void.)
+ //########################################################
+
+ //========================================================
+ // Besides printing a message this function also causes the
+ // program to exit with the value 'err_num'.
+ //========================================================
+ #define fatal_error(err_num, format, rest...) \
+ (_fatal_error((err_num) ? (err_num) : 256, format, ## rest ))
+
+ //========================================================
+ // This function justs prints the message.
+ //========================================================
+ #define warning(format, rest...) \
+ (_fatal_error(0, format, ## rest ))
+
+ //========================================================
+ // This function prints the message "Check Point."
+ // Exclusively used for debugging.
+ //========================================================
+ #define check_point() \
+ (_fatal_error(0, "Check Point.\n"))
+
+
+ #define _fatal_error(err_num, format, rest...) \
+ (_fatal_error_aux(__FILE__, __LINE__, (err_num), format, ## rest ))
+
+
+ //########################################################
+ // These are dynamic sprintf function, they malloc space as needed.
+ //########################################################
+
+ //========================================================
+ // stores the string created from FORMAT, and ..., in *str.
+ //
+ // allocates space as needed.
+ // returns the number of characters written to *str.
+ //========================================================
+ extern s32bit
+ Asprintf(char **str, s32bit *len, s32bit offset, const char *format, ... )
+ __attribute__ ((format (printf, 4, 5)));
+
+ //========================================================
+ // returns the number of characters written to *(str+offset)
+ //========================================================
+ extern s32bit
+ asprintf_my(char **str, s32bit offset, const char *format, ... )
+ __attribute__ ((format (printf, 3, 4)));
+
+
+
+ //########################################################
+ // This function does absolutely nothing.
+ //########################################################
+ extern void
+ null_command();
+
+
+ //########################################################
+ // Return a string with the printed value of a 64 bit number.
+ // Note: It returns a static buffer so don't free it, and
+ // always copy the value before you call it again.
+ //########################################################
+ extern const char*
+ u64bit_to_string(u64bit val);
+
+
+ //########################################################
+ // Internals.
+ //########################################################
+ extern void
+ _fatal_error_aux(const char *file, const s32bit line,
+ const s32bit err_num, const char *format, ... )
+ __attribute__ ((format (printf, 4, 5)));
+
+ #endif
More information about the llvm-commits
mailing list