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)