Рубрики
Без рубрики

Написание шахматных микросервисов с использованием Node.js и Seneca, часть 1

(Это часть 1 серии из трех частей [часть 2, часть 3])) Я начал обернуть голову вокруг микросервисов. До этого времени я считал его как шаблон масштабируемости и упустил из виду функциональные принципы программирования за ним. Правила шахмат могут быть легко разложены в микросервисы. Они

Автор оригинала: Jeff M Lowery.

(Это часть 1 серии из трех частей [ Часть 2 , Часть 3 ])

Я начал обернуть голову вокруг микросервисов. До этого времени я считал его как шаблон масштабируемости и упустил из виду функциональные принципы программирования за ним.

Правила шахмат можно легко разложить в микросервисы. Они не являются ни случайными, ни неоднозначными, которые идеально подходят для написания небольших служб без гражданства, которые занимаются движениями различных произведений.

В этом посте я прогулюсь по нескольким услугам, которые я создал, чтобы определить, что юридические ходы для одиноких кухней на пустой шахматной доске. Мы будем использовать Seneca Framework Инструментарий микровидсов для Node.js, потому что это интуитивно понятное и хорошо документировано.

Настройка Seneca

Сенека это модуль Node.js, который установлен с использованием NPM:

NPM установить Seneca

Кроме того, мы полагаемся на глобально установленные Mocha/Chai Модули для испытаний, которые будут проиллюстрировать функциональность.

Найти все законные шаги

На самом деле не нужно поддерживать представление в памяти шахматной доски, только кусочки и их местоположение на координатной сетке 8×8. Алгебраическое обозначение Обычно используется для описания координат на шахматной доске, где файлы обозначены буквами и рядами по номерам:

Для игрока, который белый, самый правый нижний угол – H1; Для черного это A8. Ладья на B2, переезд на квадратный F2, будет обозначен как RB2-F2.

Сырые движения

Я определяю сырые ходы Как движения кусок сделают, если они не будут безразрешены другими деталями или край доски Отказ Этот последний бит может показаться странным, но он позволяет мне построить маску перемещения 15×15, которая затем усечена, чтобы соответствовать доске 8×8. Парень по имени Прокруст придумал подобную идею лет назад.

Kings, Queens, епископы и ладьи движутся по диагоналам и/или файлам, поэтому я буду использовать одну услугу для движения этих четырех частей. Пешки имеют уникальные характеристики движения, поэтому для них будет использоваться специальная служба. То же самое касается рыцарей, так как они могут прыгать над кусочками и не двигаться по файлам или ряду.

Например, ладья может перемещать 7 квадратов вдоль любого ранга или файла на доске 15×15, в которой крупицентрируется. Подобные правила применяются к епископу и королеве. Король ограничен одним квадратным диапазоном в любом направлении (исключение – это замка, в котором я буду иметь дело с будущим постом).

Я буду использовать Шахмата Класс для хранения информации о типе и местоположении каждой шахматной фигуры. Он не будет играть слишком важную роль на сегодняшний день, но она будет позже, когда я расширяю объем правил, охватываемых услугами.

Первая услуга: ладья, епископ, королева и король движется

В Seneca сервисы вызываются через роль и CMD Отказ роль похож на категорию, а CMD имена конкретный сервис. Как мы увидим позже, услуга может быть дополнительно указана дополнительными параметрами.

Услуги добавляются с использованием SENECA.ADD () и вызывается через Seneca.act () Отказ Давайте посмотрим на сервис, сначала (от Moving.js):

 this.add({
        role: "movement",
        cmd: "rawMoves",
    }, (msg, reply) => {
        var err = null;
        var rawMoves = [];

        var pos = msg.piece.position;

        switch (msg.piece.piece) {
        case 'R':
            rawMoves = rankAndFile(pos);
            break;
        case 'B':
            rawMoves = diagonal(pos);
            break;
        case 'Q':
            rawMoves = rankAndFile(pos)
                .concat(diagonal(pos));
            break;
        case 'K':
            rawMoves = rankAndFile(pos, 1)
                .concat(diagonal(pos, 1))
            break;
        default:
            err = "unhandled " + msg.piece;
            break;
        };

        reply(err, rawMoves);
    });

Теперь давайте посмотрим, как тест призывает услугу (movestest.js):

 var Ba1 = new ChessPiece('Ba1');
        seneca.act({
            role: "movement",
            cmd: "rawMoves",
            piece: Ba1
        }, (err, msg) => {...});

Обратите внимание, что в дополнение к роль и CMD , есть кусок аргумент Это, наряду с роль и CMD , являются свойствами Msg Аргумент, полученный сервисом. Прежде чем вы сможете вызовить услугу, однако, вы должны сообщить Seneca, какие услуги использовать:

var movement = require('../services/Movement')
const seneca = require('seneca')({
        log: 'silent'
    })
   
 .use(movement);

Сырые ходы для епископа на площади A1 находятся в Msg получил назад С службы:

[{File: ‘`’, Rank: ‘0’}, {file: ‘b’, ring: ‘2’}, {file: ‘`’, RING: ‘2’}, {file: ‘b’, Ранг: «0»}, {file: ‘_’, RING: ‘/’}, {file: ‘c’, Rank: ‘3’}, {Файл: ‘_’, RING: ‘3’}, { Файл: ‘C’, RING: ‘/’}, {file: ‘^’, RING: ‘.’ }, {file: ‘d’, ring: ‘4’}, {file: ‘^’, RING: ‘4’}, {Файл: ‘D’, RING: ‘.’. ‘ }, {file: ‘]’ ‘, RING:’ – ‘}, {file:’ E ‘, RING:’ 5 ‘}, {Файл:’] ‘, RING:’ 5 ‘}, {Файл:’ E ‘ , Ранг: ‘-‘}, {file: ‘\\’, RING: ‘,’}, {file: ‘f’, ring: ‘6’}, {file: ‘\\’, RING: ‘6’ }, {file: ‘f’, Rank: ‘,’}, {file: ‘[‘, RING: ‘+’}, {file: ‘g’, RING: ‘7’}, {file: ‘[‘ , Ранг: «7»}, {file: ‘g’, ring: ‘+’}, {file: ‘z’, rank: ‘*’}, {file: ‘h’, Rank: ‘8’}, {file: ‘z’, rank: ‘8’}, {file: ‘h’, Rank: ‘*’}]

Обратите внимание, что в списке странных квадратов есть! Это позиции, которые «падают» доска 8×8 и будут устранены позже другой службой.

Что сейчас произошло?

Сервис был определен с Роль = «Движение» и cmd = "Rawphoves" Отказ Когда Закон () Позже вызывается, параметры запроса ACT сопоставляются с помощью службы, которая обрабатывает эти параметры (это называется сервис Pattern ). Как упоминалось ранее и как будет показано в следующем примере, роль и CMD Не обязательно являются единственными параметрами, которые определяют, что сервис вызывается.

Следующие услуги: пешки и рыцари

Пешки перемещают один квадрат вперед, если они не находятся на их оригинальной площади, в этом случае они могут перемещать один или два квадрата вперед. Есть и другие движения, которую может сделать пешку, когда она не является одиноким предметом на пустой доске, но это для будущего рассмотрения. Пешки всегда начинаются во втором ранже, и никогда не могут двигаться назад.

Рыцари движутся в образце L-формы. В нашем воображаемом доске 15×15 с центром рыцаря всегда будет восемь возможных ходов.

Я напишу две услуги (один для пешек, другой для рыцарей) и поместите как в одном модуле (специальные комвидеции.js):

module.exports = function specialMovement(options) {
  //...
      this.add({
        role: "movement",
        cmd: "rawMoves",
        isPawn: true
    }, (msg, reply) => {
        if (msg.piece.piece !== 'P') {
            return ("piece was not a pawn")
        }
        
        var pos = msg.piece.position;

        const rawMoves = pawnMoves(pos);
        reply(null, rawMoves);
    });

    this.add({
        role: "movement",
        cmd: "rawMoves",
        isKnight: true
    }, (msg, reply) => {
        if (msg.piece.piece !== 'N') {
            return ("piece was not a knight")
        }

        var rawMoves = [];
        var pos = msg.piece.position;

        rawMoves = knightMoves(pos);
        reply(null, rawMoves);
    });
}

Увидеть Испан и Isdnight Параметры в услугах? Первый объект передан в Сенеку Добавить () называется Услуги обслуживания Отказ Что произойдет, это то, что Seneca вызовет сервис с самый конкретный шаблон матча. Для того, чтобы вызвать правильный сервис, мне нужно добавить Ispawn: правда или Isnight: правда к запросу ACT:

var movement = require('../services/Movement')
var specialMovement = require('../services/SpecialMovement')

const seneca = require('seneca')({
        log: 'silent'
    })
    .use(specialMovement)

...

var p = new ChessPiece('Pe2');
        seneca.act({
            role: "movement",
            cmd: "rawMoves",
            piece: p,
...
            
isPawn: true
        }, (err, msg) => {...}
        
...
 var p = new ChessPiece('Nd4');
        seneca.act({
            role: "movement",
            cmd: "rawMoves",
            piece: p,
            
isKnight: true
        }, (err, msg) => {

Юридические движения

Наш рудиментарный юридический ход Service будет просто отфильтровать все квадратные позиции, которые не являются на файлах A-H или Roads 1-8. Служба юридического движения будет называться напрямую с Шахмата экземпляр как часть полезной нагрузки службы. Служба юридического движения затем включает в себя сервис Raw Move, чтобы получить маску перемещения. Маска будет усечена по краям доски, и результат станет квадратными позициями, которые могут быть на законных основаниях.

    this.add({
        role: "movement",
        cmd: "legalSquares",
    }, (msg, reply) => {
        const isPawn = msg.piece.piece === 'P';
        const isKnight = msg.piece.piece === 'N';

        this.act({
            role: "movement",
            cmd: "rawMoves",
            piece: msg.piece,
            isPawn: isPawn,
            isKnight: isKnight
        }, (err, msg) => {
            const squared = [];

            msg.forEach((move) => {
                if (move.file >= 'a' && move.file <= 'h') {
                    if (move.rank >= 1 && move.rank <= 8) {
                        squared.push(move)
                    }
                }
            })

            reply(null, squared);
        });
    })

LegalSquares Сервис сначала призывает Rawphoves услуга. Это получает нам маску перемещения 15×15 для любой части Piece Via Msg параметр. Это важно, хотя правильное обслуживание вызывает, установив Isdnight или ispawn. Поле узора к true для любого из этих двух штук … если оба ложные, то “регулярное” Rawphoves Сервис для K, Q, B, R будет вызван.

Как только сырые ходы извлекаются, то LegalSquares Сервис удаляет недопустимые позиции и возвращает то, что осталось. Так что, если я вызову сервис с куском на Na1, я получаю:

[ { file: 'c', rank: '2' }, { file: 'b', rank: '3' } ]

Если вместо этого я прохожу в RD4, regalsquares возвращается: [{file: ‘c’, Rank: ‘4’}, {Файл: ‘D’, RING: ‘5’}, {Файл: ‘E’, RING: ‘4 ‘}, {file:’ d ‘, ring:’ 3 ‘}, {file:’ b ‘, rank:’ 4 ‘}, {file:’ d ‘, ring:’ 6 ‘}, {file:’ f «Ранг: ‘4’}, {file: ‘D’, RING: ‘2’}, {file: ‘A’, RING: ‘4’}, {Файл: ‘D’, RING: ‘7’} , {file: ‘g’, rank: ‘4’}, {file: ‘d’, ring: ‘1’}, {file: ‘d’, ring: ‘8’}, {file: ‘h’, Ранг: «4»}]

Что немного сложнее расшифровать, но содержит все файлы вдоль 4-го ранга и все ранги по D-файлу (доверяйте мне!).

Вот и все сейчас! В будущем посту я отправлюсь в службу, которые занимаются дружелюбными частями, препятствующими движением, а затем иметь дело с потенциальным захватом враждебных произведений. Дальнейшие услуги будут обращаться с правилами для замки, RU Passant, Проверьте, CheckMate и Stalemate.

Все исходный код можно найти здесь Отказ

Продолжать до Часть 2 этой серии Отказ

Оригинал: “https://www.freecodecamp.org/news/follow-the-rules-with-seneca-b3cf3d08fe5d/”