Наконец, приступим к реализации последнего класса: фазы игры.
Для начального приближения воспользуемся почти что пустым классом:
class Phase(object):
def __init__(self):
pass
def __call__(self):
self.play()
def play(self):
raise NotImplementedError
def __str__(self):
return self.__class__.__name__
def __repr__(self):
return str(self)
Этого класса хватит для простых карточных игр, в которых правила не могут меняться по ходу игры, и карты не влияют на правила. Когда это может быть не так? К примеру, в игре Fluxx есть тип карт "правил", которые меняют ход игры, заставляя, к примеру, игрока играть первую карту за ход вслепую, запрещающая выиграть стандартным способом и т.п. Также текущая архитектура плохо подходит для такого рода изменений, так как тогда потребуется содавать фазы, в которых будет длинная цепочка условий "если в игре есть карта А, то ... , если В, то ...". Для того чтобы избавиться от такой проблемы, создадим возможность добавлять к классу фазы перечни других фаз, которые надо (временно) исполнять после выполнения этой фазы. Игра в слепую - особая пасле после фаза начала хода, невозможность победить - особая фаза отмены победы после фазы победы, и т.д. Реализуем это в отдельном классе, так как это не обязательный для всех игр функционал:
def HookablePhase(Phase):
__hooks = []
@staticmethod
def add_hook(hook):
__hooks.append(hook)
@staticmethod
def remove_hook(hook):
#TODO: check if safe
__hooks.remove(hook)
def __call__(self):
self.play()
self.end()
def play(self):
raise NotImplementedError
def end(self):
for h in self.__hooks:
h()()