home · contact · privacy
Refactor.
[plomrogue2-experiments] / server_ / game.py
1 import sys
2 sys.path.append('../')
3 import game_common
4
5
6 class GameError(Exception):
7     pass
8
9
10 def move_pos(direction, pos_yx):
11     if direction == 'UP':
12         pos_yx[0] -= 1
13     elif direction == 'DOWN':
14         pos_yx[0] += 1
15     elif direction == 'RIGHT':
16         pos_yx[1] += 1
17     elif direction == 'LEFT':
18         pos_yx[1] -= 1
19
20
21 class World(game_common.World):
22
23     def __init__(self):
24         super().__init__()
25         self.Thing = Thing  # use local Thing class instead of game_common's
26         self.player_id = 0
27
28     def proceed_to_next_player_turn(self):
29         """Run game world turns until player can decide their next step.
30
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.
39         """
40         while True:
41             for thing in self.things[self.player_id+1:]:
42                 thing.proceed()
43             self.turn += 1
44             for thing in self.things[:self.player_id]:
45                 thing.proceed()
46             player = self.get_thing(self.player_id)
47             player.proceed(is_AI=False)
48             if player.task is None:
49                 break
50
51
52 class Task:
53
54     def __init__(self, thing, name, args=(), kwargs={}):
55         self.name = name
56         self.thing = thing
57         self.args = args
58         self.kwargs = kwargs
59         self.todo = 1
60
61     def check(self):
62         if self.name == 'move':
63             if len(self.args) > 0:
64                 direction = self.args[0]
65             else:
66                 direction = self.kwargs['direction']
67             test_pos = self.thing.position[:]
68             move_pos(direction, test_pos)
69             if test_pos[0] < 0 or test_pos[1] < 0 or \
70                test_pos[0] >= self.thing.world.map_size[0] or \
71                test_pos[1] >= self.thing.world.map_size[1]:
72                 raise GameError('would move outside map bounds')
73             pos_i = test_pos[0] * self.thing.world.map_size[1] + test_pos[1]
74             map_tile = self.thing.world.terrain_map[pos_i]
75             if map_tile != '.':
76                 raise GameError('would move into illegal terrain')
77
78
79 class Thing(game_common.Thing):
80
81     def __init__(self, *args, **kwargs):
82         super().__init__(*args, **kwargs)
83         self.task = Task(self, 'wait')
84
85     def task_wait(self):
86         pass
87
88     def task_move(self, direction):
89         move_pos(direction, self.position)
90
91     def decide_task(self):
92         if self.position[1] > 1:
93             self.set_task('move', 'LEFT')
94         elif self.position[1] < 3:
95             self.set_task('move', 'RIGHT')
96         else:
97             self.set_task('wait')
98
99     def set_task(self, task_name, *args, **kwargs):
100         self.task = Task(self, task_name, args, kwargs)
101         self.task.check()
102
103     def proceed(self, is_AI=True):
104         """Further the thing in its tasks.
105
106         Decrements .task.todo; if it thus falls to <= 0, enacts method whose
107         name is 'task_' + self.task.name and sets .task = None. If is_AI, calls
108         .decide_task to decide a self.task.
109         """
110         self.task.todo -= 1
111         if self.task.todo <= 0:
112             task = getattr(self, 'task_' + self.task.name)
113             task(*self.task.args, **self.task.kwargs)
114             self.task = None
115         if is_AI and self.task is None:
116             self.decide_task()