6 class GameError(Exception):
10 def move_pos(direction, pos_yx):
13 elif direction == 'DOWN':
15 elif direction == 'RIGHT':
17 elif direction == 'LEFT':
21 class World(game_common.World):
25 self.Thing = Thing # use local Thing class instead of game_common's
28 def proceed_to_next_player_turn(self):
29 """Run game world turns until player can decide their next step.
31 Iterates through all non-player things, on each step
32 furthering them in their tasks (and letting them decide new
33 ones if they finish). The iteration order is: first all things
34 that come after the player in the world things list, then
35 (after incrementing the world turn) all that come before the
36 player; then the player's .proceed() is run, and if it does
37 not finish his task, the loop starts at the beginning. Once
38 the player's task is finished, the loop breaks.
41 player = self.get_player()
42 player_i = self.things.index(player)
43 for thing in self.things[player_i+1:]:
46 for thing in self.things[:player_i]:
48 player.proceed(is_AI=False)
49 if player.task is None:
53 return self.get_thing(self.player_id)
58 def __init__(self, thing, name, args=(), kwargs={}):
66 if self.name == 'move':
67 if len(self.args) > 0:
68 direction = self.args[0]
70 direction = self.kwargs['direction']
71 test_pos = self.thing.position[:]
72 move_pos(direction, test_pos)
73 if test_pos[0] < 0 or test_pos[1] < 0 or \
74 test_pos[0] >= self.thing.world.map_size[0] or \
75 test_pos[1] >= self.thing.world.map_size[1]:
76 raise GameError('would move outside map bounds')
77 pos_i = test_pos[0] * self.thing.world.map_size[1] + test_pos[1]
78 map_tile = self.thing.world.terrain_map[pos_i]
80 raise GameError('would move into illegal terrain')
83 class Thing(game_common.Thing):
85 def __init__(self, *args, **kwargs):
86 super().__init__(*args, **kwargs)
87 self.task = Task(self, 'wait')
92 def task_move(self, direction):
93 move_pos(direction, self.position)
95 def decide_task(self):
96 if self.position[1] > 1:
97 self.set_task('move', 'LEFT')
98 elif self.position[1] < 3:
99 self.set_task('move', 'RIGHT')
101 self.set_task('wait')
103 def set_task(self, task_name, *args, **kwargs):
104 self.task = Task(self, task_name, args, kwargs)
107 def proceed(self, is_AI=True):
108 """Further the thing in its tasks.
110 Decrements .task.todo; if it thus falls to <= 0, enacts method whose
111 name is 'task_' + self.task.name and sets .task = None. If is_AI, calls
112 .decide_task to decide a self.task.
114 Before doing anything, checks that task is still possible, and aborts
115 it otherwise (for AI things, decides a new task).
125 if self.task.todo <= 0:
126 task = getattr(self, 'task_' + self.task.name)
127 task(*self.task.args, **self.task.kwargs)
129 if is_AI and self.task is None:
135 def cmd_MOVE(self, direction):
136 """Set player task to 'move' with direction arg, finish player turn."""
137 if direction not in {'UP', 'DOWN', 'RIGHT', 'LEFT'}:
138 raise parser.ArgError('Move argument must be one of: '
139 'UP, DOWN, RIGHT, LEFT')
140 self.world.get_player().set_task('move', direction=direction)
142 cmd_MOVE.argtypes = 'string'
145 """Set player task to 'wait', finish player turn."""
146 self.world.get_player().set_task('wait')
149 def cmd_GET_TURN(self, connection_id):
150 """Send world.turn to caller."""
151 self.send_to(connection_id, str(self.world.turn))
153 def cmd_ECHO(self, msg, connection_id):
154 """Send msg to caller."""
155 self.send_to(connection_id, msg)
156 cmd_ECHO.argtypes = 'string'
158 def cmd_ALL(self, msg, connection_id):
159 """Send msg to all clients."""
161 cmd_ALL.argtypes = 'string'