Kropki server - details of the protocol

  1. General information
  2. Currently, communication with server is always initiated by the client, and is done by http requests, for example, by visiting a link of the form . The values of fields, like PLAYER_ID above, should be escaped if necessary (in js, by encodeURIComponent()). Note that unless explicitly stated otherwise, NO FIELD MAY BE EMPTY!

    If one wants to see how it works on examples, I recommend installing the FireBug addon for Firefox browser. It allows reading messages sent by javascript to the server, as well as the answers.

  3. Logging in
  4. To log in as a guest, one should:

    1. choose some 'idGracza' (player-id), which should be unique. Uniqueness is achieved probabilistically, by taking random string of at most 9 characters from "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.". Currently js client takes id's of length 6, and this is enough to ensure uniqueness with a very high probability. Note that player's id is never revealed to another user, so it acts as a password. Since uniqueness is very important, this should be randomly set up by the client, and not by the user!
    2. choose some 'opisGracza' (= nick). For guests, the nick always starts with a star '*', but of course this '*' should be automatically added by the client. The max length of a nick is 20 (UTF) characters, including '*'. Allowed characters are: digits (0-9), underscore '_', LATIN or CYRILLIC LETTERs (that is, UTF characters that have word LATIN or CYRILLIC, and word LETTER in its UTF description), and single spaces, but not at the beginning or at the end of a nick. LATIN and CYRILLIC letters shall not be mixed in one nick (although there is one exceptional registered user on
    3. open url: with PLAYER_ID substituted by the chosen 'idGracza'.

    To setup an account for user 'name' with password 'mypass', one does the following:

    1. calculate hash:
       hash = sha1-hash( 'name' + '9WB2qGYzzWry1vbVjoSK'  + 'mypass' )
      and convert it to 'base64' with characters in the following order: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_." (that is, char 62 = '_' and char 63 = '.', no padding character). Then take only the first 10 characters as the 'idGracza' (player's id). To let the users use different clients, id should be created exactly in the above way!
    2. Choose 'opisGracza' (nick) as for guests, but now without trailing '*'.
    3. Register by visiting the link: . Remember about escaping PLAYER_NICK and EMAIL above! User needs not to give the email, however the client cannot leave the 'email' field empty, so if user gives no email, the client should send, for example, 'email=v'.
    4. If the response of the above link starts with 'ok.zarejestrowalem', this means success, other values mean failure ('ok.tenOpisJestJuzZajety' = nick already in use, 'ok.niedozwolonyOpis' = incorrect PLAYER_NICK or PLAYER_ID, 'nieOk.' = internal error). One should continue only on success.
    5. After setting up an account, the user gets automatically logged in.

    To log in to the already existing account of user 'name' with password 'mypass', one does everything as above for setting up the account, but in step 3 one should visit the following link instead.

    Remark: guests are recognized by having a trailing star '*' in a nick, and a short ID (at most 9 characters), and registered users - by no star '*' in a nick and a longer ID (at least 10 characters).

  5. Changing table
  6. Read the link: . Note that also another method with subscriptions is supported.

  7. Adding new chat msg
  8. Visit the link: (table ID should be adjusted)

    Note that it may be also sent as a 'msg from client' in 'getMsg', see below.

  9. Making move on a non-AI table
  10. Visit the link: (table ID should be adjusted, XY=sgf coordinates of a move)

    Note that it may be also sent as a 'msg from client' in 'getMsg', see below.

    Here is how to send enclosures in territory game:
    To make 'sm.rlqmrnsmrl' move, that is, place dot at 'sm' and make (manual) enclosure rl-qm-rn-sm-rl:
    To put a dot at 'sm' and enclose enemy dot at 'rm':!rm&msgNo=1234
    In this case, the server will make a minimal-area enclosure around dot 'rm'. If such an enclosure is impossible, it will just play dot at 'sm'.
    Note: you may mix '!' and '.' mode, for example: 'sm.rlqmrnsmrl!bb' will put a dot at 'sm', make a manual enclosure rl-qm-rn-sm-rl, and enclose enemy dot at 'bb'.
    Note 2: 'Manual enclosure rl-qm-rn-sm-rl' means an enclosure in which player's dots rl, qm, rn, sm, rl are connected with line segments to produce an enclosure.

    During manual enclosure it is possible, but not obligatory, to send current enclosure to the server. This is done in the following way (example):
    1. player puts dot at 'sm' and wants to enclose something (so the move is not completely done yet):
    2. player selects own dot 'rl' and starts drawing a manual enclosure:
    3. player has finished the first enclosure 'rlsmrnqmrl' and starts drawing a second one, selecting own dot 'cb':
    4. player changed his mind and deleted the second (unfinished) enclosures:
    5. player deleted also the first enclosure:
    6. player may also delete the first dot and (later) start again at different place:

    In this command auto-enclosure ('!') does not work.

    This is only to inform the opponent and the spectators that the player draws an enclosure. They will see the process of drawing. The enclosure is anyway finished by sending a command to place a dot (graczStawiaKropke explained above, or 's' message).

  11. Propositions on the table
  12. Visit the link: where 'PROPOSITION_STRING' may be equal to, for example, 'resign', 'score', 'terr', 'drop', 'new' or 'undo'. These are the basic propositions (score=finish game with current result, terr=count territory points, drop=cancel game - should not be used now, it's prepared for ranked games, new=start new game, undo=ask to undo a move)

    Note that it may be also sent as a 'msg from client' in 'getMsg', see below.

    After such a proposal, if it is legal in this situation, server will send dj['prop'] equal to '1basic_proposition_string' or '2basic_proposition_string', where starting '1' or '2' denotes the player who proposes (1=starting player, 2=second player). For example, the server will send back '1score' in dj['prop'], if the first player proposed to finish the game with current result (and this was legal: game has not finished and it is first player's move).
    Exception: 'resign' resigns immediately and does not need opponent to agree, and after resign server does not update dj['prop'].

    Now if one of the players proposed something, say '1score', the other may agree or reject by visiting the above link with PROPOSITION_STRING equal to 'ok1score' or 'reject1score', while the first player may send 'cancel1score' to cancel his proposition.
    Exception: to agree for a new game just send 'new'. This cannot be rejected.

    Note: on each table there may be at most 1 proposition at a time. So, if the first proposed 'score', and then he proposed 'terr' or the other asked to 'undo, the first 'score' proposal will be automatically (and silently) discarded. Multiple subsequent propositions of the same type have no effect, that is, sending 'score' two times will not cancel the first 'score'.

    Summary of legal PROPOSITION STRINGS sent to the server:

    1. [resign|score|terr|drop|new|undo]
    2. [reject|ok|cancel][1|2][score|terr|drop|undo]
    3. cancel[1|2]new

    Summary of 'proposition' values sent by the server:

    1. (not sent at all)
    2. [1|2][score|terr|drop|new|undo]

  13. Invitations
  14. Inviting someone: visit the link GAME_TYPE_STRING format is explained below. To accept an incoming invitation, visit the link:, to reject -- the link, to reject and block inviting player: To cancel an invitation being sent (by you), visit When your invitation gets rejected, you get the info about it, and to discard this info you should visit

    Note that these may be also sent as a 'msg from client' in 'getMsg', see below.

  15. Game type string
  16. Examples:

    2020stanA0.0.0 = board 20x20, rules = stan (standard), A=play with AI, first 0 = InstantWin, second 0 = starting time (no limit), third 0 = added time (here of no meaning)

    2525noT4R0.180.15 = board 25x25, rules = 'noT'erritory with 4 crosses, 'R'anked game, InstantWin=0, starting time=180s, added time=15s.

    3932noT1r0.180.20_PWC 2012 = board 39x32, rules = 'noT'erritory with 1 cross, 'r'anked game and inviting player starts, InstantWin=0, starting time=180s, added time=20s, tournament game (tournament name: 'PWC 2012').

    Rules may be: 'stan' for standard, 'terr', 'noT1' or 'noT4'
    Game may be: 'A'=with AI, 'F'=free, 'R'=ranked, 'r'=ranked with inviting player starting (which may be 'unfair' ;)
    InstantWin may be 0,15 or 30.
    Starting time is in seconds, 0 means no limit.
    Added time is also in seconds, when starting time=0 (no limit), it is ignored (but set to 0).
    At the end, there may appear a tournament name.

  17. General information for the server->client
  18. Details of the server->client part
  19. After invoking (test it! -- best with your own playerId; format of msgFromClient is described in the next section, 'x' means no message = no action), server will send a sequence of messages of the following form (example):


    Another variant 'getBMsg': , then also subscribtions of players will be returned. If one uses 'getBMsg' always (and never 'getMsg'), then the above form is sufficient. However if one usually uses 'getMsg' and only sometimes switches to 'getBMsg' to get the subscribtions of players (like javascript client does), then in the *first* run of getBMsg the following form should be used: . Note: in the example above 'msgNo=1234.0', which means that messages up to 1234 have been already read by getMsg, but no subscribtions were read so far (.0). After one gets subscriptions (and all messages numbered up to, say, 1245), one may use the form 'msgNo=1245.1245' or the shorter 'msgNo=1245'. Javascript client retrieves subscribtion info only when the user clicks 'on the table' to see the spectators.

    The sequence starts with 'ok' (user logged in) or 'sd' (=set description, i.e., user not logged in) and ends with 'end'. The first message is of the form 'mi.j.k', where k is the last client's message number processed, and the server sends (some) messages with numbers from i+1 to j inclusive. So j is the current last server message number. (Server sends both, so that client can discard old sequences sent by server, for example, it may happen that the client first gets and interprets a sequence with 'm643.657.11', if then a sequence with 'm643.649.11' comes, it should be discarded.) Next messages are encoded as follows:


    In general, usually 'r' will be used when user has just logged in, or has just entered a table. After the user is subscribed to a table, the client will rather get add/delete messages.

  20. Client -> server part: format of msgFromClient field
  21. The client may send as msgFromClient 'x', or one or more of the simple messages of the following type (multiple simple messages should be separated by slash '/'). General format is 'cN.tableID.text', where 'c' is a command (currently may be 's', 'c', 'u', 'b', 'q', 't' or 'v'; 'm'), N is msg number, and text is additional info. Exception: 'i'. Examples:

    For example, to place a dot at 'ab' on table 11 and write 'hello' on table 12, one may send 's120.11.ab/c121.12.hello'. However in typical situations one would send only one simple message, as it would be probably rare for a user to produce 2 actions in 1 second.

    Currently only the basic operations are implemented in this way, the other should be handled in the 'old' way. Note, however, that logging in (as guest or as registered user) will remain in the 'old' way only, also placing dot in a game with AI. The rest may be implemented in a 'new' way.

  22. Format of the chat sent from the server
  23. Chat has the form 'time_chatMsgNo.nick.nickType.chatMsg', where:

    1373011049_0.John.3.Salut Alexey
    1313684800_0.John.B3.Hi. Have a nice game. :)
    1313685334_0...Player John resigns.

    Besides that, five characters written by users are escaped, these are '<', '>', apostroph ('), double quotes ("), dash '-', they are replaced by '&#60;', '&#62;', '&#39;', '&#34;', '&#45;', respectively. Also recall that '@' and '/' are escaped and encoded as '@A' and '@S', respectively.

  24. Proposition for the format of server chat messages
  25. The server could send messages (server-generated, like result of the game) in the following format:

    1313684800..u1undo.Player firstnick asks to undo the move.

    i.e., with the message code in 'nickType' field. Then the client could decide: it could display the standard message 'Player firstnick asks to undo the move.', or it could self decode 'u1undo' into some human-readable message.

    Concerning the codes: for propositions PROPOSITION-STRINGS seems to be most natural. There should be also something for game end (like 'B+T' to denote that B won on time), and something for the link (like 'l22222' to denote game number 22222 on eido).

    Note that 'span' will be anyway removed soon from messages generated by the server, so that only 'link' would not look well in non-browsers clients.
    Feedback is welcome...

  26. Logging out
  27. Visit the link

  28. The format of the 'i' (server->client) command
  29. A general syntax is:
    (here NICK is capitalised only to increase readability, server never changes the size of the letters).
    NOTE: prestige_and_mod_powers are not implemented yet! (TODO)

    Any field is optional. For example, after language change the server could send '', which would mean that language should be changed to 'ru', and the other info (avatar, flags, ...) should be kept unchanged.

    Flags could be:

    At most one of the flags from a group is sent, e.g. 'F' or 'N' or none of 'FN', but never both 'F' and 'N'. When no flag of a group is sent (for example, neither 'F' nor 'N'), this means that the flag should be kept unchanged.

    prestige_and_mod_powers describes prestige and moderating powers (surprise!), as flags (to be defined, now just a list of desired options) followed by a digit. For example, 'P3c2'. List of flags:

    e.g. 'x1' could mean: you may ban users with prestige <= 1, 'i2': you may add 1 to people with prestige <= 2. It is not possible to have a power on level 0, 1 is minimum, although it is possible for a user to have prestige=0. Mostly NOT impelemented!

    Also note that the client needs not to implement (immediately) all the above, it should just handle correctly the 'i' messages sent from the server (mostly, the 'F'/'N' flag).

  30. Going to page with auto log in
  31. The aim: allowing non-web clients to provide a button, that would allow to switch to the web-client.

    The following link: where PLAYER_ID, PLAYER_NICK, and XX (= 'en', 'pl', 'ru' or 'ua') are appropriately adjusted, automatically logs in the player on, and changes the link so that everything after '?' disappears (note that the link is 'insecure' and hence should not be pasted somewhere, because it contains the player's id).

    'index.html' in the above link should be used for 'lang=pl', for the other languages appropriate index*html should be used, for example, '' for 'lang=ru'. (The link will also work with index.html for non-Polish lang, but more slowly - because it will first load index.html and then the right index*html).

  32. Creating tables for tournaments
  33. The following link: creates the table between players 'pl1' and 'pl2'. They may be guests or registered. If the game type is free or 'rating I start (r)', then 'pl1' will be blue, if the game type is 'rating (R)', then the blue player is determined automatically by the server (and is the player with lower rating, or pl1 if the ratings are equal).

    'yourKey' is a secret key. If you wish to organise tournaments, please contact us and we will give you a personal secret key.

    'sayHiTimes' is of the form 'K.L', where K and L are integers from [0,7200]. After the table is set up, player 1 will have additional K seconds to make the first move (after K seconds his/her normal timer will be used). Those K seconds may be only used for the 1. move. Similarly player 2 will have additional L seconds to make his/her first move. For example, if the starting time in the game between B and W is 120 seconds, added time is 5 seconds, and sayHiTimes are both 60 seconds, then after setting up the table:

    'tourn' field is saved in EV field of sgf, and 'tRound' in RO field (if one does not want to save these in sgf, then 'tourn=x' and 'tRound=x' should be set). Both should be set according to SGF suggestions:

    EV: provides the name of the event (e.g. tournament). Additional information (e.g. final, playoff, ..) shouldn't be included (see RO).

    RO: Provides round-number and type of round. It should be written in the following way: RO[xx (tt)], where xx is the number of the round and (tt) the type: final, playoff, league, ...

    If the game *is* a tournament game (i.e., tourn!='x'), then SGF will always be saved, no matter how many moves were made. Also *not-finished* tournaments games do not vanish at least for 2 hours even if nobody watches them. However rating will be changed only if at least 24 dots were placed (either by players, or automatically by STOP function; the starting dots 1X or 4X are not counted), so this works as usually.

    In the auto-created (tournament) games it is possible that no player shows up. In such a case the result will be 'Void' (i.e., in flags, where there is normally 'W+R', 'B+3', etc., it will be 'Void'). It is also possible that only one of the players does not show up and loses on time. In such a case the result will be 'W+F' or 'B+F' instead of usual 'W+T' and 'B+T' (js client treats them the same, and also the texts send by the server are the same).

    Only the first game on the created table may be a tournament game; if players press 'new game' button, then the next game(s) will be usual games.

  34. Proposition for the format of private chats
  35. client->server: send ('_' + username) instead of a table number, for example 'c120._player.Hello my email is' = write a private chat msg 'Hello my email is' to 'player', this is message number 120.

    client->server, to get list of players with whom one chatted with the chat still being on the server: send 'get' instead of a table number, time in minutes as a message. For example 'c120.get.30' = get usernames of people with whom I chatted since last 30 minutes. Special case: 'c120.get.0' = get ALL usernames of people with whom I chatted. The usernames are returned as empty chat messages, using '-' nicktype, see below.

    client->server, to get (resp. delete) the full chat with a player: send 'get' (resp. 'del') instead of a table number, and ('_' + username) instead of the message. For example, 'c120.get._player' will get the whole conversation with 'player' which is still stored on the server, and 'c120.del._player' will delete it.

    All this also works using the old method (for example, using ...?idGracza=PLAYER_ID&co=dodajWpis&table=_username&newMsgs=privet&msgNo=1233).

    server->client: send the chats on the main table (uid=0) with '1', '2', '0' or '-' as a nick type, and chat name as a nick. Chat name is of the form 'nick1-nick2' (ordered alphabetically, but for the client it shouldn't matter), and then nick type: '1' denotes nick1's message, '2' denotes nick2's message, '0' server message (not used now), '-' denotes no message (to send with whom we talked), 'nochat' means there is no chat (sent only when the user asks to get the whole chat), 'del' means that the talk has been deleted.
    One can recognise that the chat is private by '-' in the chat name string (note that '-' is not allowed in usernames). For example:
    ca1313684800.John-Player.2.hi John, can you give me your email email is

    It is up to the client program how the private chats are shown. They may be shown in a separate tab. They could be also shown on the main table, with another colour, as the format 'server->client' may suggest, but I don't plan it.

  36. How to embed zagram's client on your webpage.
  37. First, keep in mind that you will need to update your client quite often. Please let us know that you are embedding the client, so that we could send you information about coming upgrades. If you plan to modify the client (if you don't plan it, then why embed?), try not to change the structure too much, so that you may use diff + patch to automatically upgrade your modified client.

    There are three things you need to do:

    1. Copy the following files to some directory:
      nkropki.js raphael-min-mod.js moveTree.js sha1-min.js jscolor.js index.html index.en.html style.css glosnikWlaczony.png glosnikWylaczony.png alert.wav karuzela.gif ikonki2_off_off.png ikonki2_off_on.png ikonki2_on_off.png ikonki2_on_on.png kropkaBlue1.gif kropkaBlue2.gif kropkaBlue3.gif kropkaRed1.gif kropkaRed2.gif kropkaRed3.gif kropkaOst1b.png kropkaOst2b.png kropkaOst3b.png obwodka1.png obwodka2.png obwodka3.png awatar1.png awatar2.png navtree-line.gif navtree-elbow.gif navtree-T.gif navtree-left.gif b19.png w19.png krzyzyk.png tloCien.png kropki-zasady.html kropki-taktyka.html kropki-info.html kropki-faq.html kropki-warianty.html podstawy.sgf kropki-sitemap.html doc.html kropki-rules.html kropki-tactics.html kropki-info.en.html kropki-faq.en.html kropki-variants.html podstawy-en.sgf

      Note: you may download them all using wget, just copy this long line to the terminal:


    2. In the file nkropki.js, in the function poczatek(), change lines:

      var url = document.location.toString();
      if( url.indexOf("/kropki/") > 0 && url.indexOf("")==-1 ){
      var ind = url.indexOf("/kropki/");
      rootUrl = url.substr(0, ind+8);
      rootUrl = '';


      rootUrl = ''; // could be also '' etc.

    3. Finally you need to setup your www serwer to proxy some 'files' to In apache, you may enable the proxy mod ('a2enmod proxy' as root), and add the following lines to the file /etc/apache2/mods-available/proxy.conf

      ProxyPass /a.kropki
      ProxyPass /
      ProxyPass /
      ProxyPass /awatary/

      This is assuming that you have embedded the client in the main directory; if the client is for example on '', then instead of ' ProxyPass /a.kropki' there should be 'ProxyPass /kr/a.kropki' etc.

      Note that this step may be also achieved using other method, like for example simple php-proxy scripts... But the method above is very simple and probably also effective.

      Also note that if you DO NOT change some file, for example if you do not change moveTree.js, then you may also list it in the ProxyPass directives. This way your client will always automatically use the newest version of the file (which may be good, and may be bad ;).

    These files: po-en po-ru po-ua and a few scripts ( tlumacz-en.bash tlumacz-ru.bash tlumacz-ua.bash) are not necessary, but may be helpful if you plan to change the texts in index*html files. They are used to translate index.html into 3 other language versions.

    Few hints to modifying:

    1. To change colours of html elements (backgrounds, texts, etc.), modify 'var koloryStand = [...]' in nkropki.js AND style.css. koloryStand[i] corresponds to elements described by koloryCzego[i]. The description is not always clear, but it should help in most cases.
    2. To change fonts, just change style.css. Very few elements have their fonts set in nkropki.js or moveTree.js as well, search for 'font' to find them.
    3. Changing layout may be difficult. Most items are defined only through style.css, but some, for example board size on the screen and related stuff, is adjusted by a function 'resizeElements' in moveTree.js.
    4. Changing colours of the dots is trivial -- just change the appropriate gif and png files. Colours of enclosures are hard-coded in the function 'drawEnclosure' of moveTree.js and also easy to change.
  38. New gameType format
  39. General format is: XXYYrI.(starting position).(who starts).(type).(time method).t0.t1.opt.tourn where:

    1. XXYY is the size of the board, e.g. '2020' or '3932'
    2. r is a char encoding the rules: s = standard, t = territory, n = no territory
    3. I is an integer with InstantWin, '0' for no InstantWin
    4. (starting position) is '' (empty), '1' (1 cross), '4' (4 cross) or 'SGFz' + sgf number, e.g., 'SGFz12345', or 'Hx', where x=2,...9, for handicap games
    5. (who starts) is 'a' for active player (the one who invites or the one who left a challenge), 'p' for passive, 's' for automatic (server decides). May be also empty in cases when it does not matter. For SGF starting position, 'starting' means blue and only 'p' or 'a' are allowed.
    6. (type) is 'R', 'F', 'A' or 'a', which stands for rated, free, with AI, or analysis, respectively
    7. (time method) is 'a' for starting and added time after each move and 'n' for no time limits
    8. t0 and t1 are the starting and added time, when (time method) is 'a', and are empty strings for 'n'
    9. opt are options, default is empty string, for the description see chapter 'Opt field with rights in gameType string' below.
    10. tourn is the name of the tournament, or empty string for a normal (non-tournament) game

    Examples: '2020s0...A.n....' '2020t15..s.R.a.180.15..' ' X'

  40. Some last changes
  41. 2012-10: 'x' tag (server->client) for finished games now contains also SGF number.

  42. Team games
  43. Changes:
    In 'x' tag (server->client), the side on move is sent as 1,3,5... for the first team, and 2,4,6... for the second (where 1 is the first player of 1. team, 3 is the second player of 1. team, and so on).
    Similarly in 'h' tag (server->client).

  44. Deleting chat messages
  45. Only allowed for some users.

    client->server: 'c120.delmsg.11.1313684800_0' = message no 120, delete first (_0) chat msg at time 1313684800 on table 11.

    client->server: 'c120.delmsg.11._player' = message no 120, delete all msgs of 'player' on table 11. [TODO!]

    then server sends to client: 'cd1313684800_0' on table 11 to people who already have that chat message, or it sends 'ca1313684800.John.d.' to new people, to indicate that there was a message from John that was deleted (this is important to number the messages in the same second correctly).

  46. Opt field with rights in gameType string
  47. In case of 2 players/teams having rights: tableRights_rightsForB_rightsForW and for analysis: tableRights_rightsForB_rightsForW_rightsForAnalysernNickofTheAnalyser Player rights can have the following flags:

    Table rights:

    Planned but not implemented:

    These are sent by client in propositions as well by server in 'd' (table description) message.

    Currently accepted values: '' (which means '_SRAUTP_srautp'), '_SRATP_sratp', '_SRAUP_sraup', '_SRAP_srap', and for analysis: 'c___SUsuen' + playersNick. Example: 'c___SUsuenJohn', if the game is analysed by John.