void list_filter(list_t * list, board_t * board, move_test_t test, bool keep) { int pos; int i, move, value; ASSERT(list!=NULL); ASSERT(board!=NULL); ASSERT(test!=NULL); ASSERT(keep==true||keep==false); pos = 0; for (i = 0; i < LIST_SIZE(list); i++) { ASSERT(pos>=0&&pos<=i); move = LIST_MOVE(list,i); value = LIST_VALUE(list,i); if ((*test)(move,board) == keep) { list->move[pos] = move; list->value[pos] = value; pos++; } } ASSERT(pos>=0&&pos<=LIST_SIZE(list)); list->size = pos; // debug ASSERT(list_is_ok(list)); }
int search_full_root(list_t * list, board_t * board, int a, int b, int depth, int search_type, int ThreadId) { int value; ASSERT(list_is_ok(list)); ASSERT(board_is_ok(board)); ASSERT(depth_is_ok(depth)); ASSERT(search_type==SearchNormal||search_type==SearchShort); ASSERT(list==SearchRoot[ThreadId]->list); ASSERT(!LIST_IS_EMPTY(list)); ASSERT(board==SearchCurrent[ThreadId]->board); ASSERT(board_is_legal(board)); ASSERT(depth>=1); value = full_root(list,board,a,b,depth,0,search_type, ThreadId); ASSERT(value_is_ok(value)); ASSERT(LIST_VALUE(list,0)==value); return value; }
int search_full_root(list_t * list, board_t * board, int depth, int search_type) { int value, a, b; ASSERT(list_is_ok(list)); ASSERT(board_is_ok(board)); ASSERT(depth_is_ok(depth)); ASSERT(search_type==SearchNormal||search_type==SearchShort); ASSERT(list==SearchRoot->list); ASSERT(!LIST_IS_EMPTY(list)); ASSERT(board==SearchCurrent->board); ASSERT(board_is_legal(board)); ASSERT(depth>=1); if (SearchBest[SearchCurrent->multipv].value == 0){ a = -ValueInf; b = +ValueInf; } else{ a = SearchBest[SearchCurrent->multipv].value - 40; b = SearchBest[SearchCurrent->multipv].value + 40; } if (SearchInput->multipv > 0){ a = -ValueInf; b = +ValueInf; } value = full_root(list,board,a,b,depth,0,search_type); ASSERT(value_is_ok(value)); ASSERT(LIST_VALUE(list,0)==value); return value; }
void search() { int move; int depth; int i; bool search_ready; for (i = 0; i < MultiPVMax; i++){ save_multipv[SearchCurrent->multipv].mate = 0; save_multipv[SearchCurrent->multipv].depth = 0; save_multipv[SearchCurrent->multipv].max_depth = 0; save_multipv[SearchCurrent->multipv].value = 0; save_multipv[SearchCurrent->multipv].time = 0; save_multipv[SearchCurrent->multipv].node_nb = 0; strcpy(save_multipv[SearchCurrent->multipv].pv_string,""); } SearchInput->multipv = option_get_int("MultiPV")-1; SearchCurrent->multipv = 0; ASSERT(board_is_ok(SearchInput->board)); // opening book if (option_get_bool("OwnBook") && !SearchInput->infinite) { move = book_move(SearchInput->board); if (move != MoveNone) { // play book move SearchBest[SearchCurrent->multipv].move = move; SearchBest[SearchCurrent->multipv].value = 1; SearchBest[SearchCurrent->multipv].flags = SearchExact; SearchBest[SearchCurrent->multipv].depth = 1; SearchBest[SearchCurrent->multipv].pv[0] = move; SearchBest[SearchCurrent->multipv].pv[1] = MoveNone; search_update_best(); return; } } // SearchInput gen_legal_moves(SearchInput->list,SearchInput->board); if (LIST_SIZE(SearchInput->list) < SearchInput->multipv+1){ SearchInput->multipv = LIST_SIZE(SearchInput->list)-1; } if (LIST_SIZE(SearchInput->list) <= 1) { SearchInput->depth_is_limited = true; SearchInput->depth_limit = 4; // was 1 } // SearchInfo if (setjmp(SearchInfo->buf) != 0) { ASSERT(SearchInfo->can_stop); ASSERT(SearchBest->move!=MoveNone); search_update_current(); return; } // SearchRoot list_copy(SearchRoot->list,SearchInput->list); // SearchCurrent board_copy(SearchCurrent->board,SearchInput->board); my_timer_reset(SearchCurrent->timer); my_timer_start(SearchCurrent->timer); // init trans_inc_date(Trans); sort_init(); search_full_init(SearchRoot->list,SearchCurrent->board); // analyze game for evaluation if (SearchCurrent->board->piece_size[White] < 3 && SearchCurrent->board->piece_size[Black] < 3){ trans_endgame = true; } else{ trans_endgame = false; } // iterative deepening search_ready = false; for (depth = 1; depth < DepthMax; depth++) { for (SearchCurrent->multipv = 0; SearchCurrent->multipv <= SearchInput->multipv; SearchCurrent->multipv++){ if (DispDepthStart && SearchCurrent->multipv == 0) send("info depth %d",depth); SearchCurrent->max_extensions = depth * 10; SearchRoot->bad_1 = false; SearchRoot->change = false; board_copy(SearchCurrent->board,SearchInput->board); if (UseShortSearch && depth <= ShortSearchDepth) { search_full_root(SearchRoot->list,SearchCurrent->board,depth,SearchShort); } else { search_full_root(SearchRoot->list,SearchCurrent->board,depth,SearchNormal); } search_update_current(); if (DispDepthEnd && SearchCurrent->multipv == SearchInput->multipv) { send("info depth %d seldepth %d time %.0f nodes " S64_FORMAT " nps %.0f",depth,SearchCurrent->max_depth,SearchCurrent->time*1000.0,SearchCurrent->node_nb,SearchCurrent->speed); } // update search info if (depth >= 1) SearchInfo->can_stop = true; if (depth == 1 && LIST_SIZE(SearchRoot->list) >= 2 && LIST_VALUE(SearchRoot->list,0) >= LIST_VALUE(SearchRoot->list,1) + EasyThreshold) { SearchRoot->easy = true; } if (depth > 1) { SearchRoot->bad_2 = SearchRoot->bad_1; SearchRoot->bad_1 = false; ASSERT(SearchRoot->bad_2==(SearchBest->value<=SearchRoot->last_value-BadThreshold)); } SearchRoot->last_value = SearchBest[SearchCurrent->multipv].value; // stop search? if (SearchInput->depth_is_limited && SearchCurrent->multipv >= SearchInput->multipv && depth >= SearchInput->depth_limit) { SearchRoot->flag = true; } if (SearchInput->time_is_limited && SearchCurrent->time * 2 >= SearchInput->time_limit_1 && !SearchRoot->bad_2) { SearchRoot->flag = true; } if (SearchInput->time_is_limited && SearchCurrent->time >= SearchInput->time_limit_1 * EasyRatio && SearchRoot->easy) { ASSERT(!SearchRoot->bad_2); ASSERT(!SearchRoot->change); SearchRoot->flag = true; } if (SearchInput->time_is_limited && SearchCurrent->time >= SearchInput->time_limit_1 * EarlyRatio && !SearchRoot->bad_2 && !SearchRoot->change) { SearchRoot->flag = true; } if (SearchInfo->can_stop && (SearchInfo->stop || (SearchRoot->flag && !SearchInput->infinite))) { search_ready = true; break; } } if (search_ready) break; } }
VOID ShDestroyShell ( PSHELL Shell ) /*++ Routine Description: This routine destroys a new shell object. Arguments: Shell - Supplies a pointer to the shell to destroy. Return Value: None. --*/ { PSHELL_HERE_DOCUMENT HereDocument; if (Shell->PostForkCloseDescriptor != -1) { close(Shell->PostForkCloseDescriptor); } if (Shell->Prompt != NULL) { free(Shell->Prompt); Shell->Prompt = NULL; } ShRestoreRedirections(Shell, &(Shell->ActiveRedirectList)); while (LIST_EMPTY(&(Shell->Lexer.HereDocumentList)) == FALSE) { HereDocument = LIST_VALUE(Shell->Lexer.HereDocumentList.Next, SHELL_HERE_DOCUMENT, ListEntry); LIST_REMOVE(&(HereDocument->ListEntry)); ShDestroyHereDocument(HereDocument); } ShDestroyVariableList(&(Shell->VariableList)); ShDestroyFunctionList(Shell); ShDestroyAliasList(Shell); ShDestroySignalActionList(&(Shell->SignalActionList)); if (Shell->CommandName != NULL) { free(Shell->CommandName); } ShDestroyArgumentList(&(Shell->ArgumentList)); ShDestroyLexer(&(Shell->Lexer)); assert(LIST_EMPTY(&(Shell->ExecutionStack)) != FALSE); assert(LIST_EMPTY(&(Shell->ArgumentList)) != FALSE); umask(Shell->OriginalUmask); if (Shell->NonStandardError != NULL) { fclose(Shell->NonStandardError); Shell->NonStandardError = NULL; } free(Shell); return; }
BOOL ShFieldSplit ( PSHELL Shell, PSTR *StringBuffer, PUINTN StringBufferSize, PLIST_ENTRY ExpansionList, ULONG MaxFieldCount, PSTR **FieldsArray, PULONG FieldsArrayCount ) /*++ Routine Description: This routine performs field splitting on the given string. Arguments: Shell - Supplies a pointer to the shell instance. StringBuffer - Supplies a pointer where the address of the fields string buffer is on input. On output, this may contain a different buffer that all the fields point into. StringBufferSize - Supplies a pointer that contains the size of the fields string buffer. This value will be updated to reflect the new size. ExpansionList - Supplies a pointer to the list of expansions within this string. MaxFieldCount - Supplies a maximum number of fields to create. When this number is reached, the last field contains the rest of the string. Supply 0 to indicate no limit. FieldsArray - Supplies a pointer where the array of pointers to the fields will be returned. This array will contain a NULL entry at the end of it, though that entry will not be included in the field count. The caller is responsible for freeing this memory. FieldsArrayCount - Supplies a pointer where the number of elements in the returned field array will be returned on success. This number does not include the null terminator entry. Return Value: TRUE on success. FALSE on failure. --*/ { CHAR Character; UINTN CurrentFieldSize; BOOL DeleteField; BOOL Delimit; PSHELL_EXPANSION_RANGE Expansion; PSTR *Field; ULONG FieldCapacity; ULONG FieldCount; ULONG FieldIndex; UINTN Index; BOOL InEmptyAtExpansion; BOOL InsideExpansion; PVOID NewBuffer; BOOL Quoted; BOOL Result; UINTN SeparatorCount; UINTN SeparatorIndex; PSTR Separators; BOOL SkipCharacter; PSTR String; UINTN StringSize; String = *StringBuffer; StringSize = *StringBufferSize; // // Allocate an initial array. // FieldCount = 0; FieldIndex = 0; FieldCapacity = SHELL_INITIAL_FIELDS_COUNT; Field = malloc(FieldCapacity * sizeof(PSTR)); if (Field == NULL) { Result = FALSE; goto FieldSplitEnd; } memset(Field, 0, FieldCapacity * sizeof(PSTR)); Field[0] = String; // // Get the field separator variable. // Result = ShGetVariable(Shell, SHELL_IFS, sizeof(SHELL_IFS), &Separators, &SeparatorCount); if (Result == FALSE) { Separators = SHELL_IFS_DEFAULT; SeparatorCount = sizeof(SHELL_IFS_DEFAULT); } if (SeparatorCount != 0) { SeparatorCount -= 1; } // // Tee up the first expansion. // Expansion = NULL; if (LIST_EMPTY(ExpansionList) == FALSE) { Expansion = LIST_VALUE(ExpansionList->Next, SHELL_EXPANSION_RANGE, ListEntry); } // // Loop through every character in the input. // CurrentFieldSize = 0; Delimit = FALSE; InEmptyAtExpansion = FALSE; InsideExpansion = FALSE; SkipCharacter = FALSE; Index = 0; Quoted = FALSE; while (Index < StringSize - 1) { Character = String[Index]; // // If at the end of the expansion, move to the next expansion. Being // inside an expansion decides whether or not to look for field // separators or ordinary whitespace. // if (Expansion != NULL) { if ((Expansion->Type == ShellExpansionSplitOnNull) && (Quoted != FALSE) && (Index >= Expansion->Index)) { // // If there are no arguments, then an empty at expansion in // quotes may collapse to zero arguments. // if ((Expansion->Length == 0) && (LIST_EMPTY(ShGetCurrentArgumentList(Shell)) != FALSE)) { InEmptyAtExpansion = TRUE; } } while ((Expansion != NULL) && (Index == Expansion->Index + Expansion->Length)) { InsideExpansion = FALSE; if (Expansion->ListEntry.Next != ExpansionList) { Expansion = LIST_VALUE(Expansion->ListEntry.Next, SHELL_EXPANSION_RANGE, ListEntry); } else { Expansion = NULL; } } // // If inside an expansion, look for field separators. // if ((Expansion != NULL) && (Index >= Expansion->Index)) { InsideExpansion = TRUE; } } // // If the character is an escape, skip it and the next character. // if (Character == SHELL_CONTROL_ESCAPE) { Index += 2; assert(Index <= StringSize - 1); CurrentFieldSize += 1; continue; } else if (Character == SHELL_CONTROL_QUOTE) { Quoted = !Quoted; } // // If not inside an expansion, look for quotes or blanks. // if (InsideExpansion == FALSE) { // // It's not a quote, and it's not inside an expansion, so look // for white space to field split on. // if ((Quoted == FALSE) && (isspace(Character))) { if (CurrentFieldSize != 0) { Delimit = TRUE; } else { SkipCharacter = TRUE; } } // // This is inside an expansion. // } else { switch (Expansion->Type) { case ShellExpansionSplitOnNull: if (Character == '\0') { Delimit = TRUE; break; } // // Fall throuth. // case ShellExpansionFieldSplit: if (Quoted != FALSE) { break; } for (SeparatorIndex = 0; SeparatorIndex < SeparatorCount; SeparatorIndex += 1) { // // Treat carraige returns as equal to newlines. This is // cheating a bit, but the hope is it fixes up CRLFs // seamlessly without causing much other damage. // if ((Character == Separators[SeparatorIndex]) || ((Separators[SeparatorIndex] == '\n') && (Character == '\r'))) { Delimit = TRUE; // // Whitespace separators are treated differently than // other characters. Multiple whitespaces in a row are // glossed over. // if ((CurrentFieldSize == 0) && ((Character == ' ') || (Character == '\n') || (Character == '\r') || (Character == '\t'))) { Delimit = FALSE; SkipCharacter = TRUE; } break; } } break; case ShellExpansionNoFieldSplit: break; default: assert(FALSE); Result = FALSE; goto FieldSplitEnd; } } if (Delimit != FALSE) { Delimit = FALSE; SkipCharacter = TRUE; // // Stop if the desired maximum number of fields has been reached. // if (FieldIndex + 1 == MaxFieldCount) { break; } String[Index] = '\0'; CurrentFieldSize = 0; // // Expand the array size if needed. Leave space for an empty field // at the end. // if (FieldIndex + 2 >= FieldCapacity) { FieldCapacity *= 2; NewBuffer = realloc(Field, FieldCapacity * sizeof(PSTR)); if (NewBuffer == NULL) { Result = FALSE; goto FieldSplitEnd; } Field = NewBuffer; memset(Field + FieldIndex + 1, 0, (FieldCapacity - FieldIndex - 1) * sizeof(PSTR)); } DeleteField = FALSE; if (Index + 1 != StringSize) { // // For $@ expansions, an empty "$@" expands to zero fields, and // empty parameters within $@ are not removed. // if (InEmptyAtExpansion != FALSE) { if (strcmp(Field[FieldIndex], ShEmptyQuotedString) == 0) { DeleteField = TRUE; } // // Outside of expansions, remove empty fields. // } else if (InsideExpansion == FALSE) { if (Field[FieldIndex][0] == '\0') { DeleteField = TRUE; } } if (DeleteField == FALSE) { FieldIndex += 1; } Field[FieldIndex] = String + Index + 1; } InEmptyAtExpansion = FALSE; } // // If there were two whitespaces in a row, advance the field to skip // over them. // if (SkipCharacter != FALSE) { SkipCharacter = FALSE; // // If this is the end of the string, the field can't be walked // forward anymore. Remove the field. // if (Index + 2 == StringSize) { // // If this is the first field it can't be removed. That means // the whole string was whitespace. Null out the string and // return the 1 empty field. // if (FieldIndex == 0) { Field[0] = NULL; } else { FieldIndex -= 1; } } else { Field[FieldIndex] = String + Index + 1; } } else { CurrentFieldSize += 1; } Index += 1; } Result = TRUE; FieldCount = FieldIndex; // // Check the last field. // DeleteField = FALSE; if (Field[FieldIndex] == NULL) { DeleteField = TRUE; } else if (InEmptyAtExpansion != FALSE) { if (strcmp(Field[FieldIndex], ShEmptyQuotedString) == 0) { DeleteField = TRUE; } // // Outside of expansions, remove empty fields. // } else if (InsideExpansion == FALSE) { if (Field[FieldIndex][0] == '\0') { DeleteField = TRUE; } } if (DeleteField == FALSE) { FieldCount += 1; } // // Null terminate the field array. // assert(FieldCount < FieldCapacity); Field[FieldCount] = NULL; FieldSplitEnd: if (Result == FALSE) { if (Field != NULL) { free(Field); Field = NULL; } } *StringBuffer = String; *StringBufferSize = StringSize; *FieldsArray = Field; *FieldsArrayCount = FieldCount; return Result; }