- General information
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
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=pobierz&howManyLinesOfChat=0&lastPos=0.0&lastMsg=x&writes=nie
.
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.
- Logging in
To log in as a guest, one should:
- 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!
- 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 zagram.org).
-
open url:
http://zagram.org/a.kropki?co=guestLogin&idGracza=PLAYER_ID&opis=NICK&lang=en
with PLAYER_ID substituted by the chosen 'idGracza'.
To setup an account for user 'name' with password 'mypass', one does the following:
- 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!
-
Choose 'opisGracza' (nick) as for guests, but now without trailing '*'.
-
Register by visiting the link:
http://zagram.org/auth.py?co=rejestruj&opisGracza=PLAYER_NICK&idGracza=PLAYER_ID&email=EMAIL
.
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'.
- 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.
- 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
http://zagram.org/auth.py?co=loguj&opisGracza=PLAYER_NICK&idGracza=PLAYER_ID
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).
- Changing table
Read the link:
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=zmienStol&newTable=124
.
Note that also another method with subscriptions is supported.
- Adding new chat msg
Visit the link: (table ID should be adjusted)
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=dodajWpis&table=TABLE_UID&newMsgs=privet&msgNo=1233
Note that it may be also sent as a 'msg from client' in 'getMsg', see below.
- Making move on a non-AI table
Visit the link: (table ID should be adjusted, XY=sgf coordinates of a move)
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=graczStawiaKropke&table=TABLE_UID&where=XY&msgNo=1234
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:
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=graczStawiaKropke&table=TABLE_UID&where=sm.rlqmrnsmrl&msgNo=1234
To put a dot at 'sm' and enclose enemy dot at 'rm':
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=graczStawiaKropke&table=TABLE_UID&where=sm!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):
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=okrazam&TABLE_UID=1&where=sm.
2. player selects own dot 'rl' and starts drawing a manual enclosure:
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=okrazam&TABLE_UID=1&where=sm.rl
3. player has finished the first enclosure 'rlsmrnqmrl' and starts drawing a second one, selecting own dot 'cb':
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=okrazam&TABLE_UID=1&where=sm.rlsmrnqmrl.cb
4. player changed his mind and deleted the second (unfinished) enclosures:
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=okrazam&TABLE_UID=1&where=sm.rlsmrnqmrl.
5. player deleted also the first enclosure:
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=okrazam&TABLE_UID=1&where=sm.
6. player may also delete the first dot and (later) start again at different place:
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=okrazam&TABLE_UID=1&where=-
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).
- Propositions on the table
Visit the link:
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=propose&proposal=PROPOSITION_STRING&table=TABLE_UID&msgNo=1234
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:
- [resign|score|terr|drop|new|undo]
- [reject|ok|cancel][1|2][score|terr|drop|undo]
- cancel[1|2]new
Summary of 'proposition' values sent by the server:
- (not sent at all)
- [1|2][score|terr|drop|new|undo]
- Invitations
Inviting someone: visit the link
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=zapraszam&whom=NICK&gameType=GAME_TYPE_STRING
GAME_TYPE_STRING format is explained below.
To accept an incoming invitation, visit the link:
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=zaproszenieTak,
to reject -- the link
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=zaproszenieNie,
to reject and block inviting player:
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=zaproszenieBlokuj.
To cancel an invitation being sent (by you), visit
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=zaproszenieAnuluj.
When your invitation gets rejected, you get the info about it, and to discard this info
you should visit
http://zagram.org/a.kropki?idGracza=PLAYER_ID&co=zaproszenieOdrzuconeOk.
Note that these may be also sent as a 'msg from client' in 'getMsg', see below.
- Game type string
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.
- General information for the server->client
-
Later (private and possibly also public) 'chats' will be introduced.
Chats will get IDs like game tables. Numbers for ID will not be reused.
There will be 1 global 'general' chat (like now), and there will be a possibility
of creating new chats (public or private). Each chat could have a description.
So if users want, they will be able to create 'Russian' chat, for example.
Creating private chat with 2 users will allow private talk between 2 people.
I am not sure how to do some things, for example, how long should the chat be alive.
This is in project stage. Anyone may feel free to write comments, wishes, ideas, etc.
Table with id=0 is the 'root', on which there are: game with AI, general chat,
players and games lists.
- Server keeps queues of messages for each table.
Messages get unique numbers, that is,
if there is a message with number j in some queue, then no other message in any queue will get this number.
Numbers will start from 1 and will be increasing in time.
- A typical query looks as follows: client sends the last message number obtained from server, say n.
Server looks at queues of all tables that user is subscribed to, and takes all messages from
these queues with numbers > n. It also sends current last message number, to be sent by client in subsequent calls.
-
If a user subscribes to a table, he will get the whole info of this table in the next query,
instead of updates, but it will have a similar form, see below.
- Details of the server->client part
After invoking
http://zagram.org/a.kropki?playerId=xxx&co=getMsg&msgNo=0&msgFromClient=x
(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):
ok/m643.649.120/.../.../end
Another variant 'getBMsg':
http://zagram.org/a.kropki?playerId=xxx&co=getBMsg&msgNo=0&msgFromClient=x
, 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:
http://zagram.org/a.kropki?playerId=xxx&co=getBMsg&msgNo=1234.0&msgFromClient=x
.
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:
- First letter encodes an object (to be added, deleted, replaced, etc) and may be:
- 'r'= room(s) (DROPPED, see above)
- 'g'= table(s) ('g'ames), implemented
- 'p'= player(s), implemented
- 'c'= chat, implemented
- 'u'= proposition on the table (e.g. 'undo'), also 'resign'. It is only sent when there is
some proposition -- no 'u' is sent otherwise. Implemented
- 's'= sgf properties (moves), implemented
- 'i'= player info (rank etc), implemented (also updated after rank,
lang change). See also a special chapter devoted to the format of
this command.
- 'd'= table description, implemented
- 'f'= flags. This is used to sent timers etc., see below. Implemented.
- 'b'= subscriptions of other players, will appear in the next version of the server. Will only be provided if one gives 'co=getBMsg' instead of 'co=getMsg' in request
- 'q'= set current number of table ('q'ueue) -- next messages are processed on this table. This is always used even if there are no new messages on the table -- and that allows to see subscriptions. Implemented.
- 'v'= invitation, implemented. After 'v' comes a letter with meaning: 's' = I send (the invitation),
'r' = I get rejected, 'g' = I get an invitation. More details below.
- 'w'= who writes on the table. After 'w' comes the nick (exactly 1) of a player who is writing a message. No 'w' message means that noone writes.
- 'k'= spectators ('k' comes from Polish word 'kibic'). After k comes a letter: 'a' means add an unblocked spectator, 'b' means add
a blocked spectator, that may be unblocked, 'd' means delete an ublocked spectator, 'r' means replace unblocked spectators by given,
'u' means unblock a spectator (and hence move him to unblocked), 't' means replace the list of spectators possible 't'o unblock by a given list. After that letter comes a list of players, separated by dot '.'.
This list may be empty for 'rt' (replace). This message is only sent to players on 'human' table (becuase only they can block or unblock).
- 'h'= additional info to help implementing client. After that come exactly two chars: first tells whose turn it is, second: which player you are (1,2, or spectator). More details in examples below. Note that this information MAY be deduced by client from other
information.
- 'x'= info about the number of move/result on the table. When the
game is not finished, gives 'xTABLEID.g.WHOMOVES.DOTSPLAYED',
otherwise 'xTABLEID.f.SGFRESULT.NoOfSgfFile', where NoOfSgfFile is the (positive) number under which the game is saved, or 0 if it was too short to be saved.
-
'F'=extra flags describing given time. General format: 'FK.L.M.N',
where K,L,M,N are integers. K and L are times given to the player 1
(by the player 2.), K directly by adding time, and L indirectly by
using pause. M and N are analogous (times given to the player 2 by the
player 1).
- 't'=timestamps. General format is 'tK.L.M.N', where K,L,M,N are
empty strings or integers. 'K' is the time of creating the table
(for table 0, this is the time of last server restart) and is always
non-empty (i.e., always an integer). If 'L' is
non-empty, then K+L is the time when the current game started.
If 'M' is non-empty, then K+M is the time when the current game has
finished.
If 'N' is non-empty, then K+N is the current time on the server.
-
'T'=possible tournament games. Then comes a 'a' (add) or 'r' (replace) letter, then obligatory rules (gameType) if there are some, then '_', tournament name, again '_' and then the list of possible opponents seperated by dots. For example, 'Tr3932noT1r0.180.20_PWC 2012_inDI.volodarkropek.ysipysi' or 'Ta_Liga sezon 9_kubusio.michals.Yazon'. This is sent only to the players that take part in a tournament.
- 'D'=chalenges ('open games'). General format:
'Dx.username.gameType.' (x='a' for add, ='r' for replace) or
'Dd.username' for deleting a challenge. Each player may open at most
one game, so if some player adds a new chalenge, then the old one
(if there was) is automatically discarded. So in fact 'a'
adds a challenge only when there was no challenge of the player yet,
in the other case it changes the challenge.
- 'V'=who wants to accept your challenge or whom you send a proposal. General format:
'Vx.y.dot_separeated_usernames', where x = 'a' for add, 'd' for
delete, 'r' for replace; and y='g' for the players who want to
accept my challenge ('g' from what I get), or y='s' for whom I send.
- Second letter may encode a command (depends on object), and may be 'a' = add, 'd'=delete, or 'r'=replace.
It will be used with 'gpscTDV' only (but after 'scT' only 'ar', no 'd'eleting).
Other messages will always replace.
Examples:
- 'q1' = set current table to 1
- 'ga147.148' = add tables numbered 147 and 148
- 'gr147.148' = replace tables by 147 and 148. (All tables client had should be dropped. If client already had 147 or 148, it should be dropped and replaced by a new, 'empty' one.)
-
'ca1313684800_0.John.B.Hi. Have a nice game. :)' = add a chat message to the current table (set by last 'q'). Slash '/' and at-sign '@' are escaped, and encoded by '@S' and '@A', respectively. That means that sent chat message is guaranteed not to contain any slash. Some other characters may be escaped in future, depending on needs. The exact format is explained below
in 'Format of the chat sent from the server'.
- 'u1undo' = player 1 asks for undo (on current table)
- 'pdadmin' = delete player 'admin' from the list of players
- 'pasuper_master.*guest' = add players 'super_master' and '*guest'
- 'd147.2020stanF0.180.15.playerB.playerW' = replace a description of table 147 (2020 = board size, 'stan'=rules, 'F'=free game, '0' = InstanWin value, '180' = starting time, '15' = time added after each move). Maybe it's good to add some 'status' flag, like: challenge (game not started, waiting for opponent), game (is being played), finished (game is finished), analysis. However now anyway only 'game' would be supported.
- 'isuper_master.0.F.ru.2147.222.1.0' = super_master uses avatar '0', is 'free' (F), has 'ru' as language, has rank 2147, 222 wins, 1 draw and 0 losses.
- 'i*tomek.0..pl' = *tomek uses avatar '0', is not 'free' (no F after next dot), has 'pl' as language, has no stats (compare with above)
- 'sa;B[ab];W[bc]' = add moves to current table
- 'sa;UW[bc];W[bd]' = undo last move on current table and make a new one. Note: in undo we send only the dot position of move to undo, no enclosures.
- 'sr' = replace history of moves on current table by an empty one, that is, start a new game (not used now!)
- 'sr(;RU[2020noT1F0.180.15]AB[jj][kk]AW[jk][kj]PB[t]PW[*gt]' = replace history of moves on current table by a starting cross at jj-kk-jk-kj. Note that some of the info passed here is redundant (like RU and PW, PB), anyway I send it for simplicity.
- 'f123_3612.3655_B+11.44.33' = flags for current table. '123' is the last message number used in sgf and may be ignored (probably it will be deleted, because I think it's useless). '3612.3655' is timer (3612 seconds for B, 3655 for W), it is '' (empty string) if there is no time limit. 'B+11.44.33' at the end means that Black won by 11 points, 44:33. This is of course only set if game is finished. Other possibilities are: 'SB' or 'SW', meaning that B or W pressed STOP; or current enclosure for territory rules.
- 'f144__' = no time limit on current table, game is not finished (144 is the last message number used in sgf and may be ignored)
- 'f156__SW' = no time limit on current table, game is not finished, White pressed STOP (156 is the last message number used in sgf and may be ignored)
- 'f17_209.p220__ki.kilh' = timers: 209:220, red's timer is paused
(p letter before the timer), game is not finished, 'ki.kilh' =
current enclosure (ki = dot placed, ki-lh = dots already chosen as a
border of enclosure). SayHiTimers both 0.
- 'f17_209.220__ki.kilhmiljki.' = as above, but now the enclosure is
'ki.kilhmiljki.', that is, one enclosure is finished (but maybe
another will be selected by user). SayHiTimers both 0.
- 'f17_209.220__ki.kilhmiljki.milj' = as above, user started to draw
2nd enclosure. SayHiTimers both 0.
-
'f156_180.180.14.10_' = timers: 180:180, sayHiTimers = 14:10.
- 'vsMaster.2525stanF0.180.15' = I send ('s') an invitation to 'Master'.
- 'vrMaster' = 'Master' rejected ('r') my invitation.
- 'vgPlayer.2525stanF0.180.15' = 'Player' invites me ('g') for a game 2525stanF0.180.15.
- 'wPlayer' = 'Player' writes on a current table.
- 'kaPlayer1.*guest' = do: "notBlockedSpectators += ['Player1', '*guest']"
- 'kbPlayer1.*guest' = do: "blockedSpectatorsPossibleToUnblock += ['Player1', '*guest']"
- 'kuPlayer1.*guest' = do: "blockedSpectatorsPossibleToUnblock -= ['Player1', '*guest'] and notBlockedSpectators += ['Player1', '*guest']"
- 'krPlayer1.*guest' = do: "notBlockedSpectators := ['Player1', '*guest']"
- 'ktPlayer1.*guest' = do: "blockedSpectatorsPossibleToUnblock := ['Player1', '*guest']"
- 'kdPlayer1.*guest' = do: "blockedSpectatorsPossibleToUnblock -= ['Player1', '*guest'] and notBlockedSpectators -= ['Player1', '*guest'] "
- 'h12' = now playes the first=blue ('1') player, and you are the second player=red ('2')
- 'h11' = you are blue and it's your move
- 'h2s' = now playes the second=red ('2') player, and you are a spectator ('s')
- 'bPlayer.0.11' = 'Player' is subsribed to tables '0' (always) and '11'. Note that this info is only sent if you invoke 'co=getBMsg'.
- 'x123.g.1.24' = on the table 123 the game is still played ('g'),
now '1' moves, players have already placed 24 dots.
- 'x123.f.W+R.1234' = on the table 123 the game is finished ('f'), white
won by a resign of the opponent, and the game is saved to SGF #1234.
- 'Da.nick.3030terrR30.300.20.' = a new challenge by player 'nick',
with given rules
- 'Dd.nick' = delete a challenge of player 'nick'
- 'Vr.g.Player1.anotherOne' = now exactly 2 players ('r'=replace)
want to accept your challenge
- 'Vd.g.Player1' = player 'Player1' no longer wants to accept your
challenge
- 'Va.s.John' = add John's challenge to the list of challenges that I want to accept
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.
- Client -> server part: format of msgFromClient field
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:
- 's120.11.ab' = place a dot at 'ab' on table 11, this is message number 120. Important: This works only on
'human' tables!
- 'c120.11.Hello my email is a@Aexample.com' = add a chat msg 'Hello my email is a@example.com' to table 11,
this is message number 120.
Note that the chat message is escaped as in the server->client part (i.e., '@' replaced by '@A', and '/' by '@S').
- 'u120.11.ok1score' = proposition 'ok1score' on table 11, this is message number 120. Proposition strings are explained
above.
- 'b120.11.' = subscribe to table 11, this is message number 120. Note the dot at the end.
- 'q120.11.' = as above, but unsubscribe. Currently one cannot unsubscribe the AI table ('main room').
- 'v120.0.r' = v works with invitations. It is always on the table 0. 'r' as here means 'reject' current invitation.
- 'v120.0.a' = accept current invitation
- 'v120.0.o' = 'ok' to the fact that someone rejected your invitation
- 'v120.0.c' = I cancel my invitation
- 'v120.0.b' = reject current invitation and block future invitations from the inviting player. Use with caution, blocking cannot be currenly undone, it disappears only with the next restart of the server.
- 'v120.0.s.whom.2525stanF0.180.15' = send 'whom' an invitation for a '2525stanF0.180.15' game
- 'v120.0.a.whom.2525stanF0.180.15' = accept an invitation from 'whom' for a '2525stanF0.180.15' game. Note that 'whom' and gameType are optional and currently they will be ignored, but may be sent anyway.
- 't120.11.a60' = add 60 seconds to opponent's timer on table 11. One may add an integer number of seconds (min. 1 second, max. 3600 seconds by one request).
- 't120.11.p = pause opponent's timer on table 11
- 't120.11.u = unpause opponent's timer on table 11
- 'i11y' = this is info command. 11 = uid of a table the user looks at (or writes on), y=user writes on this table (n=doesn't write). If user doesn't write, then he may send any subscribed uid -- but best of a table (or one of the tables) he sees. Note that uid of a table is important for the server to determine if the player should be on the 'free players' list.
The general format is 'iTABLEflags', for example 'i0ya' would mean that the player writes something ('y' flag)
on the table 0 and has an 'a'vailable status.
Client may send at most one of each from the 'yn', 'ab', 'KMJ', 'st' flags
('b'=busy; KMJ - type of the client used: kropki_game@www, marbles_game@www, java client; 'st' = sees the tab with zagram/t=does not see the tab with zagram, for 5 minutes).
- 'D120.0.2020t0..s.F.a.180.15..' = leave a challenge, general format is D(message number).0.(gameType) or...
- 'D120.0.SGFz1234.a' = leave a challenge, with a position from SGF #1234 as a starting position, with active player (=leaving challenge) being blue.
- 'D120.0.SGFz1234.p' = leave a challenge, with a position from SGF #1234 as a starting position, with active player (=leaving challenge) being red.
- 'V120.0.s.player.2525s0..s.F.a.180.15..' = try to accept a challenge of a 'player', with settings '2525s0..s.F.a.180.15..' (this is to protect against the situation when 'player' changes his/her challenge, so that we do not accept a changed one)
- 'V121.0.c.player' = cancel my last offer (that is, no longer try to accept a challenge of a 'player')
- 'V1234.0.r.who' = reject an offer of player 'who'
- 'V1234.0.a.who' = accept an offer of player 'who'
- 'm1234.0.a.2.180' = mod action [on table 0]: 'a' (block all users with prestige <=2 for 3 minutes) [TODO]
- 'm1234.0.w.*player.180' = mod action [on table 0]: 'w' (block *player on all tables) for 3 minutes [TODO]
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.
- Format of the chat sent from the server
Chat has the form 'time_chatMsgNo.nick.nickType.chatMsg', where:
- time is seconds from Epoch (UCT), it is an integer, and chatMsgNo is the number of the message in this second
(usually 0, but if there were more messages sent in this second, then next get 1,2,...). This field, time_chatMsgNo, describes
uniquely chat message on a table
- nick is the player's nick, and is an empty string if the message is generated by the server,
- nickType equals '', 'B', 'W', 'G', 'd', if (respectively) the user who writes is: a registered spectator,
B player (the one who starts, blue on zagram), W player (the second one, red on zagram), a guest spectator,
or whoever ('d'), but the message has been 'd'eleted.
On the main table it is always '' or 'd'. It is also '' for server messages.
Additionally (added in June 2013) a digit may follow, meaning the prestige of the player who wrote that message.
Without a digit, message is not possible to delete ('infinite prestige'), which is the case for server messages, for example.
- chatMsg is the message itself. Some characters are escaped, see below.
Examples:
1373011049_0.John.3.Salut Alexey
1313684800_0.John.B3.Hi. Have a nice game. :)
1313685334_0...Player John resigns.
1313685334_1.John.B3.thx
Besides that, five characters written by users are escaped, these are '<', '>', apostroph ('), double quotes ("), dash '-',
they are replaced by '<', '>', ''', '"', '-', respectively.
Also recall that '@' and '/' are escaped and encoded as '@A' and '@S', respectively.
- Proposition for the format of server chat messages
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...
- Logging out
Visit the link
http://zagram.org/a.kropki?playerId=xxx&co=usunGracza.
- The format of the 'i' (server->client) command
A general syntax is:
iNICK.avatar.flags.lang.rating.wins.draws.losses.prestige_and_mod_powers
(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 'iplayer...ru', which would mean
that language should be changed to 'ru', and the other info (avatar, flags, ...) should be kept unchanged.
Flags could be:
- 'F' or 'N': free/non free (busy) player
- 'a' or 'b': status of the player: available or busy
- 'K', 'M' or 'J': player plays Kropki on zagram, Marbles on zagram, or kropki on the Java client
- 's' or 't': activity of the player: has seen the tab with zagram during 5 minutes ('s') / has not seen it during last 5 minutes ('t').
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:
-
P -- : prestige, e.g., 'P3'. P=3 is default and it is so for new players (guests or registered).
Moderators may change the prestige up or down. Some chats may be blocked for people with low prestige.
This flag is in a sense different than the others, that it does not describe a 'mod power', but rather a 'user power'
(better prestige means lower risk of being blocked).
- c, p -- : delete chat message(s) on the main chat/player tables
- b, l, w -- : hide messages of a particular user with small prestige on main table/a particular player table/all tables (1-1440 minutes)
- a -- : block all users with small prestige on main table
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).
- Going to zagram.org page with auto log in
The aim: allowing non-web clients to provide a button, that would
allow to switch to the web-client.
The following link:
http://zagram.org/index.html?id=PLAYER_ID&opis=PLAYER_NICK&lang=XX
where PLAYER_ID, PLAYER_NICK, and XX (= 'en', 'pl', 'ru' or 'ua') are
appropriately adjusted, automatically logs in the player on
zagram.org, 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,
'index.ru.html' 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).
- Creating tables for tournaments
The following link:
http://zagram.org/a.kropki?co=setUpTable&key=yourKey&gameType=3030noT4r0.180.20&pl1=e&pl2=g&sayHiTimes=60.60&tourn=test&tRound=2%20%28playoff%29
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:
- If B does not show up/does not play for 180 seconds (120+60), she loses on
time.
- If B does her move in the first minute, then after that she will have 65
seconds on the timer (no matter if she makes the move immediately
after creation, or 59 seconds after). After that, W will have
120+60 seconds for his first move.
'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.
- Proposition for the format of private chats
client->server: send ('_' + username) instead of a table number, for
example 'c120._player.Hello my email is a@Aexample.com' = write a private chat msg 'Hello my email is a@example.com' 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
ca1313684807.John-Player.1.my email is john@Aexample.com
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.
- How to embed zagram's client on your webpage.
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:
-
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 index.ru.html index.ua.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
kropki-rules.ru.html kropki-tactics.ru.html kropki-info.ru.html kropki-faq.ru.html kropki-variants.ru.html
Note: you may download them all using wget, just copy this long line
to the terminal:
wget zagram.org/nkropki.js zagram.org/raphael-min-mod.js
zagram.org/moveTree.js zagram.org/sha1-min.js zagram.org/jscolor.js
zagram.org/index.html zagram.org/index.en.html
zagram.org/index.ru.html zagram.org/index.ua.html
zagram.org/style.css zagram.org/glosnikWlaczony.png
zagram.org/glosnikWylaczony.png zagram.org/alert.wav
zagram.org/karuzela.gif zagram.org/ikonki2_off_off.png
zagram.org/ikonki2_off_on.png zagram.org/ikonki2_on_off.png
zagram.org/ikonki2_on_on.png zagram.org/kropkaBlue1.gif
zagram.org/kropkaBlue2.gif zagram.org/kropkaBlue3.gif
zagram.org/kropkaRed1.gif zagram.org/kropkaRed2.gif
zagram.org/kropkaRed3.gif zagram.org/kropkaOst1b.png
zagram.org/kropkaOst2b.png zagram.org/kropkaOst3b.png
zagram.org/obwodka1.png zagram.org/obwodka2.png
zagram.org/obwodka3.png zagram.org/awatar1.png
zagram.org/awatar2.png zagram.org/navtree-line.gif
zagram.org/navtree-elbow.gif zagram.org/navtree-T.gif
zagram.org/navtree-left.gif zagram.org/b19.png zagram.org/w19.png
zagram.org/krzyzyk.png zagram.org/tloCien.png zagram.org/kropki-zasady.html zagram.org/kropki-taktyka.html zagram.org/kropki-info.html zagram.org/kropki-faq.html zagram.org/kropki-warianty.html zagram.org/podstawy.sgf zagram.org/kropki-sitemap.html zagram.org/doc.html zagram.org/kropki-rules.html zagram.org/kropki-tactics.html zagram.org/kropki-info.en.html zagram.org/kropki-faq.en.html zagram.org/kropki-variants.html zagram.org/podstawy-en.sgf zagram.org/kropki-rules.ru.html zagram.org/kropki-tactics.ru.html zagram.org/kropki-info.ru.html zagram.org/kropki-faq.ru.html zagram.org/kropki-variants.ru.html
-
In the file nkropki.js, in the function poczatek(), change lines:
var url = document.location.toString();
if( url.indexOf("/kropki/") > 0 && url.indexOf("zagram.org")==-1 ){
var ind = url.indexOf("/kropki/");
rootUrl = url.substr(0, ind+8);
}else{
rootUrl = 'http://zagram.org/';
}
to
rootUrl = 'http://yourwebpage.org/'; // could be also 'http://yourwebpage.org/kr/' etc.
-
Finally you need to setup your www serwer to proxy some 'files' to
zagram.org. 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 http://zagram.org/a.kropki
ProxyPass /auth.py http://zagram.org/auth.py
ProxyPass /nkropki.py http://zagram.org/nkropki.py
ProxyPass /awatary/ http://zagram.org/awatary/
This is assuming that you have embedded the client in the main
directory; if the client is for example on
'http://yourwebpage.org/kr/', then instead of ' ProxyPass /a.kropki
http://zagram.org/a.kropki'
there should be 'ProxyPass /kr/a.kropki http://zagram.org/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 (trans-html.py dialect.py 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:
- 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.
-
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.
-
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.
-
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.
- New gameType format
General format is:
XXYYrI.(starting position).(who starts).(type).(time method).t0.t1.opt.tourn
where:
- XXYY is the size of the board, e.g. '2020' or '3932'
- r is a char encoding the rules: s = standard, t = territory, n = no territory
- I is an integer with InstantWin, '0' for no InstantWin
- (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
- (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.
- (type) is 'R', 'F', 'A' or 'a', which stands for rated, free, with AI, or analysis, respectively
- (time method) is 'a' for starting and added time after each move and 'n' for no time limits
- t0 and t1 are the starting and added time, when (time method) is 'a', and are empty strings for 'n'
- opt are options, default is empty string, for the description see chapter 'Opt field with rights in gameType string' below.
- 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..' '3932n0.4.a.F.n...ua.tournament X'
- Some last changes
2012-10:
'x' tag (server->client) for finished games now contains also SGF number.
- Team games
- A player 'captainA' leaves a challenge for a team game by sending e.g. 'D1234.0.2525t15..s.22.a.180.15..'.
The server will then broadcast it as 'Da.captainA.2525t15..s.22.a.180.15..' Note the '22' inside the gameType string, which denotes a game with teams of two people.
- Anybody can then send a proposition to become the captain of the other team, by sending 'V1234.0.s.captainA.2525t15..s.22.a.180.15..'
- 'captainA' accepts one of the people willing to play against him, say 'captain B', by sending e.g. 'V1235.0.a.captain B'
- Now the challenge is broadcasted as 'Dr.captainA,-captain B,.2525t15..s.22.a.180.15..' , all propositions sent before to captainA should be deleted automatically by the client. Furthermore, if 'captain B' had an open challenge, it should be deleted too.
- Anybody can now send propositions to 'captainA' or 'captain B' (or both) to become a member of their team. It is sent as 'V1236.0.s.captainB.2525t15..s.22.a.180.15..'
- Captains may accept/reject players in a usual way, by sending e.g. 'V1237.0.r.bad_player' or 'V1237.0.a.nice_player'.
- After accepting some but not all team members, the challenge is broadcasted as 'Dr.captainA,nice_player-captain B,.2525t15..s.22.a.180.15..'
(this means that 1. team is already constituted, and the 2. one not yet). Accepting a member does not delete any sent propositions (neither from the accepted player, not from the others that wanted to join, even if the team is full) -- that way the captain may still change the mind and reject one of the members and accept someone else.
- Once both teams are constituted, the game starts. The challenge is deleted by broadcasting 'Dd.captainA', all propositions sent to this challenge should be (automatically) deleted by the client.
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).
- Deleting chat messages
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).
- Opt field with rights in gameType string
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:
- S,s -- play for B,W
- R,r -- propose a game-result as B,W (in particular, resign)
- A,a -- accept a game-result as B,W
- U,u -- ask for undo (and accept opponent's request for undo)
- T,t -- add time as B,W (time is added to the opponents' timer)
- P,p -- pause as B,W
- e -- instant finish without saving result (for analysis)
- n -- used as the last right to specify the nick (of the person who analyses the game). The nick comes directly afterwards.
Table rights:
- c -- save chat to the sgf file
Planned but not implemented:
- K,k -- can block/unblock spectators (TODO)
- m -- can add marks to the board (TODO)
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.