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) |
