MailRuChamps / raic-2019

Russian AI Cup — artificial intelligence programming contest. Official website: http://russianaicup.ru
GNU General Public License v3.0
73 stars 45 forks source link

Иногда при приземлении происходит "тупняк" на 1 микротик. #44

Open tyamgin opened 4 years ago

tyamgin commented 4 years ago

Карта дефолтная.

Псевдокод стратегии:

        if (currentTick == 0) {
            // do nothing
        } else {
            action.jump = true;
            if (currentTick == 67 || currentTick == 68) {
                std::cout << unit.position.y << std::endl;
            }
        }

1.00333 1.16167

Суммарное передвижение равно (1.00333 - 1) + (1.16167 - 1) = 0.165, что не соответствует заявленным 10 / 60 = 0.16666666 (т.к. скорости падения и прыжка равны).

Другой пример, где всё ожидаемо:

        if (currentTick == 0) {
            // do nothing
        } else if (currentTick == 1) {
            action.velocity = 10;
        } else {
            action.jump = true;
            if (currentTick == 52 || currentTick == 53) {
                std::cout << unit.position.y << std::endl;
            }
        }

1.06667 1.1

(1.06667 - 1) + (1.1 - 1) = 0.16667

В чате написали, что это нормально, но я так не считаю. Хотелось услышать мнения.

prospero78 commented 4 years ago

Мнение: это ненормально.

tyamgin commented 4 years ago

Итак, я запустил в режиме {"ticks_per_second": 6000, "updates_per_tick": 1}.

Лог первой игры (microtick, y):

6701 1.0016666676667
6702 1.0000000010000
6703 1.0000000010000
6704 1.0016666676667

Лог второй игры:

5239 1.0016666656667
5240 1.0000000010000
5241 1.0016666676667

В первом случае мы засыпаем 1 раз на y=1.

В чём отличие этих двух кейсов? В том, что в первом время прыжка закончилось, и canJump, соответственно, стал fasle, а во втором время ещё есть, и и canJump=true. На переключение canJump с false на true тратится 1 микротик, что абсолютно не логично, и является багом в движке (так как это в правилах не указано). Предлагаю исправить.

ud1 commented 4 years ago

Это из-за того, что при ударе об стену, игрок отодвигается от стены на EPS = 1e-9. В результате сначала игрок на земле, его координата больше целого на EPS, а когда ударяешься об потолок, то меньше целого на EPS, это и приводит к тому, что в первый раз когда высота стала почти нулевой, удар об землю не засчитывается и флаги не меняются, во второй раз уже происходит удар сразу.

Лучше механику игры не менять, так как может все сломать, плюс некоторые люди уже зареверсили то, как работает сейчас.

kuviman commented 4 years ago

В один апдейт игровой логики движение происходит лишь один раз. Если юнит вплотную к земле и падает вниз, он упрется в нее, и перейдет в состояние прыжка. Сам прыжок будет происходить лишь в следующий апдейт

tyamgin commented 4 years ago

Да я уже благодаря @ud1 понял, что y+eps и y-eps - это разные координаты. Это очень тупо, и непрерывность движений сломана. Но что поделать, остаётся смириться.

MrSmile commented 4 years ago

Как раз благодаря eps при отскоке от стен ошибки округления почти нигде себя не проявляют (кроме самого начала игры, когда игрок выставляется по круглым координатам). Хотя стоило бы размеры юнита сделать менее круглыми.

tyamgin commented 4 years ago

Ничто не мешает мне сдвинуться на 1e-9, и костыль перестанет работать (принадлежность тайлам станет неопределенной). И да, хотя бы в начале игры сдвинули бы на 1e-9 уже.

mortido commented 4 years ago

Как раз благодаря eps при отскоке от стен ошибки округления почти нигде себя не проявляют (кроме самого начала игры, когда игрок выставляется по круглым координатам). Хотя стоило бы размеры юнита сделать менее круглыми.

После фикса телепортов, кажется, стали проявлять - выталкивает теперь на min(1e-9, старое_расстояние_до_сдвига)

MrSmile commented 4 years ago

После фикса телепортов, кажется, стали проявлять - выталкивает теперь на min(1e-9, старое_расстояние_до_сдвига)

Мдя... с такими "фиксами" никаких багов не надо. Раньше проблема была только на нулевом тике, а теперь, вместо того, чтобы ее решить добавлением 1e-9 к начальной координате, ее растянули на неопределенное время (кажется, надо башкой стукнутся, чтобы прошло).

tyamgin commented 4 years ago

Такие изменения никуда не годятся. В каких случаях теперь отнимается/прибавляется эпсилон? При приземлении на земле на старте эпсилон не прибавляется, при приземлении на платформу где-то дальше - прибавляется. Раз пошла такая пьянка, надо убирать вообще эпсилоны.

MrSmile commented 4 years ago

Раз пошла такая пьянка, надо убирать вообще эпсилоны.

Нельзя, все величины слишком круглые и делятся нацело друг на друга, будет только хуже. Изначальный вариант, в принципе, неплох (лучше только переписать всю физику на целые числа), за исключением начального значения.

tyamgin commented 4 years ago

Почему нельзя? Чтобы проверить на коллизию со стеной, нужно прибавить/отнять (в зависимости какую сторону проверяем) к координате eps, и проверить получившуюся ячейку. Хранить этот eps уже приплюсаванным к координате - это мегакостыль, а потом ещё выдавать это наружу.

MrSmile commented 4 years ago

Где конкретно хранить eps, явно в координате или неявно в положении стены, — это без разницы. Важно, чтобы координата проверки на пересечение отличалась от координаты отскока.

tyamgin commented 4 years ago

Как минимум разница в том, что это сбивает с толку. Проверка на равенство предположительно целого float-числа c интом - это внутренняя кухня движка, и я не хочу видеть артефакты её работы в виде непонятного смещения, тем более, что это смещение потом на что-то ещё повлияет.

StarveTheEgo commented 4 years ago

Не понимаю, почему упарываются настолько. Смысл соревнования в написании ИИ, который ориентируется и побеждает в игре, а не в таком tryhard'e, что все пытаются устроить :-( Реверсят ещё что-то... как будто так интереснее играть