FuncBall
Coding football


Main  •  Download  •  User guide  •  Teams  •  Championship  •  Forum  •  Support: FuncBall@gmail.com
Sign in  •  Create account
  1. General
  2. Player coding basics
  3. Field and coordinate system
  4. Player moving
  5. Passes, kicks and shots
  6. Signals and flags
  7. All functions
  8. Macros (expressions in square brackets)
  9. Variables
  10. Code substitution
  11. Championship requirements

General

  • Team consists of 4 players. No goalkeepers.
  • The ball is always brought into play (kick-off) from the center of the field. If player kicks ball outside the field, then opposing team will bring ball into play. Player who always kick-off is seted in team settings. When on kick-off, only this player may locate at the central circle.
  • Players can coordinate actions by giving signals (only numbers) that are visible to everyone.
  • No shared memory. Player memory is implemented by setting flags. You can add and remove specific values (only numbers) to the player flags pool. Also you can use your own variables for each player. Variables are accessible only to the player who defines it.
  • The players speed is constant. The player with ball runs a little slower than the players without ball.
  • Ball passes and shots on goal are made with an accuracy of 15 degrees. No air passes.
  • Player programs run randomly. Code of kick-off player is executed first when on start.
  • The playing step is 50 milliseconds. Сan chose playback speed. There is a "C" mode, in which the match is calculated without visualisation. There is a "CR" mode in which the calculation is done first, and then the recording starts playing.

    Player coding basics

    Code can write in Russian or English. This guide contains all examples in English. There is guide in Russian.

    For each of the 4 players, write program of what and under what conditions to do. Conditions should write with ordinary brackets preceded by the word "If", and actions write with curly brackets following the conditions. Example:

    If(ball_owner){shoot_goal}

    In this example, a player, if he has a ball, will make a shot on goal. In curly brackets, after the word "else", you can set what the player should do if he does not own the ball:

    If(ball_owner){shoot_goal}else{run_to_ball}

    So, if a player does not own a ball, he will run towards it. There is a coding option without using brackets:

    If ball_owner, then shoot_goal, else run_to_ball.

    If you need to set several actions, then you need to separate them with a semicolon:

    If(ball_owner){shoot_goal; return_to_base}else{run_to_ball; give_signal:5}

    Without using brackets:

    If ball_owner, then shoot_goal; return_to_base, else run_to_ball; give_signal:5.

    Below all the examples will be with brackets.

    Conditions and actions (I will call all it "functions") can have parameters (arguments). For example, the "shoot_goal" command sends the ball into a random place of goal. To specify where to shoot exactly, you need to add the Y coordinate where to send the ball: "shoot_goal:168". Example:

    If(ball_owner){shoot_goal:168}

    Many functions require several arguments (some of it optionally). For example, "kick:498,142". In this example, 498 and 142 are the X and Y coordinates where to send the ball. Can specify a range of values: "kick:400-500,140-150". So the ball will be sent to a random point with an X coordinate between 400 and 500, and Y between 140 to 150. Can specify value variants using a vertical line: "kick:410|430|470,140-150". In this case, the X coordinate will be 410 or 430 or 470. Examples:

    Send the ball into 16 or 17 square (zone): If(ball_owner){kick_to_zone::16|17}
    If player 3 has the ball, then run to square 11: If(ball_owner:3){run_to_zone:11}

    In these examples, is used the "ball_owner" function, which checks what player owns the ball. If you do not specify an argument, then it checks whether current player owns the ball. There are functions in which the argument must be specified directly in the function name:

    If(ball_owner and player3_is_open){pass:3}

    In this example, the "player3_is_open" function checks if player 3 is open (can enemy players intercept a pass). In this example, there are two conditions, and a pass to player-3 will be made only if both conditions returned true. If you need to check if at least one condition returns true, then you must use "or" instead of "and": "ball_owner or player3_is_open". Conditions can be complex:

    If(ball_owner and (player3_is_open or closest_to_enemy_goal:3)){pass:3}

    Also condition blocks can be nested:

    If(ball_owner){
        If(player3_is_open or closest_to_enemy_goal:3){pass:3}
    }

    Check if the condition is NOT true can do by adding ! in front of it: If(!ball_owner:3){run_to_zone:10}

    To exit execution of current player script use $ symbol:
    If(!ball_owner:3){run_to_zone:10; $}

    Single line comments starting with # are supported:
    If(on_start){pass:3} #pass to player-3

    Field and coordinate system

    Field size: 560x376 pixels. Goal Y: 154-250. The origin (point 0,0) in the top left corner. Field markup (image).

    When programming players, you should assume that your team start on the left half of the field. Numbers of your players are 1-4, and enemies are 5-8. When playing on the right, all coordinates, square numbers, angles and numbers of players are reflected, i.e. your team will play exactly the same as on the left half of the field.

    You can find out the coordinates of a point on the field by clicking on it, a tooltip will appear. If you right-click, the coordinates will be copied to the clipboard.

    Player moving

    You can order the player to run to the ball with a command run_to_ball (no arguments required). When a player reaches the ball, he will take possession of it (now he is ball owner). GIF.

    The command be_on_ball_line, makes the player move to ball without changing his X coordinate. It looks like moving up and down the field. This command has an optional argument for specifying the X coordinate on which player should to stay: be_on_ball_line:150. GIF (player-3). If the ball is nearby (0-6px), then the ball is grabbed (now player is ball owner). Example:
    If(!ball_behind){be_on_ball_line:180}

    Running in the specified direction is realized by using command run. Arguments specify the point at which to run. Example: If(ball_owner){run:192,263}

    You can set running direction in degrees (angle of movement, 0-360). To do this, add the ^ character to the first argument. The second argument is the distance to run. Example: If(ball_owner){run:45^,70}
    In this example, the player will run in the direction of 45 degrees to a distance of 70 pixels.

    You can set a route by specifying several points:
    If(on_start){run:363,182,447,71}
    In this example, the player first runs to point 363,182, and then to point 447,71. Another example:
    If(on_start){run:90^,100,373,234}
    The player first runs for 100 pixels in the direction of 90 degrees, and then runs to point 373,234. The route can be set from any number of points.

    In difference to the "run_to_ball" and "be_on_ball_line" commands, when use "run", the ball is not grabbed if the player is near the ball. To grab ball, you should use this code: If(dist_to_ball:0-6){run_to_ball}

    To run to the specified square, you can use the command run_to_zone:
    If(!player_zone:17){run_to_zone:17}.
    The player will run to a random point inside the specified square.

    Passes, kicks and shots

    To shot on goal, you can use the command shoot_goal:
    If(dist_to_enemy_goal:0-100){shoot_goal}
    The ball goes to a random goal point. You can specify the Y coordinate to which to send the ball:
    If(dist_to_enemy_goal:0-100){shoot_goal:159}
    Shoot at a random goal point: If(dist_to_enemy_goal:0-100){shoot_goal:154-250}

    To send ball to a specific point on the field, use the command kick:
    If(on_start){kick:497,103}
    The ball will be sent to point 497,103. The speed will be such that the ball will stop at approximately the specified point. If you need to send ball at maximum speed, add the argument "1":
    If(on_start){kick:497,103,1}
    You can set the direction in degrees: If(on_start){kick:90^,100}
    In this example, the ball will be sent a distance of 100 pixels in the direction of 90 degrees. Send in random direction and random distance: If(on_start){kick:0-359^,20-150}

    You can send the ball to a random point of the specified square with the command kick_to_zone:
    If(on_start){kick_to_zone:17}

    You can pass the ball to any player using command pass:
    If(player3_is_open){pass:3}
    The ball will be sent to the point of player. To make through pass, as second parameter set distance from target player to point in front of him, to which send ball:
    If(on_start){pass:3,50}
    In this example, a pass is given at an offset of 50 pixels.

    You can make pass to player who is closest to the current player using command pass_to_closest:
    If(ball_owner and way_is_blocked){pass_to_closest}
    The closest player is calculated from the players of own team. Can make pass to the second or third closest player:
    If(ball_owner and way_is_blocked){pass_to_closest:2}

    Signals and flags

    As in real football, players can give each other signals (visible to all players on the field). There is the give_signal command to do this:
    If(on_start){give_signal:5}
    Only numerical signals are supported. By default, the signal lifetime is one second. You can set lifetime as second parameter (milliseconds):
    If(on_start){give_signal:5,2000}
    In this example, signal 5 is set for 2 seconds. You should not specify a lifetime of less than 50 msec, because then the signal will exist only in current play step, and can be read only by players whose code is executed after the signal was set. It must be remembered that the programs of the players are executed in random order, and the code of the player who start playing (kick-off) is executed first (only when kick-off). Every kick-off (not only when the match begins), all signals are deleted.

    You can check the player’s signal by the function player_signal:
    If(player3_signal:5){run_to_zone:16}
    Can check the previous non-zero signal using function player_prev_signal: If(player3_prev_signal:22){run_to_zone:16}

    Signals are displayed above the player, next to the number. Signals are also visible on records.


    Player memory functions are carried out flags. For each player, you can set up to 10 flags. You cannot read flags of another players (flags not public). To set flags use command set_flags: If(player3_signal:5){set_flags:+5}
    In this example, flag 5 is added to the current player flag list. Its lifetime is until the next kick-off (after goal or ball out of bounds). You can specify the flag lifetime (msec):
    If(player3_signal:5){set_flags:+5,2000}
    In this example, flag 5 will exist for 2 seconds.
    Can add several flags: If(player3_signal:5){set_flags:+5,2000,777,0}
    In this example, flag 5 is added for 2 seconds and flag 777 is permanent.
    Flag removing: If(player_signal:5){set_flags:-5}
    Set the exact set of flags: If(player_signal:5){set_flags:7,0,9,3000}
    In this example, is set flag 7 (permanent) and flag 9 (for 3 seconds). All other previously added flags are deleted.
    Clear flags: If(player_signal:5){set_flags:}

    Flags are displayed below the player both during the match and on the record. To hide flags on records (so that others people do not know which flags you are using), set option "hide_flags" in the ExtraParams block of team file:
    <ExtraParams>
    update_number=327
    last_update=31.07.2019
    language=en
    hide_flags=1
    </ExtraParams>

    All functions

    ConditionsActions (commands)
    1. closest_to_player*
    2. closest_to_ball
    3. closest_to_own_goal
    4. closest_to_enemy_goal
    5. on_start
    6. action_lasts
    7. flag_exists
    8. area_is_vacant
    9. player*_is_closest_to_point
    10. player*_zone
    11. player*_is_open
    12. player*_prev_signal
    13. player*_signal
    14. player*_location
    15. ball_zone
    16. ball_behind
    17. free_ball
    18. ball_owner
    19. friend_ball
    20. way_is_blocked
    21. dist_to_player*
    22. dist_to_ball
    23. dist_to_own_goal
    24. dist_to_enemy_goal
    25. nearby_enemy
    26. point_is_open
    27. point_is_vacant
    28. is_running
    1. run
    2. run_to_zone
    3. run_to_ball
    4. shoot_goal
    5. return_to_base
    6. stand_front_point
    7. be_on_ball_line
    8. kick
    9. kick_to_zone
    10. pass_to_closest
    11. pass
    12. give_signal
    13. stand_still
    14. set_flags

    There is also a special "log" command that writes the specified text to file:
    log:This is test
    For the left team it writes to logs\1.txt file, and for the right team it writes to logs\2.txt.

    And another special command - "output", which displays the specified text at the bottom of the field:
    output:Hello World
    In output string do not use special characters - a dot with a space (. ) and a semicolon (;). If you want to display some variable values, then write them with [ ]:
    output:Value of some_var: [some_var]

    It looks like this (on the left is first team output, and on the right is the second team output):


    Getting the numerical values of condition functions

    In addition to the logical value (true (1) or false (0)), condition functions can return a numerical value. For example, you can do this: run_to_zone:ball_zone;
    "ball_zone" returns the number of the square where ball is, and this value is given to action "run_to_zone". But this is not possible with all actions and conditions due to overlays with their arguments. For example, pass:closest_to_enemy_goal:1,2,1 will be handled incorrectly, as the "pass" command can take two arguments, and it is controversial situation - which arguments is for function "closest_to_enemy_goal", and which is for "pass" command? To avoid errors when parsing the script, if you use the function as an argument, you need to use brackets: pass:(closest_to_enemy_goal:1,2,1),20 .
    Another option (preferred) is to first take the result of the function to a variable, and then use this variable as command argument. For example:
    player=closest_to_enemy_goal:1,2,1; pass:player,20;
    For more information about variables, see Variables.

    Numeric values returned by condition functions

    closest_to_player*nearest player number
    closest_to_ballplayer number who closest to the ball
    closest_to_own_goalplayer number who closest to own goal
    closest_to_enemy_goalplayer number who closest to enemy goal
    on_start0 or 1
    action_lastshow long is the action (msec)
    flag_existshow many flags are set
    area_is_vacantplayer number who is at area, or 0
    player*_is_closest_to_pointplayer number who closest to point
    player*_zonenumber of square in which the player is
    player*_is_openplayer number who on the way, or 0
    player*_prev_signalprevious non-zero player signal, or 0
    player*_signalplayer signal, or 0
    player*_locationx and y of the player as x.y
    ball_zonenumber of square in which the ball is
    ball_behindx of ball
    free_ballplayer number who own ball, or 0
    ball_ownerplayer number who own ball, or 0
    friend_ballnumber of the player who last owned the ball, or 0 if the last player was enemy
    way_is_blockedenemy player number, or 0
    dist_to_player*distance to player
    dist_to_balldistance to ball
    dist_to_own_goaldistance to your goal
    dist_to_enemy_goaldistance to enemy goal
    nearby_enemyenemy player number, or 0
    point_is_openplayer number who is on the way, or 0
    point_is_vacantplayer number who is at the point (in circle), or 0
    is_runningdestenation point as x.y where the player is running


    Macros (expressions in square brackets)

    You can insert macros into the code, which are replaced with values during the execution of the script. For example, [X] is replaced by the X coordinate of the current player, and [X0] by the X coordinate of the ball. Example, run to the ball:
    If(free_ball){run:[X0],[Y0]}
    Example, through pass to player-4:
    If(ball_owner){kick:[X4+50],[Y4]}

    All macro variables and functions:

    1. I - returns the current player number.
    2. B - returns the number of player who owns the (Ball), or 0, if the ball is nobody's. Example, if the opponent has the ball, then run towards the ball:
      If([B>4]){run_to_ball}
    3. Macro function N(signal) - returns player number who gives the specified signal, or 0 if there is no such player. Example, pass to the player who gives a signal 555:
      If([N(555)>0]){pass:[N(555)]}
    4. X0 and Y0 - X and Y of ball.
    5. X1-8 and Y1-8 - returns X and Y of the specified player. Example, pass to player-2:
      If(ball_owner){kick:[X2],[Y2]}
    6. X and Y - returns X and Y of the current player. Example, if the player’s X is less than 200 and Y is greater than or equal to 100, run to point 358,182:
      If([X<200 and Y>=100]){run:358,182}
    7. R(from,to) - Random number in the specified range. Example, run to a random point with X between 400 and 450, and Y between 150 and 200:
      If(ball_owner){run:[R(400,450)],[R(150,200)]}
    8. D(x1,y1,x2,y2) - Distance between two points. Example, if the distance from the player to enemy goal (center of goal is 559,188) is less than 150 pixels, then shot on goal:
      If([D(X,Y,559,188)<150]){shoot_goal}
    9. C(x,y) - returns player number who is (Closest) to a specified point. Example, pass to player who is closest to enemy goal:
      If(ball_owner){pass:[C(559,188)]}
      In this example, function looking among only your players (1-4). To looking among only enemy players (5-8), you need to add argument 1:
      If(ball_owner){pass:[C(559,188,1)]}
      To looking among all players (1-8), you need to add argument 2:
      If(ball_owner){pass:[C(559,188,2)]}
      To get player number who is second closest to the goal, then specify 2 as the fourth argument (or, for example, 3 if you need a third closest player):
      If(ball_owner){pass:[C(559,188,0,2)]}
      The third argument 0 means that looking among only players of your team.
    10. A(x1,y1,x2,y2) - Angle, at which the point x2,y2 is located relative to the point x1,y1. Example, shot on goal with angle setting:
      If(ball_owner){kick:[A(X,Y,559,188)]^,200}
      The angles of two players relative to the player with the ball:
    11. S1-8 and P1-8 - player signal (S) and previous signal (P). Example, if player-3 signals 123, then make pass to him:
      If([S3=123]){pass:3}
    12. S and P - signal of the current player (S) and his previous signal (P). Example, if a player signals 0 (does not signal anything), then give a signal equal to the previous signal + 1:
      If([S=0]){give_signal:[P+1]}
    13. T - coordinates X,Y of the run Target of current player. It is the destination point to which the player runs. Example, check if there are any enemy players at the destination point where the player is running:
      If(point_is_vacant:[T],50){...}
    14. V(n,value1,value2,value3...) - returns the item (Value) from a list of items at a specified index (like CHOOSE in SQL). Example, to take second value from the values "123, 555, 777": [V(2,123,555,777)]. The result will be: 555. Example, from the coordinates (X,Y) output by the T macro, print X and Y separately: [V(1,T)] is X, and Y is [V(2,T)]. First, T will be replaced and, for example, it will be V(1,125,255), and then the item with index 1 will be taken (125). In the second case, the item 2 will be taken (255).
    15. O(x1,y1,x2,y2,d) - calculates the coordinates (X,Y) of a point located between two others (between x1,y1 and x2,y2), at a specified distance (d) from the first point. Over line. Goal defence example:
      If(!dist_to_ball:0-6){run:[O(0,188,x0,y0,50)]}else{run_to_ball}
      0,188 is the coordinates of the center of own goal, and [x0],[y0] - the coordinates of the ball. 50 - distance from the point 0,188 to point at witch player should stand. This is similar to using the "stand_front_point" command:
      stand_front_point:0,188,[x0],[y0],50
      The difference of "stand_front_point" command is that if the ball is nearby player then ball is grabbed. The "run" command does not automatically grab the ball. In case of the command "run:[O(0,188,x0,y0,50)]" the ball will roll past through the player if you do not use the "run_to_ball" command. Goal defence GIF. For function O and "stand_front_point" command, instead of the coordinates of the second point, you can specify the angle at which to stand relative to the first point. Here's an example, running around the field center: run:[O(280,186,A(280,186,x,y)+10,60)]. A(280,186,x,y) will be replaced by the angle at which the player is located relative to the point 280,186 (center of the field). It will turn out, for example: [O(280,186,5+10,60)]. At the next steps, the current angle will increase, and the target will change by +10 degrees: [O(280,186,8+10,60)], and next will be [O(280,186,11+10,60)] etc. Running in circle GIF. Same thing using the "stand_front_point" command: stand_front_point:280,186,[A(280,186,x,y)+10],60;
    16. F(value) - returns the integer portion of a number. Fix. Example: [F(2.55)] returns 2.

    Macros can contain operators: +, -, *, /, >, <, >=, <=, =, <>, and, or, !.

    Macros can be used inside names of functions. Example, if the closest to the goal player is open, then pass to him:
    If(player[C(559,188)]_is_open){pass:[C(559,188)]}
    You need to understand that as closest player may be the current player, and you do not need to give pass to yourself. An example of checking this:
    If([C(559,188)<>I] and player[C(559,188)]_is_open){pass:[C(559,188)]}

    Macros can be combined
    Example, get the X of player who signal 555: XN(555). First, N(555) will be replaced by player number and, for example, it will be, X4, which will be replaced by X of player-4. Substitution of values goes from right to left.
    X of ball owner player: XB. "B" will be replaced by the player’s number, and it will be, for example, X3, which will be replaced by X of player-3.
    Signal of ball owner player: SB.
    Distance from player-3 to player-4: D(X3,Y3,X4,Y4).
    X of player who is closest to enemy goal: XC(559,188).

    Macros can be nested: [...[...]...].

    Macros can be cached

    Suppose you want to send the ball to a random point by checking if this point is open. If you write:
    If(point_is_open:[R(100,150)],[R(200,250)]){kick:[R(100,150)],[R(200,250)]}
    , then the random values of X and Y will be different in the condition and in the action. Therefore, you need to cache the macro values in the condition and use them in action:
    If(point_is_open:[1@R(100,150)],[2@R(200,250)]){kick:[1@],[2@]}
    As you can see, to cache macro just add id (any number) with the @ symbol at the beginning of the macro. The value of the first macro is written to the cache with id 1, and the second value with id 2. Then they are extracted from the cache by using macros [1@] and [2@].
    Another example, if the player who is closest to the goal is open, then pass to him:
    If(player[1@C(559,188)]_is_open){pass:[1@]}
    You can omit the macro id (by default it is 0): If(player[@C(559,188)]_is_open){pass:[@]}
    The cache is cleared at each start of code execution.

    Useful macro example

    How to make the player stand at line from the ball to the center of the goal. Player-4 runs up and down, and player-3 moves along the Y axis so as to block the path of the ball in the event of a shot on goal:



    Open GIF

    It is done like this: run:50,[188-(x*(188-y0))/x0]. 50 is the X on which the player should located, and 188 is the Y of the center of the goal.

    Explanation:

    We have a triangle C-D-E.

    1. Denote side E-D as A, and side C-E as B.
    2. A = X0 (X ball). B = 188 - Y0 (Y of the center of the goal minus the Y of ball)
    3. Denote the player’s X as A2, and the distance from the ball to the player along the Y axis as B2. A2 = X. B2 = ? (need to calculate)
    4. B relates to B2 in the same way as A to A2. Therefore: B2 = A2 * B / A. I.e.: B2 = X * (188 - Y0) / X0.
    5. To get the new Y coordinate, subtract B2 from the Y center of the goal.



    Own variables

    You can set your own variables. Each player has its own variables. Variables are non-public, i.e. accessible only in code in which they are defined. Variables lifetime is until next kickoff (after a goal or leaving the ball out of bounds). Variables, like in many programming languages, are set by the assignment operator "=" (equals): myvar=155. All variables are of type Single (.NET, holds signed IEEE 32-bit (4-byte) single-precision floating-point numbers). Such variables can store both the number 325 and 325,2407. In non-integer numbers, the fractional part is written after the dot, but if you set the variable with a comma (pi = 3,14), the program also get it correctly. Variables can be set in the traditional way or in conditions or in actions. The maximum number of variables for one player is 100. Examples:


    The most important:
  • Variables can be substituted into the arguments of conditions or actions without square brackets, but any arithmetic calculations can only be inside [ ]. So it is possible: myvar=[myvar+1], but not: myvar=myvar+1.
  • Variable names must not duplicate macro variable names: I, B, T, X, Y, S, P, X0, Y0, S1, P1, X1, S1 etc. Uppercase or lowercase - it does not matter. For example, If you set the variable X, then in macros it will overwrite the macro variable X, which returns the X-coordinate of the player.
  • If you set a variable in a condition before a function (if(enemy=way_is_blocked:20)), then a numerical value calculated by the function is written to it, and not a logical value, whether the condition is true or false. The variable before the function does not play any role in the calculation of the logical value of the general condition. If the function is taken in brackets (if(enemy=(way_is_blocked:20))), then a logical value (0 or 1) will be written to the variable. As you can see, each condition function returns two values: one logical (whether the condition is satisfied), and the second is a numerical value, which is calculated to check the condition. What values return functions, see above in paragraph All functions. Actions (run, kick, stand_still, etc.) do not return any values.
  • Code substitution

    In order not to duplicate the same code in different places of the player’s script or for several players, as well as to improve the readability of the script, you can use code substitution tags. They have the following syntax:
    <tag_name>=<? content ?>
    The content of the tags (what is between <? ?>) is inserted into the script of the players when loading the team. These tags can be set and used anywhere in the script for any player (tags is public). The same tags with the same content do not need to be defined for each player. Tags that are common to all can be set in code off one player, and those that differ in content can be defined in code of each player. Example:


    When loading the player’s code, the lines above will be converted to:



    Championship requirements

    1. The team name, description and logo should not contain obscene language, curses, advertising, 18+ content and other inappropriate materials.
    2. Team code must be operational, efficient, and non redundant. It should also be mostly unique (you cannot add the same team with different names).
    3. Passive play is not welcome. It is not permitted to create artificial ball blocking. It is not permitted to specifically knock the ball out of bounds.
    



    © 2019-2020 FuncBall.com

    >>