4bdd71b2bf48f9ac717a9c16c05ea74d34faa46c
[naja.git] / naja / scenes / load_save.py
1 """
2 Load and save scenes.
3 """
4
5 import json
6 import os
7 from datetime import datetime
8
9 import pygame.locals as pgl
10
11 from naja.constants import KEYS
12 from naja.events import SceneChangeEvent, InvalidateTheWorld, LoadGameEvent
13 from naja.gamestate import GameState
14 from naja.options import options
15 from naja.scenes.scene import Scene
16 from naja.sound import sound
17 from naja.widgets.save_slot import SaveSlotWidget
18 from naja.widgets.selector import SelectorWidget
19
20
21 def save_path(path):
22     return os.path.join(options.save_location, *path.split('/'))
23
24
25 def ensure_save_path_exists():
26     location = save_path('')
27     if not os.path.isdir(location):
28         os.makedirs(location)
29
30
31 class LoadSaveGameBase(Scene):
32     def __init__(self, state):
33         super(LoadSaveGameBase, self).__init__(state)
34         selector = SelectorWidget()
35         self.add(selector)
36         self.slots = {}
37
38         for slot_num in range(8):
39             slot = self.make_slot_widget(slot_num)
40             self.slots[slot_num] = slot
41             selector.add(slot)
42
43     def save_path(self, slot_num):
44         return save_path('slot_%s.json' % (slot_num,))
45
46     def get_game_data(self, slot_num):
47         try:
48             with open(self.save_path(slot_num), 'r') as save_file:
49                 return json.load(save_file)
50         except IOError:
51             return None
52         except Exception as e:
53             print "Error reading savegame in slot %s: %s" % (slot_num, e)
54             return None
55
56     def make_slot_widget(self, slot_num):
57         game_data = self.get_game_data(slot_num)
58         y_offset = 74 * slot_num
59         slot = SaveSlotWidget((100, y_offset), slot_num, game_data)
60         slot.add_callback('click', lambda event: self.perform_action(slot_num))
61         return slot
62
63     def handle_scene_event(self, ev):
64         if ev.type == pgl.KEYDOWN and ev.key in KEYS.QUIT:
65             from naja.scenes.menu import MenuScene
66             SceneChangeEvent.post(MenuScene)
67             return
68
69     def fail(self):
70         sound.play_sound('error.ogg')
71         InvalidateTheWorld.post()
72
73     def succeed(self):
74         raise NotImplementedError("Success not implemented.")
75         from naja.scenes.menu import MenuScene
76         sound.play_sound('chirp.ogg', volume=0.5)
77         SceneChangeEvent.post(MenuScene)
78
79     def perform_action(self, slot_num):
80         raise NotImplementedError("Nothing to see here.")
81
82
83 class SaveGameScene(LoadSaveGameBase):
84     def perform_action(self, slot_num):
85         save_data = {
86             'timestamp': datetime.now().ctime(),
87             'data': self.state.gameboard.export(),
88         }
89         try:
90             ensure_save_path_exists()
91             with open(self.save_path(slot_num), 'w') as save_file:
92                 json.dump(save_data, save_file)
93         except Exception as e:
94             print "Error saving game in slot %s: %s" % (slot_num, e)
95             self.fail()
96         else:
97             self.succeed()
98
99     def succeed(self):
100         from naja.scenes.menu import MenuScene
101         sound.play_sound('chirp.ogg', volume=0.5)
102         SceneChangeEvent.post(MenuScene)
103
104
105 class LoadGameScene(LoadSaveGameBase):
106     def perform_action(self, slot_num):
107         game_data = self.get_game_data(slot_num)
108         if game_data is not None:
109             state = GameState.load(game_data['data'])
110             LoadGameEvent.post(state)
111             self.succeed()
112         else:
113             self.fail()
114
115     def succeed(self):
116         from naja.scenes.game import GameScene
117         sound.play_sound('chirp.ogg', volume=0.5)
118         SceneChangeEvent.post(GameScene)