7 class GameError(Exception):
11 def move_pos(direction, pos_yx):
14 elif direction == 'DOWN':
16 elif direction == 'RIGHT':
18 elif direction == 'LEFT':
22 class World(game_common.World):
26 self.Thing = Thing # use local Thing class instead of game_common's
29 def proceed_to_next_player_turn(self):
30 """Run game world turns until player can decide their next step.
32 Iterates through all non-player things, on each step
33 furthering them in their tasks (and letting them decide new
34 ones if they finish). The iteration order is: first all things
35 that come after the player in the world things list, then
36 (after incrementing the world turn) all that come before the
37 player; then the player's .proceed() is run, and if it does
38 not finish his task, the loop starts at the beginning. Once
39 the player's task is finished, the loop breaks.
42 player = self.get_player()
43 player_i = self.things.index(player)
44 for thing in self.things[player_i+1:]:
47 for thing in self.things[:player_i]:
49 player.proceed(is_AI=False)
50 if player.task is None:
54 return self.get_thing(self.player_id)
59 def __init__(self, thing, name, args=(), kwargs={}):
67 if self.name == 'move':
68 if len(self.args) > 0:
69 direction = self.args[0]
71 direction = self.kwargs['direction']
72 test_pos = self.thing.position[:]
73 move_pos(direction, test_pos)
74 if test_pos[0] < 0 or test_pos[1] < 0 or \
75 test_pos[0] >= self.thing.world.map_size[0] or \
76 test_pos[1] >= self.thing.world.map_size[1]:
77 raise GameError('would move outside map bounds')
78 pos_i = test_pos[0] * self.thing.world.map_size[1] + test_pos[1]
79 map_tile = self.thing.world.terrain_map[pos_i]
81 raise GameError('would move into illegal terrain')
84 class Thing(game_common.Thing):
86 def __init__(self, *args, **kwargs):
87 super().__init__(*args, **kwargs)
88 self.task = Task(self, 'wait')
89 self.last_task_result = None
94 def task_move(self, direction):
95 move_pos(direction, self.position)
98 def decide_task(self):
99 if self.position[1] > 1:
100 self.set_task('move', 'LEFT')
101 elif self.position[1] < 3:
102 self.set_task('move', 'RIGHT')
104 self.set_task('wait')
106 def set_task(self, task_name, *args, **kwargs):
107 self.task = Task(self, task_name, args, kwargs)
110 def proceed(self, is_AI=True):
111 """Further the thing in its tasks.
113 Decrements .task.todo; if it thus falls to <= 0, enacts method whose
114 name is 'task_' + self.task.name and sets .task = None. If is_AI, calls
115 .decide_task to decide a self.task.
117 Before doing anything, checks that task is still possible, and aborts
118 it otherwise (for AI things, decides a new task).
122 except GameError as e:
124 self.last_task_result = e
129 if self.task.todo <= 0:
130 task = getattr(self, 'task_' + self.task.name)
131 self.last_task_result = task(*self.task.args, **self.task.kwargs)
133 if is_AI and self.task is None:
139 def cmd_MOVE(self, direction):
140 """Set player task to 'move' with direction arg, finish player turn."""
141 if direction not in {'UP', 'DOWN', 'RIGHT', 'LEFT'}:
142 raise parser.ArgError('Move argument must be one of: '
143 'UP, DOWN, RIGHT, LEFT')
144 self.world.get_player().set_task('move', direction=direction)
146 cmd_MOVE.argtypes = 'string'
149 """Set player task to 'wait', finish player turn."""
150 self.world.get_player().set_task('wait')
153 def cmd_GET_TURN(self, connection_id):
154 """Send world.turn to caller."""
155 self.send_to(connection_id, str(self.world.turn))
157 def cmd_ECHO(self, msg, connection_id):
158 """Send msg to caller."""
159 self.send_to(connection_id, msg)
160 cmd_ECHO.argtypes = 'string'
162 def cmd_ALL(self, msg, connection_id):
163 """Send msg to all clients."""
165 cmd_ALL.argtypes = 'string'