Skip to content

Instantly share code, notes, and snippets.

@angru
Last active September 14, 2015 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save angru/0d49c710156c4d964a3c to your computer and use it in GitHub Desktop.
Save angru/0d49c710156c4d964a3c to your computer and use it in GitHub Desktop.
text quest
# # -*- 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