<q:application id="chess" type="game">

  <!-- Chess: the rules of github.com/Prashanna135/chess (MIT) — legal moves,
       castling, en passant, promotion, check, checkmate and stalemate —
       written in the game language's own statements and expressions over an
       array of 64 squares; the pieces on the screen mirror it. White is
       player 1, black player 2: on one machine both click the same board;
       over the network each machine is one colour, in lockstep. README.md
       maps the original to this file. -->

  <qg:tileset name="board" src="assets/board.png" tile="62" />
  <qg:spritesheet name="pieces" src="assets/pieces.png" tile="60" />
  <qg:multiplayer players="2" delay="2" start="game" />

  <qg:prefab name="wK" tag="piece" sheet="pieces" frame="0" hitbox="60x60" />
  <qg:prefab name="wQ" tag="piece" sheet="pieces" frame="1" hitbox="60x60" />
  <qg:prefab name="wR" tag="piece" sheet="pieces" frame="2" hitbox="60x60" />
  <qg:prefab name="wB" tag="piece" sheet="pieces" frame="3" hitbox="60x60" />
  <qg:prefab name="wN" tag="piece" sheet="pieces" frame="4" hitbox="60x60" />
  <qg:prefab name="wP" tag="piece" sheet="pieces" frame="5" hitbox="60x60" />
  <qg:prefab name="bK" tag="piece" sheet="pieces" frame="6" hitbox="60x60" />
  <qg:prefab name="bQ" tag="piece" sheet="pieces" frame="7" hitbox="60x60" />
  <qg:prefab name="bR" tag="piece" sheet="pieces" frame="8" hitbox="60x60" />
  <qg:prefab name="bB" tag="piece" sheet="pieces" frame="9" hitbox="60x60" />
  <qg:prefab name="bN" tag="piece" sheet="pieces" frame="10" hitbox="60x60" />
  <qg:prefab name="bP" tag="piece" sheet="pieces" frame="11" hitbox="60x60" />
  <!-- What the board shows besides the pieces (assets/board.png): the picked square, a dot on each
       square the picked piece may go to (a ring round a piece it may take), the last move, a king in check. -->
  <qg:prefab name="Marker" tag="marker" sheet="board" frame="2" hitbox="4x4" />
  <qg:prefab name="Dot" tag="dot" sheet="board" frame="3" hitbox="4x4" gd:z_index="1" />
  <qg:prefab name="Ring" tag="dot" sheet="board" frame="4" hitbox="4x4" gd:z_index="1" />
  <qg:prefab name="Last" tag="last" sheet="board" frame="6" hitbox="4x4" />
  <qg:prefab name="Check" tag="check" sheet="board" frame="7" hitbox="4x4" />

  <!-- the game in Portuguese and Spanish (a web page's ?lang=pt, the command line's q-lang, or the system's language) -->
  <qg:language lang="pt" name="Português">
    <qg:phrase text="CHESS" as="XADREZ" />
    <qg:phrase text="Two players, one board" as="Dois jogadores, um tabuleiro" />
    <qg:phrase text="White to move - click a piece, then where it goes" as="Brancas jogam - clique numa peça, depois aonde ela vai" />
    <qg:phrase text="White to move" as="Brancas jogam" />
    <qg:phrase text="Black to move" as="Pretas jogam" />
    <qg:phrase text="White to move - check" as="Brancas jogam - xeque" />
    <qg:phrase text="Black to move - check" as="Pretas jogam - xeque" />
    <qg:phrase text="White to move - that piece cannot move" as="Brancas jogam - essa peça não pode se mover" />
    <qg:phrase text="Black to move - that piece cannot move" as="Pretas jogam - essa peça não pode se mover" />
    <qg:phrase text="White to move - that piece cannot move - check" as="Brancas jogam - essa peça não pode se mover - xeque" />
    <qg:phrase text="Black to move - that piece cannot move - check" as="Pretas jogam - essa peça não pode se mover - xeque" />
    <qg:phrase text="Checkmate - White wins" as="Xeque-mate - as brancas vencem" />
    <qg:phrase text="Checkmate - Black wins" as="Xeque-mate - as pretas vencem" />
    <qg:phrase text="Stalemate" as="Afogamento - empate" />
      <qg:phrase text="OPTIONS" as="OPÇÕES" />
    <qg:phrase text="Full screen" as="Tela cheia" />
    <qg:phrase text="on" as="sim" />
    <qg:phrase text="off" as="não" />
    <qg:phrase text="Back" as="Voltar" />
</qg:language>
  <qg:language lang="es" name="Español">
    <qg:phrase text="CHESS" as="AJEDREZ" />
    <qg:phrase text="Two players, one board" as="Dos jugadores, un tablero" />
    <qg:phrase text="White to move - click a piece, then where it goes" as="Juegan blancas - haz clic en una pieza y luego adónde va" />
    <qg:phrase text="White to move" as="Juegan blancas" />
    <qg:phrase text="Black to move" as="Juegan negras" />
    <qg:phrase text="White to move - check" as="Juegan blancas - jaque" />
    <qg:phrase text="Black to move - check" as="Juegan negras - jaque" />
    <qg:phrase text="White to move - that piece cannot move" as="Juegan blancas - esa pieza no puede moverse" />
    <qg:phrase text="Black to move - that piece cannot move" as="Juegan negras - esa pieza no puede moverse" />
    <qg:phrase text="White to move - that piece cannot move - check" as="Juegan blancas - esa pieza no puede moverse - jaque" />
    <qg:phrase text="Black to move - that piece cannot move - check" as="Juegan negras - esa pieza no puede moverse - jaque" />
    <qg:phrase text="Checkmate - White wins" as="Jaque mate - ganan las blancas" />
    <qg:phrase text="Checkmate - Black wins" as="Jaque mate - ganan las negras" />
    <qg:phrase text="Stalemate" as="Rey ahogado - tablas" />
      <qg:phrase text="OPTIONS" as="OPCIONES" />
    <qg:phrase text="Full screen" as="Pantalla completa" />
    <qg:phrase text="on" as="sí" />
    <qg:phrase text="off" as="no" />
    <qg:phrase text="Back" as="Volver" />
</qg:language>

  <!-- The title: both colours on one board, or white and black on two machines. -->
  <qg:scene name="title" width="496" height="540" background="#2a2520">
    <qg:hud position="top-center" size="40"><qg:text value="{'CHESS'}" /></qg:hud>
    <qg:lobby local="game" local-label="Two players, one board" size="18" options="options" />
  </qg:scene>

  <qg:scene name="game" width="496" height="540" background="#2a2520">
    <!-- row 0 is the eighth rank (black's home), row 7 the first; a square is board[row * 8 + col] -->
    <q:set name="board" type="array" value="{['bR','bN','bB','bQ','bK','bB','bN','bR', 'bP','bP','bP','bP','bP','bP','bP','bP', '','','','','','','','', '','','','','','','','', '','','','','','','','', '','','','','','','','', 'wP','wP','wP','wP','wP','wP','wP','wP', 'wR','wN','wB','wQ','wK','wB','wN','wR']}" />
    <q:set name="turn" value="w" />
    <q:set name="sel_r" value="-1" type="number" />
    <q:set name="sel_c" value="-1" type="number" />
    <q:set name="legal" type="array" value="{[]}" />
    <q:set name="ep_col" value="-1" type="number" />
    <q:set name="moved" type="array" value="{[]}" />
    <q:set name="status" value="White to move - click a piece, then where it goes" />
    <q:set name="finished" value="false" type="boolean" />

    <qg:tilemap tileset="board">
1,2,1,2,1,2,1,2
2,1,2,1,2,1,2,1
1,2,1,2,1,2,1,2
2,1,2,1,2,1,2,1
1,2,1,2,1,2,1,2
2,1,2,1,2,1,2,1
1,2,1,2,1,2,1,2
2,1,2,1,2,1,2,1
    </qg:tilemap>
    <!-- the pointer: the mouse, or the arrows (Enter picks and puts); drawn as a frame round its square -->
    <qg:cursor player="1" grid="62" sheet="board" frame="5" />
    <qg:cursor player="2" grid="62" />
    <!-- the marks, kept off the board until they mean something; under the pieces -->
    <qg:instance prefab="Last" name="last_from" x="-100" y="-100" />
    <qg:instance prefab="Last" name="last_to" x="-100" y="-100" />
    <qg:instance prefab="Check" name="check_mark" x="-100" y="-100" />
    <qg:instance prefab="Marker" name="mark" x="-100" y="-100" />

    <qg:instance prefab="bR" x="31" y="31" /><qg:instance prefab="bN" x="93" y="31" /><qg:instance prefab="bB" x="155" y="31" /><qg:instance prefab="bQ" x="217" y="31" />
    <qg:instance prefab="bK" x="279" y="31" /><qg:instance prefab="bB" x="341" y="31" /><qg:instance prefab="bN" x="403" y="31" /><qg:instance prefab="bR" x="465" y="31" />
    <qg:instance prefab="bP" x="31" y="93" /><qg:instance prefab="bP" x="93" y="93" /><qg:instance prefab="bP" x="155" y="93" /><qg:instance prefab="bP" x="217" y="93" />
    <qg:instance prefab="bP" x="279" y="93" /><qg:instance prefab="bP" x="341" y="93" /><qg:instance prefab="bP" x="403" y="93" /><qg:instance prefab="bP" x="465" y="93" />
    <qg:instance prefab="wP" x="31" y="403" /><qg:instance prefab="wP" x="93" y="403" /><qg:instance prefab="wP" x="155" y="403" /><qg:instance prefab="wP" x="217" y="403" />
    <qg:instance prefab="wP" x="279" y="403" /><qg:instance prefab="wP" x="341" y="403" /><qg:instance prefab="wP" x="403" y="403" /><qg:instance prefab="wP" x="465" y="403" />
    <qg:instance prefab="wR" x="31" y="465" /><qg:instance prefab="wN" x="93" y="465" /><qg:instance prefab="wB" x="155" y="465" /><qg:instance prefab="wQ" x="217" y="465" />
    <qg:instance prefab="wK" x="279" y="465" /><qg:instance prefab="wB" x="341" y="465" /><qg:instance prefab="wN" x="403" y="465" /><qg:instance prefab="wR" x="465" y="465" />

    <qg:hud position="bottom-center" size="14"><qg:text bind="status" /></qg:hud>

    <!-- what is on a square ("x" off the board), whose it is -->
    <q:function name="at" params="r, c">
      <q:if condition="{r &lt; 0 or r &gt; 7 or c &lt; 0 or c &gt; 7}"><q:return value="{'x'}" /></q:if>
      <q:return value="{board[r * 8 + c]}" />
    </q:function>
    <q:function name="own" params="p, color">
      <q:return value="{p != '' and p != 'x' and p[0:1] == color}" />
    </q:function>
    <q:function name="enemy" params="p, color">
      <q:return value="{p != '' and p != 'x' and p[0:1] != color}" />
    </q:function>
    <q:function name="other_color" params="color">
      <q:return value="{'b' if color == 'w' else 'w'}" />
    </q:function>

    <!-- where a piece may go by its own rule (attacks only, for a pawn, when atk) -->
    <q:function name="pseudo" params="r, c, atk">
      <q:set name="result" value="{[]}" />
      <q:set name="p" value="{at(r, c)}" />
      <q:set name="color" value="{p[0:1]}" />
      <q:set name="kind" value="{p[1:2]}" />
      <q:if condition="{kind == 'P'}">
        <q:set name="dir" value="{-1 if color == 'w' else 1}" />
        <q:if condition="{not atk and at(r + dir, c) == ''}">
          <q:set name="result" value="{result + [[r + dir, c]]}" />
          <q:if condition="{(r == 6 and color == 'w' or r == 1 and color == 'b') and at(r + 2 * dir, c) == ''}">
            <q:set name="result" value="{result + [[r + 2 * dir, c]]}" />
          </q:if>
        </q:if>
        <q:loop var="dc" items="{[-1, 1]}">
          <q:if condition="{atk or enemy(at(r + dir, c + dc), color)}">
            <q:if condition="{at(r + dir, c + dc) != 'x'}">
              <q:set name="result" value="{result + [[r + dir, c + dc]]}" />
            </q:if>
          </q:if>
          <q:if condition="{not atk and ep_col == c + dc and r == (3 if color == 'w' else 4)}">
            <q:set name="result" value="{result + [[r + dir, c + dc]]}" />
          </q:if>
        </q:loop>
      </q:if>
      <q:if condition="{kind == 'N' or kind == 'K'}">
        <q:set name="steps" value="{[[1, 2], [2, 1], [2, -1], [1, -2], [-1, -2], [-2, -1], [-2, 1], [-1, 2]] if kind == 'N' else [[1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1]]}" />
        <q:loop var="s" items="{steps}">
          <q:set name="q" value="{at(r + s[0], c + s[1])}" />
          <q:if condition="{q != 'x' and not own(q, color)}">
            <q:set name="result" value="{result + [[r + s[0], c + s[1]]]}" />
          </q:if>
        </q:loop>
      </q:if>
      <q:if condition="{kind == 'R' or kind == 'B' or kind == 'Q'}">
        <q:set name="dirs" value="{[]}" />
        <q:if condition="{kind != 'B'}"><q:set name="dirs" value="{dirs + [[1, 0], [-1, 0], [0, 1], [0, -1]]}" /></q:if>
        <q:if condition="{kind != 'R'}"><q:set name="dirs" value="{dirs + [[1, 1], [1, -1], [-1, 1], [-1, -1]]}" /></q:if>
        <q:loop var="d" items="{dirs}">
          <q:set name="blocked" value="false" />
          <q:loop var="n" from="1" to="7">
            <q:if condition="{not blocked}">
              <q:set name="q" value="{at(r + d[0] * n, c + d[1] * n)}" />
              <q:if condition="{q == 'x' or own(q, color)}">
                <q:set name="blocked" value="true" />
              <q:else>
                <q:set name="result" value="{result + [[r + d[0] * n, c + d[1] * n]]}" />
                <q:if condition="{q != ''}"><q:set name="blocked" value="true" /></q:if>
              </q:else>
              </q:if>
            </q:if>
          </q:loop>
        </q:loop>
      </q:if>
      <q:return value="{result}" />
    </q:function>

    <q:function name="attacked" params="r, c, by">
      <q:loop var="i" from="0" to="63">
        <q:if condition="{own(board[i], by)}">
          <q:if condition="{[r, c] in pseudo(i // 8, i % 8, true)}"><q:return value="{true}" /></q:if>
        </q:if>
      </q:loop>
      <q:return value="{false}" />
    </q:function>
    <q:function name="in_check" params="color">
      <q:loop var="i" from="0" to="63">
        <q:if condition="{board[i] == color + 'K'}">
          <q:return value="{attacked(i // 8, i % 8, other_color(color))}" />
        </q:if>
      </q:loop>
      <q:return value="{false}" />
    </q:function>

    <!-- the board after a move: the rook of a castling, the pawn of an en passant, a promotion -->
    <q:function name="apply" params="r1, c1, r2, c2">
      <q:set name="p" value="{board[r1 * 8 + c1]}" />
      <q:if condition="{p[1:2] == 'P' and c1 != c2 and board[r2 * 8 + c2] == ''}">
        <q:set name="board" index="{r1 * 8 + c2}" value="" />
      </q:if>
      <q:if condition="{p[1:2] == 'K' and c2 - c1 == 2}">
        <q:set name="board" index="{r1 * 8 + 5}" value="{board[r1 * 8 + 7]}" />
        <q:set name="board" index="{r1 * 8 + 7}" value="" />
      </q:if>
      <q:if condition="{p[1:2] == 'K' and c1 - c2 == 2}">
        <q:set name="board" index="{r1 * 8 + 3}" value="{board[r1 * 8]}" />
        <q:set name="board" index="{r1 * 8}" value="" />
      </q:if>
      <q:set name="board" index="{r1 * 8 + c1}" value="" />
      <q:set name="board" index="{r2 * 8 + c2}" value="{p[0:1] + 'Q' if p[1:2] == 'P' and (r2 == 0 or r2 == 7) else p}" />
    </q:function>

    <!-- the moves that leave the king safe, castling included -->
    <q:function name="legal_moves" params="r, c">
      <q:set name="p" value="{at(r, c)}" />
      <q:set name="color" value="{p[0:1]}" />
      <q:set name="candidates" value="{pseudo(r, c, false)}" />
      <q:if condition="{p[1:2] == 'K' and not (color + 'K') in moved and not in_check(color)}">
        <q:if condition="{not (color + 'Rh') in moved and at(r, 5) == '' and at(r, 6) == '' and at(r, 7) == color + 'R' and not attacked(r, 5, other_color(color)) and not attacked(r, 6, other_color(color))}">
          <q:set name="candidates" value="{candidates + [[r, 6]]}" />
        </q:if>
        <q:if condition="{not (color + 'Ra') in moved and at(r, 1) == '' and at(r, 2) == '' and at(r, 3) == '' and at(r, 0) == color + 'R' and not attacked(r, 3, other_color(color)) and not attacked(r, 2, other_color(color))}">
          <q:set name="candidates" value="{candidates + [[r, 2]]}" />
        </q:if>
      </q:if>
      <q:set name="result" value="{[]}" />
      <q:loop var="m" items="{candidates}">
        <q:set name="saved" value="{board[:]}" />
        <q:call function="apply" args="r, c, m[0], m[1]" />
        <q:set name="ok" value="{not in_check(color)}" />
        <q:set name="board" value="{saved}" />
        <q:if condition="{ok}"><q:set name="result" value="{result + [m]}" /></q:if>
      </q:loop>
      <q:return value="{result}" />
    </q:function>
    <q:function name="any_legal" params="color">
      <q:loop var="i" from="0" to="63">
        <q:if condition="{own(board[i], color)}">
          <q:if condition="{len(legal_moves(i // 8, i % 8)) &gt; 0}"><q:return value="{true}" /></q:if>
        </q:if>
      </q:loop>
      <q:return value="{false}" />
    </q:function>

    <q:function name="clear_mark">
      <qg:put target="mark" x="-100" y="-100" />
      <q:loop var="m" items="{legal}">
        <q:set name="d" value="{thing_at('dot', m[1] * 62 + 31, m[0] * 62 + 31)}" />
        <q:if condition="{d != null}"><qg:destroy target="d" /></q:if>
      </q:loop>
      <q:set name="sel_r" value="-1" />
      <q:set name="sel_c" value="-1" />
      <q:set name="legal" value="{[]}" />
    </q:function>

    <!-- the red glow under the king of the side to move, when it is in check -->
    <q:function name="show_check">
      <qg:put target="check_mark" x="-100" y="-100" />
      <q:if condition="{in_check(turn)}">
        <q:loop var="i" from="0" to="63">
          <q:if condition="{board[i] == turn + 'K'}">
            <qg:put target="check_mark" x="{(i % 8) * 62 + 31}" y="{(i // 8) * 62 + 31}" />
          </q:if>
        </q:loop>
      </q:if>
    </q:function>

    <!-- a click: pick up one of your pieces, or put the picked one on a legal square. On one machine
         the same pointer plays both colours; over the network each machine plays its own. -->
    <qg:on-select>
      <q:if condition="{not finished and (net_status() != 'playing' or cursor.player == 1 and turn == 'w' or cursor.player == 2 and turn == 'b')}">
        <q:set name="r" value="{cursor.row}" />
        <q:set name="c" value="{cursor.col}" />
        <q:set name="act" value="{'move' if sel_r &gt;= 0 and [r, c] in legal else ('pick' if own(at(r, c), turn) else 'clear')}" />
        <q:if condition="{act == 'move'}">
          <q:set name="mover" value="{thing_at('piece', sel_c * 62 + 31, sel_r * 62 + 31)}" />
          <q:set name="p" value="{board[sel_r * 8 + sel_c]}" />
          <!-- what the move takes: the piece on the square, or the pawn passed en passant -->
          <q:set name="taken" value="{thing_at('piece', c * 62 + 31, r * 62 + 31)}" />
          <q:if condition="{taken == null and p[1:2] == 'P' and c != sel_c}">
            <q:set name="taken" value="{thing_at('piece', c * 62 + 31, sel_r * 62 + 31)}" />
          </q:if>
          <q:if condition="{taken != null}"><qg:destroy target="taken" /></q:if>
          <q:if condition="{p[1:2] == 'K' and c - sel_c == 2}">
            <q:set name="taken" value="{thing_at('piece', 7 * 62 + 31, r * 62 + 31)}" />
            <qg:put target="taken" x="{5 * 62 + 31}" y="{r * 62 + 31}" />
          </q:if>
          <q:if condition="{p[1:2] == 'K' and sel_c - c == 2}">
            <q:set name="taken" value="{thing_at('piece', 31, r * 62 + 31)}" />
            <qg:put target="taken" x="{3 * 62 + 31}" y="{r * 62 + 31}" />
          </q:if>
          <qg:put target="mover" x="{c * 62 + 31}" y="{r * 62 + 31}" />
          <q:if condition="{p[1:2] == 'P' and (r == 0 or r == 7)}">
            <q:if condition="{turn == 'w'}"><qg:swap target="mover" prefab="wQ" /><q:else><qg:swap target="mover" prefab="bQ" /></q:else></q:if>
          </q:if>
          <q:call function="apply" args="sel_r, sel_c, r, c" />
          <!-- the rights and the en passant square after the move -->
          <q:if condition="{p[1:2] == 'K'}"><q:set name="moved" value="{moved + [turn + 'K']}" /></q:if>
          <q:if condition="{p[1:2] == 'R' and sel_c == 0}"><q:set name="moved" value="{moved + [turn + 'Ra']}" /></q:if>
          <q:if condition="{p[1:2] == 'R' and sel_c == 7}"><q:set name="moved" value="{moved + [turn + 'Rh']}" /></q:if>
          <q:set name="ep_col" value="{c if p[1:2] == 'P' and abs(r - sel_r) == 2 else -1}" />
          <qg:put target="last_from" x="{sel_c * 62 + 31}" y="{sel_r * 62 + 31}" />
          <qg:put target="last_to" x="{c * 62 + 31}" y="{r * 62 + 31}" />
          <q:set name="turn" value="{other_color(turn)}" />
          <q:call function="clear_mark" />
          <q:call function="show_check" />
          <q:set name="status" value="{('White' if turn == 'w' else 'Black') + ' to move'}" />
          <q:if condition="{not any_legal(turn)}">
            <q:set name="finished" value="true" />
            <q:set name="status" value="{('Checkmate - ' + ('Black' if turn == 'w' else 'White') + ' wins') if in_check(turn) else 'Stalemate'}" />
          <q:elseif condition="{in_check(turn)}">
            <q:set name="status" value="{status + ' - check'}" />
          </q:elseif>
          </q:if>
        </q:if>
        <q:if condition="{act == 'pick'}">
          <q:call function="clear_mark" />
          <q:set name="sel_r" value="{r}" />
          <q:set name="sel_c" value="{c}" />
          <q:set name="legal" value="{legal_moves(r, c)}" />
          <qg:put target="mark" x="{cursor.x}" y="{cursor.y}" />
          <q:loop var="m" items="{legal}">
            <q:if condition="{at(m[0], m[1]) == ''}">
              <qg:spawn prefab="Dot" x="{m[1] * 62 + 31}" y="{m[0] * 62 + 31}" />
            <q:else>
              <qg:spawn prefab="Ring" x="{m[1] * 62 + 31}" y="{m[0] * 62 + 31}" />
            </q:else>
            </q:if>
          </q:loop>
          <q:set name="status" value="{('White' if turn == 'w' else 'Black') + (' to move' if len(legal) &gt; 0 else ' to move - that piece cannot move')}" />
          <q:if condition="{len(legal) &gt; 0 and in_check(turn)}"><q:set name="status" value="{status + ' - check'}" /></q:if>
        </q:if>
        <q:if condition="{act == 'clear'}">
          <q:call function="clear_mark" />
        </q:if>
      </q:if>
    </qg:on-select>
  </qg:scene>

  <!-- ===== Options: how loud, the full screen, the keys; kept between runs ===== -->

  <qg:scene name="options" width="496" height="540" background="#2a2520">
    <qg:hud position="top-center" size="36"><qg:text value="{tr('OPTIONS')}" /></qg:hud>
    <qg:menu position="center" size="18">
      <qg:button label="{tr('Full screen') + ': ' + (tr('on') if fullscreen() else tr('off'))}"><qg:fullscreen /></qg:button>
      <qg:button label="Back"><qg:goto-scene name="title" /></qg:button>
    </qg:menu>
  </qg:scene>

</q:application>
