#include "var.h"


static void     SetTestingDefaults(Signed2 * testDepth, Signed2 * testColor,
                                                   Signed4 testNrNodes);
static void     SetDefaults(Boolean * useTransTable, Boolean * useRefTable,
                           Unsigned1 * nrTtBits, Boolean * useTwoLevelTable,
                                            Boolean * useTtValue, Boolean * useTtMove, Boolean * timeStamp,
                                            Boolean * useFlag);
static void     PerformTest(Signed2 startingMove, Signed2 testColor,
                                            Signed2 testDepth);


void            TestArguments(int argc, char *argv[])
{
    Signed2         i;
    Signed2         testDepth,
                    testColor,
                    startingMove;
    MoveType        move;
    ValueType       value;
    char            s[MaxMoveLength];

    doTest = False;
    testDepth = testColor = -1;
    testNrNodes = -1;
    useTransTable = useRefTable = useTwoLevelTable = useTtValue = useTtMove = 2;
    useFlag = 2;
    timeStamp = 2;
    debugDepth = 0;
    nrTtBits = 0;
    keepPly = 0;
    keepMethod = Big1;
    for (i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-file") == 0) {
            i++;
            LoadGame(argv[i]);
        } else if (strcmp(argv[i], "-test") == 0) {
            interActive = False;
            i++;
            /* test vanaf zet argv[ i ] */
            if (argv[i][0] == '-') {
                printf("ERROR: move number expected after '-test'\n");
                exit(0);
            }
            startingMove = (Signed2) atoi(argv[i]);
            doTest = True;
        } else if (strcmp(argv[i], "-color") == 0) {
            interActive = False;
            i++;
            /* color = argv[ i ] */
            if (argv[i][0] == '-') {
                printf("ERROR: color expected after '-color'\n");
                exit(0);
            }
            if (strcmp(argv[i], "white") == 0) {
                testColor = White;
            } else if (strcmp(argv[i], "black") == 0) {
                testColor = Black;
            } else {
                printf("ERROR: 'white' or 'black' expected after '-color'\n");
                exit(0);
            }
        } else if (strcmp(argv[i], "-depth") == 0) {
            interActive = False;
            i++;
            /* diepte = argv[ i ] ply */
            if (argv[i][0] == '-') {
                printf("ERROR: ply number expected after '-depth'\n");
                exit(0);
            }
            testDepth = (Signed2) atoi(argv[i]);
        } else if (strcmp(argv[i], "-nodes") == 0) {
            interActive = False;
            i++;
            /* number of nodes = argv[ i ] ply */
            if (argv[i][0] == '-') {
                printf("ERROR: node number expected after '-nodes'\n");
                exit(0);
            }
            testNrNodes = (Signed4) atol(argv[i]);
        } else if (strcmp(argv[i], "-time") == 0) {
            interActive = False;
            i++;
            /* tijd = argv[ i ] sec */
            printf("Sorry, option '-time' is not yet implemented\n");
        } else if (strcmp(argv[i], "-transpos") == 0) {
            i++;
            /* transpo = argv[ i ] */
            if (argv[i][0] == '-' || strlen(argv[i]) != 1) {
                printf("ERROR: 0 or 1 expected after '-transpos'\n");
                exit(0);
            }
            useTransTable = (Signed2) atoi(argv[i]);
        } else if (strcmp(argv[i], "-refs") == 0) {
            i++;
            /* ref = argv[ i ] */
            if (argv[i][0] == '-' || strlen(argv[i]) != 1) {
                printf("ERROR: 0 or 1 expected after '-refs'\n");
                exit(0);
            }
            useRefTable = (Signed2) atoi(argv[i]);
        } else if (strcmp(argv[i], "-ttBits") == 0) {
            i++;
            /* nrTtBits = argv[ i ] */
            if (argv[i][0] == '-') {
                printf("ERROR: number of bits expected after '-ttBits'\n");
                exit(0);
            }
            nrTtBits = (Signed2) atoi(argv[i]);
        } else if (strcmp(argv[i], "-keepPly") == 0) {
            i++;
            /* keepPly = argv[ i ] */
            if (argv[i][0] == '-') {
                printf("ERROR: number expected after '-keepPly'\n");
                exit(0);
            }
            keepPly = (Signed2) atoi(argv[i]);
        } else if (strcmp(argv[i], "-scheme") == 0) {
            i++;
            /* keepMethod = argv[ i ] */
            if (argv[i][0] == '-') {
                printf("ERROR: string expected after '-scheme'\n");
                exit(0);
            }
            useTransTable = 1;
            if (strcmp(argv[i], "new") == 0) {
                keepMethod = New;
            } else if (strcmp(argv[i], "old") == 0) {
                keepMethod = Old;
            } else if (strcmp(argv[i], "deep") == 0) {
                keepMethod = Deep;
            } else if (strcmp(argv[i], "big1") == 0) {
                keepMethod = Big1;
            } else if (strcmp(argv[i], "bigAll") == 0) {
                keepMethod = BigAll;
            } else {
                printf("ERROR: 'new', 'old', 'deep', 'big1' or 'bigAll'");
                printf(" expected after '-scheme'\n");
                exit(0);
            }
        } else if (strcmp(argv[i], "-table") == 0) {
            i++;
            /* keepMethod = argv[ i ] */
            if (argv[i][0] == '-') {
                printf("ERROR: string expected after '-table'\n");
                exit(0);
            }
            if (strcmp(argv[i], "1") == 0) {
                useTwoLevelTable = 0;
            } else if (strcmp(argv[i], "2") == 0) {
                useTwoLevelTable = 1;
            } else {
                printf("ERROR: '1' or '2' expected after '-table'\n");
                exit(0);
            }
        } else if (strcmp(argv[i], "-debugDepth") == 0) {
            i++;
            /* debugDepth = argv[ i ] */
            if (argv[i][0] == '-') {
                printf("ERROR: number expected after '-debugDepth'\n");
                exit(0);
            }
            debugDepth = (Signed2) atoi(argv[i]);
        } else if (strcmp(argv[i], "-ttValue") == 0) {
            i++;
            /* ttValue = argv[ i ] */
            if (argv[i][0] == '-' || strlen(argv[i]) != 1) {
                printf("ERROR: 0 or 1 expected after '-ttValue'\n");
                exit(0);
            }
            useTtValue = (Boolean) atoi(argv[i]);
        } else if (strcmp(argv[i], "-ttMove") == 0) {
            i++;
            /* ttMove = argv[ i ] */
            if (argv[i][0] == '-' || strlen(argv[i]) != 1) {
                printf("ERROR: 0 or 1 expected after '-ttMove'\n");
                exit(0);
            }
            useTtMove = (Boolean) atoi(argv[i]);
        } else if (strcmp(argv[i], "-timeStamp") == 0) {
            i++;
            /* timeStamp = argv[ i ] */
            if (argv[i][0] == '-' || strlen(argv[i]) != 1) {
                printf("ERROR: 0 or 1 expected after '-timeStamp'\n");
                exit(0);
            }
            timeStamp = (Boolean) atoi(argv[i]);
        } else if (strcmp(argv[i], "-flag") == 0) {
            i++;
            /* useFlag = argv[ i ] */
            if (argv[i][0] == '-' || strlen(argv[i]) != 1) {
                printf("ERROR: 0 or 1 expected after '-flag'\n");
                exit(0);
            }
            useFlag = (Boolean) atoi(argv[i]);
        } else {
            printf("ERROR: unknown argument '%s'\n", argv[i]);
            exit(0);
        }
    }

    SetDefaults(&useTransTable, &useRefTable, &nrTtBits, &useTwoLevelTable,
                &useTtValue, &useTtMove, &timeStamp, &useFlag);
    PrintSettings();
    if (useTransTable) {
        printf("Initializing transposition table (%lu entries * %d)",
               1L << nrTtBits, sizeof(TtEntry));
        printf(" --> %lu bytes", (1L << nrTtBits) * sizeof(TtEntry));
        fflush(stdout);
        InitTransTable();
        printf("\n");
        if (useTwoLevelTable) { /* 2 positions per entry: hash,
                                 * hash+1<<nrTtBits */
            nrTtBits--;
        }
        if (nrTtBits < (sizeof(TtEntry) <= 16 ? 15 : 7)) {
            printf("\nERROR: nrTtBits must be at least %d.\n",
                   (sizeof(TtEntry) <= 16 ? 15 : 7));
            exit(0);
        }
    }
    if (!interActive) {
        SetTestingDefaults(&testDepth, &testColor, testNrNodes);
        PrintTestSettings(testDepth, testColor, testNrNodes);
        if (doTest) {
            PerformTest(startingMove, testColor, testDepth);
        } else {                /* Calculate one move */
            if (testColor != toMove) {
                if (nrGamePlies == 0) {
                    printf("ERROR: cannot search for '%s'\n",
                           moveColorString[testColor]);
                    exit(0);
                } else {
                    printf("Undoing last move\n");
                    UndoMove();
                }
            }
            Search((Signed1) testDepth, &move, &value);
            if (move.from) {
                SPrintMove(s, move);
                printf("My move: %s\n", s);
            }
        }
    }
}                               /* TestArguments */


static void     SetTestingDefaults(Signed2 * testDepth, Signed2 * testColor,
                                                   Signed4 testNrNodes)
{
    if (*testDepth == -1) {
        if (testNrNodes == -1) {
            *testDepth = DepthDefault;
            printf("\nChoosing default depth %d", DepthDefault);
        } else {
            *testDepth = MaxSearchDepth;
        }
    }
    if (*testColor == -1) {
        *testColor = ColorDefault;
        printf("\nChoosing default color %s", moveColorString[ColorDefault]);
    }
    printf("\n");
}                               /* SetTestingDefaults */


static void     SetDefaults(Boolean * useTransTable, Boolean * useRefTable,
                           Unsigned1 * nrTtBits, Boolean * useTwoLevelTable,
                                            Boolean * useTtValue, Boolean * useTtMove, Boolean * timeStamp,
                                            Boolean * useFlag)
{
    if (*useTransTable == 2) {
        if (*nrTtBits != 0 || *useTwoLevelTable != 2) {
            *useTransTable = 1;
        } else {
            *useTransTable = TransTableDefault;
        }
        printf("Choosing default transpo %d\n", *useTransTable);
    }
    if (*useRefTable == 2) {
        *useRefTable = RefTableDefault;
        printf("Choosing default ref %d\n", *useRefTable);
    }
    if (*nrTtBits == 0 && *useTransTable) {
        *nrTtBits = TtBitsDefault;
        printf("Choosing default nrTtBits %d\n", *nrTtBits);
    }
    if (*useTwoLevelTable == 2 && *useTransTable) {
        *useTwoLevelTable = TwoLevelTableDefault;
        printf("Choosing default twoLevelTable %d\n", *useTwoLevelTable);
    }
    if (*useTtValue == 2 && *useTransTable) {
        *useTtValue = TtValueDefault;
        printf("Choosing default ttValue %d\n", *useTtValue);
    }
    if (*useTtMove == 2 && *useTransTable) {
        *useTtMove = TtMoveDefault;
        printf("Choosing default ttMove %d\n", *useTtMove);
    }
    if (*timeStamp == 2 && *useTransTable) {
        *timeStamp = TimeStampDefault;
        printf("Choosing default timeStamp %d\n", *timeStamp);
    }
    if (*useFlag == 2 && *useTransTable) {
        *useFlag = UseFlagDefault;
        printf("Choosing default useFlag %d\n", *useFlag);
    }
}                               /* SetDefaults */


static void     PerformTest(Signed2 startingMove, Signed2 testColor,
                                            Signed2 testDepth)
{
    Signed2         startingPly,
                    i;
    Unsigned2       testMaxGamePlies;
    char            testGameString[MaxGamePlies][MaxMoveLength];
    MoveType        testGame[MaxGamePlies];
    Boolean         blackBegin;
    char            s[MaxMoveLength];
    MoveType        move;
    ValueType       value;

    startingPly = (startingMove - 1) * 2;
    if ((toMove == White && nrGamePlies % 2 == 0) ||
        (toMove == Black && nrGamePlies % 2 == 1)) {
        if (testColor == Black) {
            ++startingPly;
        }
        blackBegin = False;
    } else {
        if (testColor == White) {
            --startingPly;
        }
        blackBegin = True;
    }
    if (startingPly < 0 || startingPly >= nrGamePlies) {
        printf("ERROR: Starting move '%d' not possible\n", startingMove);
        exit(0);
    }
    /* Save variables */
    testMaxGamePlies = maxGamePlies;
    for (i = 0; i < testMaxGamePlies; i++) {
        testGame[i] = game[i];
        strcpy(testGameString[i], gameString[i]);
    }
    /* Take moves back */
    for (i = 0; i < maxGamePlies - startingPly; i++) {
        UndoMove();
    }
    /* Calculate the moves */
    for (i = startingPly; i < testMaxGamePlies; i++) {
        if (material[White] <= EndgameMaterial ||
            material[Black] <= EndgameMaterial) {
            printf("Stop: endgame reached\n");
            break;
        }
        if ((i - startingPly) % 2 == 0) {
            if (testColor != toMove) {
                printf("ERROR: wrong search color\n");
                exit(0);
            }
            printf("\nCalculating move %d\n", blackBegin ? (i + 3) / 2 : (i + 2) / 2);
            Search((Signed1) testDepth, &move, &value);
            if (move.from) {
                SPrintMove(s, move);
                printf("My move: %s\n", s);
            }
        }
        DoMove(&(testGame[i]));
        printf("Forward: %s\n", testGameString[i]);
    }
}                               /* PerformTest */
