Появилась у меня с маленьким ребенком новая красивая настолка — классическая ходилка с одним кубиком. Симпатичная картинка, достаточная длина игровой сессии. И есть в этой игре странная особенность — чёрная дыра на 39 шаге (из 120), которая сразу отбрасывает игрока в самое начало. Давайте посчитаем насколько это сТранно. И мелкий совет в конце по расширению правил для возможного исправления.
![Игровое поле Игровое поле](https://habrastorage.org/getpro/habr/upload_files/550/82a/112/55082a112ec70486d654b7ba3953adb6.jpg)
В чем проблема?
У игрока нет никакого контроля и возможности повлиять на результат. То есть победа или поражение — полная случайность. Поэтому если уж не повезло попасть на черную дыру, то догнать оппонента почти нереально, ведь это одна треть всего маршрута.
В игре нет никакой механики камбека. Более того всегда есть заметная вероятность второй раз попасть на черную дыру. Уныние у такого игрока обеспечено.
Насколько проблема большая?
С ходу может показаться, что риск такого события всего лишь ~17% (1/6 для шестигранного кубика). Вроде терпимо. Но если подумать ещё, то окажется, что проверять надо не одного игрока, а двух, т.к. нас интересует интересность в игре обоих игроков. Ещё хуже если игроков больше двух. Но можно подумать ещё, и тогда окажется, что для одного игрока опасных бросков не один, а обычно больше (2, иногда 3). Например, игрок находится на расстоянии 6 от чёрной дыры, выпадает 2 и он вздыхает с облегчением, но зря, т.к. на следующий свой ход он опять в той же ситуации и фатальной для него теперь является четвёрка.
Рассчитать вероятность всего этого через теорию вероятности несколько проблематично. Зато можно заэмулировать и просто собрать статистику.
const bonusTurn = [7, 22, 55, 70, 77, 93, 104, 115]; const skipTurn = [13, 28, 46, 62, 85, 98, 110]; function main(gamesCount) { let games = []; for (i = 0; i < gamesCount; i++) { games[i] = emulateGame(); } //console.log(games); let catchedGames = 0; let catchedGamesUnfair = 0; let catchedMoreLoseGames = 0; for (i = 0; i < gamesCount; i++) { if (games[i].p1Catched > 0 || games[i].p2Catched > 0) { catchedGames++; if (games[i].p1Catched != games[i].p2Catched) { catchedGamesUnfair++; } } if (games[i].p1Catched > games[i].p2Catched && games[i].winner == 'p2') { catchedMoreLoseGames++; } else if (games[i].p1Catched < games[i].p2Catched && games[i].winner == 'p1') { catchedMoreLoseGames++; } } console.log('Count of games: ' + gamesCount); console.log('Percent of games with black hole: ' + Math.round(100*catchedGames/gamesCount) + '%'); console.log('Percent of unfair games with black hole: ' + Math.round(100*catchedGamesUnfair/gamesCount) + '%'); console.log('If go to black hole more then lose: ' + Math.round(100*catchedMoreLoseGames/catchedGamesUnfair) + '%'); } function emulateGame() { let game = { 'p1': 0, 'p2': 0, 'winner': null, 'p1Catched': 0, 'p2Catched': 0, 'turn': 0 } while(true) { game.turn++; game.p1 += getDice(); game = checkMove(game, 'p1'); if (game.p1 >= 120) { game.winner = 'p1'; break; } game.p2 += getDice(); game = checkMove(game, 'p2'); if (game.p2 >= 120) { game.winner = 'p2'; break; } } return game; } function checkMove(game, player) { let anotherPlayer = 'p1'; if (player == anotherPlayer) { anotherPlayer = 'p2'; } if (bonusTurn.indexOf(game[player]) !== -1) { game[player] += getDice(); game = checkMove(game, player); } if (skipTurn.indexOf(game[player]) !== -1) { game[anotherPlayer] += getDice(); game = checkMove(game, anotherPlayer); } if (game[player] == 39) { game[player] = 0; game[player + 'Catched']++; } if (game[player] == 4) { game[player] = 8; } if (game[player] == 23) { game[player] = 9; } if (game[player] == 24) { game[player] = 34; } if (game[player] == 30) { game[player] = 20; } if (game[player] == 42) { game[player] = 52; } if (game[player] == 60) { game[player] = 50; } if (game[player] == 65) { game[player] = 74; } if (game[player] == 79) { game[player] = 88; } if (game[player] == 101) { game[player] = 91; } if (game[player] == 107) { game[player] = 112; } return game; } function getDice() { return Math.floor(Math.random() * 6 + 1); } main(1000000);
![Для запуска подойдет любое окно браузера, F12, console, copy-paste Для запуска подойдет любое окно браузера, F12, console, copy-paste](https://habrastorage.org/getpro/habr/upload_files/2ba/d92/c29/2bad92c29a1353f3855abcd49b22145c.png)
Итого, при эмуляции одного миллиона игр мы получаем такую статистику:
-
Вероятность того, что хоть кто-нибудь хотя бы раз попадет в черную дыру: 50% (!!!);
-
Вероятность того, что игра будет несправедливой, когда у кого-то будет больше попаданий в черную дыру, чем у оппонента: 45%;
-
Вероятность того, что игрок с большим попаданием в чёрную дыру проиграет: 92%.
А что можно сделать?
Самый примитивный вариант: игнорировать чёрную дыру или считать её за обычный пропуск хода.
Вариант посложнее: каждому игроку дать по две фишки, чтобы была возможность выбора, кем передвигаться. В этом случае игра превращается из простого рандома в чуть более тактическую игру. И ребёнку гораздо полезнее, когда он не просто тренируется соблюдать игровые правила, но и учится играм с контролем.
Заключение
Вероятность попадания в черную дыру на 50% меня весьма удивила, я ожидал поменьше. Не менее удивительны целых 8% победы даже в случае чёрной дыры. Вот они когнитивные искажения.
А вот гейм-дизайнерам, я считаю, нужно всё же тестировать свои собственные игры получше. Анализ «на глазок» может подложить подобную свинью. Данная механика приносит почти всегда только разочарование и 8% на «победу вопреки» того не стоит. Особенно в игре, где это «вопреки» происходит исключительно по воле случая.
ссылка на оригинал статьи https://habr.com/ru/articles/706188/
Добавить комментарий