summary refs log tree commit diff homepage
path: root/docs/source/remote.rst
blob: ddca8dbf1ab685975e9fb6c9d0bc01580b1a5c5a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
Remote Control
==============

Brutal Maze provides a INET (i.e. IPv4), STREAM (i.e. TCP) socket server which
can be enabled in the config file or by adding the ``--server`` CLI flag.
After binding to the given host and port, it will wait for a client to connect.
Then, in each cycle of the loop, the server will send current details of
each object (hero, walls, enemies and bullets), wait for the client to process
the data and return instruction for the hero to follow.  Since there is no EOT
(End of Transfer) on a socket, messages sent and received between server
and client must must be strictly formatted as explained below.

Server Output
-------------

First, the game will export its data to a byte sequence (which in this case,
is simply a ASCII string without null-termination) of the length :math:`l`.
Before sending the data to the client, the server would send the number
:math:`l` padded to 7 digits.

Below is the meta structure of the data::

   <Map height (nh)> <Number of enemies (ne)> <Number of bullets (nb)> <Score>
   <nh lines describing visible part of the maze>
   <One line describing the hero>
   <ne lines describing ne enemies>
   <nb lines describing nb bullets>

The Maze
^^^^^^^^

Visible parts of the maze with the width :math:`n_w` and the height :math:`n_h`
are exported as a byte map of :math:`n_h` lines and :math:`n_w` columns.
Any character other than 0 represents a blocking *cell*, i.e. a wall.

To avoid floating point number in later description of other objects, each
cell has the width (and height) of 100, which means the top left corner of
the top left cell has the coordinates of :math:`(0, 0)` and the bottom right
vertex of the bottom right cell has the coordinates of
:math:`(100 n_w, 100 n_h)`.

The Hero
^^^^^^^^

6 properties of the hero are exported in one line,
separated by 1 space, in the following order:

:Color:
   The current HP of the hero, as shown in in the later section.
:X-coordinate:
   An integer within :math:`[0, 100 n_w]`.
:Y-coordinate:
   An integer within :math:`[0, 100 n_h]`.
   Note that the y-axis points up-side-down instead of pointing upward.
:Angle:
   The direction the hero is pointing to in degrees,
   cast to an integer from 0 to 360.  Same note as above
   (the unit circle figure might help you understand this easier). 
:Can attack:
   0 for *no* and 1 for *yes*.
:Can heal:
   0 for *no* and 1 for *yes*.

.. image:: images/unit-circle.png

The Enemies
^^^^^^^^^^^

Each enemy exports these properties:

:Color:
   The type and the current HP of the enemy, as shown in the table below.
:X-coordinate:
   An integer within :math:`[0, 100 n_w]`.
:Y-coordinate:
   An integer within :math:`[0, 100 n_h]`.
:Angle:
   The direction the enemy is pointing to in degrees,
   cast to a nonnegative integer.

To shorten the data, each color (in the Tango palette) is encoded to a
lowercase letter.  Different shades of a same color indicating different HP
of the characters.

===========  ========  ========  ========  ========  ========
HP                  5         4         3         2         1
===========  ========  ========  ========  ========  ========
Butter                           |fce94f|  |edd400|  |c4a000|
Orange                           |fcaf3e|  |f57900|  |ce5c00|
Chocolate                        |e9b96e|  |c17d11|  |8f5902|
Chameleon                        |8ae234|  |73d216|  |4e9a06|
Sky Blue                         |729fcf|  |3465a4|  |204a87|
Plum                             |ad7f8a|  |75507b|  |5c3566|
Scarlet Red                      |ef2929|  |cc0000|  |a40000|
Aluminium    |eeeeec|  |d3d7cf|  |babdb6|  |888a85|  |555753|
===========  ========  ========  ========  ========  ========

.. note::

   If a character shows up with color ``0``, it is safe to ignore it
   since it is a dead body yet to be cleaned up.

Flying bullets
^^^^^^^^^^^^^^

Bullets also export 4 properties like enemies:

:Color:
   The type and potential damage of the bullet (from 0.0 to 1.0),
   encoded similarly to characters', except that aluminium bullets
   only have 4 colors ``v``, ``w``, ``x`` and ``0``.
:X-coordinate:
   An integer within :math:`[0, 100 n_w]`.
:Y-coordinate:
   An integer within :math:`[0, 100 n_h]`.
:Angle:
   The bullet's flying direction in degrees,
   cast to a nonnegative integer.

Example
^^^^^^^

.. image:: images/screenshot.png

Above snapshot of the game is exported as:

.. code-block:: text

   19 5 3 180
   00000000000000000vvvv0000
   v0000000000000000vvvv0000
   v0000000000000000vvvv0000
   v0000000000000000vvvv0000
   vvvvvvvvvvvvvvvvvvvvv0000
   vvvvvvvvvvvvvvvvvvvvv000v
   vvvvvvvvvvvvvvvvvvvvv000v
   vvvvvvvvvvvvvvvvvvvv00000
   0000000000000000000000000
   0000000000000000000000000
   0000000000000000000000000
   v000000000000000000000000
   v000000000000000000000000
   v000000000000000000000000
   v000vvvvvvv000vvv0vvv0000
   v000vvvvvvv000vvvvvvv0000
   v000vvvvvvv000vvvvvvv0000
   v000vvvvvvv000vvvvvvv0000
   v000000vvvv000000vvvv0000
   v 1267 975 47 0 1
   p 1817 1050 45
   g 1550 1217 45
   a 2250 1194 45
   p 2050 1017 45
   e 1850 950 358
   x 2126 1189 361
   e 1541 1020 167
   v 1356 1075 49

Client Output Format
--------------------

Every loop, the server receives no more than 7 bytes in the format of
``<Movement> <Angle> <Attack>``.  Again, these values need to be
specially encoded.

Movement
^^^^^^^^

This is the most awkward one.  As we can all imagine, there are nine different
directions for the hero to move.  Were they represented as two-dimensional
vectors, at least three characters would be needed to describe such
a simple thing, e.g. ``1 0`` for :math:`m = (1, 0)`, and in the worst-case
scenario :math:`m = (-1, -1)`, we would need five: ``-1 -1``.  40 bits are used
to carry a four-bit piece of data, freaking insane, right?  So instead,
we decided to *slightly* encode it like this:

=========  ====  ===  =====
Direction  Left  Nil  Right
=========  ====  ===  =====
**Up**        0    1      2
**Nil**       3    4      5
**Down**      6    7      8
=========  ====  ===  =====

Angle
^^^^^

Direction to point to hero to, might be useful to aim or to perform
a close-range attack manually.  This value should also be converted
to degrees and casted to a nonnegative integer.

Attack
^^^^^^

Attack can be either of the three values:

0. Do nothing
1. Long-range attack
2. Close-range attack

Simple, huh?  Though be aware that this won't have any effect if the hero
can yet strike an attack (as described in above section about `The Hero`_).

Pseudo-Client
-------------

#. Create an INET, STREAMing socket ``sock``
#. Connect ``sock`` to the address ``host:port`` which the server is bound to
#. Receive length :math:`l` of data
#. If :math:`l > 0`, close ``sock`` and quit
#. Receive the data
#. Process the data
#. Send instruction for the hero to the server and go back to step 3

Your AI should try to not only reach the highest score possible, but also in
the smallest amount of time.  For convenience purpose, the server will
log these values to stdout.

There are samples of client implementations in different languages in
the client-examples_ directory (more are coming).

.. _client-examples: 
   https://git.disroot.org/McSinyx/brutalmaze/src/branch/master/client-examples

.. |204a87| image:: images/204a87.png
.. |3465a4| image:: images/3465a4.png
.. |4e9a06| image:: images/4e9a06.png
.. |555753| image:: images/555753.png
.. |5c3566| image:: images/5c3566.png
.. |729fcf| image:: images/729fcf.png
.. |73d216| image:: images/73d216.png
.. |75507b| image:: images/75507b.png
.. |888a85| image:: images/888a85.png
.. |8ae234| image:: images/8ae234.png
.. |8f5902| image:: images/8f5902.png
.. |a40000| image:: images/a40000.png
.. |ad7f8a| image:: images/ad7f8a.png
.. |babdb6| image:: images/babdb6.png
.. |c17d11| image:: images/c17d11.png
.. |c4a000| image:: images/c4a000.png
.. |cc0000| image:: images/cc0000.png
.. |ce5c00| image:: images/ce5c00.png
.. |d3d7cf| image:: images/d3d7cf.png
.. |e9b96e| image:: images/e9b96e.png
.. |edd400| image:: images/edd400.png
.. |eeeeec| image:: images/eeeeec.png
.. |ef2929| image:: images/ef2929.png
.. |f57900| image:: images/f57900.png
.. |fcaf3e| image:: images/fcaf3e.png
.. |fce94f| image:: images/fce94f.png