Домашнее задание #5 (ua)
Это задание направлено на проектировние архитектуры приложения с использованием принципов ООП и паттернов проектирования. В частности затрагивается обработка команд и ошибок, управление состоянием и жизненным циклом объектов, геймификация.
Установка показана в рабочем окружении OS Linux:
git clone https://github.com/BinaryStudioAcademy/bsa-2019-php-5.git
cd bsa-2019-php-5
composer install
Вам необходимо разработать консольную игру "Pirates".
Игрок - корабль пиратов. Враги - королевский флот.
Корабль имеет такие свойства:
int strength // определяет наносимый урон (1 до 10)
int armour // защиту к урону (1 - 10)
int luck // определяет удачу попадания (1-10)
int health // здоровье корабля (1 - 100)
array hold // трюм корабля для добычи, вместительность: 3 элемента добычи.
С побежденного корабля можно собрать сундук золота (💰) или ром (🍾). Золото можно обменять на одну из характеристик (силу, защиту или удачу) или на бутылку рома, выпив который можно поднять здоровье на 30 единиц.
В игровом мире должно быть 8 гаваней:
-
1 пиратская гавань без вражеских кораблей, где и начинается игра (
(1) Pirates Hardbor
). Здесь же можно обменять сундуки с золотом. Когда корабль возвращается в пиратскую гавань - здоровье возобновляется до 60 автоматически, если оно ниже 60. -
4 гавани с патрульными шхунами (
Royal Patrool Schooner
) с низкими статами ((2) Southhampton
,(3) Fishguard
,(4) Salt End
,(5) Isle of Grain
):
strength: 2-4
armour: 2-4
luck: 1-4
health: 50
hold: [ 💰 _ _ ]
- 2 гавани с боевым королевским флотом (
Royal Battle Ship
) со средними статами ((6) Grays
,(7) Felixstowe
):
strength: 4-8
armour: 4-8
luck: 4-7
health: 80
hold: [ 🍾 _ _ ]
- И 1 гавань с королевским фрегатом ее величества (
HMS Royal Sovereign
) с самыми высокими статами ((8) London Docks
):
strength: 10
armour: 10
luck: 10
health: 100
hold: [ 💰 💰 🍾 ]
Игра начинается в гавани пиратов. Корабль изначально должен иметь следующие характеристики:
strength: 4
armour: 4
luck: 4
health: 60
Возвращаться в каждую гавань разрешается неограниченное количество раз, и каждый раз там должен генерироваться новый корабль соответствующий гавани.
Если игрок проигрывает, то он возвращается в пиратскую гавань и с него снимается по одной характеристике и опустошается трюм.
Задача игры потопить королевский фрегат, после чего игра считается завершенной.
-
help
- выводит список доступных команд -
stats
- выводит статы корабля и содержимое трюма -
set-sail <east|west|north|south>
- плыть в следующую гавань. Переплывать между гаванями можно в любой момент -
fire
- выстрелить в корабль. Сражение происходит пошагово, сперва стреляет игрок, затем NPC. Вероятность попадания должна зависеть от удачи корабля. А нанесенный урон от силы и защиты (нужно использовать хелпер Math). -
aboard
- собрать добычу с побежденного корабля. -
buy <strength|armour|luck|rum>
- купить 1у характеристику или бутылку рома. Покупать можно только в пиратской гавани за сундуки с золотом. -
drink
- выпить бутылку рома. Бутылка рома увеличивает здоровье на 30 единиц. -
whereami
- выводит информацию о текущей гавани -
exit
- завершить игру
Карта локаций и возможных перемещений:
/**
* Запускает игру в бесконечном цикле и опрашивает пользовательский ввод.
*/
public function start(Reader $reader, Writer $writer);
/**
* Пошаговое выполнение.
* Запускает игру и выполняет только одну команду с $reader'a. При этом состояние игрового мира должно сохранятся
* Этот режим необходим для тестирования.
*/
public function run(Reader $reader, Writer $writer);
Для того, чтобы тесты работали корректно, необходимо использовать предоставленные хелперы Math и Random:
Random::get(): float - возвращает случайное число от 0 до 1. Обратите внимание, что инстанс Random передается в конструктор игры, больше нигде он инстанцироваться не должен, иначе тесты работать не будут.
Math::luck(Random, int): bool - расчитывает значение попадания в корабль, на основании характеристики удачи корабля. Обратите внимание, что реализация использует константу Stats::MAX_LUCK, которая определяет максимальное значение характеристики удачи.
Math::damage(int, int): int - рассчитывает наносимый урон, на основании силы атакующего корабля, и брони защищающегося корабля.
Также обратите внимание на класс tests\Stubs\Messages
, здесь представлены сообщения, которые ожидаются в тесте.
- Игра должна запускаться через терминал и исполнять комманды через пользовательский ввод в соответствии с условиями задания.
php game.php
- Проверить себя можно с помощью юнит тестов:
./vendor/bin/phpunit
Необходимо склонировать этот репозиторий и разместить свое решение на Bitbucket.
Форкать репозиторий запрещено!
Оцениваться решение будет по следующим критериям:
-
Игра работает в соответствии с заданием: 5 баллов (будьте внимательны, тесты могут покрывать не все случаи)
-
Обработаны исключительные ситуации (значения здоровья и харакетериситик корабля не превышают максимальное количество, нельзя перейти в локацию которой нет на карте и т.д.): 1 балл
-
Использовано минимум 3-и паттерна проектирования: 3 балла (подсказка: для задачи подойдет Command, Builder, Factory)
-
Код написан чисто и аккуратно в соответствии со стандартом PSR-2, без комментариев в коде, без функций отладки: 1 балл
Разрешается использовать любое тестовое окружение с PHP >7.1.
Или использовать предоставленное docker окружение. Для этого достаточно сбилдить image:
docker-compose build
Установить зависимости:
docker-compose run --rm composer install
Запустить приложение:
docker-compose run --rm php php game.php
Запустить тесты:
docker-compose run --rm php ./vendor/bin/phpunit
Для удобства отладки также в контейнере есть XDebug, который легко подключить к вашей IDE.
Примеры для VS Code и PHP Storm можно найти в инструкции.