X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=gnushogi%2Fcommondsp.c;h=b8e1ca8a2eee623b44c4d99574c486a08ff020ec;hb=3498bb2ccdfccd0c5f5c25bc2e2a855ea5b9334f;hp=36a5f8dc41290a8254cb72779e8014ec824e028f;hpb=d5950fc45c863579313dd37abff008838c10c5ce;p=gnushogi.git diff --git a/gnushogi/commondsp.c b/gnushogi/commondsp.c index 36a5f8d..b8e1ca8 100644 --- a/gnushogi/commondsp.c +++ b/gnushogi/commondsp.c @@ -6,6 +6,7 @@ * ---------------------------------------------------------------------- * Copyright (c) 1993, 1994, 1995 Matthias Mutz * Copyright (c) 1999 Michael Vanier and the Free Software Foundation + * Copyright (c) 2008, 2013, 2014 Yann Dirson and the Free Software Foundation * * GNU SHOGI is based on GNU CHESS * @@ -31,6 +32,10 @@ * */ +/* request *snprintf prototypes */ +#define _POSIX_C_SOURCE 200112L +#include + #if defined HAVE_GETTIMEOFDAY #include #endif @@ -45,10 +50,11 @@ #include "gnushogi.h" char mvstr[4][6]; -char *InPtr; -int InBackground = false; +int mycnt1, mycnt2; +static char *InPtr; struct display *dsp = &raw_display; +short xboard = false; #if defined(BOOKTEST) @@ -89,20 +95,20 @@ movealgbr(short m, char *s) s++; *s = '*'; s++; - *s = cxx[column(t)]; + *s = COL_NAME(column(t)); s++; - *s = rxx[row(t)]; + *s = ROW_NAME(row(t)); s++; } else { - *s = cxx[column(f)]; + *s = COL_NAME(column(f)); s++; - *s = rxx[row(f)]; + *s = ROW_NAME(row(f)); s++; - *s = cxx[column(t)]; + *s = COL_NAME(column(t)); s++; - *s = rxx[row(t)]; + *s = ROW_NAME(row(t)); s++; if (flag & promote) @@ -133,7 +139,10 @@ movealgbr(short m, char *s) * - NO_SQUARES <= f NO_SQUARES + 2*NO_PIECES dropped piece modulo NO_PIECES * - t & 0x7f target square * - t & 0x80 promotion flag - * - flag FIXME: must be zero ? + * - flag + * - if flag & dropmask, piece type encoded in flag & pmask + * + * FIXME: that makes 2 ways to specify drops and promotions, why ? * * OUTPUT: * - GLOBAL mvstr @@ -162,7 +171,7 @@ algbr(short f, short t, short flag) if ((f == t) && ((f != 0) || (t != 0))) { - if (!barebones) { + if (!XSHOGI) { dsp->Printf("error in algbr: FROM=TO=%d, flag=0x%4x\n", t, flag); } @@ -173,9 +182,9 @@ algbr(short f, short t, short flag) short piece = flag & pmask; mvstr[0][0] = pxx[piece]; - mvstr[0][1] = '*'; - mvstr[0][2] = cxx[column(t)]; - mvstr[0][3] = rxx[row(t)]; + mvstr[0][1] = xboard ? '@' : '*'; + mvstr[0][2] = COL_NAME(column(t)); + mvstr[0][3] = ROW_NAME(row(t)); mvstr[0][4] = '\0'; strcpy(mvstr[1], mvstr[0]); strcpy(mvstr[2], mvstr[0]); @@ -183,20 +192,27 @@ algbr(short f, short t, short flag) } else if ((f != 0) || (t != 0)) { - /* algebraic notation */ - mvstr[0][0] = cxx[column(f)]; - mvstr[0][1] = rxx[row(f)]; - mvstr[0][2] = cxx[column(t)]; - mvstr[0][3] = rxx[row(t)]; - mvstr[0][4] = mvstr[3][0] = '\0'; + /* pure coordinates notation */ + mvstr[0][0] = COL_NAME(column(f)); + mvstr[0][1] = ROW_NAME(row(f)); + mvstr[0][2] = COL_NAME(column(t)); + mvstr[0][3] = ROW_NAME(row(t)); + mvstr[0][4] = '\0'; + + /* algebraic notation without disambiguation */ mvstr[1][0] = pxx[board[f]]; + mvstr[1][1] = mvstr[0][2]; /* to column */ + mvstr[1][2] = mvstr[0][3]; /* to row */ + mvstr[1][3] = '\0'; + /* algebraic notation with row disambiguation */ mvstr[2][0] = mvstr[1][0]; mvstr[2][1] = mvstr[0][1]; + mvstr[2][2] = mvstr[0][2]; /* to column */ + mvstr[2][3] = mvstr[0][3]; /* to row */ + mvstr[2][4] = '\0'; - mvstr[2][2] = mvstr[1][1] = mvstr[0][2]; /* to column */ - mvstr[2][3] = mvstr[1][2] = mvstr[0][3]; /* to row */ - mvstr[2][4] = mvstr[1][3] = '\0'; + /* algebraic notation with column disambiguation */ strcpy(mvstr[3], mvstr[2]); mvstr[3][1] = mvstr[0][0]; @@ -269,6 +285,7 @@ VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv) MoveList(opponent, 2, -1, true); generate_move_flags = false; pnt = TrPnt[2]; + if(s[4] == '=') s[4] = '\0'; /* deferral is implied */ while (pnt < TrPnt[3]) { @@ -295,7 +312,7 @@ VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv) if (SqAttacked(PieceList[opponent][0], computer, &blocked)) { UnmakeMove(opponent, &xnode, &tempb, &tempc, &tempsf, &tempst); - dsp->AlwaysShowMessage("Illegal move (in check) %s", s); + dsp->AlwaysShowMessage("Illegal move (in check): %s", s); return false; } else @@ -337,9 +354,9 @@ VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv) } } - dsp->AlwaysShowMessage("Illegal move (no match) %s", s); + dsp->AlwaysShowMessage("Illegal move (no match): %s", s); - if (!barebones && (cnt > 1)) + if (!XSHOGI && (cnt > 1)) { sprintf(buffer, "Ambiguous Move %s!", s); dsp->ShowMessage(buffer); @@ -350,7 +367,7 @@ VerifyMove(char *s, VerifyMove_mode iop, unsigned short *mv) static int -parser(char *f, int side, short *fpiece) +parser(char *f, short *fpiece) { int c1, r1, c2, r2; short i, p = false; @@ -369,17 +386,17 @@ parser(char *f, int side, short *fpiece) if (f[1] == '*' || f[1] == '\'') { - c2 = COL_NAME(f[2]); - r2 = ROW_NAME(f[3]); + c2 = COL_NUM(f[2]); + r2 = ROW_NUM(f[3]); return ((NO_SQUARES + *fpiece) << 8) | locn(r2, c2); } else { - c1 = COL_NAME(f[1]); - r1 = ROW_NAME(f[2]); - c2 = COL_NAME(f[3]); - r2 = ROW_NAME(f[4]); + c1 = COL_NUM(f[1]); + r1 = ROW_NUM(f[2]); + c2 = COL_NUM(f[3]); + r2 = ROW_NUM(f[4]); p = (f[5] == '+') ? 0x80 : 0; return (locn(r1, c1) << 8) | locn(r2, c2) | p; @@ -424,7 +441,7 @@ void RequestInputString(char* buffer, unsigned bufsize) } -void +static void GetGame(void) { FILE *fd; @@ -588,7 +605,7 @@ GetGame(void) InPtr = fname; skipb(); g = &GameList[GameCnt]; - g->gmove = parser(InPtr, side, &g->fpiece); + g->gmove = parser(InPtr, &g->fpiece); skip(); g->score = atoi(InPtr); skip(); @@ -647,7 +664,7 @@ GetGame(void) } -void +static void SaveGame(void) { FILE *fd; @@ -799,7 +816,7 @@ SaveGame(void) * xshogi wasn't defined -- wonder why? */ -void +static void GetXGame(void) { FILE *fd; @@ -928,7 +945,7 @@ GetXGame(void) } -void +static void SaveXGame(void) { FILE *fd; @@ -1008,7 +1025,7 @@ SaveXGame(void) } -void +static void BookSave(void) { FILE *fd; @@ -1023,8 +1040,10 @@ BookSave(void) RequestInputString(fname, sizeof(fname)-1); } - if (fname[0] == '\0') + if (fname[0] == '\0') { + dsp->AlwaysShowMessage("aborting book save"); return; + } if ((fd = fopen(fname, "a")) != NULL) { @@ -1227,7 +1246,7 @@ ListGame(void) } -void +static void FlagMove(char c) { switch(c) @@ -1253,7 +1272,7 @@ FlagMove(char c) * Undo the most recent half-move. */ -void +static void Undo(void) { short f, t; @@ -1310,59 +1329,7 @@ Undo(void) } -void -FlagString(unsigned short flags, char *s) -{ - short l, piece; - *s = '\0'; - - if (flags & promote) - strcat(s, " promote"); - - if (flags & dropmask) - strcat(s, " drop:"); - - if ((piece = (flags & pmask))) - { - l = strlen(s); - - if (is_promoted[piece]) - s[l++] = '+'; - - s[l++] = pxx[piece]; - s[l] = '\0'; - } - - if (flags & capture) - strcat(s, " capture"); - - if (flags & exact) - strcat(s, " exact"); - - if (flags & tesuji) - strcat(s, " tesuji"); - - if (flags & check) - strcat(s, " check"); - - if (flags & draw) - strcat(s, " draw"); - - if (flags & stupid) - strcat(s, " stupid"); - - if (flags & questionable) - strcat(s, " questionable"); - - if (flags & kingattack) - strcat(s, " kingattack"); - - if (flags & book) - strcat(s, " book"); -} - - -void +static void TestSpeed(void(*f)(short side, short ply, short in_check, short blockable), unsigned j) @@ -1416,10 +1383,10 @@ TestSpeed(void(*f)(short side, short ply, } -void +static void TestPSpeed(short(*f) (short side), unsigned j) { - short i; + unsigned i; long cnt, t1, t2; #ifdef HAVE_GETTIMEOFDAY struct timeval tv; @@ -1453,20 +1420,18 @@ TestPSpeed(short(*f) (short side), unsigned j) } -void -SetOppTime(char *s) +static void +SetOppTime(char *time) { - char *time; - int m, t, sec; + int m, t; - sec = 0; - time = &s[strlen("otime")]; t = (int)strtol(time, &time, 10); if (*time == ':') { time++; - sec = (int)strtol(time, &time, 10); + /* FIXME: sec is parsed but ignored */ + (void)strtol(time, &time, 10); } m = (int)strtol(time, &time, 10); @@ -1487,20 +1452,18 @@ SetOppTime(char *s) } -void -SetMachineTime(char *s) +static void +SetMachineTime(char *time) { - char *time; - int m, t, sec; + int m, t; - time = &s[strlen("time")]; - sec = 0; t = (int)strtol(time, &time, 10); if (*time == ':') { time++; - sec = (int)strtol(time, &time, 10); + /* FIXME: sec is parsed but ignored */ + (void)strtol(time, &time, 10); } m = (int)strtol(time, &time, 10); @@ -1520,6 +1483,122 @@ SetMachineTime(char *s) } } +/* + * Set up a board position. Pieces are entered by typing the piece followed + * by the location. For example, Nf3 will place a knight on square f3. + */ +static void +ReadFEN(char *fen) +{ + short a = white, r, c, sq, i, error = 0; + char s[80]; + + flag.regularstart = true; + Book = BOOKFAIL; + + for (sq = 0; sq < NO_SQUARES; sq++) + { + board[sq] = no_piece; + color[sq] = neutral; + } + + ClearCaptured(); + + /* read board */ + r = NO_ROWS-1; c = 0; + while(*fen) + { + if (isdigit(*fen)) + { + c += *fen++ - '0'; /* assumes single digit! */ + } + else if (*fen == '/') + { /* next rank */ + if (c != NO_COLS) error++; + c = 0; fen++; + if (--r < 0) break; + } + else + { + int promo = 0, found = 0; + if (*fen == '+') + { + promo++; fen++; + } + + if (!isalpha(*fen)) break; + + for (i = no_piece; i <= king; i++) + { + if ((*fen == pxx[i]) || (*fen == qxx[i])) + { + sq = locn(r, c); + color[sq] = (islower(*fen) ? white : black); + if (promo) + board[sq] = promoted[i]; + else + board[sq] = i; + + found = 1; + break; + } + } + + if (!found) error++; + c++; fen++; + } + } + if(r || c != NO_COLS) error++; + + while (*fen == ' ') fen++; + + /* read holdings */ + if(!strncmp(fen, "[-]", 3)) fen += 3; /* empty holdings */ + else if(*fen == '[') + { + fen++; + while(isalpha(*fen)) + { + int found = 0; + for (i = pawn; i <= king; i++) + { + if ((*fen == pxx[i]) || (*fen == qxx[i])) + { + Captured[islower(*fen) ? white : black][i]++; + found = 1; + break; + } + } + if (!found) error++; + fen++; + } + if(*fen == ']') fen++; else error++; + } + + while (*fen == ' ') fen++; + + if (*fen == 'w') + a = black; + else if (*fen == 'b') + a = white; + else + error++; + + if (error) printf("tellusererror bad FEN\n"); + + for (sq = 0; sq < NO_SQUARES; sq++) + Mvboard[sq] = ((board[sq] != Stboard[sq]) ? 10 : 0); + + computer = otherside[a]; + opponent = a; + flag.force = true; + GameCnt = 0; + Game50 = 1; + ZeroRPT(); + Sdepth = 0; + InitializeStats(); +} + /* FIXME! This is truly the function from hell! */ @@ -1527,19 +1606,20 @@ SetMachineTime(char *s) * Process the user's command. If easy mode is OFF (the computer is thinking * on opponents time) and the program is out of book, then make the 'hint' * move on the board and call SelectMove() to find a response. The user - * terminates the search by entering ^C (quit siqnal) before entering a - * command. If the opponent does not make the hint move, then set Sdepth to - * zero. + * terminates the search by entering a command. If the opponent does not make + * the hint move, then set Sdepth to zero. */ -void -InputCommand(char *command) +int +InputCommand(char *command, int root) { - int eof = 0; +#ifdef QUIETBACKGROUND short have_shown_prompt = false; +#endif short ok, done, is_move = false; unsigned short mv; - char s[80], sx[80]; + char s[200], sx[200]; + static char backlog[200]; ok = flag.quit = done = false; player = opponent; @@ -1549,7 +1629,7 @@ InputCommand(char *command) ZeroTTable(); #endif - if ((hint > 0) && !flag.easy && !flag.force) + if ((hint > 0) && !flag.easy && !flag.force && !command && !backlog[0] && root) { /* * A hint move for the player is available. Compute a move for the @@ -1562,10 +1642,8 @@ InputCommand(char *command) algbr((short) hint >> 8, (short) hint & 0xff, false); strcpy(s, mvstr[0]); -#if !defined NOPOST if (flag.post) dsp->GiveHint(); -#endif /* do the hint move */ if (VerifyMove(s, VERIFY_AND_TRY_MODE, &mv)) @@ -1615,6 +1693,10 @@ InputCommand(char *command) { player = opponent; + if (flag.analyze && !command && !backlog[0] && root) { + SelectMove(opponent, BACKGROUND_MODE); + } + #ifdef QUIETBACKGROUND if (!have_shown_prompt) { @@ -1628,24 +1710,28 @@ InputCommand(char *command) have_shown_prompt = false; #endif /* QUIETBACKGROUND */ - if (command == NULL) { - if (NOT_CURSES) - s[0] = '\0'; + if (!command && backlog[0]) command = backlog; /* pick up backlogged command */ - eof = dsp->GetString(sx); + if (command == NULL) { + int eof = dsp->GetString(sx); + if (eof) + dsp->ExitShogi(); } else { strcpy(sx, command); + backlog[0]= '\0'; /* make sure no backlog is left */ done = true; } - sscanf(sx, "%s", s); - - if (eof) - dsp->ExitShogi(); - - if (s[0] == '\0') + /* extract first word */ + if (sscanf(sx, "%s", s) < 1) continue; + if (!root && strcmp(s, ".")) + { /* during search most commands can only be done after abort */ + strcpy(backlog, sx); /* backlog the command */ + return true; /* and order search abort */ + } + if (strcmp(s, "bd") == 0) /* bd -- display board */ { /* FIXME: Hack alert! */ @@ -1662,29 +1748,83 @@ InputCommand(char *command) } else if (strcmp(s, "post") == 0) { - flag.post = !flag.post; + flag.post = (xboard ? 1 : !flag.post); } - else if (strcmp(s, "alg") == 0) + else if (strcmp(s, "nopost") == 0) { - /* noop */ ; /* alg */ + flag.post = 0; } - else if ((strcmp(s, "quit") == 0) - || (strcmp(s, "exit") == 0)) +#ifdef MINISHOGI + else if (strcmp(s, "variant") == 0) + { /* only variant we play is minishogi */ + printf("setup (P.BR.S...G.+.++.+Kp.br.s...g.+.++.+k) 5x5+5_shogi rbsgk/4p/5/P4/KGSBR [-] w 0 1\n"); + } +#endif + else if (strcmp(s, "alg") == 0 || + strcmp(s, "accepted") == 0 || strcmp(s, "rejected") == 0 || + strcmp(s, "variant") == 0 || strcmp(s, "computer") == 0) + { + /* noop */ ; + } + else if ((strcmp(s, "quit") == 0) || + (strcmp(s, "exit") == 0) && !xboard) { flag.quit = true; } -#if !defined NOPOST - else if (strcmp(s, "post") == 0) + else if (strcmp(s, "xboard") == 0) { - flag.post = !flag.post; + xboard = true; + strcpy(ColorStr[0], "White"); + strcpy(ColorStr[1], "Black"); } + else if (strcmp(s, "protover") == 0) + { + printf("feature option=\"tsume -check 0\"\n"); + printf("feature option=\"contempt -spin %d -1000 1000\"\n", contempt); + printf("feature option=\"Hash-file search depth -spin %d 0 100\"\n", HashDepth); + printf("feature option=\"Hash-file move number -spin %d 0 100\"\n", HashMoveLimit); + printf("feature myname=\"GNU %s %s\" ", +#ifdef MINISHOGI + "MiniShogi", +#else + "Shogi", #endif - else if ((strcmp(s, "set") == 0) - || (strcmp(s, "edit") == 0)) + PACKAGE_VERSION + ); + printf("variants=\"%s\" ", +#ifdef MINISHOGI + "5x5+5_shogi,minishogi" +#else + "shogi" +#endif + ); + printf("debug=1 setboard=1 sigint=0 memory=1 done=1\n"); + } + else if (strcmp(s, ".") == 0) + { // periodic update request of analysis info: send stat01 info + ElapsedTime(2); + algbr((short)(currentMove >> 8), (short)(currentMove & 0xFF), 0); + printf("stat01: %4ld %8ld %2d %2d %2d %s\n", + et, NodeCnt, Sdepth, movesLeft, TrPnt[2]-TrPnt[1], mvstr[0]); + fflush(stdout); + if (!root) return false; /* signal no abort needed */ + } + else if (strcmp(s, "exit") == 0) + { + flag.analyze = false; + flag.force = true; + } + else if (strcmp(s, "analyze") == 0) + { + flag.analyze = true; + flag.force = true; + } + else if ((strcmp(s, "set") == 0) || + (strcmp(s, "edit") == 0)) { dsp->EditBoard(); } - else if ((strcmp(s, "setup") == 0)) + else if (strcmp(s, "setup") == 0) { dsp->SetupBoard(); } @@ -1692,6 +1832,17 @@ InputCommand(char *command) { ok = true; } +#if ttblsz + else if (strcmp(s, "memory") == 0) + { + unsigned int mem, size, t = 1; + sscanf(sx, "memory %d", &mem); + if(mem > 2048) mem = 2048; /* prevent integer overflow for > 2GB hash */ + size = (mem << 20) / sizeof(struct hashentry) - rehash; + while(t <= size/4) t <<= 1; + AllocateTT(t); + } +#endif else if (strcmp(s, "go") == 0) { ok = true; @@ -1738,14 +1889,21 @@ InputCommand(char *command) NewGame(); dsp->UpdateDisplay(0, 0, 1, 0); } + else if (strcmp(s, "setboard") == 0) + { + ReadFEN(sx + 9); + } else if (strcmp(s, "list") == 0) { ListGame(); } - else if ((strcmp(s, "level") == 0) - || (strcmp(s, "clock") == 0)) + else if (strcmp(s, "level") == 0) { - dsp->SelectLevel(sx); + dsp->SelectLevel(sx + strlen("level")); + } + else if (strcmp(s, "clock") == 0) + { + dsp->SelectLevel(sx + strlen("clock")); } else if (strcmp(s, "hash") == 0) { @@ -1761,11 +1919,12 @@ InputCommand(char *command) } else if (strcmp(s, "time") == 0) { - SetMachineTime(sx); + SetMachineTime(sx + strlen("time")); } - else if (strcmp(s, "otime") == 0) + else if ((strcmp(s, "otime") == 0) || + (xboard && (strcmp(s, "otim")) == 0)) { - SetOppTime(sx); + SetOppTime(sx + strlen("otime")); } else if (strcmp(s, "Awindow") == 0) { @@ -1806,8 +1965,9 @@ InputCommand(char *command) flag.force = false; Sdepth = 0; ok = true; + dsp->UpdateDisplay(0, 0, 1, 0); } - else if (strcmp(s, "black") == 0) + else if (xboard ? strcmp(s, "white") == 0 : strcmp(s, "black") == 0) { computer = white; opponent = black; @@ -1819,7 +1979,7 @@ InputCommand(char *command) * ok = true; don't automatically start with black command */ } - else if (strcmp(s, "white") == 0) + else if (xboard ? strcmp(s, "black") == 0 : strcmp(s, "white") == 0) { computer = black; opponent = white; @@ -1854,12 +2014,12 @@ InputCommand(char *command) BookSave(); } #ifdef EASY_OPENINGS - else if ((strcmp(s, "?") == 0) - || (strcmp(s, "!") == 0) - || (strcmp(s, "~") == 0)) + else if ((strcmp(s, "?") == 0) || + (strcmp(s, "!") == 0) || + (strcmp(s, "~") == 0)) #else - else if ((strcmp(s, "?") == 0) - || (strcmp(s, "!") == 0)) + else if ((strcmp(s, "?") == 0) || + (strcmp(s, "!") == 0)) #endif { FlagMove(*s); @@ -1874,7 +2034,11 @@ InputCommand(char *command) } else if (strcmp(s, "depth") == 0) { - dsp->ChangeSearchDepth(); + dsp->ChangeSearchDepth(sx + strlen("depth")); + } + else if (strcmp(s, "sd") == 0) + { + dsp->ChangeSearchDepth(sx + strlen("sd")); } else if (strcmp(s, "hashdepth") == 0) { @@ -1892,6 +2056,14 @@ InputCommand(char *command) { flag.easy = !flag.easy; } + else if (strcmp(s, "option") == 0) + { + sscanf(sx, "option tsume=%hd", &flag.tsume) || + sscanf(sx, "option hash=%hd", &flag.hash) || + sscanf(sx, "option Hash-file search depth=%hd", &HashDepth) || + sscanf(sx, "option Hash-file move number=%hd", &HashMoveLimit) || + sscanf(sx, "option contempt=%hd", &contempt); + } else if (strcmp(s, "tsume") == 0) { flag.tsume = !flag.tsume; @@ -2019,45 +2191,7 @@ InputCommand(char *command) printf("%d. %s %ld\n", ++mycnt2, s, TimeControl.clock[player] * 10); } - -#ifdef notdef /* optional pass best line to frontend with move */ -# if !defined NOPOST - - if (flag.post && !flag.mate) - { - int i; - - printf(" %6d ", MSCORE); - - for (i = 1; MV[i] > 0; i++) - { - algbr((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false); - printf("%5s ", mvstr[0]); - } - } -# endif - printf("\n"); -#endif - } -} - - -void -SetTimeControl(void) -{ - if (TCflag) - { - TimeControl.moves[black] = TimeControl.moves[white] = TCmoves; - TimeControl.clock[black] += 6000L * TCminutes + TCseconds * 100; - TimeControl.clock[white] += 6000L * TCminutes + TCseconds * 100; - } - else - { - TimeControl.moves[black] = TimeControl.moves[white] = 0; - TimeControl.clock[black] = TimeControl.clock[white] = 0; } - flag.onemove = (TCmoves == 1); - et = 0; - ElapsedTime(COMPUTE_AND_INIT_MODE); + return true; }