Mercurial > touhou
comparison eosd @ 416:e23871eddb7a
Importing everything makes the --help slow, call parse_args before the imports.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 16 Jul 2013 21:13:56 +0200 |
parents | 236bc32597f1 |
children | b1248bab2d0f |
comparison
equal
deleted
inserted
replaced
415:236bc32597f1 | 416:e23871eddb7a |
---|---|
13 ## GNU General Public License for more details. | 13 ## GNU General Public License for more details. |
14 ## | 14 ## |
15 | 15 |
16 import argparse | 16 import argparse |
17 import os | 17 import os |
18 import sys | |
19 import logging | |
20 | |
21 import pyximport | |
22 pyximport.install() | |
23 | |
24 from pytouhou.resource.loader import Loader | |
25 from pytouhou.game.background import Background | |
26 from pytouhou.ui.gamerunner import GameRunner | |
27 from pytouhou.games.eosd import EoSDGame | |
28 from pytouhou.game.game import GameOver | |
29 from pytouhou.game.player import PlayerState | |
30 from pytouhou.formats.t6rp import T6RP, Level | |
31 from pytouhou.utils.random import Random | |
32 from pytouhou.vm.msgrunner import NextStage | |
33 from pytouhou.formats.hint import Hint | |
34 | |
35 | |
36 class EoSDGameBossRush(EoSDGame): | |
37 def run_iter(self, keystate): | |
38 for i in range(20): | |
39 skip = not (self.enemies or self.items or self.lasers | |
40 or self.bullets or self.cancelled_bullets) | |
41 if skip: | |
42 keystate &= ~1 | |
43 EoSDGame.run_iter(self, keystate | 256 if i == 0 else 0) | |
44 if not self.enemies and self.frame % 90 == 0: | |
45 for player in self.players: | |
46 if player.state.power < 128: | |
47 player.state.power += 1 | |
48 if not skip: | |
49 break | |
50 | |
51 | |
52 def cleanup(self): | |
53 boss_wait = any(ecl_runner.boss_wait for ecl_runner in self.ecl_runners) | |
54 if not (self.boss or self.msg_wait or boss_wait): | |
55 self.enemies = [enemy for enemy in self.enemies | |
56 if enemy.boss_callback != -1 or enemy.frame > 1] | |
57 self.lasers = [laser for laser in self.lasers if laser.frame > 1] | |
58 self.effects = [effect for effect in self.effects | |
59 if not hasattr(effect, '_laser') | |
60 or effect._laser in self.lasers] | |
61 self.bullets = [bullet for bullet in self.bullets if bullet.frame > 1] | |
62 EoSDGame.cleanup(self) | |
63 | |
64 | |
65 | |
66 def main(path, data, stage_num, rank, character, replay, save_filename, | |
67 skip_replay, boss_rush, fps_limit, single_buffer, debug, | |
68 fixed_pipeline, display_background, display_particles, hints, | |
69 verbosity): | |
70 | |
71 resource_loader = Loader(path) | |
72 | |
73 try: | |
74 resource_loader.scan_archives(data) | |
75 except IOError: | |
76 sys.stderr.write('Some data files were not found, did you forget the -p option?\n') | |
77 exit(1) | |
78 | |
79 if stage_num is None: | |
80 story = True | |
81 stage_num = 1 | |
82 continues = 3 | |
83 else: | |
84 story = False | |
85 continues = 0 | |
86 | |
87 if debug: | |
88 if not verbosity: | |
89 verbosity = 'DEBUG' | |
90 continues = float('inf') | |
91 | |
92 if verbosity: | |
93 logging.basicConfig(level=logging.__getattribute__(verbosity)) | |
94 | |
95 if replay: | |
96 with open(replay, 'rb') as file: | |
97 replay = T6RP.read(file) | |
98 rank = replay.rank | |
99 character = replay.character | |
100 | |
101 save_keystates = None | |
102 if save_filename: | |
103 save_replay = T6RP() | |
104 save_replay.rank = rank | |
105 save_replay.character = character | |
106 | |
107 if hints: | |
108 with open(hints, 'rb') as file: | |
109 hints = Hint.read(file) | |
110 | |
111 difficulty = 16 | |
112 default_power = [0, 64, 128, 128, 128, 128, 0][stage_num - 1] | |
113 states = [PlayerState(character=character, power=default_power)] | |
114 | |
115 game_class = EoSDGameBossRush if boss_rush else EoSDGame | |
116 | |
117 runner = GameRunner(resource_loader, fps_limit=fps_limit, double_buffer=(not single_buffer), fixed_pipeline=fixed_pipeline, skip=skip_replay) | |
118 while True: | |
119 if replay: | |
120 level = replay.levels[stage_num - 1] | |
121 if not level: | |
122 raise Exception | |
123 | |
124 prng = Random(level.random_seed) | |
125 | |
126 #TODO: apply the replay to the other players. | |
127 #TODO: see if the stored score is used or if it’s the one from the previous stage. | |
128 if stage_num != 1 and stage_num - 2 in replay.levels: | |
129 previous_level = replay.levels[stage_num - 1] | |
130 states[0].score = previous_level.score | |
131 states[0].effective_score = previous_level.score | |
132 states[0].point_items = level.point_items | |
133 states[0].power = level.power | |
134 states[0].lives = level.lives | |
135 states[0].bombs = level.bombs | |
136 difficulty = level.difficulty | |
137 else: | |
138 prng = Random() | |
139 | |
140 if save_filename: | |
141 if not replay: | |
142 save_replay.levels[stage_num - 1] = level = Level() | |
143 level.score = states[0].score | |
144 level.random_seed = prng.seed | |
145 level.point_items = states[0].points | |
146 level.power = states[0].power | |
147 level.lives = states[0].lives | |
148 level.bombs = states[0].bombs | |
149 level.difficulty = difficulty | |
150 save_keystates = [] | |
151 | |
152 hints_stage = hints.stages[stage_num - 1] if hints else None | |
153 | |
154 # Load stage data | |
155 stage = resource_loader.get_stage('stage%d.std' % stage_num) | |
156 | |
157 game = game_class(resource_loader, states, stage_num, rank, difficulty, prng=prng, continues=continues, hints=hints_stage) | |
158 | |
159 if not display_particles: | |
160 def new_particle(pos, anim, amp, number=1, reverse=False, duration=24): | |
161 pass | |
162 game.new_particle = new_particle | |
163 | |
164 if display_background: | |
165 background_anm_wrapper = resource_loader.get_anm_wrapper(('stg%dbg.anm' % stage_num,)) | |
166 background = Background(stage, background_anm_wrapper) | |
167 else: | |
168 background = None | |
169 | |
170 # Main loop | |
171 runner.load_game(game, background, stage.bgms, replay, save_keystates) | |
172 try: | |
173 runner.start() | |
174 break | |
175 except NextStage: | |
176 game.music.pause() | |
177 if not story or stage_num == (7 if boss_rush else 6 if rank > 0 else 5): | |
178 break | |
179 stage_num += 1 | |
180 states = [player.state.copy() for player in game.players] # if player.state.lives >= 0] | |
181 except GameOver: | |
182 print('Game over') | |
183 break | |
184 finally: | |
185 if save_filename: | |
186 last_key = -1 | |
187 for time, key in enumerate(save_keystates): | |
188 if key != last_key: | |
189 level.keys.append((time, key, 0)) | |
190 last_key = key | |
191 | |
192 if save_filename: | |
193 with open(save_filename, 'wb+') as file: | |
194 save_replay.write(file) | |
195 | 18 |
196 | 19 |
197 pathsep = os.path.pathsep | 20 pathsep = os.path.pathsep |
198 default_data = (pathsep.join(('CM.DAT', 'th06*_CM.DAT', '*CM.DAT', '*cm.dat')), | 21 default_data = (pathsep.join(('CM.DAT', 'th06*_CM.DAT', '*CM.DAT', '*cm.dat')), |
199 pathsep.join(('ST.DAT', 'th6*ST.DAT', '*ST.DAT', '*st.dat')), | 22 pathsep.join(('ST.DAT', 'th6*ST.DAT', '*ST.DAT', '*st.dat')), |
222 parser.add_argument('--hints', metavar='HINTS', default=None, help='Hints file, to display text while playing.') | 45 parser.add_argument('--hints', metavar='HINTS', default=None, help='Hints file, to display text while playing.') |
223 parser.add_argument('--verbosity', metavar='VERBOSITY', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], help='Select the wanted logging level.') | 46 parser.add_argument('--verbosity', metavar='VERBOSITY', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], help='Select the wanted logging level.') |
224 | 47 |
225 args = parser.parse_args() | 48 args = parser.parse_args() |
226 | 49 |
50 | |
51 import sys | |
52 import logging | |
53 | |
54 import pyximport | |
55 pyximport.install() | |
56 | |
57 from pytouhou.resource.loader import Loader | |
58 from pytouhou.game.background import Background | |
59 from pytouhou.ui.gamerunner import GameRunner | |
60 from pytouhou.games.eosd import EoSDGame | |
61 from pytouhou.game.game import GameOver | |
62 from pytouhou.game.player import PlayerState | |
63 from pytouhou.formats.t6rp import T6RP, Level | |
64 from pytouhou.utils.random import Random | |
65 from pytouhou.vm.msgrunner import NextStage | |
66 from pytouhou.formats.hint import Hint | |
67 | |
68 | |
69 class EoSDGameBossRush(EoSDGame): | |
70 def run_iter(self, keystate): | |
71 for i in range(20): | |
72 skip = not (self.enemies or self.items or self.lasers | |
73 or self.bullets or self.cancelled_bullets) | |
74 if skip: | |
75 keystate &= ~1 | |
76 EoSDGame.run_iter(self, keystate | 256 if i == 0 else 0) | |
77 if not self.enemies and self.frame % 90 == 0: | |
78 for player in self.players: | |
79 if player.state.power < 128: | |
80 player.state.power += 1 | |
81 if not skip: | |
82 break | |
83 | |
84 def cleanup(self): | |
85 boss_wait = any(ecl_runner.boss_wait for ecl_runner in self.ecl_runners) | |
86 if not (self.boss or self.msg_wait or boss_wait): | |
87 self.enemies = [enemy for enemy in self.enemies | |
88 if enemy.boss_callback != -1 or enemy.frame > 1] | |
89 self.lasers = [laser for laser in self.lasers if laser.frame > 1] | |
90 self.effects = [effect for effect in self.effects | |
91 if not hasattr(effect, '_laser') | |
92 or effect._laser in self.lasers] | |
93 self.bullets = [bullet for bullet in self.bullets if bullet.frame > 1] | |
94 EoSDGame.cleanup(self) | |
95 | |
96 | |
97 def main(path, data, stage_num, rank, character, replay, save_filename, | |
98 skip_replay, boss_rush, fps_limit, single_buffer, debug, | |
99 fixed_pipeline, display_background, display_particles, hints, | |
100 verbosity): | |
101 | |
102 resource_loader = Loader(path) | |
103 | |
104 try: | |
105 resource_loader.scan_archives(data) | |
106 except IOError: | |
107 sys.stderr.write('Some data files were not found, did you forget the -p option?\n') | |
108 exit(1) | |
109 | |
110 if stage_num is None: | |
111 story = True | |
112 stage_num = 1 | |
113 continues = 3 | |
114 else: | |
115 story = False | |
116 continues = 0 | |
117 | |
118 if debug: | |
119 if not verbosity: | |
120 verbosity = 'DEBUG' | |
121 continues = float('inf') | |
122 | |
123 if verbosity: | |
124 logging.basicConfig(level=logging.__getattribute__(verbosity)) | |
125 | |
126 if replay: | |
127 with open(replay, 'rb') as file: | |
128 replay = T6RP.read(file) | |
129 rank = replay.rank | |
130 character = replay.character | |
131 | |
132 save_keystates = None | |
133 if save_filename: | |
134 save_replay = T6RP() | |
135 save_replay.rank = rank | |
136 save_replay.character = character | |
137 | |
138 if hints: | |
139 with open(hints, 'rb') as file: | |
140 hints = Hint.read(file) | |
141 | |
142 difficulty = 16 | |
143 default_power = [0, 64, 128, 128, 128, 128, 0][stage_num - 1] | |
144 states = [PlayerState(character=character, power=default_power)] | |
145 | |
146 game_class = EoSDGameBossRush if boss_rush else EoSDGame | |
147 | |
148 runner = GameRunner(resource_loader, fps_limit=fps_limit, double_buffer=(not single_buffer), fixed_pipeline=fixed_pipeline, skip=skip_replay) | |
149 while True: | |
150 if replay: | |
151 level = replay.levels[stage_num - 1] | |
152 if not level: | |
153 raise Exception | |
154 | |
155 prng = Random(level.random_seed) | |
156 | |
157 #TODO: apply the replay to the other players. | |
158 #TODO: see if the stored score is used or if it’s the one from the previous stage. | |
159 if stage_num != 1 and stage_num - 2 in replay.levels: | |
160 previous_level = replay.levels[stage_num - 1] | |
161 states[0].score = previous_level.score | |
162 states[0].effective_score = previous_level.score | |
163 states[0].point_items = level.point_items | |
164 states[0].power = level.power | |
165 states[0].lives = level.lives | |
166 states[0].bombs = level.bombs | |
167 difficulty = level.difficulty | |
168 else: | |
169 prng = Random() | |
170 | |
171 if save_filename: | |
172 if not replay: | |
173 save_replay.levels[stage_num - 1] = level = Level() | |
174 level.score = states[0].score | |
175 level.random_seed = prng.seed | |
176 level.point_items = states[0].points | |
177 level.power = states[0].power | |
178 level.lives = states[0].lives | |
179 level.bombs = states[0].bombs | |
180 level.difficulty = difficulty | |
181 save_keystates = [] | |
182 | |
183 hints_stage = hints.stages[stage_num - 1] if hints else None | |
184 | |
185 # Load stage data | |
186 stage = resource_loader.get_stage('stage%d.std' % stage_num) | |
187 | |
188 game = game_class(resource_loader, states, stage_num, rank, difficulty, prng=prng, continues=continues, hints=hints_stage) | |
189 | |
190 if not display_particles: | |
191 def new_particle(pos, anim, amp, number=1, reverse=False, duration=24): | |
192 pass | |
193 game.new_particle = new_particle | |
194 | |
195 if display_background: | |
196 background_anm_wrapper = resource_loader.get_anm_wrapper(('stg%dbg.anm' % stage_num,)) | |
197 background = Background(stage, background_anm_wrapper) | |
198 else: | |
199 background = None | |
200 | |
201 # Main loop | |
202 runner.load_game(game, background, stage.bgms, replay, save_keystates) | |
203 try: | |
204 runner.start() | |
205 break | |
206 except NextStage: | |
207 game.music.pause() | |
208 if not story or stage_num == (7 if boss_rush else 6 if rank > 0 else 5): | |
209 break | |
210 stage_num += 1 | |
211 states = [player.state.copy() for player in game.players] # if player.state.lives >= 0] | |
212 except GameOver: | |
213 print('Game over') | |
214 break | |
215 finally: | |
216 if save_filename: | |
217 last_key = -1 | |
218 for time, key in enumerate(save_keystates): | |
219 if key != last_key: | |
220 level.keys.append((time, key, 0)) | |
221 last_key = key | |
222 | |
223 if save_filename: | |
224 with open(save_filename, 'wb+') as file: | |
225 save_replay.write(file) | |
226 | |
227 | |
227 main(args.path, tuple(args.data), args.stage, args.rank, args.character, | 228 main(args.path, tuple(args.data), args.stage, args.rank, args.character, |
228 args.replay, args.save_replay, args.skip_replay, args.boss_rush, | 229 args.replay, args.save_replay, args.skip_replay, args.boss_rush, |
229 args.fps_limit, args.single_buffer, args.debug, args.fixed_pipeline, | 230 args.fps_limit, args.single_buffer, args.debug, args.fixed_pipeline, |
230 args.no_background, args.no_particles, args.hints, args.verbosity) | 231 args.no_background, args.no_particles, args.hints, args.verbosity) |