ifmapper 1.0.0 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
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