1 (north
, south
, east
, west
) = range(4)
2 border_names
= ("north", "south", "east", "west")
3 special_keys
= ("encounter_frequency", "encounter_delay", "encounter_min_level", "encounter_max_level", "encounter_min_critters", "encounter_max_critters", "critter_types", "tileset")
5 from shop
import make_shop
6 from random
import randint
7 from battle
import simple_battle
10 class MapException(Exception):
13 class game_map(object):
14 def __init__(self
, name
, map_lines
):
20 (ascii_art
, key
) = range(2)
24 for line
in map_lines
:
27 if len(line
) == 0 or line
[0] == "'":
28 #Comment or blank line. Ignore it.
31 if phase
!= ascii_art
:
32 raise MapException("Error in processing map %s: non-key line %d found after start of key." % (name
, line_num
))
33 self
.game_map
.append(line
)
36 (key
, value_unsplit
) = line
.split(':')
37 value
= value_unsplit
.split()
38 self
.map_key
[key
] = value
40 def is_tile(self
, key
):
41 return hasattr(tiles
, key
)
43 def get_tile_class(self
, key
):
44 return getattr(tiles
, key
)
46 def is_game_map(self
, key
):
47 return key
in self
.maps
.keys()
49 def get_game_map(self
, key
):
52 def make_tile(self
, char
, pos
):
53 tile_key
= self
.map_key
[char
][0]
54 tile_args
= self
.map_key
[char
][1:]
55 if self
.is_tile(tile_key
):
56 tile_class
= self
.get_tile_class(tile_key
)
57 return tile_class((self
, pos
), *tile_args
)
58 elif self
.is_game_map(tile_key
):
59 game_map
= self
.get_game_map(tile_key
)
60 return tiles
.map_tile((self
, pos
), game_map
, *tile_args
)
62 raise MapException("No tile or map named %s. (Used by symbol %s in map %s)" % (tile_key
, char
, self
.name
))
64 def validate(self
, maps
):
65 # We'll need this later.
68 # Look for bad characters, collect all starting positions, and initialize
72 for row_num
in range(len(self
.game_map
)):
73 row
= self
.game_map
[row_num
]
75 max_row_length
= max(row_len
, max_row_len
)
76 self
.tiles
.append([None]*row_len
)
77 for char_num
in range(row_len
):
79 if char
not in self
.map_key
.keys():
80 message
= "Error in processing map %s: Character missing from key. Line %d:\n" % (self
.name
, row_num
+ 1)
82 message
+= (" " * char_num
) + "^"
83 raise MapException(message
)
84 if self
.map_key
[char
][0] in ("start", "start_and_movement_tutorial"):
85 starts
.append([row_num
, char_num
])
86 self
.tiles
[row_num
][char_num
] = self
.make_tile(char
, (row_num
, char_num
))
88 self
.borders
= [None] * 4
89 for border
in range(4):
90 key
= "border_" + border_names
[border
]
91 self
.borders
[border
] = self
.make_tile(key
, (-1, border
))
93 # More than one start point is fatal, 0 is bad but non-fatal.
94 # If there is one, that's the starting position until set differently.
96 raise MapException("More than one start point in map %s." % self
.name
)
97 elif len(starts
) == 0:
98 print "Warning, map %s has no start point." % self
.name
101 self
.start
= starts
[0]
102 self
.pos
= self
.start
104 # Each value in the map key should be either a function or map. If neither,
105 # that's a fatal error.
106 for key
in self
.map_key
.keys():
107 if key
in special_keys
:
109 value
= self
.map_key
[key
][0]
110 if not hasattr(tiles
, value
):
111 if value
not in maps
.keys():
112 raise MapException("No tile or map named %s. (Used by symbol %s in map %s)" % (value
, key
, self
.name
))
114 def go(self
, direction
):
117 newpos
= [p
for p
in pos
]
118 if direction
== north
:
120 elif direction
== south
:
122 elif direction
== west
:
124 elif direction
== east
:
126 return self
.go_tile_at(newpos
)
128 def go_tile_at(self
, pos
):
129 tile
= self
.get_tile(pos
)
131 # Check to see if we moved.
132 moved
= tile
.passable()
134 # If we moved, update self.pos.
135 if (moved
== True) and (self
.border(pos
) == None):
137 # Passable returns "None" when the player is transported off the map.
138 # So we reset the position on this map.
140 self
.pos
= self
.start
142 # Do the tile's action regardless.
146 def border(self
, pos
):
148 # Return the appropriate border if it's beyond the edge of the map.
153 elif row
>= len(self
.tiles
):
155 elif char
>= len(self
.tiles
[row
]):
160 def get_tile(self
, pos
):
163 border
= self
.border(pos
)
165 return self
.tiles
[row
][char
]
167 return self
.borders
[border
]
170 return hasattr(self
.get_tile(self
.pos
), "shop")
172 def enter_shop(self
):
173 if not self
.is_shop():
177 shop
= self
.get_tile(self
.pos
).shop
180 self
.game
.ui
.shop_mode(shop
)
182 def hp_mp_ticks(self
):
183 party
= self
.game
.party
184 for i
in range(len(party
.chars
)):
185 self
.game
.ui
.hp_tick(i
, party
.chars
[i
].hp_tick())
186 self
.game
.ui
.mp_tick(i
, party
.chars
[i
].mp_tick())
188 def get_window(self
):
189 '''Returns a grid of tiles, centered on the player's location.'''
190 (row
, col
) = self
.pos
191 if "window_size" in self
.map_key
.keys():
192 window_size
= int(self
.map_key
["window_size"])
195 rowrange
= range(row
- window_size
, row
+ window_size
+ 1)
196 colrange
= range(col
- window_size
, col
+ window_size
+ 1)
198 window
= tuple(tuple(self
.get_tile((r
, c
)) for c
in colrange
) for r
in rowrange
)
201 def make_make_map(maps_file
, maps_dict
):
202 from os
.path
import dirname
, abspath
, join
203 directory
= dirname(abspath(maps_file
))
204 def make_map(map_name
):
205 map_file
= open(join(directory
, map_name
+ ".map"))
206 the_map
= game_map(map_name
, map_file
.readlines())
207 maps_dict
[map_name
] = the_map