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
data/lib/IFMapper/Room.rb CHANGED
@@ -1,151 +1,153 @@
1
-
2
- #
3
- # Class used to represent a Room or Location in a Map.
4
- #
5
- class Room
6
- attr_accessor :name # Name of room
7
- attr_accessor :objects # Objects found in room
8
- attr_accessor :tasks # Tasks that need to be performed in room
9
- attr_reader :exits # An array of 8 possible exits in room
10
- attr_accessor :darkness # Is room in darkness?
11
- attr_accessor :x, :y # Room location in grid
12
- attr_accessor :desc # Room description
13
-
14
- DIR_TO_VECTOR = {
15
- 0 => [ 0, -1 ],
16
- 1 => [ 1, -1 ],
17
- 2 => [ 1, 0 ],
18
- 3 => [ 1, 1 ],
19
- 4 => [ 0, 1 ],
20
- 5 => [ -1, 1 ],
21
- 6 => [ -1, 0 ],
22
- 7 => [ -1, -1 ]
23
- }
24
-
25
- def marshal_load(vars)
26
- @name = vars.shift
27
- @objects = vars.shift
28
- @tasks = vars.shift
29
- @exits = vars.shift
30
- @darkness = vars.shift
31
- @x = vars.shift
32
- @y = vars.shift
33
- if not vars.empty? and vars[0].kind_of?(String)
34
- @desc = vars.shift
35
- @desc.gsub!(/(\w)\s*\n/, '\1 ')
36
- @desc.sub!(/\n+$/, '')
37
- @desc.strip!
38
- end
39
- end
40
-
41
- def marshal_dump
42
- [ @name, @objects, @tasks, @exits, @darkness, @x, @y, @desc ]
43
- end
44
-
45
- def [](dir)
46
- return @exits[dir]
47
- end
48
-
49
- def []=(dir, connection)
50
- @exits[dir] = connection
51
- end
52
-
53
- #
54
- # Return the number of doors present in room
55
- #
56
- def num_doors
57
- num = 0
58
- @exits.each { |e|
59
- next if not e
60
- num += 1 if e.door?
61
- }
62
- return num
63
- end
64
-
65
- #
66
- # Return the number of exits present in room
67
- #
68
- def num_exits
69
- return @exits.nitems
70
- end
71
-
72
- #
73
- # Return a direction from the vector of the exit that would take
74
- # us to the 'b' room more cleanly.
75
- #
76
- def self.vector_to_dir(dx, dy)
77
- if dx == 0
78
- return 4 if dy > 0
79
- return 0 if dy < 0
80
- raise "vector_to_dir: dx == 0 and dy == 0"
81
- elsif dx > 0
82
- return 1 if dy < 0
83
- return 2 if dy == 0
84
- return 3
85
- else
86
- return 7 if dy < 0
87
- return 6 if dy == 0
88
- return 5
89
- end
90
- end
91
-
92
- def vector_to_dir(dx, dy)
93
- return Room::vector_to_dir( dx, dy )
94
- end
95
-
96
- #
97
- # Given an 'adjacent' room, return the most direct exit from this
98
- # room to room b.
99
- #
100
- def exit_to(b)
101
- dx = (b.x - @x)
102
- dy = (b.y - @y)
103
- return vector_to_dir(dx, dy)
104
- end
105
-
106
- # Check if two rooms are next to each other. If so,
107
- # return the exit that would take us from this room to the other.
108
- # Otherwise, return nil
109
- def next_to?(b)
110
- if not b.kind_of?(Room)
111
- raise "next_to?(b): #{b} is not a room."
112
- end
113
- if self == b
114
- raise "next_to? comparing same room #{self}"
115
- end
116
- if b.x == @x and b.y == @y
117
- raise "#{self} and #{b} in same location."
118
- end
119
- dx = (b.x - @x)
120
- dy = (b.y - @y)
121
- return nil if dx.abs > 1 or dy.abs > 1
122
- return vector_to_dir(dx, dy)
123
- end
124
-
125
- #
126
- # Copy a room to another
127
- #
128
- def copy(b)
129
- @name = b.name
130
- @objects = b.objects
131
- @tasks = b.tasks
132
- @darkness = b.darkness
133
- @desc = b.desc
134
- end
135
-
136
-
137
- def initialize(x, y, name = 'Room')
138
- @exits = Array.new( DIRECTIONS.size )
139
- @darkness = false
140
- @name = name
141
- @x = x
142
- @y = y
143
-
144
- @objects = ''
145
- @tasks = ''
146
- end
147
-
148
- def to_s
149
- "\"#{@name}\""
150
- end
151
- end
1
+
2
+ #
3
+ # Class used to represent a Room or Location in a Map.
4
+ #
5
+ class Room
6
+ attr_accessor :name # Name of room
7
+ attr_accessor :objects # Objects found in room
8
+ attr_accessor :tasks # Tasks that need to be performed in room
9
+ attr_reader :exits # An array of 8 possible exits in room
10
+ attr_accessor :darkness # Isxxxxxxxxxx room in darkness?
11
+ attr_accessor :x, :y # Room location in grid
12
+ attr_accessor :desc # Room description
13
+
14
+ DIR_TO_VECTOR = {
15
+ 0 => [ 0, -1 ],
16
+ 1 => [ 1, -1 ],
17
+ 2 => [ 1, 0 ],
18
+ 3 => [ 1, 1 ],
19
+ 4 => [ 0, 1 ],
20
+ 5 => [ -1, 1 ],
21
+ 6 => [ -1, 0 ],
22
+ 7 => [ -1, -1 ]
23
+ }
24
+
25
+ def marshal_load(vars)
26
+ @name = vars.shift
27
+ @objects = vars.shift
28
+ @tasks = vars.shift
29
+ @exits = vars.shift
30
+ @darkness = vars.shift
31
+ @x = vars.shift
32
+ @y = vars.shift
33
+ @desc = nil
34
+ if not vars.empty? and vars[0].kind_of?(String)
35
+ @desc = vars.shift
36
+ @desc.gsub!(/(\w)\s*\n/, '\1 ')
37
+ @desc.sub!(/\n+$/, '')
38
+ @desc.strip!
39
+ end
40
+ end
41
+
42
+ def marshal_dump
43
+ [ @name, @objects, @tasks, @exits, @darkness, @x, @y, @desc ]
44
+ end
45
+
46
+ def [](dir)
47
+ return @exits[dir]
48
+ end
49
+
50
+ def []=(dir, connection)
51
+ @exits[dir] = connection
52
+ end
53
+
54
+ #
55
+ # Return the number of doors present in room
56
+ #
57
+ def num_doors
58
+ num = 0
59
+ @exits.each { |e|
60
+ next if not e
61
+ num += 1 if e.door?
62
+ }
63
+ return num
64
+ end
65
+
66
+ #
67
+ # Return the number of exits present in room
68
+ #
69
+ def num_exits
70
+ return @exits.nitems
71
+ end
72
+
73
+ #
74
+ # Return a direction from the vector of the exit that would take
75
+ # us to the 'b' room more cleanly.
76
+ #
77
+ def self.vector_to_dir(dx, dy)
78
+ if dx == 0
79
+ return 4 if dy > 0
80
+ return 0 if dy < 0
81
+ raise "vector_to_dir: dx == 0 and dy == 0"
82
+ elsif dx > 0
83
+ return 1 if dy < 0
84
+ return 2 if dy == 0
85
+ return 3
86
+ else
87
+ return 7 if dy < 0
88
+ return 6 if dy == 0
89
+ return 5
90
+ end
91
+ end
92
+
93
+ def vector_to_dir(dx, dy)
94
+ return Room::vector_to_dir( dx, dy )
95
+ end
96
+
97
+ #
98
+ # Given an 'adjacent' room, return the most direct exit from this
99
+ # room to room b.
100
+ #
101
+ def exit_to(b)
102
+ dx = (b.x - @x)
103
+ dy = (b.y - @y)
104
+ return vector_to_dir(dx, dy)
105
+ end
106
+
107
+ # Check if two rooms are next to each other. If so,
108
+ # return the exit that would take us from this room to the other.
109
+ # Otherwise, return nil
110
+ def next_to?(b)
111
+ if not b.kind_of?(Room)
112
+ raise "next_to?(b): #{b} is not a room."
113
+ end
114
+ if self == b
115
+ raise "next_to? comparing same room #{self}"
116
+ end
117
+ if b.x == @x and b.y == @y
118
+ raise "#{self} and #{b} in same location."
119
+ end
120
+ dx = (b.x - @x)
121
+ dy = (b.y - @y)
122
+ return nil if dx.abs > 1 or dy.abs > 1
123
+ return vector_to_dir(dx, dy)
124
+ end
125
+
126
+ #
127
+ # Copy a room to another
128
+ #
129
+ def copy(b)
130
+ @name = b.name
131
+ @objects = b.objects
132
+ @tasks = b.tasks
133
+ @darkness = b.darkness
134
+ @desc = b.desc
135
+ end
136
+
137
+
138
+ def initialize(x, y, name = 'Room')
139
+ @exits = Array.new( DIRECTIONS.size )
140
+ @darkness = false
141
+ @name = name
142
+ @x = x
143
+ @y = y
144
+
145
+ @desc = nil
146
+ @objects = ''
147
+ @tasks = ''
148
+ end
149
+
150
+ def to_s
151
+ "\"#{@name}\""
152
+ end
153
+ end
@@ -1,234 +1,234 @@
1
-
2
-
3
- require 'IFMapper/Connection'
4
- require 'IFMapper/Room'
5
-
6
- class Section
7
- attr_accessor :rooms
8
- attr_accessor :connections
9
- attr_accessor :name
10
-
11
- class ConnectionError < StandardError; end
12
-
13
- def marshal_load(v)
14
- @rooms = v[0]
15
- @connections = v[1]
16
- @name = v[2]
17
- end
18
-
19
- def marshal_dump
20
- return [ @rooms, @connections, @name ]
21
- end
22
-
23
- #
24
- # Return the number of rooms in width and height for this page
25
- #
26
- def rooms_width_height
27
- minXY, maxXY = min_max_rooms
28
- return [
29
- maxXY[0] - minXY[0] + 1,
30
- maxXY[1] - minXY[1] + 1
31
- ]
32
- end
33
-
34
- #
35
- # Return the min and max coordinates of all rooms in page
36
- #
37
- def min_max_rooms
38
- return [[0, 0],[0, 0]] if @rooms.empty?
39
-
40
- minXY = [ @rooms[0].x, @rooms[0].y ]
41
- maxXY = minXY.dup
42
- @rooms.each { |r|
43
- minXY[0] = r.x if r.x < minXY[0]
44
- minXY[1] = r.y if r.y < minXY[1]
45
- maxXY[0] = r.x if r.x > maxXY[0]
46
- maxXY[1] = r.y if r.y > maxXY[1]
47
- }
48
- return [ minXY, maxXY ]
49
- end
50
-
51
- #
52
- # Return true or false if map is free at location x,y
53
- #
54
- def free?(x,y)
55
- @rooms.each { |r|
56
- return false if r.x == x and r.y == y
57
- }
58
- return true
59
- end
60
-
61
- #
62
- # Shift rooms in dx and dy direction from x,y position on.
63
- #
64
- def shift(x, y, dx, dy)
65
- @rooms.each { |r|
66
- ox = oy = 0
67
- if (dx < 0 and r.x <= x) or
68
- (dx > 0 and r.x >= x)
69
- ox = dx
70
- end
71
- if (dy < 0 and r.y <= y) or
72
- (dy > 0 and r.y >= y)
73
- oy = dy
74
- end
75
- r.x += ox
76
- r.y += oy
77
- }
78
- end
79
-
80
-
81
- #
82
- # Delete a connection from section
83
- #
84
- def delete_connection(c)
85
- a = c.roomA
86
- if a
87
- e = a.exits.index(c)
88
- a[e] = nil if e
89
- end
90
- b = c.roomB
91
- if b
92
- e = b.exits.rindex(c)
93
- b[e] = nil if e
94
- end
95
- @connections.delete(c)
96
- end
97
-
98
- #
99
- # Delete a connection at a certain index location
100
- #
101
- def delete_connection_at( idx )
102
- c = @connections[idx]
103
-
104
- a = c.roomA
105
- if a
106
- e = a.exits.index(c)
107
- a[e] = nil if e
108
- end
109
- b = c.roomB
110
- if b
111
- e = b.exits.rindex(c)
112
- b[e] = nil if e
113
- end
114
- @connections.delete_at(idx)
115
- end
116
-
117
- #
118
- # Create a new connection among two rooms thru their exits
119
- #
120
- def new_connection( roomA, exitA, roomB, exitB = nil )
121
-
122
- # Verify rooms exist in section (ie. don't allow links across
123
- # sections)
124
- if not @rooms.include?(roomA)
125
- raise ConnectionError, "Room '#{roomA}' not in section #{self}"
126
- end
127
- if roomB and not @rooms.include?(roomB)
128
- raise ConnectionError, "Room '#{roomB}' not in section #{self}"
129
- end
130
-
131
- c = Connection.new( roomA, roomB )
132
- _new_connection( c, roomA, exitA, roomB, exitB )
133
- end
134
-
135
- #
136
- # Delete a room at a certain index
137
- #
138
- def delete_room_at(idx)
139
- r = @rooms[idx]
140
- r.exits.each { |e|
141
- next if not e
142
- delete_connection(e)
143
- }
144
- @rooms.delete_at(idx)
145
- end
146
-
147
- #
148
- # Delete a room, leaving its connections intact
149
- #
150
- def delete_room_only(r)
151
- @rooms.delete(r)
152
- end
153
-
154
- #
155
- # Delete a room and all of its connections
156
- #
157
- def delete_room(r)
158
- r.exits.each { |e|
159
- next if not e
160
- delete_connection(e)
161
- }
162
- delete_room_only(r)
163
- end
164
-
165
- #
166
- # Create a new room (note: FXSection overrides this creating an
167
- # FXRoom instead).
168
- #
169
- def new_room( x, y )
170
- r = Room.new( x, y, 'New Location' )
171
- return _new_room(r, x, y)
172
- end
173
-
174
- def initialize()
175
- @rooms = []
176
- @connections = []
177
- @name = ''
178
- end
179
-
180
- protected
181
-
182
- def _new_room( r, x, y )
183
- @rooms.push(r)
184
- return r
185
- end
186
-
187
- def _new_connection(c, roomA, exitA, roomB, exitB)
188
- exitA = roomA.exit_to(roomB) if not exitA
189
- if not exitA
190
- err = <<"EOF"
191
- No exit given or guessed to connect:
192
- Room #{roomA} (#{roomA.x}, #{roomA.y})
193
- Room #{roomB} (#{roomB.x}, #{roomB.y})
194
- EOF
195
- raise ConnectionError, err
196
- end
197
-
198
- if roomA[exitA]
199
- if not @connections.include?(roomA[exitA])
200
- raise ConnectionError, "roomA exit #{exitA} for '#{roomA}' filled but not in section"
201
- end
202
- raise ConnectionError, "roomA exit #{exitA} for '#{roomA}' is filled"
203
- end
204
-
205
- roomA[exitA] = c
206
-
207
- if roomB and not exitB
208
- dx, dy = Room::DIR_TO_VECTOR[exitA]
209
- x = roomA.x + dx
210
- y = roomA.y + dy
211
- if roomB.x == x and roomB.y == y
212
- exitB = (exitA + 4) % 8
213
- else
214
- dx = x - roomB.x
215
- dy = y - roomB.y
216
- exitB = roomB.vector_to_dir(dx, dy)
217
- end
218
- end
219
-
220
- if roomB and roomB[exitB] and roomB[exitB] != c
221
- roomA[exitA] = nil
222
- raise ConnectionError, "roomB exit #{exitB} for #{roomB} is filled with #{roomB[exitB]}"
223
- end
224
- roomB[exitB] = c if roomB
225
-
226
- @connections.push( c )
227
- return c
228
- end
229
-
230
- def to_s
231
- return @name
232
- end
233
-
234
- end
1
+
2
+
3
+ require 'IFMapper/Connection'
4
+ require 'IFMapper/Room'
5
+
6
+ class Section
7
+ attr_accessor :rooms
8
+ attr_accessor :connections
9
+ attr_accessor :name
10
+
11
+ class ConnectionError < StandardError; end
12
+
13
+ def marshal_load(v)
14
+ @rooms = v[0]
15
+ @connections = v[1]
16
+ @name = v[2]
17
+ end
18
+
19
+ def marshal_dump
20
+ return [ @rooms, @connections, @name ]
21
+ end
22
+
23
+ #
24
+ # Return the number of rooms in width and height for this page
25
+ #
26
+ def rooms_width_height
27
+ minXY, maxXY = min_max_rooms
28
+ return [
29
+ maxXY[0] - minXY[0] + 1,
30
+ maxXY[1] - minXY[1] + 1
31
+ ]
32
+ end
33
+
34
+ #
35
+ # Return the min and max coordinates of all rooms in page
36
+ #
37
+ def min_max_rooms
38
+ return [[0, 0],[0, 0]] if @rooms.empty?
39
+
40
+ minXY = [ @rooms[0].x, @rooms[0].y ]
41
+ maxXY = minXY.dup
42
+ @rooms.each { |r|
43
+ minXY[0] = r.x if r.x < minXY[0]
44
+ minXY[1] = r.y if r.y < minXY[1]
45
+ maxXY[0] = r.x if r.x > maxXY[0]
46
+ maxXY[1] = r.y if r.y > maxXY[1]
47
+ }
48
+ return [ minXY, maxXY ]
49
+ end
50
+
51
+ #
52
+ # Return true or false if map is free at location x,y
53
+ #
54
+ def free?(x,y)
55
+ @rooms.each { |r|
56
+ return false if r.x == x and r.y == y
57
+ }
58
+ return true
59
+ end
60
+
61
+ #
62
+ # Shift rooms in dx and dy direction from x,y position on.
63
+ #
64
+ def shift(x, y, dx, dy)
65
+ @rooms.each { |r|
66
+ ox = oy = 0
67
+ if (dx < 0 and r.x <= x) or
68
+ (dx > 0 and r.x >= x)
69
+ ox = dx
70
+ end
71
+ if (dy < 0 and r.y <= y) or
72
+ (dy > 0 and r.y >= y)
73
+ oy = dy
74
+ end
75
+ r.x += ox
76
+ r.y += oy
77
+ }
78
+ end
79
+
80
+
81
+ #
82
+ # Delete a connection from section
83
+ #
84
+ def delete_connection(c)
85
+ a = c.roomA
86
+ if a
87
+ e = a.exits.index(c)
88
+ a[e] = nil if e
89
+ end
90
+ b = c.roomB
91
+ if b
92
+ e = b.exits.rindex(c)
93
+ b[e] = nil if e
94
+ end
95
+ @connections.delete(c)
96
+ end
97
+
98
+ #
99
+ # Delete a connection at a certain index location
100
+ #
101
+ def delete_connection_at( idx )
102
+ c = @connections[idx]
103
+
104
+ a = c.roomA
105
+ if a
106
+ e = a.exits.index(c)
107
+ a[e] = nil if e
108
+ end
109
+ b = c.roomB
110
+ if b
111
+ e = b.exits.rindex(c)
112
+ b[e] = nil if e
113
+ end
114
+ @connections.delete_at(idx)
115
+ end
116
+
117
+ #
118
+ # Create a new connection among two rooms thru their exits
119
+ #
120
+ def new_connection( roomA, exitA, roomB, exitB = nil )
121
+
122
+ # Verify rooms exist in section (ie. don't allow links across
123
+ # sections)
124
+ if not @rooms.include?(roomA)
125
+ raise ConnectionError, "Room '#{roomA}' not in section #{self}"
126
+ end
127
+ if roomB and not @rooms.include?(roomB)
128
+ raise ConnectionError, "Room '#{roomB}' not in section #{self}"
129
+ end
130
+
131
+ c = Connection.new( roomA, roomB )
132
+ _new_connection( c, roomA, exitA, roomB, exitB )
133
+ end
134
+
135
+ #
136
+ # Delete a room at a certain index
137
+ #
138
+ def delete_room_at(idx)
139
+ r = @rooms[idx]
140
+ r.exits.each { |e|
141
+ next if not e
142
+ delete_connection(e)
143
+ }
144
+ @rooms.delete_at(idx)
145
+ end
146
+
147
+ #
148
+ # Delete a room, leaving its connections intact
149
+ #
150
+ def delete_room_only(r)
151
+ @rooms.delete(r)
152
+ end
153
+
154
+ #
155
+ # Delete a room and all of its connections
156
+ #
157
+ def delete_room(r)
158
+ r.exits.each { |e|
159
+ next if not e
160
+ delete_connection(e)
161
+ }
162
+ delete_room_only(r)
163
+ end
164
+
165
+ #
166
+ # Create a new room (note: FXSection overrides this creating an
167
+ # FXRoom instead).
168
+ #
169
+ def new_room( x, y )
170
+ r = Room.new( x, y, 'New Location' )
171
+ return _new_room(r, x, y)
172
+ end
173
+
174
+ def initialize()
175
+ @rooms = []
176
+ @connections = []
177
+ @name = ''
178
+ end
179
+
180
+ protected
181
+
182
+ def _new_room( r, x, y )
183
+ @rooms.push(r)
184
+ return r
185
+ end
186
+
187
+ def _new_connection(c, roomA, exitA, roomB, exitB)
188
+ exitA = roomA.exit_to(roomB) if not exitA
189
+ if not exitA
190
+ err = <<"EOF"
191
+ No exit given or guessed to connect:
192
+ Room #{roomA} (#{roomA.x}, #{roomA.y})
193
+ Room #{roomB} (#{roomB.x}, #{roomB.y})
194
+ EOF
195
+ raise ConnectionError, err
196
+ end
197
+
198
+ if roomA[exitA]
199
+ if not @connections.include?(roomA[exitA])
200
+ raise ConnectionError, "roomA exit #{exitA} for '#{roomA}' filled but not in section"
201
+ end
202
+ raise ConnectionError, "roomA exit #{exitA} for '#{roomA}' is filled"
203
+ end
204
+
205
+ roomA[exitA] = c
206
+
207
+ if roomB and not exitB
208
+ dx, dy = Room::DIR_TO_VECTOR[exitA]
209
+ x = roomA.x + dx
210
+ y = roomA.y + dy
211
+ if roomB.x == x and roomB.y == y
212
+ exitB = (exitA + 4) % 8
213
+ else
214
+ dx = x - roomB.x
215
+ dy = y - roomB.y
216
+ exitB = roomB.vector_to_dir(dx, dy)
217
+ end
218
+ end
219
+
220
+ if roomB and roomB[exitB] and roomB[exitB] != c
221
+ roomA[exitA] = nil
222
+ raise ConnectionError, "roomB exit #{exitB} for #{roomB} is filled with #{roomB[exitB]}"
223
+ end
224
+ roomB[exitB] = c if roomB
225
+
226
+ @connections.push( c )
227
+ return c
228
+ end
229
+
230
+ def to_s
231
+ return @name
232
+ end
233
+
234
+ end