-
Notifications
You must be signed in to change notification settings - Fork 159
/
old-good-west.txt
365 lines (295 loc) · 20.3 KB
/
old-good-west.txt
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
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
Задача добавить новые интересные карты в карточную игру.
0. «Осмотр реквизита»
Для начала осмотрись:
- Запусти index.html и понаблюдай как игра играет сама в себя.
- Посмотри index.js. В этом файле создаются колоды карты и запускается игра.
В заданиях ты будешь править только этот файл.
- Загляни в Game.js, обрати внимания на стадии хода.
- Изучи Card.js, чтобы разобраться какие действия происходят с картой, какие возможности по расширению заложены.
Твоя задача - создавать новые типы карт, наследующиеся от Card.
В этой задаче можно использовать только прототипное наследование.
Никакого синтаксического сахара в виде классов!
1. «Утки против собак»
Добавь антуража в игру! Создай в index.js две новые карты, унаследовав их от Card:
- Duck с именем «Мирная утка» и силой 2
- Dog с именем «Пес-бандит» и силой 3
Посмотреть, как унаследовать один тип от другого с помощью прототипов можно тут:
https://learn.javascript.ru/class-inheritance#%D0%BF%D0%BE%D0%BB%D0%BD%D1%8B%D0%B9-%D0%BA%D0%BE%D0%B4-%D0%BD%D0%B0%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F
Не забудь вызвать базовый конструктор Card!
- Новые карты должны создаваться, даже если им не передать параметров: new Duck() и new Dog().
- Методы quacks и swims утки должны переехать в прототип.
- После добавления новых типов замени карты в колоде шерифа на уток, а в колоде бандита - на собак.
- Функция isDuck должна возвращать true для утки, а функция isDog — для собаки.
- Если все сделано правильно, то внизу карты утки должен быть текст Duck➔ Card, а у собаки Dog➔ Card.
2. «Утка или собака?»
Метод getDescriptions в Card создан для того, чтобы на картах появлялась дополнительная информация.
Его функционал хочется расширить. Причем так, чтобы это работало и для уток, и для собак,
и для всех остальных существ, которые будут добавляться.
- Создай новый тип Creature и унаследуй его от Card.
- Сделай так, чтобы Duck и Dog наследовались от Creature.
- Переопредели в прототипе Creature реализацию getDescriptions на новую.
Теперь в ней должны возвращаться две строки описания в виде массива.
Первая из них — из функции getCreatureDescription, которая определена в index.js.
Вторая — из getDescriptions в Card.
Для этого надо вызывать эту базовую версию функции getDescriptions из прототипа Card.
Заметь, что getDescriptions должен возвращать массив строк, а не просто строку!
Верный признак, что ты напутал что-то с возвращаемым значением - вертикальная надпись на карте: У
т
к
а
Используй spread-оператор (так: [newValue, ...values]) или метод unshift массива,
чтобы дополнить возвращаемый базовой версией getDescriptions массив новыми значениями.
Используя те же колоды убедись, что у уток появилась надпись «Утка» над строкой с цепочкой наследования,
а у собак надпись «Собака» над цепочкой наследования.
3. «Громила»
Для уток все становится плохо, когда в рядах бандитов появляется Громила.
Добавь карту Trasher:
- называется Громила, сила 5, наследуется от Dog.
- если Громилу атакуют, то он получает на 1 меньше урона.
Подсказки:
- переопредели метод modifyTakenDamage, чтобы уменшать урон
- this.view.signalAbility — используй, чтобы при применении способности карта мигала
Работает это так:
this.view.signalAbility(() => {
// то, что надо сделать сразу после мигания.
}
Обрати внимание, что если Громиле нанести 2 урона,
то он сначала должен мигнуть «белым», потому что применилась способность и урон уменьшился на 1,
а затем мигнуть «красным» так как он все же получит единицу урона.
За красное мигание отвечает signalDamage, и он будет вызван сам в методе takeDamage в Card.js.
Переопредели getDescriptions, чтобы на лицевой стороне карты выводилось краткое описание способности Громилы.
Не забудь вызвать реализацию из базового типа, чтобы информация «Утка или Собака» никуда не делась.
Помни, что базовый тип это Dog, а не Card!
Если вызвать getDescriptions у Card, то для Trasher все будет работать правильно, но идеологически это неверно.
Колоды для проверки:
const seriffStartDeck = [
new Duck(),
new Duck(),
new Duck(),
new Duck(),
];
const banditStartDeck = [
new Trasher(),
];
4. «Гатлинг»
Нехорошо нападать на мирных жителей. Это еще может быть опасно, если в сарае припрятан Гатлинг.
Добавь карту Gatling:
- называется Гатлинг, сила 6, наследуется от Creature.
- при атаке наносит 2 урона по очереди всем картам противника на столе, но не атакует игрока-противника.
Таким образом урон сначала получает самая левая карта противника, затем вторая слева и так далее.
Урон не должен наноситься одновременно.
Подсказки:
- переопредели метод attack так, чтобы урон наносился всем картам противника
- список карт противника можно получить через gameContext.oppositePlayer.table
- в качестве примера выполнения действий над несколькими картами можешь использовать applyCards из Player.js
Колоды для проверки:
const seriffStartDeck = [
new Duck(),
new Duck(),
new Duck(),
new Gatling(),
];
const banditStartDeck = [
new Trasher(),
new Dog(),
new Dog(),
];
5. «Братки»
Чем их больше, тем они сильнее.
Добавь карту Lad:
- называется Браток, сила 2, наследуется от Dog.
- чем больше братков находится в игре, тем больше урона без потерь поглощается
и больше урона по картам наносится каждым из них.
Защита от урона = количество * (количество + 1) / 2
Дополнительный урон = количество * (количество + 1) / 2
Подсказки:
- текущее количество братков в игре надо где-то хранить, свойство в функции-конструкторе Lad — подходящее место.
Выглядеть будет как-то так: Lad.inGameCount = 0;
- чтобы обновлять количество братков в игре переопредели методы doAfterComingIntoPlay, doBeforeRemoving
- чтобы рассчитывать бонус к урону и защите стоит завести метод в функции Lad (статический метод).
Выглядеть будет как-то так: Lad.getBonus = function () { ... }
- обрати внимание на то, чему равен this в методе getBonus. Можно догадаться, либо посмотреть в отладчике.
Можно ли упростить метод getBonus за счет этого?
- переопредели методы modifyDealedDamageToCreature и modifyTakenDamage, чтобы они использовали бонус.
Добавь в описание карты «Чем их больше, тем они сильнее».
Этот текст должен появляться только если непосредственно у братков (т.е. в Lad.prototype)
переопределены методы modifyDealedDamageToCreature или modifyTakenDamage.
Проверка на наличие свойства непосредственно у объекта выполняется с помщью метода hasOwnProperty.
Проверка наличия метода modifyDealedDamageToCreature у братков выглядит так:
Lad.prototype.hasOwnProperty('modifyDealedDamageToCreature')
Эта особенность понадобится на следующем шаге.
Колоды для проверки:
const seriffStartDeck = [
new Duck(),
new Duck(),
new Duck(),
new Gatling(),
];
const banditStartDeck = [
new Lad(),
new Lad(),
new Lad(),
];
6. «Изгой»
От него все бегут, потому что он приходит и отнимает силы...
Добавь карту Rogue:
- называется Изгой, сила 2, наследуется от Creature.
- перед атакой на карту забирает у нее все способности к увеличению наносимого урона или уменьшению получаемого урона.
Одновременно эти способности забираются у всех карт того же типа, но не у других типов карт.
Изгой получает эти способности, но не передает их другим Изгоям.
Подсказки:
- Изгой похищает эти способности: modifyDealedDamageToCreature, modifyDealedDamageToPlayer, modifyTakenDamage
- Чтобы похитить способности у всех карт некоторого типа, надо взять их из прототипа
- Получить доступ к прототипу некоторой карты можно так: Object.getPrototypeOf(card)
- Чтобы не похищать способности у других типов, нельзя задевать прототип прототипа
- Object.getOwnPropertyNames и obj.hasOwnProperty позволяют получать только собственные свойства объекта
- Удалить свойство из объекта можно с помощью оператора delete так: delete obj[propName]
Это не то же самое, что obj[propName] = undefined
- После похищения стоит обновить вид всех объектов игры. updateView из gameContext поможет это сделать.
Колоды для проверки:
const seriffStartDeck = [
new Duck(),
new Duck(),
new Duck(),
new Rogue(),
];
const banditStartDeck = [
new Lad(),
new Lad(),
new Lad(),
];
7*. «Кузен»
Нагрянула проверка бизнеса из Семьи. Кузен все расставит на свои места.
Добавь карту Cousin:
- называется Кузен, сила 3, наследуется от Dog.
- Пока Кузен находится в игре, все собаки получают на 1 единицу урона меньше.
Эффект от нескольких Кузенов не суммируется.
Подсказки:
- Все необходимое ты уже знаешь :)
Колоды для проверки:
const seriffStartDeck = [
new Rogue(),
new Duck(),
new Duck(),
new Duck(),
new Duck(),
];
const banditStartDeck = [
new Cousin(),
new Dog(),
new Dog(),
];
8*. «Пивовар»
Живительное пиво помогает уткам творить невозможное!
Добавь карту Brewer:
- называется Пивовар, сила 2, наследуется от Duck.
- перед атакой на карту Пивовар раздает пиво,
которое изменяет максимальную силу карты на +1, а затем текущую силу на +2.
- Пивовар угощает пивом все карты на столе: и текущего игрока и игрока-противника,
но только с утками, проверяя их с помощью isDuck.
- Пивовар само собой утка, поэтому его сила тоже возврастает.
Подсказки:
- Все карты на столе можно получить из gameContext так: currentPlayer.table.concat(oppositePlayer.table).
- this.view.signalHeal — используй, чтобы подсветить карту, у которой увеличилась сила.
- card.updateView() — используй, чтобы обновлять вид карт, у которых увеличилась сила.
Важно, чтобы при увеличении текущей силы она не превышала максимальную.
Добиться этого можно по разному, но решить этот вопрос раз и навсегда иначе определив свойство currentPower в Card.
Сейчас оно определяется в конструкторе Card довольно просто:
this.currentPower = maxPower
Пусть так и определяется.
А вот в конструкторе Creature определи заново currentPower через Object.defineProperty.
При этом используй дескриптор доступа, в котором можно задать геттер и сеттер.
Геттер должен просто возвращать текущее значение, а сеттер не давать устанавливать значение выше, чем this.maxPower.
Подробнее про Object.defineProperty тут:
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Пример определения свойства с геттером и сеттером:
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#Example:_Custom_setters_and_getters
Колоды для проверки:
const seriffStartDeck = [
new Duck(),
new Brewer(),
];
const banditStartDeck = [
new Dog(),
new Cousin(),
new Dog(),
new Dog(),
];
9*. «Псевдоутка»
Чтобы получить доступ к живительному напитку надо всего лишь
выглядеть как утка, плавать как утка и крякать как утка!
Добавь карту PseudoDuck:
- называется Псевдоутка, сила 3, наследуется от Dog.
- Псевдоутка — это обычный пес, но еще умеет крякать и плавать, поэтому легко проходит проверку на утиность isDuck.
Подсказки:
- чтобы быть похожим на утку надо всего лишь реализовывать пару методов: quacks и swims
- убедись, что в описании Псевдоутки присутстует «Утка-Собака».
Колоды для проверки:
const seriffStartDeck = [
new Duck(),
new Brewer(),
new Duck(),
];
const banditStartDeck = [
new PseudoDuck(),
new Cousin(),
new PseudoDuck(),
];
10*. «Хитрый гусь»
Охота на замаскировавшихся собак начинается.
Добавь карту SlyGoose:
- называется Хитрый гусь, сила 2, наследуется от Creature.
- урон удваивается, если Хитрый гусь атакует Псевдоутку.
Подсказки:
- убедись, что увеличение урона работает только против Псевдоуток.
Колоды для проверки:
const seriffStartDeck = [
new SlyGoose(),
new SlyGoose(),
new SlyGoose(),
];
const banditStartDeck = [
new PseudoDuck(),
new Dog(),
new PseudoDuck(),
];
11*. «Снайпер»
Неуловимый и смертоносный.
Добавь карту Sniper:
- называется Снайпер, сила 2, наследуется от Creature.
- урон по противоположенной карте утраивается.
- урон по игроку-противнику утраивается.
- урон по Снайперу уменьшается в 3 раза с округлением вниз.
Колоды для проверки:
const seriffStartDeck = [
new Duck(),
new Gatling(),
new Brewer(),
new Duck(),
];
const banditStartDeck = [
new Sniper(),
new Sniper(),
];
12*. «Немо»
«The one without a name without an honest heart as compass»
Добавь карту Nemo:
- называется Немо, сила 4, наследуется от Creature.
- перед атакой на карту крадет ее прототип и назначает себе, получая все ее способности,
но вместе со своим старым прототипом теряет способность красть.
- если карта, у которой был украден прототип, обладает способностями, выполняющимися перед атакой,
то они должны быть выполнены сразу после кражи прототипа.
Подсказки:
- updateView из gameContext позволяет обновить вид всех объектов игры.
- Object.getPrototypeOf(obj) позволяет получить прототип объекта.
- Object.setPrototypeOf(obj, proto) позволяет задать протип объекту.
- функция doBeforeAttack из прототипа должна быть вызвана сразу после кражи прототипа.
Колоды для проверки:
const seriffStartDeck = [
new Nemo(),
new Nemo(),
];
const banditStartDeck = [
new Brewer(),
new Sniper(),
];