#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
#if defined(_WIN32)
# include <process.h>
#else
+# include <arpa/inet.h>
+# include <sys/types.h>
+# include <unistd.h>
# include <sched.h>
#endif
#include "shogi.h"
+
+#if defined(TLP) || defined(DFPN_CLIENT)
+int CONV
+lock_init( lock_t *plock )
+{
+# if defined(_MSC_VER)
+ *plock = 0;
+# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+ *plock = 0;
+# else
+ if ( pthread_mutex_init( plock, 0 ) )
+ {
+ str_error = "pthread_mutex_init() failed.";
+ return -1;
+ }
+# endif
+ return 1;
+}
+
+
+int CONV
+lock_free( lock_t *plock )
+{
+# if defined(_MSC_VER)
+ *plock = 0;
+# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+ *plock = 0;
+# else
+ if ( pthread_mutex_destroy( plock ) )
+ {
+ str_error = "pthread_mutex_destroy() failed.";
+ return -1;
+ }
+# endif
+ return 1;
+}
+
+
+void CONV
+unlock( lock_t *plock )
+{
+# if defined(_MSC_VER)
+ *plock = 0;
+# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+ *plock = 0;
+# else
+ pthread_mutex_unlock( plock );
+# endif
+}
+
+
+void CONV
+lock( lock_t *plock )
+{
+# if defined(_MSC_VER)
+ while ( _InterlockedExchange( (void *)plock, 1 ) )
+ {
+ while ( *plock ) { tlp_yield();}
+ }
+# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+ int itemp;
+
+ for ( ;; )
+ {
+ asm ( "1: movl $1, %1 \n\t"
+ " xchgl (%0), %1 \n\t"
+ : "=g" (plock), "=r" (itemp) : "0" (plock) );
+ if ( ! itemp ) { return; }
+ while ( *plock ) { tlp_yield();}
+ }
+# else
+ pthread_mutex_lock( plock );
+# endif
+}
+
+
+void
+tlp_yield( void )
+{
+#if defined(_WIN32)
+ Sleep( 0 );
+#else
+ sched_yield();
+#endif
+}
+#endif /* TLP || DFPN_CLIENT */
+
+
+#if defined(DFPN_CLIENT)
+
+static int CONV proce_line( char *line_buf );
+# if defined(_WIN32)
+static unsigned int __stdcall dfpn_client_receiver( void *arg );
+# else
+static void *dfpn_client_receiver( void *arg );
+# endif
+
+void CONV
+dfpn_client_start( const tree_t * restrict ptree )
+{
+ if ( root_turn != min_posi_no_handicap.turn_to_move
+ || HAND_B != min_posi_no_handicap.hand_black
+ || HAND_W != min_posi_no_handicap.hand_white
+ || memcmp( BOARD, min_posi_no_handicap.asquare, nsquare ) )
+ {
+ sckt_shutdown( dfpn_client_sckt );
+ dfpn_client_sckt = SCKT_NULL;
+ return;
+ }
+
+ if ( dfpn_client_sckt != SCKT_NULL ) { return; }
+ if ( dfpn_client_str_addr[0] == '\0' ) { return; }
+
+ dfpn_client_sckt = sckt_connect( dfpn_client_str_addr, dfpn_client_port );
+ if ( dfpn_client_sckt == SCKT_NULL )
+ {
+ out_warning( "Connection to DFPN server failed." );
+ return;
+ }
+ else {
+ Out( "New connection to DFPN server: %s %d\n",
+ dfpn_client_str_addr, dfpn_client_port );
+ }
+
+# if defined(_WIN32)
+ if ( ! _beginthreadex( 0, 0, &dfpn_client_receiver, NULL, 0, 0 ) )
+ {
+ sckt_shutdown( dfpn_client_sckt );
+ dfpn_client_sckt = SCKT_NULL;
+ out_warning( "_beginthreadex() failed." );
+ }
+# else
+ {
+ pthread_t pt;
+ if ( pthread_create( &pt, &pthread_attr, &dfpn_client_receiver, NULL ) )
+ {
+ sckt_shutdown( dfpn_client_sckt );
+ dfpn_client_sckt = SCKT_NULL;
+ out_warning( "_beginthreadex() failed." );
+ }
+ }
+# endif
+
+ dfpn_client_out( "Client: anonymous\n" );
+}
+
+
+# if defined(_MSC_VER)
+# pragma warning(disable:4100)
+# elif defined(__ICC)
+# pragma warning(disable:869)
+# endif
+
+# if defined(_MSC_VER)
+static unsigned int __stdcall dfpn_client_receiver( void *arg )
+# else
+static void *dfpn_client_receiver( void *arg )
+#endif
+{
+#define SIZE_RECV_BUF ( 1024 * 16 )
+#define SIZE_LINE_BUF 1024
+ char recv_buf[ SIZE_RECV_BUF ];
+ char line_buf[ SIZE_LINE_BUF ];
+ char *str_end, *str_line_end;
+ size_t size;
+ int len_recv_buf;
+ struct timeval tv;
+ fd_set readfds;
+ int iret;
+
+ recv_buf[0] = '\0';
+
+ /* recv loop */
+ for ( ;; ) {
+
+ /* select loop */
+ for ( ;; ) {
+ tv.tv_sec = SEC_KEEP_ALIVE;
+ tv.tv_usec = 0;
+ FD_ZERO( &readfds );
+# if defined(_MSC_VER)
+# pragma warning(disable:4127)
+# endif
+ FD_SET( dfpn_client_sckt, &readfds );
+# if defined(_MSC_VER)
+# pragma warning(default:4127)
+# endif
+
+ iret = select( (int)dfpn_client_sckt+1, &readfds, NULL, NULL, &tv );
+ if ( iret == SOCKET_ERROR )
+ {
+ out_warning( "%s", str_error );
+ goto dfpn_client_receiver_shutdown;
+ }
+
+ /* message arrived */
+ if ( iret ) { break; }
+
+ /* timeout and keepalive */
+ lock( &dfpn_client_lock);
+ iret = dfpn_client_out( "ping\n" );
+ unlock( &dfpn_client_lock);
+ if ( iret < 0 ) { return 0; }
+ }
+
+ /* read messages */
+ len_recv_buf = (int)strlen( recv_buf );
+ str_end = recv_buf + len_recv_buf;
+
+ iret = recv( dfpn_client_sckt, str_end, SIZE_RECV_BUF-1-len_recv_buf, 0 );
+ if ( iret == SOCKET_ERROR )
+ {
+ str_error = str_WSAError( "recv() failed:" );
+ out_warning( "%s", str_error );
+ goto dfpn_client_receiver_shutdown;
+ }
+ if ( ! iret ) { goto dfpn_client_receiver_shutdown; }
+ recv_buf[ len_recv_buf + iret ] = '\0';
+
+ /* take each line */
+ lock( &dfpn_client_lock );
+ for ( ;; ) {
+
+ str_line_end = strchr( recv_buf, '\n' );
+ if ( str_line_end == NULL )
+ {
+ if ( iret + len_recv_buf + 1 >= SIZE_RECV_BUF )
+ {
+ unlock( &dfpn_client_lock );
+ out_warning( "%s", str_ovrflw_line );
+ goto dfpn_client_receiver_shutdown;
+ }
+ break;
+ }
+
+ size = str_line_end - recv_buf;
+ if ( size + 1 >= SIZE_LINE_BUF )
+ {
+ unlock( &dfpn_client_lock );
+ out_warning( "%s", str_ovrflw_line );
+ goto dfpn_client_receiver_shutdown;
+ }
+
+ memcpy( line_buf, recv_buf, size );
+ memmove( recv_buf, str_line_end+1, strlen(str_line_end+1) + 1 );
+
+ line_buf[size] = '\0';
+
+ if ( proce_line( line_buf ) < 0 )
+ {
+ unlock( &dfpn_client_lock );
+ out_warning( "invalid messages from DFPN server" );
+ goto dfpn_client_receiver_shutdown;
+ }
+ }
+ unlock( &dfpn_client_lock );
+ }
+
+ dfpn_client_receiver_shutdown:
+ sckt_shutdown( dfpn_client_sckt );
+ dfpn_client_sckt = SCKT_NULL;
+ out_warning( "A connection to DFPN server is down." );
+
+ return 0;
+}
+# if defined(_MSC_VER)
+# pragma warning(default:4100)
+# elif defined(__ICC)
+# pragma warning(default:869)
+#endif
+
+
+static int CONV proce_line( char *line_buf )
+{
+ const char *token;
+ volatile dfpn_client_cresult_t *pcresult;
+ char *last;
+
+ token = strtok_r( line_buf, str_delimiters, &last );
+ if ( token == NULL ) { return -1; }
+
+ /* check signature */
+ if ( strcmp( token, (const char *)dfpn_client_signature ) ) { return 1; }
+
+ token = strtok_r( NULL, str_delimiters, &last );
+ if ( token == NULL ) { return -1; }
+
+ /* root node */
+ if ( ! strcmp( token, "WIN" ) )
+ {
+ token = strtok_r( NULL, str_delimiters, &last );
+ if ( token == NULL || ! is_move( token ) ) { return -1; }
+ dfpn_client_rresult = dfpn_client_win;
+ dfpn_client_flag_read = 1;
+ memcpy( (char *)dfpn_client_str_move, token, 7 );
+ return 1;
+ }
+
+ if ( ! strcmp( token, "LOSE" ) )
+ {
+ dfpn_client_rresult = dfpn_client_lose;
+ dfpn_client_flag_read = 1;
+ return 1;
+ }
+
+ if ( ! strcmp( token, "UNSOLVED" ) )
+ {
+ dfpn_client_rresult = dfpn_client_misc;
+ dfpn_client_flag_read = 1;
+ return 1;
+ }
+
+ /* child node */
+ if ( ! is_move( token ) ) { return -1; }
+ if ( MAX_LEGAL_MOVES <= dfpn_client_num_cresult ) { return -1; }
+ pcresult = &dfpn_client_cresult[dfpn_client_num_cresult];
+ memcpy( (char *)pcresult->str_move, token, 7 );
+
+ token = strtok_r( NULL, str_delimiters, &last );
+ if ( token == NULL ) { return -1; }
+
+ if ( ! strcmp( token, "WIN" ) )
+ {
+ pcresult->result = dfpn_client_win;
+ dfpn_client_flag_read = 1;
+ dfpn_client_num_cresult += 1;
+ return 1;
+ }
+
+ if ( ! strcmp( token, "LOSE" ) )
+ {
+ pcresult->result = dfpn_client_lose;
+ dfpn_client_flag_read = 1;
+ dfpn_client_num_cresult += 1;
+ return 1;
+ }
+
+ if ( ! strcmp( token, "UNSOLVED" ) )
+ {
+ pcresult->result = dfpn_client_misc;
+ dfpn_client_flag_read = 1;
+ dfpn_client_num_cresult += 1;
+ return 1;
+ }
+
+ return -1;
+}
+
+#endif /* DFPN_CLINET */
+
+
#if defined(TLP)
# if defined(_WIN32)
}
-#if defined(MNJ_LAN)
+#if defined(MNJ_LAN) || defined(USI)
uint64_t
tlp_count_node( tree_t * restrict ptree )
{
}
-int
-lock_init( lock_t *plock )
-{
-# if defined(_MSC_VER)
- *plock = 0;
-# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
- *plock = 0;
-# else
- if ( pthread_mutex_init( plock, 0 ) )
- {
- str_error = "pthread_mutex_init() failed.";
- return -1;
- }
-# endif
- return 1;
-}
-
-
-int
-lock_free( lock_t *plock )
-{
-# if defined(_MSC_VER)
- *plock = 0;
-# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
- *plock = 0;
-# else
- if ( pthread_mutex_destroy( plock ) )
- {
- str_error = "pthread_mutex_destroy() failed.";
- return -1;
- }
-# endif
- return 1;
-}
-
-
-void
-unlock( lock_t *plock )
-{
-# if defined(_MSC_VER)
- *plock = 0;
-# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
- *plock = 0;
-# else
- pthread_mutex_unlock( plock );
-# endif
-}
-
-
-void
-lock( lock_t *plock )
-{
-# if defined(_MSC_VER)
- long l;
-
- for ( ;; )
- {
- l = _InterlockedExchange( (void *)plock, 1 );
- if ( ! l ) { return; }
- while ( *plock );
- }
-# elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
- int itemp;
-
- for ( ;; )
- {
- asm ( "1: movl $1, %1 \n\t"
- " xchgl (%0), %1 \n\t"
- : "=g" (plock), "=r" (itemp) : "0" (plock) );
- if ( ! itemp ) { return; }
- while ( *plock );
- }
-# else
- pthread_mutex_lock( plock );
-# endif
-}
-
-
-void
-tlp_yield( void )
-{
-#if defined(_WIN32)
- Sleep( 0 );
-#else
- sched_yield();
-#endif
-}
-
-
# if defined(_MSC_VER)
static unsigned int __stdcall start_address( void *arg )
# else
child->nperpetual_check = 0;
child->nsuperior_rep = 0;
child->nrep_tried = 0;
- child->nreject_tried = 0;
- child->nreject_done = 0;
child->ntrans_always_hit = 0;
child->ntrans_prefer_hit = 0;
child->ntrans_probe = 0;
child->anext_move[ply].move_cap2 = parent->anext_move[ply].move_cap2;
child->move_last[ply] = child->amove;
- child->stand_pat[ply] = parent->stand_pat[ply];
+ child->save_eval[ply] = parent->save_eval[ply];
child->current_move[ply-1] = parent->current_move[ply-1];
child->nsuc_check[ply-1] = parent->nsuc_check[ply-1];
child->nsuc_check[ply] = parent->nsuc_check[ply];
+ child->nrep = parent->nrep;
memcpy( child->hist_good, parent->hist_good, sizeof(parent->hist_good) );
memcpy( child->hist_tried, parent->hist_tried, sizeof(parent->hist_tried) );
- for ( i = 0; i < root_nrep + ply - 1; i++ )
+ for ( i = 0; i < child->nrep + ply - 1; i++ )
{
child->rep_board_list[i] = parent->rep_board_list[i];
child->rep_hand_list[i] = parent->rep_hand_list[i];
parent->nfour_fold_rep += child->nfour_fold_rep;
parent->nperpetual_check += child->nperpetual_check;
parent->nsuperior_rep += child->nsuperior_rep;
- parent->nreject_tried += child->nreject_tried;
- parent->nreject_done += child->nreject_done;
parent->ntrans_always_hit += child->ntrans_always_hit;
parent->ntrans_prefer_hit += child->ntrans_prefer_hit;
parent->ntrans_probe += child->ntrans_probe;
if ( child->tlp_abort || value <= parent->tlp_best ) { return; }
- ply = parent->tlp_ply;
- parent->tlp_best = (short)value;
- parent->pv[ply] = child->pv[ply];
+ ply = parent->tlp_ply;
+ parent->tlp_best = (short)value;
+ parent->pv[ply] = child->pv[ply];
+
+ lock( &parent->tlp_lock );
parent->current_move[ply] = child->current_move[ply];
-
memcpy( parent->hist_tried, child->hist_tried, sizeof(child->hist_tried) );
memcpy( parent->hist_good, child->hist_good, sizeof(child->hist_good) );
-
for ( i = ply; i < PLY_MAX; i++ )
{
parent->amove_killer[i] = child->amove_killer[i];
parent->killers[i] = child->killers[i];
}
+ unlock( &parent->tlp_lock );
}