Last active
September 14, 2015 19:49
-
-
Save angru/0d49c710156c4d964a3c to your computer and use it in GitHub Desktop.
text quest
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# # -*- coding: utf-8 -*- | |
from __future__ import print_function | |
from functools import partial | |
from collections import namedtuple | |
Locations = namedtuple('Locations', ('yard', 'road', 'house', 'barn', 'backyard', 'road_left', 'road_right')) | |
ActionResult = namedtuple('ActionResult', ('location', 'message')) | |
class World(object): | |
def __init__(self): | |
self.game_over = False | |
self.locations = Locations( | |
Yard(self), | |
Road(self), | |
House(self), | |
Barn(self), | |
Backyard(self), | |
RoadLeft(self), | |
RoadRight(self), | |
) | |
self.player = Player() | |
def start(self): | |
location = self.locations.yard | |
self.print_msg(location.description) | |
while not self.check_game_over(): | |
choice = input('>:') | |
actions = { | |
'?': self.get_help(location), | |
'инв': self.show_inventory(location), | |
} | |
actions.update(location.actions) | |
action = actions.get(choice) | |
if action: | |
result = action() | |
location = result.location | |
msg = result.message | |
else: | |
msg = 'unknown command' | |
self.print_msg(msg) | |
self.print_msg(self.check_game_over()) | |
def get_help(self, source): | |
def action(): | |
msg = '\r\n'.join([source.description, str(source.actions.keys())]) | |
return ActionResult(source, msg) | |
return action | |
def show_inventory(self, source): | |
def action(): | |
return ActionResult(source, self.player.items) | |
return action | |
def print_msg(self, msg): | |
"""Так легче управлять выводом информации""" | |
print(msg) | |
def check_game_over(self): | |
if self.game_over: | |
return 'Вы победили!' | |
elif not self.player.alive: | |
return 'Вы проиграли' | |
else: | |
return False | |
class Player(object): | |
def __init__(self): | |
self.items = [] | |
self.alive = True | |
class Location(object): | |
def __init__(self, world): | |
self._world = world | |
def enter(self, source): | |
raise NotImplementedError() | |
@property | |
def actions(self): | |
""" | |
Список действий, возможных на этой локации. | |
Декоратор property используется потому что действия | |
зависят от состояния локации и инвентаря игрока | |
""" | |
raise NotImplementedError() | |
@property | |
def description(self): | |
""" | |
Описание локации. | |
Зависит от состояния локации и предметов в инвентаре игрока | |
""" | |
raise NotImplementedError() | |
@property | |
def locations(self): | |
""" | |
чтобы слишком много не писать | |
""" | |
return self._world.locations | |
class House(Location): | |
@property | |
def description(self): | |
return "Заброшенный дом" | |
def enter(self, source): | |
world = self._world | |
if 'key' in world.player.items: | |
msg = ( | |
"Ура! Вы зашли в дом!\r\n" | |
"Поздравляю, вы прошли игру!\r\n" | |
"Продолжение следует..." | |
) | |
self._world.game_over = True | |
return ActionResult(self, msg) | |
else: | |
return ActionResult( | |
source, "Вы подошли к дому, но у вас нет ключа, чтобы открыть его." | |
) | |
@property | |
def actions(self): | |
return {} | |
class Yard(Location): | |
@property | |
def description(self): | |
return "Внутренний двор." | |
def enter(self, source): | |
return ActionResult(self, 'Вы стоите во дворе перед домом\r\n') | |
@property | |
def actions(self): | |
return { | |
'на задний двор': partial(self.locations.backyard.enter, self), | |
'к сараю': partial(self.locations.barn.enter, self), | |
'на дорогу': partial(self.locations.road.enter, self), | |
'к дому': partial(self.locations.house.enter, self), | |
} | |
class Backyard(Location): | |
@property | |
def description(self): | |
return 'Задний двор.' | |
def __init__(self, world): | |
super(Backyard, self).__init__(world) | |
self.items = ['map'] | |
def enter(self, source): | |
if self.items: | |
self._world.player.items.extend(self.items) | |
self.items.clear() | |
msg = ( | |
"Убедившись, что задняя дверь дома тоже закрыта, вы внимательно осмотрели двор.\r\n" | |
"Увидев беседку в нем, вы зашли в нее и нашли сложенную бумажку.\r\n" | |
"Развернув лист бумаги, вы поняли что это - карта местности, на которой\r\n" | |
"был отмечен правый тупик дороги. Что же там может быть закопано?!\r\n" | |
"Больше на заднем дворе ничего интересного нет. Вы вернулись ко входу дома." | |
) | |
else: | |
msg = "Больше на заднем дворе ничего нет. Вы вернулись к дому." | |
return ActionResult(source, msg) | |
@property | |
def actions(self): | |
return {} | |
class Road(Location): | |
@property | |
def description(self): | |
return "Дорога. Можно пойти [налево] или [направо]." | |
def enter(self, source): | |
return ActionResult(self, self.description) | |
@property | |
def actions(self): | |
return { | |
'во двор': partial(self.locations.yard.enter, self), | |
'налево': partial(self.locations.road_left.enter, self), | |
'направо': partial(self.locations.road_right.enter, self), | |
} | |
class RoadLeft(Location): | |
def __init__(self, world): | |
super(RoadLeft, self).__init__(world) | |
self.vampire_alive = True | |
@property | |
def description(self): | |
if self.vampire_alive: | |
return 'Дорога. У обочины стоит человек.' | |
else: | |
return 'Дорога. У обочины лежит труп человека.' | |
def enter(self, source): | |
if self.vampire_alive: | |
msg = ( | |
"Вы пошли налево и встретили человека.\r\n" | |
"Что вы хотите с ним сделать?\r\n" | |
"[Поговорить] с ним. Вдруг он расскажет что-нибудь полезное?\r\n" | |
"[Убить] его. От него исходит слабое свечение, кажется, он нечитсь." | |
) | |
return ActionResult(self, msg) | |
else: | |
return ActionResult(source, 'Вампир убит, тут делать больше нечего.') | |
def talk_to_vampire(self): | |
if self.vampire_alive: | |
msg = ( | |
'Мужчина оказался поклонником охотников за привидениями.\r\n' | |
'Он рассказал вам, что семья в доме была жестоко убита, но владелец дома успел закопать ключ.\r\n' | |
'Не зная, как больше вам помочь, он дал вам серебрянный топор. Осталось найти чем можно копать и сама место, где нужно копать.' | |
) | |
self._world.player.items.append('axe') | |
else: | |
msg = 'Вампир мертв.' | |
return ActionResult(self, msg) | |
def kill_vampire(self): | |
player = self._world.player | |
if 'axe' in player.items and self.vampire_alive: | |
msg = ( | |
'Мужчина оказался высшим вампиром. Наверняка он хотел заманить Вас в дом и съесть Вас.\r\n' | |
'Ваши инстинкты не подвели вас, повезло, что вы его зарубили.' | |
) | |
self.vampire_alive = False | |
else: | |
msg = ( | |
'Попытаться убить человека голыми руками – плохое решение.\r\n' | |
'Мужчина с нечеловеческой скоростью переместился за вашу спину и сломал Вам шею.' | |
) | |
player.alive = False | |
return ActionResult(self, msg) | |
@property | |
def actions(self): | |
return { | |
'поговорить': self.talk_to_vampire, | |
'убить': self.kill_vampire, | |
'на дорогу': partial(self.locations.road.enter, self), | |
} | |
class RoadRight(Location): | |
def __init__(self, world): | |
super(RoadRight, self).__init__(world) | |
self.items = ['key'] | |
@property | |
def description(self): | |
if 'map' in self._world.player.items: | |
return 'Дорога. Где-то здесь зарыт клад' | |
else: | |
return 'Дорога.' | |
def enter(self, source): | |
return ActionResult(self, self.description) | |
def dig(self): | |
player = self._world.player | |
if 'shovel' in player.items: | |
msg = ( | |
'Вы нашли место, где закопан клад, и начали рыть землю лопатой.' | |
) | |
player.items.extend(self.items) | |
self.items.clear() | |
else: | |
msg = ( | |
'Вы попробовали вырыть яму руками, но обнаружили, что земля оказалась ядовитой!=\r\n' | |
'Яд быстро распространился по телу и вы умерли.' | |
) | |
player.alive = False | |
return ActionResult(self, msg) | |
@property | |
def actions(self): | |
actions = { | |
'на дорогу': partial(self.locations.road.enter, self), | |
} | |
if 'map' in self._world.player.items and self.items: | |
actions['копать'] = self.dig | |
return actions | |
class Barn(Location): | |
def __init__(self, world): | |
super(Barn, self).__init__(world) | |
self.is_open = False | |
self.items = ['shovel'] | |
@property | |
def description(self): | |
if not self.is_open: | |
return 'Старый сарай, закрыт на висячий замок.' | |
else: | |
return 'Пустой старый сарай' | |
def enter(self, source): | |
world = self._world | |
return ActionResult(self, self.description) | |
def open(self): | |
if not self.is_open and self.items and 'axe' in self._world.player.items: | |
self.is_open = True | |
self._world.player.items.extend(self.items) | |
self.items.clear() | |
msg = ( | |
"Вам удалось сбить замок с помощью топора.\r\n" | |
"В сарае вы нашли лопату, больше ничего интересного тут нет." | |
) | |
else: | |
msg = ( | |
"Замок заржавел и даже если у вас получится найти ключ от него,\r\n" | |
"то вряд ли вы сможете открыть его.\r\n" | |
"Придется вернуться к дому и начать поиски сначала." | |
) | |
return ActionResult(self, msg) | |
@property | |
def actions(self): | |
actions = { | |
'во двор': partial(self.locations.yard.enter, self), | |
} | |
if not self.is_open: | |
actions.update({ | |
'взломать': self.open | |
}) | |
return actions | |
if __name__ == '__main__': | |
World().start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment