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;
}