ifmapper 0.9.5 → 0.9.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.
- data/HISTORY.txt +66 -0
- data/IFMapper.gemspec +2 -2
- data/lib/IFMapper/FXConnection.rb +1 -0
- data/lib/IFMapper/FXMap.rb +9 -10
- data/lib/IFMapper/FXMapFileDialog.rb +1 -1
- data/lib/IFMapper/FXMapperWindow.rb +49 -8
- data/lib/IFMapper/FXRoomDialogBox.rb +1 -1
- data/lib/IFMapper/InformReader.rb +39 -25
- data/lib/IFMapper/Room.rb +1 -3
- data/lib/IFMapper/TADSReader.rb +170 -103
- data/lib/IFMapper/TranscriptDialogBox.rb +74 -16
- data/lib/IFMapper/TranscriptReader.rb +73 -34
- data/maps/AMFV.map +0 -0
- data/maps/AllRoads.map +0 -0
- data/maps/CityOfSecrets.map +0 -0
- data/maps/Janitor.map +0 -0
- data/maps/Tangle.map +0 -0
- data/maps/balances.map +0 -0
- data/maps/bear.map +0 -0
- data/maps/break_in.map +0 -0
- data/maps/deadline.map +0 -0
- data/maps/delusions.map +0 -0
- data/maps/dreamhold.map +0 -0
- data/maps/drift3.map +0 -0
- data/maps/eas.map +0 -0
- data/maps/eas2.map +0 -0
- data/maps/eas3.map +0 -0
- data/maps/fallacy.map +0 -0
- data/maps/heist.map +0 -0
- data/maps/heroes.map +0 -0
- data/maps/lurkinghorror.map +0 -0
- data/maps/moonmist.map +0 -0
- data/maps/photograph.map +0 -0
- data/maps/pkgirl.map +0 -0
- data/maps/risorgimento.map +0 -0
- data/maps/sherbet.map +0 -0
- data/maps/slouch.map +0 -0
- data/maps/wasp.map +0 -0
- data/maps/zerosum.map +0 -0
- metadata +21 -9
data/HISTORY.txt
CHANGED
@@ -1,3 +1,69 @@
|
|
1
|
+
v0.9.6 What's new:
|
2
|
+
|
3
|
+
- IFM exporting had gotten broken around v0.9 due to a refactoring
|
4
|
+
bug. Fixed.
|
5
|
+
|
6
|
+
- CTRL selection was never quite working as advertised. Now it
|
7
|
+
properly does toggle selecting of rooms/connections.
|
8
|
+
|
9
|
+
- Minor improvement to the automapper. Now places that have Dr.,
|
10
|
+
St., Ave. and Inc. in them will be recognized as locations.
|
11
|
+
Previously, they were ignored due to the period.
|
12
|
+
|
13
|
+
- The automapper will now correctly parse objects from take commands
|
14
|
+
when the response is something like:
|
15
|
+
You take the pencil from the bag.
|
16
|
+
Previously, the object was considered to be 'pencil from the bag'
|
17
|
+
instead of just 'pencil'.
|
18
|
+
|
19
|
+
- Slight improvement to the automapper room description
|
20
|
+
identification. When comparing descriptions and a perfect match
|
21
|
+
or submatch of the description cannot be found against a room, all
|
22
|
+
words in that room description will be compared for a
|
23
|
+
potential match. A room will be matched as already present if
|
24
|
+
at least 20 words match (they also have to be in the same order).
|
25
|
+
However, if multiple rooms happen to match 20 words, then the room
|
26
|
+
with more words matched will be considered as the correct match.
|
27
|
+
This improvement helps with locations that have identical
|
28
|
+
descriptions but that perhaps only change the exit paths.
|
29
|
+
|
30
|
+
- I bug fixed the problem with TADS transcripts with the automapper
|
31
|
+
crashing it. This was supposed to be fixed in 0.9.5 but I had
|
32
|
+
inadvertedly reverted the fix before release.
|
33
|
+
|
34
|
+
- Added a new mode to Automapper of transcripts. The new
|
35
|
+
mode is called Capitalized and helps map rooms where the room name
|
36
|
+
uses a single capitalized sentence, like:
|
37
|
+
Women's change room
|
38
|
+
Western closet
|
39
|
+
instead of the more standard:
|
40
|
+
Women's Change Room
|
41
|
+
Western Closet
|
42
|
+
This format seems somewhat popular among IFComp entries, which are
|
43
|
+
probably trying to follow Infocom's format, but do so incorrectly.
|
44
|
+
|
45
|
+
- Added a new ADRIFT mode to Automapper. This mode helps map
|
46
|
+
ADRIFT games, which have some weird form of transcripts, lacking a
|
47
|
+
prompt. Tested with The PK Girl mainly.
|
48
|
+
|
49
|
+
- TADS3 source code reader is now much improved.
|
50
|
+
It recognizes PathPassages, TravelMessage and noTravel
|
51
|
+
exits properly.
|
52
|
+
It does not consider a missing room as a fatal error and
|
53
|
+
will properly find names of rooms when room line is split into
|
54
|
+
multiple lines.
|
55
|
+
It will also display passage and stairway exits properly (previously,
|
56
|
+
they were considered door exits).
|
57
|
+
Also, TADS3 reader can now properly parse a t3m Makefile for
|
58
|
+
sources.
|
59
|
+
You should now be able to map the big TADS3 demo game
|
60
|
+
Return to Ditch Day from source, which previously would run
|
61
|
+
into some issues.
|
62
|
+
|
63
|
+
- TADS and Inform readers now use a slightly different algorithm for
|
64
|
+
laying out rooms. This new algorithm results in smaller maps and
|
65
|
+
usually less complex exits failing.
|
66
|
+
|
1
67
|
v0.9.5 What's new:
|
2
68
|
|
3
69
|
- IFMapper now looks for Fox1.4 and 1.2, in that order. Note that
|
data/IFMapper.gemspec
CHANGED
@@ -2,7 +2,7 @@ require "rubygems"
|
|
2
2
|
|
3
3
|
spec = Gem::Specification.new do |spec|
|
4
4
|
spec.name = "ifmapper"
|
5
|
-
spec.version = '0.9.
|
5
|
+
spec.version = '0.9.6'
|
6
6
|
spec.author = "Gonzalo Garramuno"
|
7
7
|
spec.email = 'ggarram@advance.dsl.com.ar'
|
8
8
|
spec.homepage = 'http://www.rubyforge.org/projects/ifmapper/'
|
@@ -17,5 +17,5 @@ EOF
|
|
17
17
|
spec.extra_rdoc_files = ["HISTORY.txt", "TODO.txt", "IFMapper.gemspec"]
|
18
18
|
spec.has_rdoc = true
|
19
19
|
spec.rubyforge_project = 'ifmapper'
|
20
|
-
spec.required_ruby_version = '>= 1.
|
20
|
+
spec.required_ruby_version = '>= 1.8.0'
|
21
21
|
end
|
@@ -345,6 +345,7 @@ class FXConnection < Connection
|
|
345
345
|
# Draw any exit text if available (exit text is 'U', 'D', 'I', 'O', etc)
|
346
346
|
#
|
347
347
|
def draw_exit_text(dc, zoom)
|
348
|
+
return if zoom < 0.5
|
348
349
|
if @exitText[0] != 0
|
349
350
|
dir = @room[0].exits.index(self)
|
350
351
|
x, y = @room[0].corner(self, zoom, dir)
|
data/lib/IFMapper/FXMap.rb
CHANGED
@@ -875,10 +875,10 @@ class FXMap < Map
|
|
875
875
|
w = x2 - x1
|
876
876
|
h = y2 - y1
|
877
877
|
|
878
|
-
x1 = (x1 / WW).floor
|
879
|
-
y1 = (y1 / HH).floor
|
880
|
-
x2 = (x2 / WW).ceil
|
881
|
-
y2 = (y2 / HH).ceil
|
878
|
+
x1 = ((x1 - WS_2) / WW).floor
|
879
|
+
y1 = ((y1 - HS_2) / HH).floor
|
880
|
+
x2 = ((x2 - WS_2) / WW).ceil
|
881
|
+
y2 = ((y2 - HS_2) / HH).ceil
|
882
882
|
|
883
883
|
@sections[@section].rooms.each { |r|
|
884
884
|
if r.x >= x1 and r.x <= x2 and
|
@@ -1156,12 +1156,13 @@ class FXMap < Map
|
|
1156
1156
|
draw
|
1157
1157
|
return
|
1158
1158
|
else
|
1159
|
-
if event.state & SHIFTMASK == 0
|
1159
|
+
if event.state & SHIFTMASK == 0 and
|
1160
|
+
event.state & CONTROLMASK == 0
|
1160
1161
|
clear_selection
|
1161
1162
|
end
|
1162
1163
|
# Select the stuff
|
1163
1164
|
selection.update_properties(self)
|
1164
|
-
if event.state & CONTROLMASK
|
1165
|
+
if event.state & CONTROLMASK != 0
|
1165
1166
|
selection.selected ^= true # toggle selection
|
1166
1167
|
else
|
1167
1168
|
selection.selected = true
|
@@ -1478,10 +1479,8 @@ class FXMap < Map
|
|
1478
1479
|
end
|
1479
1480
|
|
1480
1481
|
def cannot_automap(why)
|
1481
|
-
p '----CANNOT AUTOMAP'
|
1482
1482
|
w = FXWarningBox.new(@window, "Cannot automap.\n#{why}")
|
1483
1483
|
w.execute
|
1484
|
-
p '----CANNOT AUTOMAP AFTER EXECUTE'
|
1485
1484
|
end
|
1486
1485
|
|
1487
1486
|
|
@@ -1965,7 +1964,7 @@ class FXMap < Map
|
|
1965
1964
|
def export_ifm(file)
|
1966
1965
|
require 'IFMapper/IFMWriter'
|
1967
1966
|
file += '.ifm' if file !~ /\.ifm$/
|
1968
|
-
IFMWriter.new(
|
1967
|
+
IFMWriter.new(self, file)
|
1969
1968
|
end
|
1970
1969
|
|
1971
1970
|
|
@@ -2048,6 +2047,7 @@ class FXMap < Map
|
|
2048
2047
|
begin
|
2049
2048
|
@automap = TranscriptReader.new(self, file)
|
2050
2049
|
@automap.properties(true)
|
2050
|
+
@automap.start
|
2051
2051
|
rescue Errno::EACCES, Errno::ENOENT => e
|
2052
2052
|
dlg = FXWarningBox.new(@window, "Cannot open transcript\n#{e}")
|
2053
2053
|
dlg.execute
|
@@ -2058,7 +2058,6 @@ class FXMap < Map
|
|
2058
2058
|
dlg.execute
|
2059
2059
|
raise
|
2060
2060
|
end
|
2061
|
-
@automap.start
|
2062
2061
|
create_pathmap
|
2063
2062
|
draw
|
2064
2063
|
update_title
|
@@ -59,7 +59,7 @@ require 'IFMapper/FXRoomList'
|
|
59
59
|
class FXMapperWindow < FXMainWindow
|
60
60
|
|
61
61
|
PROGRAM_NAME = "Interactive Fiction Mapper"
|
62
|
-
VERSION = '0.9.
|
62
|
+
VERSION = '0.9.6'
|
63
63
|
AUTHOR = "Gonzalo Garramuno"
|
64
64
|
TITLE = "#{PROGRAM_NAME} v#{VERSION} - Written by #{AUTHOR}"
|
65
65
|
|
@@ -84,7 +84,7 @@ class FXMapperWindow < FXMainWindow
|
|
84
84
|
begin
|
85
85
|
IFMReader.new(file, map)
|
86
86
|
rescue => e
|
87
|
-
return e
|
87
|
+
return "#{e} #{e.backtrace}"
|
88
88
|
end
|
89
89
|
return map
|
90
90
|
end
|
@@ -94,7 +94,7 @@ class FXMapperWindow < FXMainWindow
|
|
94
94
|
begin
|
95
95
|
TADSReader.new(file, map)
|
96
96
|
rescue => e
|
97
|
-
return e
|
97
|
+
return "#{e} #{e.backtrace}"
|
98
98
|
end
|
99
99
|
return map
|
100
100
|
end
|
@@ -104,7 +104,7 @@ class FXMapperWindow < FXMainWindow
|
|
104
104
|
begin
|
105
105
|
InformReader.new(file, map)
|
106
106
|
rescue => e
|
107
|
-
return e
|
107
|
+
return "#{e} #{e.backtrace}"
|
108
108
|
end
|
109
109
|
return map
|
110
110
|
end
|
@@ -172,13 +172,14 @@ class FXMapperWindow < FXMainWindow
|
|
172
172
|
tmp = open_ifm(file, map)
|
173
173
|
elsif file =~ /\.inf$/i
|
174
174
|
tmp = open_inform(file, map)
|
175
|
-
elsif file =~ /\.t$/i
|
175
|
+
elsif file =~ /\.t$/i or file =~ /\.t3m$/
|
176
176
|
tmp = open_tads(file, map)
|
177
177
|
else
|
178
178
|
tmp = open_map(file)
|
179
179
|
end
|
180
180
|
|
181
181
|
if not tmp.kind_of?(Map) and not tmp.kind_of?(FXMap)
|
182
|
+
$stderr.puts tmp
|
182
183
|
status "Could not load '#{file}'. Error: #{tmp}."
|
183
184
|
if make_new_map
|
184
185
|
if map.close_cb
|
@@ -755,6 +756,43 @@ class FXMapperWindow < FXMainWindow
|
|
755
756
|
@search.show
|
756
757
|
end
|
757
758
|
|
759
|
+
#
|
760
|
+
# Find task in map
|
761
|
+
#
|
762
|
+
def find_desc_in_map(s, m, e)
|
763
|
+
map = current_map
|
764
|
+
return unless map
|
765
|
+
|
766
|
+
re = /#{s.text}/
|
767
|
+
matches = []
|
768
|
+
(0...map.sections.size).each { |p|
|
769
|
+
map.sections[p].rooms.each { |r|
|
770
|
+
next unless r.desc =~ re
|
771
|
+
matches.push( [p, r] )
|
772
|
+
}
|
773
|
+
}
|
774
|
+
idx = @search.index
|
775
|
+
@search.index = matches.size-1 if idx >= matches.size
|
776
|
+
hilite_matches(map, matches, re, @search.index)
|
777
|
+
end
|
778
|
+
|
779
|
+
#
|
780
|
+
# Find description in map
|
781
|
+
#
|
782
|
+
def find_desc_in_map_cb(s, m, e)
|
783
|
+
map = current_map
|
784
|
+
return unless map
|
785
|
+
|
786
|
+
title = "Find In Description In Map"
|
787
|
+
if not @search
|
788
|
+
@search = FXSearchDialogBox.new(self)
|
789
|
+
end
|
790
|
+
@search.proc = method(:find_desc_in_map)
|
791
|
+
@search.title = title
|
792
|
+
@search.text = ''
|
793
|
+
@search.show
|
794
|
+
end
|
795
|
+
|
758
796
|
#
|
759
797
|
# Pop-up color preferences
|
760
798
|
#
|
@@ -803,12 +841,12 @@ class FXMapperWindow < FXMainWindow
|
|
803
841
|
|
804
842
|
def about_cb(sender, id, event )
|
805
843
|
FXAboutDialogBox.new(self, "About This Software...", <<"EOF").execute
|
806
|
-
#{
|
844
|
+
#{PROGRAM_NAME} - #{VERSION}
|
845
|
+
Written by Gonzalo Garramuno.
|
807
846
|
|
808
847
|
FXRuby Version: #{Fox::fxrubyversion}
|
809
848
|
|
810
849
|
A WYSIWYG mapping tool for interactive fiction.
|
811
|
-
Written by Gonzalo Garramuno.
|
812
850
|
|
813
851
|
ggarra@advancedsl.com.ar
|
814
852
|
EOF
|
@@ -899,6 +937,8 @@ EOF
|
|
899
937
|
cmd.connect(SEL_COMMAND, method(:find_object_in_map_cb))
|
900
938
|
cmd = FXMenuCommand.new(submenu, "&Task in Map\tAlt-T\tFind Location with a Task in the Map")
|
901
939
|
cmd.connect(SEL_COMMAND, method(:find_task_in_map_cb))
|
940
|
+
cmd = FXMenuCommand.new(submenu, "&Keyword in Descriptions\tAlt-D\tFind Location with Description Keyword in the Map")
|
941
|
+
cmd.connect(SEL_COMMAND, method(:find_desc_in_map_cb))
|
902
942
|
FXMenuCascade.new(editmenu, "Search", nil, submenu)
|
903
943
|
|
904
944
|
# Complex Connection
|
@@ -1189,7 +1229,8 @@ EOF
|
|
1189
1229
|
|
1190
1230
|
cmd = FXMenuCommand.new(helpmenu, "&Resource Code", nil)
|
1191
1231
|
cmd.connect(SEL_COMMAND) {
|
1192
|
-
file = FXMapFileDialog.new(self, "Resource a Ruby File"
|
1232
|
+
file = FXMapFileDialog.new(self, "Resource a Ruby File",
|
1233
|
+
['Ruby File (*.rb)']).filename
|
1193
1234
|
if file != ''
|
1194
1235
|
begin
|
1195
1236
|
Kernel.load file
|
@@ -10,7 +10,7 @@ class FXRoomDialogBox < FXDialogBox
|
|
10
10
|
def copy_to()
|
11
11
|
@room.name = @name.text
|
12
12
|
@room.objects = @objects.text
|
13
|
-
@room.objects.gsub!(/[
|
13
|
+
@room.objects.gsub!(/[,\t]+/, "\n")
|
14
14
|
@room.tasks = @tasks.text
|
15
15
|
@room.darkness = (@darkness.checkState == 1)
|
16
16
|
@room.desc = @desc.text
|
@@ -13,7 +13,7 @@ class InformReader
|
|
13
13
|
|
14
14
|
# Take a quoted Inform string and return a valid ASCII one, replacing
|
15
15
|
# Inform's special characters.
|
16
|
-
def self.
|
16
|
+
def self.unquote(text)
|
17
17
|
return '' unless text
|
18
18
|
text.gsub!(/\~/, '"')
|
19
19
|
text.gsub!(/\^/, "\n")
|
@@ -29,7 +29,7 @@ class InformReader
|
|
29
29
|
attr_accessor :tag, :location, :enterable
|
30
30
|
|
31
31
|
def name=(x)
|
32
|
-
@name = InformReader::
|
32
|
+
@name = InformReader::unquote(x)
|
33
33
|
end
|
34
34
|
|
35
35
|
def to_s
|
@@ -67,7 +67,10 @@ class InformReader
|
|
67
67
|
"#@name tag:#@tag"
|
68
68
|
end
|
69
69
|
def name=(x)
|
70
|
-
@name = InformReader::
|
70
|
+
@name = InformReader::unquote(x)
|
71
|
+
end
|
72
|
+
def num_exits
|
73
|
+
return @exits.nitems
|
71
74
|
end
|
72
75
|
def method_missing(*x)
|
73
76
|
end
|
@@ -492,20 +495,25 @@ EOF
|
|
492
495
|
return best
|
493
496
|
end
|
494
497
|
|
495
|
-
def make_room(
|
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 )
|
496
514
|
elem = @tags[to.tag]
|
497
515
|
if elem.kind_of?(InformRoom)
|
498
|
-
|
499
|
-
@map.shift(x, y, dx, dy)
|
500
|
-
end
|
501
|
-
room = @map.new_room(x, y)
|
502
|
-
room.name = to.name
|
503
|
-
desc = to.desc
|
504
|
-
desc.gsub!(/[\t\n]/, ' ')
|
505
|
-
desc.squeeze!(' ')
|
506
|
-
room.desc = InformReader::inform_unquote(desc)
|
507
|
-
room.darkness = !to.light
|
508
|
-
@tags[to.tag] = room
|
516
|
+
room = create_room(to, x, y, dx, dy)
|
509
517
|
return [room, Connection::FREE]
|
510
518
|
elsif elem.kind_of?(InformDoor)
|
511
519
|
if elem.locked
|
@@ -519,8 +527,8 @@ EOF
|
|
519
527
|
o.exits.each { |e|
|
520
528
|
next unless e
|
521
529
|
if @tags[e] == elem
|
522
|
-
res =
|
523
|
-
return [ res
|
530
|
+
res = create_room( o, x, y, dx, dy )
|
531
|
+
return [ res, type ]
|
524
532
|
end
|
525
533
|
}
|
526
534
|
}
|
@@ -530,8 +538,8 @@ EOF
|
|
530
538
|
next if @tags[tag] == from
|
531
539
|
@rooms.each { |o|
|
532
540
|
next if o.tag != tag
|
533
|
-
res =
|
534
|
-
return [ res
|
541
|
+
res = create_room( o, x, y, dx, dy )
|
542
|
+
return [ res, type ]
|
535
543
|
}
|
536
544
|
}
|
537
545
|
|
@@ -542,8 +550,9 @@ EOF
|
|
542
550
|
end
|
543
551
|
end
|
544
552
|
|
545
|
-
def create_room(r, x, y, dx =
|
546
|
-
|
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)
|
547
556
|
debug "CREATE ROOM #{r.name} SET FROM TO: #{from}"
|
548
557
|
|
549
558
|
r.exits.each_with_index { |e, exit|
|
@@ -587,7 +596,7 @@ EOF
|
|
587
596
|
x = from.x + dx
|
588
597
|
y = from.y + dy
|
589
598
|
debug "#{exit} CREATE TO #{from} -> #{to.tag}"
|
590
|
-
to, type =
|
599
|
+
to, type = get_exit(from, to, x, y, dx, dy)
|
591
600
|
next if not to
|
592
601
|
end
|
593
602
|
|
@@ -667,14 +676,20 @@ EOF
|
|
667
676
|
end
|
668
677
|
}
|
669
678
|
|
670
|
-
return
|
679
|
+
return from
|
671
680
|
end
|
672
681
|
|
673
682
|
#
|
674
683
|
# Create all the stuff we found
|
675
684
|
#
|
676
685
|
def create
|
677
|
-
@rooms.
|
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
|
+
}
|
678
693
|
@rooms = []
|
679
694
|
|
680
695
|
# Add objects to rooms
|
@@ -781,7 +796,6 @@ EOF
|
|
781
796
|
|
782
797
|
if @map.kind_of?(FXMap)
|
783
798
|
@map.filename = file.sub(/\.inf$/i, '.map')
|
784
|
-
@map.navigation = true
|
785
799
|
@map.options['Location Description'] = true
|
786
800
|
@map.window.show
|
787
801
|
end
|