Saved games can now be loaded as well.
[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.widgets.save_slot import SaveSlotWidget
17 from naja.widgets.selector import SelectorWidget
18
19
20 def save_path(path):
21     return os.path.join(options.save_location, *path.split('/'))
22
23
24 def ensure_save_path_exists():
25     location = save_path('')
26     if not os.path.isdir(location):
27         os.makedirs(location)
28
29
30 class LoadSaveGameBase(Scene):
31     def __init__(self, state):
32         super(LoadSaveGameBase, self).__init__(state)
33         selector = SelectorWidget()
34         self.add(selector)
35         self.slots = {}
36
37         for slot_num in range(8):
38             slot = self.make_slot_widget(slot_num)
39             self.slots[slot_num] = slot
40             selector.add(slot)
41
42     def save_path(self, slot_num):
43         return save_path('slot_%s.json' % (slot_num,))
44
45     def get_game_data(self, slot_num):
46         try:
47             with open(self.save_path(slot_num), 'r') as save_file:
48                 return json.load(save_file)
49         except IOError:
50             return None
51         except Exception as e:
52             print "Error reading savegame in slot %s: %s" % (slot_num, e)
53             return None
54
55     def make_slot_widget(self, slot_num):
56         game_data = self.get_game_data(slot_num)
57         y_offset = 74 * slot_num
58         slot = SaveSlotWidget((100, y_offset), slot_num, game_data)
59         slot.add_callback('click', lambda event: self.perform_action(slot_num))
60         return slot
61
62     def handle_scene_event(self, ev):
63         if ev.type == pgl.KEYDOWN and ev.key in KEYS.QUIT:
64             from naja.scenes.menu import MenuScene
65             SceneChangeEvent.post(MenuScene)
66             return
67
68     def perform_action(self, slot_num):
69         raise NotImplementedError("Nothing to see here.")
70
71
72 class SaveGameScene(LoadSaveGameBase):
73     def perform_action(self, slot_num):
74         save_data = {
75             'timestamp': datetime.now().ctime(),
76             'data': self.state.gameboard.export(),
77         }
78         try:
79             ensure_save_path_exists()
80             with open(self.save_path(slot_num), 'w') as save_file:
81                 json.dump(save_data, save_file)
82         except Exception as e:
83             print "Error saving game in slot %s: %s" % (slot_num, e)
84         self.slots[slot_num].game_data = self.get_game_data(slot_num)
85         InvalidateTheWorld.post()
86
87
88 class LoadGameScene(LoadSaveGameBase):
89     def perform_action(self, slot_num):
90         game_data = self.get_game_data(slot_num)
91         state = GameState(game_data['data'])
92         if game_data is not None:
93             LoadGameEvent.post(state)