ifmapper 1.0.0 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. data/HISTORY.txt +648 -627
  2. data/IFMapper.gemspec +29 -28
  3. data/IFMapper.rbw +31 -31
  4. data/TODO.txt +8 -7
  5. data/bin/IFMapper +31 -31
  6. data/docs/en/index.html +0 -0
  7. data/docs/en/start.html +3 -2
  8. data/docs/en/start.html~ +516 -0
  9. data/docs/es/index.html +0 -0
  10. data/docs/es/start.html +13 -14
  11. data/docs/es/start.html~ +1280 -0
  12. data/docs/images/IFMapper_main.gif +0 -0
  13. data/docs/images/automap.gif +0 -0
  14. data/docs/images/complex_connection.gif +0 -0
  15. data/docs/images/connection.gif +0 -0
  16. data/docs/images/connection_menu.gif +0 -0
  17. data/docs/images/room_description.gif +0 -0
  18. data/docs/images/room_small.gif +0 -0
  19. data/icons/copy.png +0 -0
  20. data/icons/cut.png +0 -0
  21. data/icons/filenew.png +0 -0
  22. data/icons/fileopen.png +0 -0
  23. data/icons/filesave.png +0 -0
  24. data/icons/filesaveas.png +0 -0
  25. data/icons/help.png +0 -0
  26. data/icons/kill.png +0 -0
  27. data/icons/nextpage.png +0 -0
  28. data/icons/paste.png +0 -0
  29. data/icons/prevpage.png +0 -0
  30. data/icons/printicon.png +0 -0
  31. data/icons/redo.png +0 -0
  32. data/icons/room_e.gif +0 -0
  33. data/icons/room_e.xpm +0 -0
  34. data/icons/room_n.gif +0 -0
  35. data/icons/room_n.xpm +0 -0
  36. data/icons/room_ne.gif +0 -0
  37. data/icons/room_ne.xpm +0 -0
  38. data/icons/room_nw.gif +0 -0
  39. data/icons/room_nw.xpm +0 -0
  40. data/icons/room_s.gif +0 -0
  41. data/icons/room_s.xpm +0 -0
  42. data/icons/room_se.gif +0 -0
  43. data/icons/room_se.xpm +0 -0
  44. data/icons/room_sw.gif +0 -0
  45. data/icons/room_sw.xpm +0 -0
  46. data/icons/room_w.gif +0 -0
  47. data/icons/room_w.xpm +0 -0
  48. data/icons/saveas.png +0 -0
  49. data/icons/undo.png +0 -0
  50. data/icons/winapp.png +0 -0
  51. data/icons/zoom.png +0 -0
  52. data/lib/IFMapper/AStar.rb +250 -250
  53. data/lib/IFMapper/Connection.rb +202 -202
  54. data/lib/IFMapper/FXAboutDialogBox.rb +32 -32
  55. data/lib/IFMapper/FXConnection.rb +364 -364
  56. data/lib/IFMapper/FXConnectionDialogBox.rb +124 -124
  57. data/lib/IFMapper/FXDCPostscript.rb +404 -404
  58. data/lib/IFMapper/FXDCPrint.rb +15 -15
  59. data/lib/IFMapper/FXItemList.rb +108 -0
  60. data/lib/IFMapper/FXMap.rb +2147 -2116
  61. data/lib/IFMapper/FXMapColorBox.rb +88 -88
  62. data/lib/IFMapper/FXMapDialogBox.rb +127 -127
  63. data/lib/IFMapper/FXMapFileDialog.rb +34 -34
  64. data/lib/IFMapper/FXMapperSettings.rb +206 -205
  65. data/lib/IFMapper/FXMapperWindow.rb +1592 -1571
  66. data/lib/IFMapper/FXPDFMapExporterOptionsDialogBox.rb +46 -0
  67. data/lib/IFMapper/FXRoom.rb +263 -263
  68. data/lib/IFMapper/FXRoomDialogBox.rb +159 -159
  69. data/lib/IFMapper/FXRoomList.rb +95 -95
  70. data/lib/IFMapper/FXSearchDialogBox.rb +51 -51
  71. data/lib/IFMapper/FXSection.rb +33 -33
  72. data/lib/IFMapper/FXSectionDialogBox.rb +38 -38
  73. data/lib/IFMapper/FXSpline.rb +52 -52
  74. data/lib/IFMapper/FXWarningBox.rb +51 -50
  75. data/lib/IFMapper/GUEReader.rb +445 -445
  76. data/lib/IFMapper/IFMReader.rb +584 -584
  77. data/lib/IFMapper/IFMWriter.rb +245 -227
  78. data/lib/IFMapper/Inform7Writer.rb +579 -573
  79. data/lib/IFMapper/InformReader.rb +478 -478
  80. data/lib/IFMapper/InformWriter.rb +364 -359
  81. data/lib/IFMapper/Map.rb +202 -200
  82. data/lib/IFMapper/MapPrinting.rb +162 -162
  83. data/lib/IFMapper/MapReader.rb +900 -900
  84. data/lib/IFMapper/PDFMapExporter.rb +526 -483
  85. data/lib/IFMapper/Room.rb +153 -151
  86. data/lib/IFMapper/Section.rb +234 -234
  87. data/lib/IFMapper/TADSReader.rb +474 -471
  88. data/lib/IFMapper/TADSWriter.rb +375 -370
  89. data/lib/IFMapper/TranscriptDialogBox.rb +0 -0
  90. data/lib/IFMapper/TranscriptReader.rb +1361 -1359
  91. data/lib/IFMapper/locales/en/Messages.rb +446 -435
  92. data/lib/IFMapper/locales/es/Messages.rb +451 -440
  93. data/lib/IFMapper/locales/es/Messages_iso-8859-1.rb +455 -440
  94. data/lib/IFMapper/locales/es/runme.sh +3 -3
  95. data/maps/A New Life.map b/data/maps/A New → Life.map +0 -0
  96. data/maps/AMFV.map +0 -0
  97. data/maps/AllRoads.map +0 -0
  98. data/maps/Aotearoa.map +0 -0
  99. data/maps/Bronze.map +0 -0
  100. data/maps/Bureaucracy.ifm +0 -0
  101. data/maps/Bureaucracy.map +0 -0
  102. data/maps/CityOfSecrets.map +0 -0
  103. data/maps/DDIV.map +0 -0
  104. data/maps/Following_A_Star.map +0 -0
  105. data/maps/Heated.map +0 -0
  106. data/maps/Heroine.map +0 -0
  107. data/maps/History Repeating.map b/data/maps/History → Repeating.map +0 -0
  108. data/maps/Hollywood_Hijinx.ifm +0 -0
  109. data/maps/Janitor.map +0 -0
  110. data/maps/Jigsaw.ifm +0 -0
  111. data/maps/Jigsaw.map +0 -0
  112. data/maps/LGOP.ifm +0 -0
  113. data/maps/Mercy.ifm +0 -0
  114. data/maps/Ninjas_Fate.map +0 -0
  115. data/maps/Pen_and_Paint.map +0 -0
  116. data/maps/Planetfall.ifm +0 -0
  117. data/maps/Planetfall.map +0 -0
  118. data/maps/Plundered_Hearts.ifm +0 -0
  119. data/maps/QuietEvening.map +0 -0
  120. data/maps/Ralph.ifm +0 -0
  121. data/maps/Reliques_of_Tolti_Alph.map +0 -0
  122. data/maps/Revolution.map +0 -0
  123. data/maps/Robots_of_Dawn.ifm +0 -0
  124. data/maps/SavoirFare.map +0 -0
  125. data/maps/Seastalker.ifm +0 -0
  126. data/maps/Seastalker.map +0 -0
  127. data/maps/Sherlock.ifm +0 -0
  128. data/maps/SoFar.ifm +0 -0
  129. data/maps/Starcross.ifm +0 -0
  130. data/maps/Suspended.ifm +0 -0
  131. data/maps/Tangle.map +0 -0
  132. data/maps/The_Lost_Sheep.map +0 -0
  133. data/maps/Unforgotten.map +0 -0
  134. data/maps/Warbler's Nest.map +0 -0
  135. data/maps/Warbler's_Nest.map +0 -0
  136. data/maps/Westminster_Abbey.map +0 -0
  137. data/maps/WinterWonderland.map +0 -0
  138. data/maps/Wishbringer.ifm +0 -0
  139. data/maps/Wishbringer2.ifm +0 -0
  140. data/maps/Zork1.ifm +0 -0
  141. data/maps/Zork2.ifm +0 -0
  142. data/maps/Zork3.ifm +0 -0
  143. data/maps/Zork_Zero.ifm +0 -0
  144. data/maps/anchor.ifm +0 -0
  145. data/maps/anchor.map +0 -0
  146. data/maps/atrox.ifm +0 -0
  147. data/maps/awaken.ifm +0 -0
  148. data/maps/babel.ifm +0 -0
  149. data/maps/balances.map +0 -0
  150. data/maps/ballerina.map +0 -0
  151. data/maps/bear.map +0 -0
  152. data/maps/bluechairs.map +0 -0
  153. data/maps/break_in.map +0 -0
  154. data/maps/bse.ifm +0 -0
  155. data/maps/building.map +0 -0
  156. data/maps/change.ifm +0 -0
  157. data/maps/christminster.map +0 -0
  158. data/maps/curses.ifm +0 -0
  159. data/maps/curves.ifm +0 -0
  160. data/maps/deadline.map +0 -0
  161. data/maps/delusions.map +0 -0
  162. data/maps/devours.map +0 -0
  163. data/maps/distress.map +0 -0
  164. data/maps/djinni.map +0 -0
  165. data/maps/dreamhold.map +0 -0
  166. data/maps/drift3.map +0 -0
  167. data/maps/eas.map +0 -0
  168. data/maps/eas2.map +0 -0
  169. data/maps/eas3.map +0 -0
  170. data/maps/edifice.ifm +0 -0
  171. data/maps/fallacy.map +0 -0
  172. data/maps/frozen.ifm +0 -0
  173. data/maps/gamlet.map +0 -0
  174. data/maps/glow.ifm +0 -0
  175. data/maps/guilty_bastards.map +0 -0
  176. data/maps/heist.map +0 -0
  177. data/maps/heroes.map +0 -0
  178. data/maps/inhumane.map +0 -0
  179. data/maps/kaged.map +0 -0
  180. data/maps/library.ifm +0 -0
  181. data/maps/lurkinghorror.map +0 -0
  182. data/maps/metamorphoses.map +0 -0
  183. data/maps/mindelec.ifm +0 -0
  184. data/maps/minster.ifm +0 -0
  185. data/maps/mite.map +0 -0
  186. data/maps/moonmist.map +0 -0
  187. data/maps/muldoon_legacy.map +0 -0
  188. data/maps/muse.ifm +0 -0
  189. data/maps/paperchase.ifm +0 -0
  190. data/maps/party.map +0 -0
  191. data/maps/pawn.map +0 -0
  192. data/maps/photograph.map +0 -0
  193. data/maps/pkgirl.map +0 -0
  194. data/maps/pytho.map +0 -0
  195. data/maps/risorgimento.map +0 -0
  196. data/maps/sherbet.map +0 -0
  197. data/maps/simple.map +0 -0
  198. data/maps/slouch.map +0 -0
  199. data/maps/space_st.ifm +0 -0
  200. data/maps/splashdown.map +0 -0
  201. data/maps/spring.map +0 -0
  202. data/maps/squarecircle.map +0 -0
  203. data/maps/stationfall.ifm +0 -0
  204. data/maps/theatre.ifm +0 -0
  205. data/maps/toonesia.ifm +0 -0
  206. data/maps/tortoise.ifm +0 -0
  207. data/maps/trinity.map +0 -0
  208. data/maps/vespers.map +0 -0
  209. data/maps/vgame.ifm +0 -0
  210. data/maps/wasp.map +0 -0
  211. data/maps/weather.ifm +0 -0
  212. data/maps/windhall.ifm +0 -0
  213. data/maps/worlds.map +0 -0
  214. data/maps/xtcontest.map +0 -0
  215. data/maps/zdungeon.map +0 -0
  216. data/maps/zebulon.ifm +0 -0
  217. data/maps/zerosum.map +0 -0
  218. metadata +226 -183
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
data/icons/copy.png CHANGED
File without changes
data/icons/cut.png CHANGED
File without changes
data/icons/filenew.png CHANGED
File without changes
data/icons/fileopen.png CHANGED
File without changes
data/icons/filesave.png CHANGED
File without changes
data/icons/filesaveas.png CHANGED
File without changes
data/icons/help.png CHANGED
File without changes
data/icons/kill.png CHANGED
File without changes
data/icons/nextpage.png CHANGED
File without changes
data/icons/paste.png CHANGED
File without changes
data/icons/prevpage.png CHANGED
File without changes
data/icons/printicon.png CHANGED
File without changes
data/icons/redo.png CHANGED
File without changes
data/icons/room_e.gif CHANGED
File without changes
data/icons/room_e.xpm CHANGED
File without changes
data/icons/room_n.gif CHANGED
File without changes
data/icons/room_n.xpm CHANGED
File without changes
data/icons/room_ne.gif CHANGED
File without changes
data/icons/room_ne.xpm CHANGED
File without changes
data/icons/room_nw.gif CHANGED
File without changes
data/icons/room_nw.xpm CHANGED
File without changes
data/icons/room_s.gif CHANGED
File without changes
data/icons/room_s.xpm CHANGED
File without changes
data/icons/room_se.gif CHANGED
File without changes
data/icons/room_se.xpm CHANGED
File without changes
data/icons/room_sw.gif CHANGED
File without changes
data/icons/room_sw.xpm CHANGED
File without changes
data/icons/room_w.gif CHANGED
File without changes
data/icons/room_w.xpm CHANGED
File without changes
data/icons/saveas.png CHANGED
File without changes
data/icons/undo.png CHANGED
File without changes
data/icons/winapp.png CHANGED
File without changes
data/icons/zoom.png CHANGED
File without changes
@@ -1,250 +1,250 @@
1
-
2
-
3
-
4
- #
5
- # A class used for path finding.
6
- # This is largely based on C++ code by Justin Heyes-Jones, albeit simplified
7
- #
8
- class AStar
9
-
10
- attr :start, :goal
11
- attr_reader :state
12
- attr :successors
13
- attr :open_list
14
- attr :closed_list
15
-
16
- SEARCH_STATE_NOT_INITIALIZED = 0
17
- SEARCH_STATE_SEARCHING = 1
18
- SEARCH_STATE_SUCCEEDED = 2
19
- SEARCH_STATE_FAILED = 3
20
-
21
- def open_list
22
- puts "Open List:"
23
- @open_list.each { |n|
24
- p n
25
- }
26
- puts "Closed List # of nodes: #{@open_list.size}"
27
- end
28
-
29
- def closed_list
30
- puts "Closed List:"
31
- @closed_list.each { |n|
32
- p n
33
- }
34
- puts "Closed List # of nodes: #{@closed_list.size}"
35
- end
36
-
37
-
38
- class Node
39
- attr_accessor :parent, :child
40
- attr_accessor :h, :g, :f
41
-
42
- attr_reader :info
43
-
44
- def <=>(b)
45
- return -1 if @f > b.f
46
- return 0 if @f == b.f
47
- return 1
48
- end
49
-
50
- def inspect
51
- "AStarNode: #{@f} = #{@g} + #{@h} #{@info.inspect}"
52
- end
53
-
54
- def initialize( info = nil )
55
- @h = @g = @f = 0.0
56
- @info = info
57
- end
58
- end
59
-
60
- # sets start and end goals and initializes A* search
61
- def goals( start, goal )
62
- @start = Node.new( start )
63
- @start.g = 0.0
64
- @start.h = start.distance_estimate( goal )
65
- @start.f = @start.h
66
-
67
- @open_list = []
68
- @open_list.push( @start )
69
- @closed_list = []
70
-
71
- @goal = Node.new( goal )
72
-
73
- @state = SEARCH_STATE_SEARCHING
74
- end
75
-
76
- # Advances one search step
77
- def search_step
78
- if @open_list.empty?
79
- @state = SEARCH_STATE_FAILED
80
- return @state
81
- end
82
-
83
- # Pop the best node (the one with the lowest f)
84
- n = @open_list.pop
85
-
86
- # Check for the goal. Once we pop that, we are done
87
- if n.info.is_goal?( @goal.info )
88
- # The user is going to use the Goal Node he passed in
89
- # so copy the parent pointer of n
90
- @goal.parent = n.parent
91
- # Special case is that the goal was passed in as the start state
92
- # so handle that here
93
- if n != @start
94
- child = @goal
95
- parent = @goal.parent
96
-
97
- while child != @start
98
- parent.child = child
99
- child = parent
100
- parent = parent.parent
101
- end
102
- end
103
- @state = SEARCH_STATE_SUCCEEDED
104
- return @state
105
- else
106
- # Not goal, get successors
107
- n.info.successors( self, n.parent )
108
- @successors.each do |s|
109
- newg = n.g + n.info.cost( s.info )
110
-
111
- # Now, we need to find out if this node is on the open or close lists
112
- # If it is, but the node that is already on them is better (lower g)
113
- # then we can forget about this successor
114
- open = @open_list.find { |e| e.info.is_same?( s.info ) }
115
- # State in open list is cheaper than this successor
116
- next if open and open.g <= newg
117
-
118
- closed = @closed_list.find { |e| e.info.is_same?( s.info ) }
119
- # We found a cheaper state in closed list
120
- next if closed and closed.g <= newg
121
-
122
- # This node is the best node so far so let's keep it and set up
123
- # its A* specific data
124
- s.parent = n
125
- s.g = newg
126
- s.h = s.info.distance_estimate( @goal.info )
127
- s.f = s.g + s.h
128
-
129
- # Remove succesor from closed list if it was on it
130
- @closed_list.delete(closed) if closed
131
- # Change succesor from open list if it was on it
132
- if open
133
- open.parent = s.parent
134
- open.g = s.g
135
- open.h = s.h
136
- open.f = s.f
137
- else
138
- @open_list.push(s)
139
- end
140
- end
141
- # Make sure open list stays sorted based on f
142
- @open_list.sort!
143
-
144
- @closed_list.push(n)
145
- @successors.clear
146
- end
147
- return @state
148
- end
149
-
150
- def add_successor( info )
151
- @successors << Node.new(info)
152
- end
153
-
154
- # return solution as an path (ie. an array of [x,y] coordinates)
155
- def path
156
- p = []
157
- curr = @start
158
- while curr
159
- p << [curr.info.x, curr.info.y]
160
- curr = curr.child
161
- end
162
- return p
163
- end
164
-
165
- def initialize
166
- @state = SEARCH_STATE_NOT_INITIALIZED
167
- @successors = []
168
- end
169
- end
170
-
171
-
172
- #
173
- # Simple class used as an adapter for our FXMap<->AStar
174
- #
175
- class MapNode
176
- attr_reader :x, :y
177
- @@pmap = nil
178
-
179
- def self.map(pmap)
180
- @@pmap = pmap
181
- end
182
-
183
- def initialize(x, y)
184
- @x = x
185
- @y = y
186
- end
187
-
188
- def is_same?(node)
189
- return true if node and @x == node.x and @y == node.y
190
- return false
191
- end
192
-
193
- def is_goal?( goal )
194
- return true if @x == goal.x and @y == goal.y
195
- return false
196
- end
197
-
198
- def distance_estimate( goal )
199
- dx = @x - goal.x
200
- dy = @y - goal.y
201
- return dx*dx + dy*dy
202
- end
203
-
204
- MAX_SCALE = 9
205
-
206
- def get_map(x, y)
207
- if x < 0 or y < 0 or x >= @@pmap.size or y >= @@pmap[0].size
208
- return MAX_SCALE
209
- else
210
- t = @@pmap.at(x).at(y)
211
- return MAX_SCALE if t.kind_of?(Room)
212
- return MAX_SCALE-1 if t.kind_of?(Connection)
213
- return 1
214
- end
215
- end
216
-
217
- def successors( astar, parent = nil )
218
- info = nil
219
- info = parent.info if parent
220
- Room::DIR_TO_VECTOR.each_value { |x, y|
221
- new_node = MapNode.new(@x + x, @y + y)
222
- if get_map( new_node.x, new_node.y ) < MAX_SCALE and
223
- not new_node.is_same?(info)
224
- astar.add_successor(new_node)
225
- end
226
- }
227
- end
228
-
229
- def inspect
230
- "pos: #{@x}, #{@y}"
231
- end
232
-
233
- def to_s
234
- inspect
235
- end
236
-
237
- def cost( successor )
238
- g = get_map(@x,@y)
239
-
240
- dx = (@x - successor.x).abs
241
- dy = (@y - successor.y).abs
242
- if dx + dy == 1
243
- g += 10 # straight move
244
- else
245
- g += 14 # diagonal move
246
- end
247
- return g
248
- end
249
-
250
- end
1
+
2
+
3
+
4
+ #
5
+ # A class used for path finding.
6
+ # This is largely based on C++ code by Justin Heyes-Jones, albeit simplified
7
+ #
8
+ class AStar
9
+
10
+ attr :start, :goal
11
+ attr_reader :state
12
+ attr :successors
13
+ attr_writer :open_list
14
+ attr_writer :closed_list
15
+
16
+ SEARCH_STATE_NOT_INITIALIZED = 0
17
+ SEARCH_STATE_SEARCHING = 1
18
+ SEARCH_STATE_SUCCEEDED = 2
19
+ SEARCH_STATE_FAILED = 3
20
+
21
+ def open_list
22
+ puts "Open List:"
23
+ @open_list.each { |n|
24
+ p n
25
+ }
26
+ puts "Closed List # of nodes: #{@open_list.size}"
27
+ end
28
+
29
+ def closed_list
30
+ puts "Closed List:"
31
+ @closed_list.each { |n|
32
+ p n
33
+ }
34
+ puts "Closed List # of nodes: #{@closed_list.size}"
35
+ end
36
+
37
+
38
+ class Node
39
+ attr_accessor :parent, :child
40
+ attr_accessor :h, :g, :f
41
+
42
+ attr_reader :info
43
+
44
+ def <=>(b)
45
+ return -1 if @f > b.f
46
+ return 0 if @f == b.f
47
+ return 1
48
+ end
49
+
50
+ def inspect
51
+ "AStarNode: #{@f} = #{@g} + #{@h} #{@info.inspect}"
52
+ end
53
+
54
+ def initialize( info = nil )
55
+ @h = @g = @f = 0.0
56
+ @info = info
57
+ end
58
+ end
59
+
60
+ # sets start and end goals and initializes A* search
61
+ def goals( start, goal )
62
+ @start = Node.new( start )
63
+ @start.g = 0.0
64
+ @start.h = start.distance_estimate( goal )
65
+ @start.f = @start.h
66
+
67
+ @open_list = []
68
+ @open_list.push( @start )
69
+ @closed_list = []
70
+
71
+ @goal = Node.new( goal )
72
+
73
+ @state = SEARCH_STATE_SEARCHING
74
+ end
75
+
76
+ # Advances one search step
77
+ def search_step
78
+ if @open_list.empty?
79
+ @state = SEARCH_STATE_FAILED
80
+ return @state
81
+ end
82
+
83
+ # Pop the best node (the one with the lowest f)
84
+ n = @open_list.pop
85
+
86
+ # Check for the goal. Once we pop that, we are done
87
+ if n.info.is_goal?( @goal.info )
88
+ # The user is going to use the Goal Node he passed in
89
+ # so copy the parent pointer of n
90
+ @goal.parent = n.parent
91
+ # Special case is that the goal was passed in as the start state
92
+ # so handle that here
93
+ if n != @start
94
+ child = @goal
95
+ parent = @goal.parent
96
+
97
+ while child != @start
98
+ parent.child = child
99
+ child = parent
100
+ parent = parent.parent
101
+ end
102
+ end
103
+ @state = SEARCH_STATE_SUCCEEDED
104
+ return @state
105
+ else
106
+ # Not goal, get successors
107
+ n.info.successors( self, n.parent )
108
+ @successors.each do |s|
109
+ newg = n.g + n.info.cost( s.info )
110
+
111
+ # Now, we need to find out if this node is on the open or close lists
112
+ # If it is, but the node that is already on them is better (lower g)
113
+ # then we can forget about this successor
114
+ open = @open_list.find { |e| e.info.is_same?( s.info ) }
115
+ # State in open list is cheaper than this successor
116
+ next if open and open.g <= newg
117
+
118
+ closed = @closed_list.find { |e| e.info.is_same?( s.info ) }
119
+ # We found a cheaper state in closed list
120
+ next if closed and closed.g <= newg
121
+
122
+ # This node is the best node so far so let's keep it and set up
123
+ # its A* specific data
124
+ s.parent = n
125
+ s.g = newg
126
+ s.h = s.info.distance_estimate( @goal.info )
127
+ s.f = s.g + s.h
128
+
129
+ # Remove succesor from closed list if it was on it
130
+ @closed_list.delete(closed) if closed
131
+ # Change succesor from open list if it was on it
132
+ if open
133
+ open.parent = s.parent
134
+ open.g = s.g
135
+ open.h = s.h
136
+ open.f = s.f
137
+ else
138
+ @open_list.push(s)
139
+ end
140
+ end
141
+ # Make sure open list stays sorted based on f
142
+ @open_list.sort!
143
+
144
+ @closed_list.push(n)
145
+ @successors.clear
146
+ end
147
+ return @state
148
+ end
149
+
150
+ def add_successor( info )
151
+ @successors << Node.new(info)
152
+ end
153
+
154
+ # return solution as an path (ie. an array of [x,y] coordinates)
155
+ def path
156
+ p = []
157
+ curr = @start
158
+ while curr
159
+ p << [curr.info.x, curr.info.y]
160
+ curr = curr.child
161
+ end
162
+ return p
163
+ end
164
+
165
+ def initialize
166
+ @state = SEARCH_STATE_NOT_INITIALIZED
167
+ @successors = []
168
+ end
169
+ end
170
+
171
+
172
+ #
173
+ # Simple class used as an adapter for our FXMap<->AStar
174
+ #
175
+ class MapNode
176
+ attr_reader :x, :y
177
+ @@pmap = nil
178
+
179
+ def self.map(pmap)
180
+ @@pmap = pmap
181
+ end
182
+
183
+ def initialize(x, y)
184
+ @x = x
185
+ @y = y
186
+ end
187
+
188
+ def is_same?(node)
189
+ return true if node and @x == node.x and @y == node.y
190
+ return false
191
+ end
192
+
193
+ def is_goal?( goal )
194
+ return true if @x == goal.x and @y == goal.y
195
+ return false
196
+ end
197
+
198
+ def distance_estimate( goal )
199
+ dx = @x - goal.x
200
+ dy = @y - goal.y
201
+ return dx*dx + dy*dy
202
+ end
203
+
204
+ MAX_SCALE = 9
205
+
206
+ def get_map(x, y)
207
+ if x < 0 or y < 0 or x >= @@pmap.size or y >= @@pmap[0].size
208
+ return MAX_SCALE
209
+ else
210
+ t = @@pmap.at(x).at(y)
211
+ return MAX_SCALE if t.kind_of?(Room)
212
+ return MAX_SCALE-1 if t.kind_of?(Connection)
213
+ return 1
214
+ end
215
+ end
216
+
217
+ def successors( astar, parent = nil )
218
+ info = nil
219
+ info = parent.info if parent
220
+ Room::DIR_TO_VECTOR.each_value { |x, y|
221
+ new_node = MapNode.new(@x + x, @y + y)
222
+ if get_map( new_node.x, new_node.y ) < MAX_SCALE and
223
+ not new_node.is_same?(info)
224
+ astar.add_successor(new_node)
225
+ end
226
+ }
227
+ end
228
+
229
+ def inspect
230
+ "pos: #{@x}, #{@y}"
231
+ end
232
+
233
+ def to_s
234
+ inspect
235
+ end
236
+
237
+ def cost( successor )
238
+ g = get_map(@x,@y)
239
+
240
+ dx = (@x - successor.x).abs
241
+ dy = (@y - successor.y).abs
242
+ if dx + dy == 1
243
+ g += 10 # straight move
244
+ else
245
+ g += 14 # diagonal move
246
+ end
247
+ return g
248
+ end
249
+
250
+ end