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