1

Тема: Обход игрока на пути

Для определения, что на пути игрока находится противник, используется функция противник_на_пути:
Если(противник_на_пути:40){
#код обхода
}

Обходить препятствие можно сверху или снизу.
Пример обхода сверху: бежать:30^,50
Пример обхода снизу: бежать:150^,50
Можно задать маршрут обхода: бежать:30^,50,90^,50,150^,50

Для того, чтобы определить, как лучше обходить, нужно получить расположение препятствия относительно игрока. Если игрок ниже препятствия (Y игрока > Y препятствия ), то лучше обойти его снизу, а если выше, то сверху.
При движении к чужим воротам можно задавать обход, используя расположение мяча относительно игрока:
Если([y0<y]){бежать:150^,50}иначе{отправить_мяч:30^,50}

В этом примере, если мяч находится выше игрока, то обход делается снизу, а если мяч снизу, то обход делается сверху.
Более сложный способ заключается в определении Y препятствия:
Если([YC(X+20,Y,1)<Y]){бежать:150^,50}иначе{отправить_мяч:30^,50}

В этом примере YC(X+20,Y,1) это Y чужого игрока, который находится перед игроком. Напомню, что C(X+20,Y,1) возвращает номер ближнего к точке (X+20,Y) чужого игрока (третий параметр 1 указывает, что нужно учитывать только чужих игроков). X и Y это расположение текущего игрока, а (X+20,Y) - точка перед игроком.

А вот сложный пример, в котором если Y препятствия меньше Y игрока, то бежать в направлении угол препятствия плюс 45 градусов, либо минус 45 градусов в противном случае:
Если([Y[@C(X+20,Y,1)]<Y]){бежать:[A(x,y,x[@],y[@])+45]^,50}иначе{бежать:[A(x,y,x[@],y[@])-45]^,50}

В этом примере в условии сначала заменяется и кэшируется макрос [@C(X+20,Y,1)]. Потом его значение подставляется макросами [@] в действие, где A(x,y,x[@],y[@]) - это угол, на котором находится препятствие, относительно текущего игрока (другими словами, направление в котором оно находится - см. изображение для лучшего понимания). Допустим, макросная функция C возвращает значение 5. Тогда, после его замены, в условии будет: [Y5<Y], а в действии [A(x,y,x5,y5)+45].
Подстановка значений макросов происходит не для всей строки сразу, а для каждой инструкции в момент её выполнения. Т.е. в примере выше, если условие выполняется, то макросы будут обработаны только в первом блоке, а в том, который после "иначе" не будут.

Ещё один вариант:
Если([[@A(x,y,x[1@C(X+20,Y,1)],y[1@])]<90]){бежать:[[@]+45]^,50}иначе{бежать:[[@]-45]^,50}

В этом примере, в условии, определяется, что угол расположения препятствующего игрока относительно текущего меньше 90. Значение угла кэшируется и потом используется в действиях. Т.к. здесь несколько вложенных макросов, рассмотрим подробнее, как происходит их обработка.
В условии мы видим вложенный кэширующийся макрос [@A(x,y,x[1@C(X+20,Y,1)],y[1@])], который возвращает угол расположения  чужого игрока. Этот макрос содержит вложенный макрос [1@C(X+20,Y,1)]. Т.к. он самый вложенный, то он будет обрабатываться первым. Допустим, он вернёт номер игрока 5. Тогда условие будет выглядеть так:
[[@A(x,y,x5,y[1@])]<90]
Потом заменится макрос [1@] на кэшированное значение 5:
[[@A(x,y,x5,y5)]<90]
Потом заменится и закэшируется [@A(x,y,x5,y5)]:
[85<90]
Т.к. условие выполняется, то будет выполнено действие "бежать:[[@]+45]^,50", в котором [@] будет заменено на 85, и получится: "бежать:[85+45]^,50", а после сложения: "бежать:130^,50".
Напомню, что для кэширования макроса в его начало ставится символ @, перед которым идёт его id (любое число). Если id не указать, то он будет закэширован с id 0. В примере выше используется кэширование с id и без.