U0 AnimationDelaySet()
{
    animation_delay = PopUpRangeF64(0, 100, 25, "%3f% %%", "Animation Delay\n")/100;
}

U0 TurnNew()
{
    I64 i, j;
    for (j = 0; j < 2; j++)
        for (i = 0; i < UNITS_NUM; i++)
        {
            units[j][i].remaining_movement = units[j][i].movement;
            units[j][i].fired = FALSE;
        }
    phase = PHASE_START;
    moving_unit = NULL;

    SleepUntil(message_off_timeout);
    message_off_timeout = counts.jiffies + JIFFY_FREQ * 2 * animation_delay + 1;
    Sound(74);
    StrPrint(message_buf, "Turn %d", ++turn);
    VRSetUp(0);
    VRSetUp(1);
    VisRecalc(VR_ALL_UNITS);
    cur_player = (turn & 1) ^ 1;
    enemy_player = cur_player ^ 1;
}

U0 PhaseNew()
{
    cur_player ^= 1;
    enemy_player = cur_player ^ 1;
    if (++phase >= PHASE_END)
    {
        IndirectResolveAll;
        TurnNew;
    }

    SleepUntil(message_off_timeout);
    message_off_timeout = counts.jiffies + JIFFY_FREQ * 2 * animation_delay + 1;
    Sound(74);
    switch (phase)
    {
        case PHASE_INDIRECT0:
        case PHASE_INDIRECT1:
            StrPrint(message_buf, "Player %d Artillery Plot", cur_player + 1);
            break;

        case PHASE_MOVE0:
        case PHASE_MOVE1:
            StrPrint(message_buf, "Player %d Move", cur_player + 1);
            break;

        case PHASE_DIRECT0:
        case PHASE_DIRECT1:
            StrPrint(message_buf, "Player %d Fire", cur_player + 1);
            break;
    }
}

U0 CharDo(U8 ch)
{
    I64  old_inhibit, old_draw_it;
    Bool old_cursor;

    switch (ch)
    {
        case CH_ESC:
        case CH_SHIFT_ESC:
            throw('ExitGame', TRUE);

        case CH_SPACE:
            throw('PhaseOvr', TRUE);

        case '\n':
            throw('NewGame', TRUE);

        case '1':
            ViewPlayerSet(0);
            break;

        case '2':
            ViewPlayerSet(1);
            break;

        case 'c':
            old_draw_it = Fs->draw_it;
            old_inhibit = Fs->win_inhibit;
            Fs->draw_it = Fs->next_settings->draw_it;
            Fs->win_inhibit = WIG_USER_TASK_DEFAULT;
            old_cursor = DocCursor(ON);
            DocBottom;
            "\n$GREEN$<SHIFT-ESC>$FG$ to return to game.\n";
            View;
            DocBottom;
            DocCursor(old_cursor);
            Fs->win_inhibit = old_inhibit;
            Fs->draw_it = old_draw_it;
            break;

        case 'd':
            AnimationDelaySet;
            break;
    }
}

U0 UserCheck()
{
    I64 ch;

    if (!alive_count[0] || !alive_count[1])
        throw('GameOver', TRUE);
    if (ch = CharScan)
        CharDo(ch);
}

U0 TaskEndCB()
{
    Sound;
    progress4 = progress4_max = progress1 = progress1_max = 0;
    Exit;
}

I64 PhaseDo()
{
    I64 res = 'ExitGame';

    PhaseNew;
    try
    {
        if (phase & ~1 == PHASE_INDIRECT)
            Call(player_indirect[cur_player]);
        else if (phase & ~1 == PHASE_MOVE)
            Call(player_move[cur_player]);
        else
            Call(player_direct[cur_player]);
    }
    catch
    {
        res = Fs->except_ch;
        Fs->catch_except = TRUE;
    }
    return res;
}

U0 ToTheFront()
{
    I64 res, ch;

    map_dc = DCNew(MAP_WIDTH, MAP_HEIGHT);

    SettingsPush; //See SettingsPush
    Cd(__DIR__);
    Fs->win_inhibit |= WIF_SELF_MS_L | WIF_SELF_MS_R | WIG_DBL_CLICK;

    MenuPush(   "File {"
                "  Abort(,CH_SHIFT_ESC);"
                "  Exit(,CH_ESC);"
                "}"
                "Play {"
                "  EndPhase(,CH_SPACE);"
                "  Restart(,'\n');"
                "}"
                "View {"
                "  Player1(,'1');"
                "  Player2(,'2');"
                "  OddsCalculations(,'c');"
                "  LOS(,0,SCF_SHIFT);"
                "}"
                "Settings {"
                "  AnimationDelay(,'d');"
                "}"
                );

    AutoComplete;
    WinBorder;
    WinMax;
    DocCursor;
    DocMax;
    Init;
    PlayerPick("AIs", 0);
    PlayerPick("AIs", 1);

    PopUpOk(    "$PURPLE$$TX+CX,\"ToTheFront\"$$FG$\n\n"
                "$GREEN${Left-click}$FG$ to move or fire units.\n"
                "$GREEN$<SPACE>$FG$\tor $GREEN${Right-click}$FG$ to end phase.\n"
                "$GREEN$<SHIFT>$FG$\tto show line-of-sight.\n"
                "$GREEN$<ENTER>$FG$\tto start new game.\n"
                "$GREEN$  1$FG$\tPlayer 1 view.\n"
                "$GREEN$  2$FG$\tPlayer 2 view.\n"
                "$GREEN$  c$FG$\tView odds calculations.\n"
                "$GREEN$  d$FG$\tSet animation delay.");
    Fs->task_end_cb = &TaskEndCB; //<CTRL-ALT-x>
    Fs->draw_it = &DrawIt;
    try
    {
        do
        {
            res = PhaseDo;
            if (res == 'GameOver')
            {
                while (TRUE)
                {
                    message_off_timeout = 0;
                    StrCopy(message_buf, "Game Over");
                    Sound;
                    ch = CharGet(, FALSE);
                    if (ch == '\n')
                    {
                        CleanUp;
                        Init;
                        break;
                    }
                    else if (ch == CH_ESC || ch == CH_SHIFT_ESC)
                    {
                        res = 'ExitGame';
                        break;
                    }
                    else if (ch == '1')
                        ViewPlayerSet(0);
                    else if (ch == '2')
                        ViewPlayerSet(1);
                    else if (ch == 'd')
                        AnimationDelaySet;
                }
            }
            else if (res == 'NewGame')
            {
                CleanUp;
                Init;
            }
        }
        while (res != 'ExitGame');
    }
    catch
        PutExcept;
    ProgressBarsReset;

    SettingsPop;
    DCDel(map_dc);
    CleanUp;
    MenuPop;
    Seed;
}