ifmapper 0.9.6 → 0.9.7

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.
@@ -167,7 +167,13 @@ class IFMWriter
167
167
  @f.puts
168
168
  @f.puts '#' * 79
169
169
  @f.puts
170
- @f.puts "map \"#{section.name}\";" if section.name != ''
170
+ if section.name.to_s == ''
171
+ if @map.sections.size > 1
172
+ @f.puts "map \"Section #{idx+1}\";"
173
+ end
174
+ else
175
+ @f.puts "map \"#{section.name}\";"
176
+ end
171
177
  @map.section = idx
172
178
  @link = nil
173
179
  section.rooms.each { |r|
@@ -192,10 +198,12 @@ class IFMWriter
192
198
  # (C) 2005 - Gonzalo Garramuno
193
199
  #
194
200
 
195
- title "#{@map.name}";
196
-
197
201
  HEADER
198
202
 
203
+ if @map.name.to_s != ''
204
+ puts "title \"#{@map.name}\";\n"
205
+ end
206
+
199
207
  end
200
208
 
201
209
 
@@ -1,85 +1,129 @@
1
1
 
2
- require "IFMapper/Map"
3
-
4
- class FXMap; end
5
-
6
- #
7
- # Class that allows creating a map from an Inform source file.
8
- #
9
- class InformReader
10
-
11
- class ParseError < StandardError; end
12
- class MapError < StandardError; end
2
+ require "IFMapper/MapReader"
3
+
4
+
5
+ # Take a quoted Inform string and return a valid ASCII one, replacing
6
+ # Inform's special characters.
7
+ module InformUnquote
8
+ TABLES = {
9
+ ":a" => "\204",
10
+ ":e" => "\211",
11
+ ":i" => "\213",
12
+ ":o" => "\224",
13
+ ":u" => "\201",
14
+ ":y" => "\230",
15
+
16
+ ":A" => "\216",
17
+ ":E" => "\323",
18
+ ":I" => "\330",
19
+ ":O" => "\231",
20
+ ":U" => "\232",
21
+
22
+ "'a" => "\240",
23
+ "'e" => "\202",
24
+ "'i" => "\241",
25
+ "'o" => "\242",
26
+ "'u" => "\243",
27
+ "'y" => "\354",
28
+
29
+ "'A" => "\265",
30
+ "'E" => "\220",
31
+ "'I" => "\326",
32
+ "'O" => "\340",
33
+ "'U" => "\351",
34
+ "'Y" => "\355",
35
+
36
+ "^a" => "\203",
37
+ "^e" => "\210",
38
+ "^i" => "\214",
39
+ "^o" => "\223",
40
+ "^u" => "\226",
41
+
42
+ "^A" => "\266",
43
+ "^E" => "\322",
44
+ "^I" => "\327",
45
+ "^O" => "\342",
46
+ "^U" => "\352",
47
+
48
+ "`a" => "\205",
49
+ "`e" => "\212",
50
+ "`i" => "\215",
51
+ "`o" => "\225",
52
+ "`u" => "\227",
53
+
54
+ "`A" => "\267",
55
+ "`E" => "\324",
56
+ "`I" => "\336",
57
+ "`O" => "\343",
58
+ "`U" => "\353",
59
+
60
+ ",c" => "\207",
61
+ ",C" => "\200",
62
+
63
+ "~a" => "\306",
64
+ "~A" => "\307",
65
+ "~o" => "\344",
66
+ "~o" => "\345",
67
+
68
+
69
+ "~n" => "\244",
70
+ "~N" => "\245",
71
+
72
+ "!!" => "\255",
73
+ '\?\?' => "\250",
74
+
75
+ ">>" => ">>",
76
+ "<<" => "<<",
77
+
78
+ # Missing
79
+ "LL" => "", # British pound
80
+
81
+ # greek letters
82
+ "ss" => "", # beta
83
+
84
+ "et" => "", #
85
+ "Et" => "", #
86
+ "th" => "", # thorn
87
+ "Th" => "", # thorn
88
+
89
+ '\\o' => "", #
90
+ '\\O' => "", #
91
+
92
+ "oa" => "", # o over a
93
+ "oA" => "", # o over A
94
+ "ae" => "",
95
+ "AE" => "",
96
+ "oe" => "",
97
+ "OE" => "",
98
+ }
13
99
 
14
- # Take a quoted Inform string and return a valid ASCII one, replacing
15
- # Inform's special characters.
16
- def self.unquote(text)
100
+ def unquote(text)
17
101
  return '' unless text
102
+ # deal with quotes
18
103
  text.gsub!(/\~/, '"')
104
+ # and newlines
19
105
  text.gsub!(/\^/, "\n")
106
+
107
+ # deal with accents and intl. chars
108
+ TABLES.each { |k, v|
109
+ text.gsub! /@#{k}/, v
110
+ }
111
+
112
+ # deal with zscii chars as numbers
20
113
  while text =~ /(@@(\d+))/
21
114
  text.sub!($1, $2.to_i.chr)
22
115
  end
23
116
  return text
24
117
  end
118
+ end
25
119
 
26
- # Temporary classes used to store inform room information
27
- class InformObject
28
- attr_reader :name
29
- attr_accessor :tag, :location, :enterable
30
-
31
- def name=(x)
32
- @name = InformReader::unquote(x)
33
- end
34
-
35
- def to_s
36
- "#@name tag:#@tag"
37
- end
38
-
39
- def method_missing(*a)
40
- end
41
-
42
- def initialize(location)
43
- if location
44
- @location = Array[*location]
45
- else
46
- @location = []
47
- end
48
- @enterable = []
49
- end
50
- end
51
-
52
- class InformDoor
53
- attr_accessor :location
54
- attr_accessor :locked
55
- attr_accessor :tag
56
- def method_missing(*x)
57
- end
58
- def initialize
59
- @location = []
60
- end
61
- end
62
120
 
63
- class InformRoom
64
- attr_reader :name
65
- attr_accessor :exits, :tag, :light, :desc
66
- def to_s
67
- "#@name tag:#@tag"
68
- end
69
- def name=(x)
70
- @name = InformReader::unquote(x)
71
- end
72
- def num_exits
73
- return @exits.nitems
74
- end
75
- def method_missing(*x)
76
- end
77
- def initialize
78
- @desc = ''
79
- @exits = Array.new(12, nil)
80
- end
81
- end
121
+ #
122
+ # Class that allows creating a map from an Inform source file.
123
+ #
124
+ class InformReader < MapReader
82
125
 
126
+ STORY = /Constant\s+Story\s+\"([^"]+)\"/i
83
127
 
84
128
  DIRECTIONS = {
85
129
  'n_to' => 0,
@@ -111,17 +155,28 @@ class InformReader
111
155
 
112
156
  attr_reader :map
113
157
 
114
- @@debug = nil
115
- def debug(*x)
116
- return unless @@debug
117
- $stdout.puts x
118
- $stdout.flush
158
+
159
+ include InformUnquote
160
+
161
+ class InformRoom < MapRoom
162
+ include InformUnquote
163
+ end
164
+
165
+ class InformObject < MapObject
166
+ include InformUnquote
167
+ end
168
+
169
+
170
+ def new_room
171
+ super(InformRoom)
172
+ end
173
+
174
+ def new_obj(loc = nil)
175
+ super(loc, InformObject)
119
176
  end
120
177
 
121
178
  #
122
- # Main parsing loop. We basically parse the file twice to
123
- # solve dependencies. Yes, this is inefficient, but the alternative
124
- # was to build a full parser that understands forward dependencies.
179
+ # Main parsing loop.
125
180
  #
126
181
  def parse(file)
127
182
  # We start map at 0, 0
@@ -158,11 +213,12 @@ class InformReader
158
213
  full_line = @line.dup
159
214
  begin
160
215
  parse_line
161
- rescue ParseError => e
162
- $stderr.puts
163
- $stderr.puts "#{e} at #{file.path}, line #{line_number}:"
164
- $stderr.puts ">>>> #{full_line};"
165
- $stderr.puts
216
+ rescue ParseError, MapError => e
217
+ message = "#{e}.\nat #{file.path}, line #{line_number}:\n>>>> #{full_line};\n"
218
+ raise message
219
+ rescue => e
220
+ message = "#{e}\n#{e.backtrace}"
221
+ raise message
166
222
  end
167
223
  end
168
224
  debug "...End Parse..."
@@ -170,7 +226,7 @@ class InformReader
170
226
 
171
227
 
172
228
  CLASS = /^class\s+(\w+)/i
173
- DOOR = /(?:^|\s+)door_to(?:\s+([^,;]*)|$)/i
229
+ DOOR = /(?:^|\s+)door_to(?:\s+([^,;\[]*)|$)/i
174
230
  INCLUDE = /^#?include\s+"([^"]+)"/i
175
231
  PLAYER_TO = /\bplayerto\((\w+)/i
176
232
  DESCRIPTION = /(?:^|\s+)description(?:\s*$|\s+"([^"]+)?("?))/i
@@ -182,28 +238,6 @@ class InformReader
182
238
  ]
183
239
 
184
240
 
185
- def new_room
186
- debug "+++ ROOM: #@name"
187
-
188
- # We assume we are a room (albeit we could be an obj)
189
- @room = InformRoom.new
190
- @room.tag = @tag
191
- @room.name = @name
192
- @room.desc = @desc
193
- @room.light = @classes[@clas][:light]
194
- @tags[@tag] = @room
195
- @rooms << @room
196
- end
197
-
198
- def new_obj(loc = nil)
199
- debug "+++ OBJ #@name"
200
- @obj = InformObject.new(loc)
201
- @obj.tag = @tag
202
- @obj.name = @name
203
- @tags[@tag] = @obj
204
- @objects << @obj
205
- end
206
-
207
241
 
208
242
  def find_file(file)
209
243
  return file if File.exists?(file)
@@ -221,14 +255,20 @@ class InformReader
221
255
  # Parse a line of file
222
256
  #
223
257
  def parse_line
258
+ if @line =~ STORY
259
+ @map.name = $1
260
+ return
261
+ end
262
+
224
263
  if @line =~ INCLUDE
225
264
  name = $1
226
265
  unless STD_LIB.include?(name)
227
266
  file = find_file(name)
267
+ debug "include #{file}"
228
268
  if file
229
269
  File.open(file, 'r') { |f| parse(f) }
230
270
  else
231
- raise ParseError, "Include file #{name} not found"
271
+ raise ParseError, "Include file '#{name}' not found"
232
272
  end
233
273
  end
234
274
  end
@@ -273,17 +313,15 @@ EOF
273
313
 
274
314
  c = @classes[@clas]
275
315
  if c[:door]
276
- debug "+++ DOOR"
277
- @obj = InformDoor.new
278
- @obj.tag = @tag
279
- @tags[@tag] = @obj
280
- @doors << @obj
281
- elsif loc or c[:scenery] or c[:static]
282
- debug "+++ OBJECT #{loc} #{c[:scenery]}, #{c[:static]}"
283
- new_obj(loc) if @tag
316
+ new_door
317
+ elsif @tag and (loc or c[:scenery] or c[:static])
318
+ new_obj(loc)
319
+ if c[:scenery] or c[:static]
320
+ @obj.scenery = true
321
+ end
284
322
  else
285
323
  @obj = @room = nil
286
- new_room if @tag and @name and c.has_key?(:light)
324
+ new_room if @tag and @name and c.has_key?(:light)
287
325
  end
288
326
  @before = false
289
327
  @go = false
@@ -306,16 +344,27 @@ EOF
306
344
 
307
345
  if @line =~ FUNCTION
308
346
  @functions << $1
347
+ elsif @tag and @line =~ DOOR
348
+ old_locations = []
349
+ if @obj
350
+ old_locations = @obj.location
351
+ @objects.delete(@obj) if @obj.tag == @tag
352
+ @tags[@tag] = nil
353
+ end
354
+ new_door
355
+ @obj.location = $1.split(' ')
356
+ @obj.location += old_locations if old_locations.size > 0
357
+ else
358
+ dirs = @line.scan(DIR_TO) + @line.scan(DIR) + @line.scan(ENTER_DIR)
359
+ if dirs.size > 0
360
+ new_room if not @room
361
+ dirs.each { |d, room|
362
+ dir = DIRECTIONS[d]
363
+ @room.exits[dir] = room
364
+ }
365
+ end
309
366
  end
310
367
 
311
- dirs = @line.scan(DIR_TO) + @line.scan(DIR) + @line.scan(ENTER_DIR)
312
- if dirs.size > 0
313
- new_room if not @room
314
- dirs.each { |d, room|
315
- dir = DIRECTIONS[d]
316
- @room.exits[dir] = room
317
- }
318
- end
319
368
 
320
369
  if @line =~ /\bbefore\b/i
321
370
  @before = true
@@ -330,25 +379,20 @@ EOF
330
379
  end
331
380
  end
332
381
 
333
- if @obj.kind_of?(InformObject) and @before
382
+ if @obj.kind_of?(MapObject) and @before
334
383
  if @line =~ PLAYER_TO
335
384
  @obj.enterable << $1
385
+ @obj.scenery = nil
336
386
  end
337
387
  end
338
388
 
339
- if @tag and @line =~ DOOR
340
- door = InformDoor.new
341
- door.location = $1.split(' ')
342
- door.location += @obj.location if @obj
343
- door.tag = @tag
344
- @obj = door
345
- @tags[@tag] = door
346
- @doors << door
347
- @objects.delete(@obj) if @obj and @obj.tag == @tag
348
- end
349
389
 
350
390
  if @line =~ /(?:^|\s+)has\s+([\w\s]+)[,;]/i
351
391
  props = $1.split
392
+ char = props.include?('male') or props.include?('female')
393
+ if @obj and char
394
+ @obj.scenery = false
395
+ end
352
396
  props.each { |p|
353
397
  if not @tag
354
398
  if p[0,1] == '~'
@@ -357,11 +401,13 @@ EOF
357
401
  @classes[@clas][p.to_sym] = true
358
402
  end
359
403
  else
360
- if p =~ /locked/ and @doors.size > 0
404
+ if p == 'locked' and @doors.size > 0
361
405
  @doors[-1].locked = true
362
406
  end
363
- if p =~ /(static|scenery)/ and @obj
364
- @objects.delete(@obj)
407
+ if not char
408
+ if p =~ /(?:static|scenery)/ and @obj
409
+ @objects.delete(@obj)
410
+ end
365
411
  end
366
412
  if p =~ /(\~)?light/
367
413
  new_room if not @room
@@ -371,7 +417,10 @@ EOF
371
417
  }
372
418
  end
373
419
 
374
- if @line =~ /\bfound_in\s+(.*)[,;]?/
420
+ if @line =~ /\bfound_in\s+([^;,\[]*)/
421
+ if @tag and not @obj
422
+ new_obj(loc)
423
+ end
375
424
  if @obj
376
425
  locs = $1.split
377
426
  @obj.location = locs
@@ -381,371 +430,6 @@ EOF
381
430
  end
382
431
 
383
432
 
384
- def shift_link(room, dir)
385
- idx = dir + 1
386
- idx = 0 if idx > 7
387
- while idx != dir
388
- break if not room[idx]
389
- idx += 1
390
- idx = 0 if idx > 7
391
- end
392
- if idx != dir
393
- room[idx] = room[dir]
394
- room[dir] = nil
395
- # get position of other room
396
- ox, oy = Room::DIR_TO_VECTOR[dir]
397
- c = room[idx]
398
- if c.roomA == room
399
- b = c.roomB
400
- else
401
- b = c.roomA
402
- end
403
- x, y = [b.x, b.y]
404
- x -= ox
405
- y -= oy
406
- dx, dy = Room::DIR_TO_VECTOR[idx]
407
- @map.shift(x, y, -dx, -dy)
408
- else
409
- # raise "Warning. Cannot shift connection for #{room}."
410
- end
411
- end
412
-
413
-
414
- def oneway_link?(a, b)
415
- # First, check if room already has exit moving towards other room
416
- a.exits.each_with_index { |e, idx|
417
- next if not e or e.dir != Connection::AtoB
418
- roomA = e.roomA
419
- roomB = e.roomB
420
- if roomA == a and roomB == b
421
- return e
422
- end
423
- }
424
- return nil
425
- end
426
-
427
-
428
- # Choose a direction to represent up/down/in/out.
429
- def choose_dir(a, b, go = nil, exitB = nil)
430
- if go
431
- rgo = go % 2 == 0? go - 1 : go + 1
432
- # First, check if room already has exit moving towards other room
433
- a.exits.each_with_index { |e, idx|
434
- next if not e or e.stub?
435
- roomA = e.roomA
436
- roomB = e.roomB
437
- if roomA == a and roomB == b
438
- e.exitAtext = go
439
- return idx
440
- elsif roomB == a and roomA == b
441
- e.exitBtext = go
442
- return idx
443
- end
444
- }
445
- end
446
-
447
- # We prefer directions that travel less... so we need to figure
448
- # out where we start from...
449
- if b
450
- x = b.x
451
- y = b.y
452
- else
453
- x = a.x
454
- y = a.y
455
- end
456
- if exitB
457
- dx, dy = Room::DIR_TO_VECTOR[exitB]
458
- x += dx
459
- y += dy
460
- end
461
-
462
- # No such luck... Pick a direction.
463
- best = nil
464
- bestscore = nil
465
-
466
- DIRLIST.each { |dir|
467
- # We prefer straight directions to diagonal ones
468
- inc = dir % 2 == 1 ? 100 : 140
469
- score = 1000
470
- # We prefer directions where both that dir and the opposite side
471
- # are empty.
472
- if (not a[dir]) or a[dir].stub?
473
- score += inc
474
- score += 4 if a[dir] #attaching to stubs is better
475
- end
476
- # rdir = (dir + 4) % 8
477
- # score += 1 unless a[rdir]
478
-
479
- # Measure distance for that exit, we prefer shorter
480
- # paths
481
- dx, dy = Room::DIR_TO_VECTOR[dir]
482
- dx = (a.x + dx) - x
483
- dy = (a.y + dy) - y
484
- d = dx * dx + dy * dy
485
- score -= d
486
- next if bestscore and score <= bestscore
487
- bestscore = score
488
- best = dir
489
- }
490
-
491
- if not bestscore
492
- raise "No free exit for choose_dir"
493
- end
494
-
495
- return best
496
- end
497
-
498
- def make_room(to, x, y, dx = 1, dy = 0)
499
- if not @map.free?(x, y)
500
- @map.shift(x, y, dx, dy)
501
- end
502
- room = @map.new_room(x, y)
503
- room.name = to.name
504
- desc = to.desc
505
- desc.gsub!(/[\t\n]/, ' ')
506
- desc.squeeze!(' ')
507
- room.desc = InformReader::unquote(desc)
508
- room.darkness = !to.light
509
- @tags[to.tag] = room
510
- return room
511
- end
512
-
513
- def get_exit(from, to, x, y, dx = 1, dy = 0 )
514
- elem = @tags[to.tag]
515
- if elem.kind_of?(InformRoom)
516
- room = create_room(to, x, y, dx, dy)
517
- return [room, Connection::FREE]
518
- elsif elem.kind_of?(InformDoor)
519
- if elem.locked
520
- type = Connection::LOCKED_DOOR
521
- else
522
- type = Connection::CLOSED_DOOR
523
- end
524
-
525
- @rooms.each { |o|
526
- next if @tags[o.tag] == from
527
- o.exits.each { |e|
528
- next unless e
529
- if @tags[e] == elem
530
- res = create_room( o, x, y, dx, dy )
531
- return [ res, type ]
532
- end
533
- }
534
- }
535
-
536
- # Okay, connecting room is missing. Check door's locations property
537
- elem.location.each { |tag|
538
- next if @tags[tag] == from
539
- @rooms.each { |o|
540
- next if o.tag != tag
541
- res = create_room( o, x, y, dx, dy )
542
- return [ res, type ]
543
- }
544
- }
545
-
546
- #raise "error: no room with door #{to.name} #{elem.name}"
547
- return [nil, nil]
548
- else
549
- return [elem, Connection::FREE]
550
- end
551
- end
552
-
553
- def create_room(r, x, y, dx = 2, dy = 0)
554
- return @tags[r.tag] if @tags[r.tag].kind_of?(Room)
555
- from, = make_room(r, x, y, dx, dy)
556
- debug "CREATE ROOM #{r.name} SET FROM TO: #{from}"
557
-
558
- r.exits.each_with_index { |e, exit|
559
- next unless e
560
- next if e == 'nothing' or e == '0'
561
- debug "#{r.name} EXIT:#{exit} points to #{e}"
562
-
563
- to = @tags[e]
564
- if not to
565
- next if @functions.include?(e)
566
- raise "Room #{e} #{e.class} not found." if not to
567
- end
568
-
569
- go = c = nil
570
-
571
- dir = exit
572
- type = 0
573
-
574
- # If exit leads to an enterable object, find out where does that
575
- # enterable object lead to.
576
- if to.kind_of?(InformObject)
577
- rooms = to.enterable
578
- rooms.each { |room|
579
- next if room == r
580
- to = @tags[room]
581
- break
582
- }
583
- # Skip it if we are still an object. This means we are just
584
- # a container, like the phone booth in the Fate game demo.
585
- next if to.kind_of?(InformObject)
586
- end
587
-
588
- if to.kind_of?(InformRoom) or to.kind_of?(InformDoor)
589
- if dir > 7
590
- # choose a dir for up/down/in/out
591
- go = dir - 7
592
- dir = choose_dir(from, nil, go)
593
- end
594
-
595
- dx, dy = Room::DIR_TO_VECTOR[dir]
596
- x = from.x + dx
597
- y = from.y + dy
598
- debug "#{exit} CREATE TO #{from} -> #{to.tag}"
599
- to, type = get_exit(from, to, x, y, dx, dy)
600
- next if not to
601
- end
602
-
603
- if exit > 7
604
- # choose a dir for up/down/in/out
605
- go = exit - 7
606
- dir = choose_dir(from, to, go)
607
- end
608
-
609
- b = @rooms.find { |r2| r2.tag == e }
610
- odir = nil
611
- odir = b.exits.rindex(r.tag) if b
612
- odir = (dir + 4) % 8 if not odir or odir > 7
613
-
614
- if from[dir]
615
- c = from[dir]
616
- if to[odir] == c and c.roomB == from
617
- debug "LINK TRAVELLED BOTH"
618
- c.dir = Connection::BOTH
619
- c.exitBtext = go if go
620
- next
621
- else
622
- debug "#{exit} FROM #{from}->#{to} BLOCKED DIR: #{dir}"
623
- shift_link(from, dir)
624
- end
625
- end
626
-
627
- # Check we don't have a connection already
628
- if to[odir]
629
- c = to[odir]
630
- debug "#{from} #{dir} -> #{to} dir:#{odir} filled. Swap..."
631
-
632
- # We need to change odir to something else
633
- rgo = 0
634
- if go
635
- rgo = go % 2 == 0? go - 1 : go + 1
636
- end
637
-
638
- # First, check if we have a dangling one-way link going to->from
639
- # If we do, we use it.
640
- c = oneway_link?(from, to)
641
- if not c
642
- odir = choose_dir(to, from, rgo, dir)
643
- debug "Swapped to #{odir}"
644
- else
645
- debug "FOUND LINK #{c} -- filling it."
646
- idx = from.exits.index(c)
647
- from[idx] = nil
648
- from[dir] = c
649
- c.dir = Connection::BOTH
650
- c.exitBtext = go if go
651
- end
652
- else
653
- debug "to[odir] empty."
654
- # First, check if we have a dangling one-way link going to->from
655
- # If we do, we use it.
656
- c = oneway_link?(to, from)
657
- if c
658
- debug "FOUND LINK #{c} -- filling it."
659
- idx = from.exits.index(c)
660
- from[idx] = nil
661
- from[dir] = c
662
- c.dir = Connection::BOTH
663
- c.exitBtext = go if go
664
- end
665
- end
666
-
667
- if not c
668
- debug "NEW LINK #{from} #{dir} to #{to} #{odir}"
669
- begin
670
- c = @map.new_connection(from, dir, to, odir)
671
- c.exitAtext = go if go
672
- c.dir = Connection::AtoB
673
- c.type = type
674
- rescue Section::ConnectionError
675
- end
676
- end
677
- }
678
-
679
- return from
680
- end
681
-
682
- #
683
- # Create all the stuff we found
684
- #
685
- def create
686
- @rooms = @rooms.sort_by { |r| r.num_exits }
687
- @rooms.reverse!
688
-
689
- @rooms.each { |r|
690
- min, max = @map.sections[@map.section].min_max_rooms
691
- create_room(r, max[0] + 2, 0)
692
- }
693
- @rooms = []
694
-
695
- # Add objects to rooms
696
- @objects.each { |obj|
697
- obj.location.each { |loc|
698
- r = @tags[loc]
699
- next unless r and r.kind_of?(Room)
700
- r.objects << obj.name + "\n"
701
- }
702
- }
703
- end
704
-
705
-
706
- if RUBY_PLATFORM =~ /win/
707
- SEP = ';'
708
- else
709
- SEP = ':'
710
- end
711
-
712
- #
713
- # Bring up the Inform properties window, to allow user to change
714
- # settings
715
- #
716
- def properties
717
- decor = DECOR_TITLE|DECOR_BORDER
718
-
719
- dlg = FXDialogBox.new( @map.window.parent, "Inform Settings", decor )
720
- mainFrame = FXVerticalFrame.new(dlg,
721
- FRAME_SUNKEN|FRAME_THICK|
722
- LAYOUT_FILL_X|LAYOUT_FILL_Y)
723
-
724
- frame = FXHorizontalFrame.new(mainFrame, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
725
-
726
- FXLabel.new(frame, "Include Dirs: ", nil, 0, LAYOUT_FILL_X)
727
- inc = FXTextField.new(frame, 80, nil, 0, LAYOUT_FILL_ROW)
728
- inc.text = @include_dirs.join(SEP)
729
-
730
- buttons = FXHorizontalFrame.new(mainFrame,
731
- LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|
732
- PACK_UNIFORM_WIDTH)
733
- # Accept
734
- FXButton.new(buttons, "&Accept", nil, dlg, FXDialogBox::ID_ACCEPT,
735
- FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
736
-
737
- # Cancel
738
- FXButton.new(buttons, "&Cancel", nil, dlg, FXDialogBox::ID_CANCEL,
739
- FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
740
- if dlg.execute != 0
741
- @include_dirs = inc.text.split(SEP)
742
- return true
743
- end
744
- return false
745
- end
746
-
747
-
748
-
749
433
  def set_include_dirs
750
434
  # Try to find inform(.exe) in path.
751
435
  paths = ENV['PATH'].split(SEP)
@@ -757,42 +441,19 @@ EOF
757
441
  @include_dirs << p + "/Base"
758
442
  @include_dirs << p + "/Contrib"
759
443
  @include_dirs << p + "/../Contrib"
444
+ @include_dirs << p + "/../Lib/Contrib"
760
445
  break
761
446
  end
762
447
  }
763
448
  }
764
449
  end
765
450
 
451
+
766
452
  def initialize(file, map = Map.new('Inform Map'))
767
453
  debug "Initialize"
768
454
  @classes = { 'Object' => {} }
769
- @tags = {}
770
- @map = map
771
- @objects = []
772
- @doors = []
773
- @functions = []
774
- @rooms = []
775
-
776
- @include_dirs = [File.dirname(file)]
777
- set_include_dirs
778
-
779
-
780
- debug "Get properties"
781
- if @map.kind_of?(FXMap)
782
- return unless properties
783
- end
784
-
785
- debug "Start parsing #{file}"
786
- File.open(file) { |f|
787
- parse(f)
788
- }
789
- debug "Done parsing #{file}"
790
- puts "Rooms: #{@rooms.size}"
791
- puts "Doors: #{@doors.size}"
792
- puts "Objects: #{@objects.size}"
793
455
 
794
- create
795
- debug "Done creating #{file}"
456
+ super
796
457
 
797
458
  if @map.kind_of?(FXMap)
798
459
  @map.filename = file.sub(/\.inf$/i, '.map')