ifmapper 0.9.6 → 0.9.7

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