Use location bit glyphs in action text.
[naja.git] / naja / actions.py
1 from naja.constants import BITS, CHESS_PIECES
2 from naja.utils import bit_glyphs
3
4
5 class LocationAction(object):
6     """
7     An action that may be performed on a location.
8     """
9
10     TEXT = None
11     USES_MSB = False
12
13     def __init__(self, required_bits, **data):
14         self.required_bits = required_bits
15         self.data = data
16
17     def get_text(self, location=None):
18         substitutions = self.data.copy()
19
20         if 'direction' in self.data:
21             substitutions['rowcol'] = {
22                 'NORTH': 'column',
23                 'SOUTH': 'column',
24                 'EAST': 'row',
25                 'WEST': 'row',
26             }[self.data['direction']]
27
28         if 'chesspiece' in self.data:
29             substitutions['chesspiece_name'] = self.data['chesspiece'].lower()
30
31         if location is None:
32             substitutions['location_bits'] = 'bits specified by this location'
33         else:
34             substitutions['location_bits'] = bit_glyphs(
35                 location.bitwise_operand)
36
37         return self.TEXT % substitutions
38
39     def check_available(self, player):
40         return player.bits.check_bits(self.required_bits)
41
42     def perform_action(self, board, location):
43         raise NotImplementedError(
44             "%s does not implement perform_action()." % (type(self).__name__,))
45
46     def check_and_clear_MSB(self, player):
47         if player.bits.check_bit(BITS.MSB):
48             player.bits.clear_bit(BITS.MSB)
49             return True
50         else:
51             return False
52
53     def export(self):
54         return {'required_bits': list(self.required_bits),
55                 'data': self.data,
56                 'action_class': self.__class__.__name__}
57
58
59 class DoNothing(LocationAction):
60     TEXT = "No effect."
61
62     def perform_action(self, board, location):
63         pass
64
65
66 class LoseHealthOrMSB(LocationAction):
67     TEXT = "Lose HEALTH or MSB."
68     USES_MSB = True
69
70     def perform_action(self, board, location):
71         if not self.check_and_clear_MSB(board.player):
72             board.lose_health()
73
74
75 class SetBits(LocationAction):
76     TEXT = "Set %(location_bits)s."
77
78     def perform_action(self, board, location):
79         board.player.bits.set_bits(location.bitwise_operand)
80
81
82 class ToggleBits(LocationAction):
83     TEXT = "Toggle %(location_bits)s."
84
85     def perform_action(self, board, location):
86         board.player.bits.toggle_bits(location.bitwise_operand)
87
88
89 class LoseHealthOrMSBAndSetBits(LocationAction):
90     TEXT = "Lose HEALTH or MSB, then set %(location_bits)s."
91     USES_MSB = True
92
93     def perform_action(self, board, location):
94         if not self.check_and_clear_MSB(board.player):
95             board.lose_health()
96         board.player.bits.set_bits(location.bitwise_operand)
97
98
99 class AcquireWinToken(LocationAction):
100     TEXT = "Gain WINTOKEN, then clear {RED,GREEN,BLUE}."
101
102     def perform_action(self, board, location):
103         board.acquire_win_token()
104         board.player.bits.clear_bits(set([
105             BITS.RED, BITS.GREEN, BITS.BLUE,
106         ]))
107
108
109 class GainHealthAndClearBitsOrMSB(LocationAction):
110     TEXT = "Gain HEALTH, then clear %(location_bits)s or MSB."
111     USES_MSB = True
112
113     def perform_action(self, board, location):
114         board.gain_health()
115         if not self.check_and_clear_MSB(board.player):
116             board.player.bits.clear_bits(location.bitwise_operand)
117
118
119 class ShiftLocations(LocationAction):
120     TEXT = "Shift current %(rowcol)s %(direction)s."
121
122     def perform_action(self, board, location):
123         board.shift_locations(self.data['direction'])
124
125
126 class AllowChessMove(LocationAction):
127     TEXT = "Move like a %(chesspiece_name)s for one turn."
128
129     def perform_action(self, board, location):
130         if self.data['chesspiece'] in CHESS_PIECES:
131             chesspiece = CHESS_PIECES[self.data['chesspiece']]
132             board.allow_chess_move(chesspiece)