프로모션 규칙: void 행마(소용돌이) 클릭 시 퀸으로 프로모션, take 행마(X자) 클릭 시 비숍으로 프로모션, jump 행마(화살표) 클릭 시 나이트로 프로모션, block 행마(정사각형) 클릭 시 룩으로 프로모션

Chessembly 설명

Chessembly는 변형 체스 기물의 행마법을 표현하기 위한 표기법입니다. 실제 게임 실행을 목적으로 제작되었고, 실용성을 지향합니다.

오른쪽 입력칸에 입력한 규칙대로 얼굴모양 기물이 움직입니다. 직접 행마법을 디자인하고 바로 성능을 실험해보세요.

[기본 문법]

동작을 종류별로 분류해서 세미콜론으로 나누어 적습니다. 한 동작은 여러 식으로 구성됩니다. 식은 행마를 나타내거나, 조건식, 제어식, 상태식으로 보드의 상황을 고려해서 움직임을 계산할 수도 있습니다.

식은 true 혹은 false값을 가집니다. 식의 값에 따라서 식 실행의 흐름이 달라집니다. 식이 false값을 가진다면, 다음 식이 논리식이 아닌 경우, 해당 동작은 종료됩니다.

여러 식을 중괄호로 감쌀 수 있습니다. 중괄호 블록 안에서 false를 만나 동작이 종료된다면, 전체 동작이 종료되는 대신 중괄호 안의 동작들만 종료되고 중괄호 밖으로 나가게 됩니다. 기준 위치는 중괄호 이전의 위치로 돌아갑니다. (Tempest-Rook 예시 참조)

행마식과 peek식은 기준 위치를 이동시킵니다. 첫 번째 식에서 기준 위치는 기물의 위치입니다.

piece(test) transition(<기물 모양 이름>) move(0, 1); 을 입력하고 기물을 1칸 전진시켜 기물의 모양을 바꿀 수 있습니다.

기물 모양 목록

[행마식]

[행마법 총정리]

take-move(dx, dy) : take-move 행마법을 기준 위치로부터 좌우로 dx, 상하로 dy 떨어진 곳에 배치합니다. 아군 기물에 막히거나 벽에 막힌다면 false값을 가집니다.

move(dx, dy) : move 행마법을 설치합니다. 기물에 막힌다면 false가 됩니다.

catch(dx, dy) : catch 행마법을 설치합니다. 아군 기물에 막힌다면 false가 됩니다.

take(dx, dy) : take 행마법을 설치합니다. 아군 기물에 막힌다면 false가 됩니다.

[조건식]

peek(dx, dy) : 기준으로부처 dx, dy 움직인 위치에 기물이 없으면 true의 값을 가집니다. 장기의 말처럼 막히는 나이트를 만들 수 있습니다. 값이 true라면 기준 위치를 변경합니다.

observe(dx, dy) : peek와 동일하지만 기준 위치를 움직이지 않습니다.

bound(dx, dy) : 기준으로부터 dx, dy 움직인 위치가 체스판을 벗어난다면 true의 값을 가집니다.

edge(dx, dy) : 기준으로부터 dx, dy 움직인 위치가 체스판의 변을 벗어난다면 true의 값을 가집니다.

corner(dx, dy) : 기준으로부터 dx, dy 움직인 위치가 체스판의 모서리를 벗어난다면 true의 값을 가집니다.

edge-(top/bottom/left/right)(dx, dy) : 기준으로부터 dx, dy 움직인 위치가 체스판의 어느 변을 벗어났는지에 따라 true/false 값을 가집니다.

corner-(top/bottom)-(left/right)(dx, dy) : 기준으로부터 dx, dy 움직인 위치가 체스판의 어느 모서리를 벗어났는지에 따라 true/false 값을 가집니다.

check : 아군 킹이 체크가 되었을 때에만 true의 값을 가집니다.

danger(dx, dy) : dx, dy 이동한 칸으로 움직였을 때 다음 턴에 적에게 되잡힐 수 있다면 true의 값을 가집니다.

piece-on(piece, dx, dy) : dx, dy 이동한 칸에 piece 종류(rook, king 등)의 기물이 있으면 true의 값을 가집니다. 얼굴 모양 기물의 piece 이름은 test입니다.

enemy(dx, dy) : dx, dy 이동한 칸에 적 기물이 있으면 true의 값을 가집니다.

friendly(dx, dy) : dx, dy 이동한 칸에 아군 기물이 있으면 true의 값을 가집니다.

[상태식]

piece(piece) : 기물의 종류가 piece와 같으면 true의 값을 가집니다. 이것을 이용해서 비숍, 룩, 퀸, 나이트의 행마법을 하나의 Chessembly로 엮어낼 수 있습니다.

set-state(key, n) : 해당 식 이후에 설치된 행마법을 클릭하면 key로 지정된 값을 정수 n으로 바꿉니다. set-state를 단독으로 쓴 식 이후에 설치된 행마법은 값을 바꾸지 않습니다.

(예시) set-state(mode, 1) take-move(0, 1) set-state take-move(0, 1) : 1칸 전진 시에만 mode값을 1로 갱신, 2칸 전진 시 mode값을 0으로 갱신

if-state(key, n) : key로 지정된 값이 정수 n과 같을 때 true의 값을 가집니다. 이전에 지정된 값이 없었다면 기본값은 0입니다.

transition(piece) : 해당 식 이후에 설치된 행마법을 클릭하면 piece로 지정된 기물로 바뀝니다.

[제어식]

repeat(n) : 식을 앞으로 n개 되돌아가서 다시 실행합니다. 직전 식의 값이 false라면 실행되지 않고 동작이 종료됩니다.

do ... while : 직전 식의 값이 true라면 대응하는 do로 이동합니다.

label(n) : 점프할 레이블을 표시합니다. n에는 레이블을 구분하는 고유한 정수 id를 사용합니다.

jmp(n) : 직전 식의 값이 true라면 n값이 일치하는 레이블로 이동하고 해당 레이블부터의 식을 실행합니다. 항상 true의 값을 가집니다.

jne(n) : 직전 식의 값이 false라면 n값이 일치하는 레이블로 이동하고 해당 레이블부터의 식을 실행합니다. 항상 true의 값을 가집니다.

not : 직전 식의 값을 반전한 값을 가집니다.


다양한 예시를 작성하였습니다. 복사해서 사용해보며 직접 기물을 창작해보세요.

예시 - 알필

take-move(2, 2);
take-move(2, -2);
take-move(-2, 2);
take-move(-2, -2);

예시 - 비숍

take-move(1, 1) repeat(1);
take-move(1, -1) repeat(1);
take-move(-1, 1) repeat(1);
take-move(-1, -1) repeat(1);

예시 - 룩

take-move(1, 0) repeat(1);
take-move(-1, 0) repeat(1);
take-move(0, 1) repeat(1);
take-move(0, -1) repeat(1);

예시 - Wasp

take-move(0, 1) repeat(1);
move(1, -1) repeat(1);
move(-1, -1) repeat(1);

예시 - Bouncing-Bishop

do take-move(1, 1) while peek(0, 0) edge-right(1, 1) jne(0) take-move(-1, 1) repeat(1) label(0) edge-top(1, 1) jne(1) take-move(1, -1) repeat(1) label(1);
do take-move(-1, 1) while peek(0, 0) edge-left(-1, 1) jne(0) take-move(1, 1) repeat(1) label(0) edge-top(-1, 1) jne(1) take-move(-1, -1) repeat(1) label(1);
do take-move(1, -1) while peek(0, 0) edge-right(1, -1) jne(0) take-move(-1, -1) repeat(1) label(0) edge-bottom(1, -1) jne(1) take-move(1, 1) repeat(1) label(1);
do take-move(-1, -1) while peek(0, 0) edge-left(-1, -1) jne(0) take-move(1, -1) repeat(1) label(0) edge-bottom(-1, -1) jne(1) take-move(-1, 1) repeat(1) label(1);

예시 - Tempest-Rook

take-move(1, 1) { take-move(1, 0) repeat(1) } { take-move(0, 1) repeat(1) };
take-move(-1, 1) { take-move(-1, 0) repeat(1) } { take-move(0, 1) repeat(1) };
take-move(1, -1) { take-move(1, 0) repeat(1) } { take-move(0, -1) repeat(1) };
take-move(-1, -1) { take-move(-1, 0) repeat(1) } { take-move(0, -1) repeat(1) };

예시 - Windmill (State 이용)

if-state(mode, 0) set-state(mode, 1)
    { take-move(1, 1) repeat(1) }
    { take-move(1, -1) repeat(1) }
    { take-move(-1, 1) repeat(1) }
    { take-move(-1, -1) repeat(1) };

if-state(mode, 1) set-state(mode, 0)
    { take-move(1, 0) repeat(1) }
    { take-move(-1, 0) repeat(1) }
    { take-move(0, 1) repeat(1) }
    { take-move(0, -1) repeat(1) };

예시 - Windmill (Transition + Piece 이용)

piece(test) transition(windmill-bishop) move(0, 1); # test piece를 앞으로 1칸 움직여 windmill로 변신;
            
piece(windmill-bishop) transition(windmill-rook)
    { take-move(1, 1) repeat(1) }
    { take-move(-1, 1) repeat(1) }
    { take-move(1, -1) repeat(1) }
    { take-move(-1, -1) repeat(1) };

piece(windmill-rook) transition(windmill-bishop)
    { take-move(1, 0) repeat(1) }
    { take-move(0, 1) repeat(1) }
    { take-move(-1, 0) repeat(1) }
    { take-move(0, -1) repeat(1) };