From d14b636ec7aa012d08e56e523e7dd7d77a683cf2 Mon Sep 17 00:00:00 2001 From: JustSock Date: Thu, 28 Oct 2021 22:41:45 +0500 Subject: [PATCH 1/4] =?UTF-8?q?=D0=A3=D1=81=D1=8B=D0=BD=D0=B8=D0=BD=20?= =?UTF-8?q?=D0=90.=D0=92.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 226 +++++++++++++++++++++++++++++++++++++++++++++- src/TaskQueue.js | 55 +++++------ src/index.js | 45 ++++++--- 3 files changed, 283 insertions(+), 43 deletions(-) diff --git a/package-lock.json b/package-lock.json index 62879f0..076e3be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,232 @@ { "name": "west", "version": "0.0.1", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "west", + "version": "0.0.1", + "dependencies": { + "http-server": "^0.12.3" + } + }, + "node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/basic-auth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", + "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/ecstatic": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", + "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", + "deprecated": "This package is unmaintained and deprecated. See the GH Issue 259.", + "dependencies": { + "he": "^1.1.1", + "mime": "^1.6.0", + "minimist": "^1.1.0", + "url-join": "^2.0.5" + }, + "bin": { + "ecstatic": "lib/ecstatic.js" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-server": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz", + "integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==", + "dependencies": { + "basic-auth": "^1.0.3", + "colors": "^1.4.0", + "corser": "^2.0.1", + "ecstatic": "^3.3.2", + "http-proxy": "^1.18.0", + "minimist": "^1.2.5", + "opener": "^1.5.1", + "portfinder": "^1.0.25", + "secure-compare": "3.0.1", + "union": "~0.5.0" + }, + "bin": { + "hs": "bin/http-server", + "http-server": "bin/http-server" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "node_modules/secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=" + }, + "node_modules/union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dependencies": { + "qs": "^6.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=" + } + }, "dependencies": { "async": { "version": "2.6.3", diff --git a/src/TaskQueue.js b/src/TaskQueue.js index f3a9c6a..e79ef4b 100644 --- a/src/TaskQueue.js +++ b/src/TaskQueue.js @@ -1,12 +1,12 @@ -const TaskQueue = function() { - function TaskQueue() { +export default class TaskQueue { + constructor() { this.tasks = []; this.running = false; } - TaskQueue.prototype.push = function(run, dispose, duration) { + push(run, dispose, duration) { if (duration === undefined || duration === null) { - this.tasks.push({runAndContinue: run, dispose}); + this.tasks.push({ runAndContinue: run, dispose }); } else { this.tasks.push({ runAndContinue: (continuation) => { @@ -21,35 +21,30 @@ const TaskQueue = function() { runNextTask(this); }; - TaskQueue.prototype.continueWith = function(action) { + continueWith(action) { this.push(action, null, 0); }; +}; - function runNextTask(taskQueue) { - if (taskQueue.running || taskQueue.tasks.length === 0) { - return; - } - taskQueue.running = true; - const task = taskQueue.tasks.shift(); - - if (task.runAndContinue) { - setTimeout(() => { - task.runAndContinue(() => { - task.dispose && task.dispose(); - taskQueue.running = false; +function runNextTask(taskQueue) { + if (taskQueue.running || taskQueue.tasks.length === 0) { + return; + } + taskQueue.running = true; + const task = taskQueue.tasks.shift(); - setTimeout(() => { - runNextTask(taskQueue); - }); + if (task.runAndContinue) { + setTimeout(() => { + task.runAndContinue(() => { + task.dispose && task.dispose(); + taskQueue.running = false; + setTimeout(() => { + runNextTask(taskQueue); }); - }, 0); - } - else { - runNextTask(taskQueue); - } + }); + }, 0); } - - return TaskQueue; -}(); - -export default TaskQueue; + else { + runNextTask(taskQueue); + } +}; diff --git a/src/index.js b/src/index.js index a01f912..486a003 100644 --- a/src/index.js +++ b/src/index.js @@ -27,30 +27,51 @@ function getCreatureDescription(card) { return 'Существо'; } - - -// Основа для утки. -function Duck() { - this.quacks = function () { console.log('quack') }; - this.swims = function () { console.log('float: both;') }; +class Creature extends Card{ + constructor(name, maxPower){ + super(name, maxPower) + }; + getDescriptions(){ + return [getCreatureDescription(this), ...super.getDescriptions()]; + }; } +class Duck extends Creature{ + constructor(name = 'Мирная утка', maxPower = 2){ + super(name, maxPower) + } + quacks = function () { console.log('quack') }; + swims = function () { console.log('float: both;') }; +} -// Основа для собаки. -function Dog() { +class Dog extends Creature{ + constructor(name = 'Пес-бандит', maxPower = 3){ + super(name, maxPower) + } } +class Trasher extends Dog{ + constructor(name = 'Громила', maxPower=5){ + super(name, maxPower) + }; + modifyTakenDamage(actualValue, fromCard, gameContext, continuation){ + this.view.signalAbility(() => continuation(actualValue-1)); + } + getDescriptions(){ + return ['Получает на один меньше урона', ...super.getDescriptions()]; + }; +} // Колода Шерифа, нижнего игрока. const seriffStartDeck = [ - new Card('Мирный житель', 2), - new Card('Мирный житель', 2), - new Card('Мирный житель', 2), + new Duck(), + new Duck(), + new Duck(), ]; // Колода Бандита, верхнего игрока. const banditStartDeck = [ - new Card('Бандит', 3), + new Trasher(), ]; From 89831f98e54c973506c08b64c3e10904ab429918 Mon Sep 17 00:00:00 2001 From: JustSock Date: Fri, 29 Oct 2021 00:46:01 +0500 Subject: [PATCH 2/4] =?UTF-8?q?=D0=A3=D1=81=D1=8B=D0=BD=D0=B8=D0=BD=20?= =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1-6 --- README.md | 12 ++++++------ src/index.js | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f07ca4a..f6ad4b4 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Chrome уже поддерживает использование модулей Инструктаж окончен. Твоя задача - создавать новые типы карт, наследующиеся от Card. Можешь приступать к решению задачи! -1. «Классы» +✓1. «Классы» Во всем коде типы определены по-старому, через прототипы. Изоляция кода при этом обеспечивает за счет техники IIFE: https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/IIFE @@ -98,7 +98,7 @@ function secret(value) { ``` -2. «Утки против собак» +✓2. «Утки против собак» Создай в `index.js` две новые карты, используй `class` и унаследовав их от `Card`: - `Duck` с именем «Мирная утка» и силой 2 - `Dog` с именем «Пес-бандит» и силой 3 @@ -130,7 +130,7 @@ const banditStartDeck = [ ``` -3. «Утка или собака?» +✓3. «Утка или собака?» Метод `getDescriptions` в `Card` создан для того, чтобы на картах появлялась дополнительная информация. Его функционал хочется расширить. Причем так, чтобы это работало и для уток, и для собак, и для всех остальных существ, которые будут добавляться. @@ -157,7 +157,7 @@ const banditStartDeck = [ а у собак надпись «Собака» над цепочкой наследования. -4. «Громила» +✓4. «Громила» Для уток все становится плохо, когда в рядах бандитов появляется Громила. Добавь карту `Trasher`: @@ -192,7 +192,7 @@ const banditStartDeck = [ ``` -5. «Гатлинг» +✓5. «Гатлинг» Нехорошо нападать на мирных жителей. Это еще может быть опасно, если в сарае припрятан Гатлинг. Добавь карту `Gatling`: @@ -222,7 +222,7 @@ const banditStartDeck = [ ``` -6. «Братки» +✓6. «Братки» Чем их больше, тем они сильнее. Добавь карту `Lad`: diff --git a/src/index.js b/src/index.js index 486a003..1a317cb 100644 --- a/src/index.js +++ b/src/index.js @@ -62,16 +62,67 @@ class Trasher extends Dog{ }; } +class Gatling extends Creature{ + constructor(name = 'Гатлинг', maxPower = 6){ + super(name, maxPower) + } + attack(gameContext, continuation){ + gameContext.oppositePlayer.table.forEach(element => { + this.dealDamageToCreature(2, element, gameContext, continuation) + }); + } + getDescriptions(){ + return ['Наносит 2 урона всем картам противника', ...super.getDescriptions()]; + } +} + +class Lad extends Dog{ + constructor(name='Браток', maxPower=2){ + super(name, maxPower) + } + static getInGameCount() { return this.inGameCount || 0; } + static setInGameCount(value) { this.inGameCount = value; } + + doAfterComingIntoPlay(gameContext, continuation){ + Lad.setInGameCount(Lad.getInGameCount() + 1); + continuation(); + } + doBeforeRemoving(continuation){ + Lad.setInGameCount(Lad.getInGameCount() - 1); + continuation(); + } + + static getBonus(){ + return this.inGameCount*(this.inGameCount+1)/2; + } + + modifyDealedDamageToCreature(value, toCard, gameContext, continuation){ + this.view.signalAbility(()=> + super.modifyTakenDamage(value + Lad.getBonus(), toCard, gameContext, continuation)) + } + modifyTakenDamage(value, fromCard, gameContext, continuation){ + this.view.signalAbility(() => + super.modifyTakenDamage(value - Lad.getBonus(), fromCard, gameContext, continuation)); + } + getDescriptions(){ + if (Lad.prototype.hasOwnProperty('modifyDealedDamageToCreature') + || Lad.prototype.hasOwnProperty('modifyTakenDamage')) + return ['Чем их больше, тем они сильнее', ...super.getDescriptions()]; + return super.getDescriptions(); + } +} // Колода Шерифа, нижнего игрока. const seriffStartDeck = [ new Duck(), new Duck(), new Duck(), + new Gatling(), ]; // Колода Бандита, верхнего игрока. const banditStartDeck = [ - new Trasher(), + new Lad(), + new Lad(), ]; @@ -79,7 +130,7 @@ const banditStartDeck = [ const game = new Game(seriffStartDeck, banditStartDeck); // Глобальный объект, позволяющий управлять скоростью всех анимаций. -SpeedRate.set(1); +SpeedRate.set(5); // Запуск игры. game.play(false, (winner) => { From 9b1fad0705dcf846dace217f35fcc122b0d75826 Mon Sep 17 00:00:00 2001 From: JustSock Date: Thu, 23 Dec 2021 23:24:20 +0500 Subject: [PATCH 3/4] Update index.js --- src/index.js | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/src/index.js b/src/index.js index 1a317cb..68065c7 100644 --- a/src/index.js +++ b/src/index.js @@ -31,6 +31,12 @@ class Creature extends Card{ constructor(name, maxPower){ super(name, maxPower) }; + get currentPower() { + return this._currentPower; + }; + set currentPower(value) { + this._currentPower = Math.min(Math.max(value, 0), this.maxPower); + }; getDescriptions(){ return [getCreatureDescription(this), ...super.getDescriptions()]; }; @@ -111,18 +117,53 @@ class Lad extends Dog{ return super.getDescriptions(); } } + +class Rogue extends Creature{ + constructor(name='Изгой', maxPower=2){ + super(name, maxPower) + } + getDescriptions(){ + return ['Отнимает силы', ...super.getDescriptions()]; + } +} + +class Brewer extends Duck{ + constructor(name='Пивовар', maxPower=2){ + super(name, maxPower) + } + doBeforeAttack(gameContext, continuation){ + const newQueue = new TaskQueue(); + gameContext.currentPlayer.table + .concat(gameContext.oppositePlayer.table) + .filter(card => isDuck(card)) + .forEach(element =>{ + taskQueue.push(whenEnd => { + element.maxPower += 1; + element.currentPower += 2; + element.view.signalHeal(whenEnd); + element.updateView(); + }); + }) + newQueue.continueWith(continuation); + } + + getDescriptions(){ + return ['Востанавливает силу уток!', ...super.getDescriptions()]; + } +} + // Колода Шерифа, нижнего игрока. const seriffStartDeck = [ new Duck(), - new Duck(), - new Duck(), - new Gatling(), + new Brewer(), ]; // Колода Бандита, верхнего игрока. const banditStartDeck = [ - new Lad(), - new Lad(), + new Dog(), + new Dog(), + new Dog(), + new Dog() ]; From 7879df15a90655599a15913bc7a235a9a8085075 Mon Sep 17 00:00:00 2001 From: JustSock Date: Thu, 23 Dec 2021 23:49:09 +0500 Subject: [PATCH 4/4] =?UTF-8?q?=D0=A3=D1=81=D1=8B=D0=BD=D0=B8=D0=BD=20?= =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed Brewer --- src/index.js | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/index.js b/src/index.js index 68065c7..6b41f2d 100644 --- a/src/index.js +++ b/src/index.js @@ -133,17 +133,17 @@ class Brewer extends Duck{ } doBeforeAttack(gameContext, continuation){ const newQueue = new TaskQueue(); - gameContext.currentPlayer.table - .concat(gameContext.oppositePlayer.table) - .filter(card => isDuck(card)) - .forEach(element =>{ - taskQueue.push(whenEnd => { + const { currentPlayer, oppositePlayer, position, updateView } = gameContext; + let elements = currentPlayer.table.concat(oppositePlayer.table).filter(x => isDuck(x)); + + for (let element of elements) { + newQueue.push(whenOver => { element.maxPower += 1; element.currentPower += 2; - element.view.signalHeal(whenEnd); + element.view.signalHeal(whenOver); element.updateView(); }); - }) + } newQueue.continueWith(continuation); } @@ -151,6 +151,19 @@ class Brewer extends Duck{ return ['Востанавливает силу уток!', ...super.getDescriptions()]; } } +class PseudoDuck extends Dog { + constructor(name = 'Уткопёс', maxPower = 3) { + super(name, maxPower); + } + + quacks = function () {}; + swims = function () {}; + + getDescriptions() { + return ['Утка-Собака', + ...super.getDescriptions()] + } +} // Колода Шерифа, нижнего игрока. const seriffStartDeck = [