Текстовые приключенческие игры имеют довольно строгую формулу; есть мир, состоящий из серии комнат / пространств, игрок может перемещаться по этим комнатам, и в комнатах есть некоторые предметы. Предметы могут быть отобраны игроком, отложены, использованы для доступа в другие комнаты (например, ключи) и объединены с другими предметами для создания новых предметов.
Вызов
Ваша задача состоит в том, чтобы написать текстовую среду выполнения приключений с наименьшим количеством байтов (код гольф) Для простоты все, что вам нужно сделать, это вывести истинное или ошибочное значение в зависимости от того, выиграет ли данная серия команд в данной игре или нет (без интерактивности, без дружественного для человека вывода и т. Д.)
Правила игры
- Мир всегда состоит из коридора с 10 смежными комнатами. В каждую комнату требуется ключ для входа, но в любой момент можно выйти без ключа (так что, думаю, это какой-то замок с защелкой);
- Игрок начинает игру в комнате 0 и выигрывает, если он когда-либо входит в комнату 9 (как только он достигает комнаты 9, он может делать все, что ему нравится, включая переход в другую комнату, и он все равно выиграет);
- Каждая комната может содержать любое количество предметов;
- Существует до 26 предметов с именем AZ, и ни один предмет не появится в мире более одного раза;
- Игрок может забрать предметы из текущей комнаты и поместить их в свой инвентарь (они также могут бросить предметы из своего инвентаря в текущую комнату);
- Максимальный размер инвентаря игрока конечен, и ему будут предоставлены детали уровня;
- В начале игры инвентарь игрока всегда пуст;
- Максимальное количество предметов в комнате не ограничено (хотя неявное ограничение составляет 26, поскольку это общее количество предметов);
- Пункты AJ - это ключи, которые можно использовать для входа в комнаты 0-9 (т. Е. Игрок может перейти в комнату 0, если у него есть пункт A, в комнату 1, если у них есть B и т. Д., Обратите внимание, что ключи не требуются, чтобы покинуть комнату, и игрок начинает игру в комнате 0, поэтому клавиша «А» требуется только в том случае, если игрок хочет вернуться в комнату 0);
- Предметы в инвентаре игрока могут быть объединены для создания новых предметов (которые будут созданы в инвентаре игрока) - разрешенные комбинации будут предоставлены с деталями уровня;
- Объединение предметов потребляет исходные предметы (т. Е. Если один из предметов был ключом, то больше нельзя будет использовать этот ключ);
- Если игрок пытается сделать что-то невозможное (например, взять предмет, которого нет в текущей комнате / бросить предмет, которого у него нет / объединить предметы, которых у него нет / перейти в комнату, в которой нет ключа) ибо) ничего не происходит и они могут продолжаться;
- Игрок никогда не даст бессмысленную команду (например, зайдите в комнату 11).
Так что простая игра может выглядеть так:
v
+---+---+---+---+---+---+---+---+---+---+
| C | | J | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
| CORRIDOR |
+---------------------------------------+
Inventory capacity: 99
Комната 0 содержит пункт «С» (который является ключом к комнате 2). Комната 2 содержит пункт «J» (который является ключом к комнате 9). Игрок может выиграть игру, подняв C, перейдя в комнату 2, подняв J, а затем перейдя в комнату 9.
Более сложная игра может быть:
v
+---+---+---+---+---+---+---+---+---+---+
| C | | X |YZ | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
| CORRIDOR |
+---------------------------------------+
Inventory capacity: 10
C+X => D
Y+Z => J
Теперь игрок может выиграть, подняв C, перейдя в комнату 2, подняв X, скомбинировав C с X, чтобы создать D, а затем переместившись в комнату 3. Теперь они могут собирать и комбинировать Y и Z, чтобы получить J, что позволяет им перейти в комнату 9.
Формат ввода
Есть довольно много входных данных для обработки, и это довольно скучная задача, поэтому формат ввода очень гибкий. Вы получите следующие данные, и способ их отправки в вашу программу в значительной степени зависит от вас:
- Начальное содержимое каждой комнаты (список из 0 или более предметов для каждой комнаты);
- Коллекция разрешенных комбинаций элементов (каждая содержит 2 элемента ввода и их элемент вывода - обратите внимание, что элементы ввода неупорядочены);
- Максимальный размер инвентаря (целое число, 0 <= размер <= 26);
- Список команд, которые пытался выполнить игрок.
Команды игрока могут быть:
[P]ick up <item>
- берет предмет из комнаты и кладет его в инвентарь игрока (если есть место)[D]rop <item>
- бросает предмет из инвентаря игрока в текущую комнату[C]ombine <item1> <item2>
- объединяет 2 предмета в инвентаре игрока, чтобы произвести новый предмет[G]o to <room>
- путешествует в выбранную комнату, если у игрока есть требуемый ключ
Например, формат ввода, который я использовал для тестирования, был простыми аргументами программы:
./adventure YZ '' '' '' '' '' '' '' '' '' 1 YZJ 2 PY PZ CYZ G9
# r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 combinations inv. size commands...
# means:
# room 0 starts with items Y & Z, all other rooms start empty
# 1 combination is possible: Y+Z => J
# max inventory size is 2
# player commands are [P]ick up Y, [P]ick up Z, [C]ombine Y and Z, [G]o to room 9
# (in this example, the player wins)
Но если какой-то другой формат облегчает задачу, это нормально (например, специальные символы-разделители / несколько строк / другой порядок / сериализация в JSON / и т. Д.)
Выходной формат
Ваша программа должна возвращать некоторые достоверные результаты, если команды игрока заставляют их выиграть игру, а некоторые ошибочные результаты в противном случае. Это может быть узнаваемое сообщение для stdout, код возврата программы или любой другой язык, который вы выберете. Все остальные выходные данные будут игнорироваться.
Тестовые случаи
Следующий скрипт bash предоставляет тестовый набор, который будет проверять большинство ситуаций. Он был написан для использования формата, описанного выше, но изменение его для использования другого формата - это всего лишь случай добавления преобразования в invoke
функцию.
#!/bin/sh
PROG="$1";
if [[ -z "$PROG" ]]; then
echo "Usage: $0 <program-to-test>";
exit 1;
fi;
function invoke {
"$PROG" "$@"
}
RED="\033[1;31m";
GREEN="\033[1;32m";
RESET="\033[m";
FAILURES="0";
function pass {
if ! invoke "$@" >/dev/null 2>&1; then
echo "${RED}Expected pass, got fail:${RESET} $*" >&2;
(( FAILURES = "$FAILURES" + 1 ));
invoke "$@" 2>&1;
fi;
}
function fail {
if invoke "$@" >/dev/null 2>&1; then
echo "${RED}Expected fail, got pass:${RESET} $*" >&2;
(( FAILURES = "$FAILURES" + 1 ));
invoke "$@" 2>&1;
fi;
}
echo "Running tests...";
# R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 C I Cmd...
pass J '' '' '' '' '' '' '' '' '' 0 9 PJ G9;
fail '' J '' '' '' '' '' '' '' '' 0 9 PJ G9;
pass J '' '' '' '' '' '' '' '' '' 0 9 PJ PJ G9;
fail J '' '' '' '' '' '' '' '' '' 0 9 PJ;
fail J '' '' '' '' '' '' '' '' '' 0 9 G9;
pass J '' '' '' '' '' '' '' '' '' 0 9 G9 PJ G9;
pass J '' '' '' '' '' '' '' '' '' 0 1 PJ G9;
fail J '' '' '' '' '' '' '' '' '' 0 0 PJ G9;
fail J '' '' '' '' '' '' '' '' '' 0 9 PJ DJ G9;
fail J '' '' '' '' '' '' '' '' '' 0 9 PJ PJ DJ G9;
pass J '' '' '' '' '' '' '' '' '' 0 9 PJ DJ PJ G9;
pass J '' '' '' '' '' '' '' '' '' 0 9 PJ DJ PJ G9;
pass B CJ '' '' '' '' '' '' '' '' 0 2 PB G1 DB PC PJ G9;
fail B CJ '' '' '' '' '' '' '' '' 0 2 PB G1 DB PB PC PJ G9;
pass AJ '' '' '' '' '' '' '' '' '' 0 2 PA PJ G9;
pass B D '' J '' '' '' '' '' '' 0 2 PB G1 PD G3 DB PJ G9;
fail B D '' J '' '' '' '' '' '' 0 2 PB G1 PD G2 DB PJ G9;
fail B D '' J '' '' '' '' '' '' 0 2 PB G1 PD G3 PJ G9;
fail B D J C '' '' '' '' '' '' 0 2 PB G1 PD G3 PJ G9;
pass AJ '' '' '' '' '' '' '' '' '' 0 2 PA PJ G9 G0;
fail ADJ '' '' '' '' '' '' '' '' '' 0 3 PA PD PJ G3 DJ G0 PJ G9;
pass ADJ '' '' '' '' '' '' '' '' '' 0 3 PA PD PJ G3 DJ G0 G3 PJ G9;
fail ADJ '' '' '' '' '' '' '' '' '' 0 3 PA PD PJ G3 DJ G0 DD G3 PJ G9;
pass ADJ '' '' '' '' '' '' '' '' '' 0 3 PA PD PJ DD G3 DJ G0 DD G3 PJ G9;
fail ADJ '' '' '' '' '' '' '' '' '' 0 1 PA DA DA PD PJ G9;
pass ADJ '' '' '' '' '' '' '' '' '' 0 1 PA DA DA PJ G9;
fail ABCDEFGHIKLMNOPQRSTUVWXYZ J '' '' '' '' '' '' '' '' 0 26 PA PB PC PD PE PF PG PH PI PJ PK PL PM PN PO PP PQ PR PS PT PU PV PW PX PY PZ G9;
pass ABCDEFGHIJKLMNOPQRSTUVWXYZ '' '' '' '' '' '' '' '' '' 0 26 PA PB PC PD PE PF PG PH PI PJ PK PL PM PN PO PP PQ PR PS PT PU PV PW PX PY PZ G9;
fail YZJ '' '' '' '' '' '' '' '' '' 0 2 PY PZ CYZ PJ G9;
pass YZJ '' '' '' '' '' '' '' '' '' 1 YZW 2 PY PZ CYZ PJ G9;
pass YZJ '' '' '' '' '' '' '' '' '' 1 YZW 2 PY PZ CYZ PJ CWJ G9;
fail XYZJ '' '' '' '' '' '' '' '' '' 1 YZW 2 PY PZ CYZ PX PJ G9;
fail XYZJ '' '' '' '' '' '' '' '' '' 1 YZW 2 PY PZ CYZ PX DY DZ PJ G9;
pass XYZJ '' '' '' '' '' '' '' '' '' 1 YZW 2 PY PZ CYZ PX DW PJ G9;
pass YZ '' '' '' '' '' '' '' '' '' 1 YZJ 2 PY PZ CYZ G9;
fail YZ '' '' '' '' '' '' '' '' '' 1 YZJ 2 CYZ G9;
pass YZ '' '' '' '' '' '' '' '' '' 1 YZJ 2 PY PZ CYZ CYZ G9;
fail YZ '' '' '' '' '' '' '' '' '' 1 YZJ 2 PY PZ CYZ DJ CYZ G9;
fail YZ '' '' '' '' '' '' '' '' '' 1 YZJ 2 PY PZ CYZ DJ PY PZ CYZ G9;
fail WZ '' '' '' '' '' '' '' '' '' 1 YZJ 2 PW PZ CYZ G9;
fail WZ '' '' '' '' '' '' '' '' '' 1 YZJ 2 PY PZ CYZ G9;
pass YZ '' '' '' '' '' '' '' '' '' 1 YZJ 2 PY PZ CZY G9;
pass YZ '' '' '' '' '' '' '' '' '' 1 ZYJ 2 PY PZ CYZ G9;
fail YZ '' '' '' '' '' '' '' '' '' 1 YZJ 1 PY PZ CYZ G9;
fail YZ '' '' '' '' '' '' '' '' '' 1 YZJ 1 PY PZ CYZ PY PZ CYZ G9;
fail YZ '' '' '' '' '' '' '' '' '' 1 YZJ 1 PY PZ CYZ PJ G9;
fail YZ '' '' '' '' '' '' '' '' '' 1 YZJ 1 PJ G9;
pass BW UV '' '' '' '' '' '' '' '' 3 BUR WVS RSJ 2 PB PW G1 DW PU CBU DR PW PV CVW PR CRS G9;
fail BW AUV '' '' '' '' '' '' '' '' 3 BUR WVS RSJ 2 PB G1 PU CBU DR PA PB G0 DA PW G1 PV CVW PR CRS G9;
pass BCW AUV '' '' '' '' '' '' '' '' 3 CUR WVS RSJ 2 PB PC G1 DB PU CCU DR PC PA PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW UV '' '' '' '' '' '' '' '' 3 CUR WVS RSJ 2 PB PC G1 DB PU CCU DR PC PA PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV '' '' '' '' '' '' '' '' 3 CUR WVS RSJ 2 PB PC G1 DB PU CCU PA PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV '' '' '' '' '' '' '' '' 3 CUR WVS RSJ 2 PB PC G1 DB PU CCU DR PA G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV '' '' '' '' '' '' '' '' 3 CUR WVS RSJ 2 PB PC G1 DB PU CCU DR PB G0 DA PW G1 DB PV CVW PR CRS G9;
fail BCW AUV '' '' '' '' '' '' '' '' 3 CUR WVS RSJ 2 PB PC G1 DB PU CCU DR PA PB G0 DA G1 DB PV CVW PR CRS G9;
fail BCW AUV '' '' '' '' '' '' '' '' 3 CUR WVS RSJ 2 PB PC G1 DB PU CCU DR PA PB G0 DA PW G1 DB CVW PR CRS G9;
pass BFK LG M N O CDE PQR U W '' 10 BPT CQS TSH HUI IWV VFA GRX MXZ ANY YZJ 5 \
PB PF PK G1 PL PG G6 DB DK DL G5 PC PD PE G6 DF G2 PM G6 DM DC G3 PN G4 PO G6 DN DO DD DE \
PB PP CBP PC PQ CCQ CTS G7 PU CUH G8 PW CWI G6 PF CVF PR PM PN CGR CMX CAN CYZ G9
fail BFK LG M N O CDE PQR U W '' 10 BPT CQS TSH HUI IWV VFA GRX MXZ ANY YZJ 5 \
PB PF PK G1 PL PG G6 DB DK DL G5 PC PD PE G6 DF G6 DM DC G3 PN G4 PO PM G6 DN DO DD DE \
PB PP CBP PC PQ CCQ CTS G7 PU CUH G8 PW CWI G6 PF CVF PR PM PN CGR CMX CAN CYZ G9
if (( "$FAILURES" == "0" )); then
echo "${GREEN}All tests passed${RESET}";
else
echo "${RED}Total failures: $FAILURES${RESET}";
fi;
выигрыш
Стандартный код гольфа: выигрывает самый короткий код (в байтах). Записи должны соответствовать правилам игры, что на практике означает, что они должны пройти все тестовые случаи (при необходимости может быть добавлено больше тестов).