ifmapper 0.8 → 0.8.1

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 CHANGED
@@ -1,4 +1,16 @@
1
1
 
2
+ v0.8.1 - Just some fixes to the automapper, as it was failing on some relatively
3
+ simple games.
4
+
5
+ Automapper was not matching rooms with periods in them. This was
6
+ causing problems with games that had rooms like "Mr. Hellman's Bedroom".
7
+
8
+ Improved the handling of multiple directional commands. A command
9
+ like: 'n, e, w' is now handled properly.
10
+
11
+ Moved 'fox' requires together so it is easy to upgrade to
12
+ upcoming fox14.
13
+
2
14
  v0.8 - Added the ability to create linked rooms using the Numeric Keypad.
3
15
  Turn on NUM LOCK, select a single room and then use the numbers in
4
16
  the keypad to move thru an exit or add a room in a certain direction.
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.8'
5
+ spec.version = '0.8.1'
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/'
@@ -37,6 +37,7 @@ class Connection
37
37
  @exitBtext = 0
38
38
  end
39
39
 
40
+
40
41
  def stub?
41
42
  return true unless @roomB
42
43
  return false
@@ -787,9 +787,9 @@ class FXMap < Map
787
787
  # Based on mouse position on canvas, create a tooltip
788
788
  #
789
789
  def update_cb(sender, sel, event)
790
- if sel == FXWindow::ID_QUERY_TIP
791
- p "tooltip"
792
- end
790
+ # if sel == FXWindow::ID_QUERY_TIP
791
+ # p "tooltip"
792
+ # end
793
793
  end
794
794
 
795
795
  #
@@ -1216,6 +1216,8 @@ class FXMap < Map
1216
1216
  pix = []
1217
1217
  32.times { 32.times { pix << 255 << 255 << 255 << 255 } }
1218
1218
  pix = pix.pack('c*')
1219
+
1220
+
1219
1221
  ['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'].each { |d|
1220
1222
  eval(<<-"EOF")
1221
1223
  @@cursor_#{d} = FXGIFCursor.new(@window.getApp, pix)
@@ -1784,9 +1786,13 @@ class FXMap < Map
1784
1786
  pos = @scrollwindow.position
1785
1787
  w = @scrollwindow.getViewportWidth
1786
1788
  h = @scrollwindow.getViewportHeight
1789
+ cx = -pos[0]-5
1790
+ cx = 0 if cx < 0
1791
+ cy = -pos[1]-5
1792
+ cy = 0 if cy < 0
1787
1793
 
1788
1794
  dc = FXDCWindow.new(@image)
1789
- dc.setClipRectangle( -pos[0]-5, -pos[1]-5, w, h)
1795
+ dc.setClipRectangle( cx, cy, w, h)
1790
1796
  dc.font = @font
1791
1797
  #dc.lineCap = CAP_ROUND
1792
1798
  draw_background(dc, event)
@@ -1805,7 +1811,7 @@ class FXMap < Map
1805
1811
 
1806
1812
  # Blit the off-screen image into canvas
1807
1813
  dc = FXDCWindow.new(@canvas)
1808
- dc.setClipRectangle( -pos[0]-5, -pos[1]-5, w, h)
1814
+ dc.setClipRectangle( cx, cy, w, h)
1809
1815
  dc.drawImage(@image,0,0)
1810
1816
  dc.end
1811
1817
  end
@@ -1,5 +1,4 @@
1
1
 
2
- require 'fox12/colors'
3
2
 
4
3
  class FXMapColorBox < FXDialogBox
5
4
 
@@ -8,6 +8,7 @@ end
8
8
 
9
9
  begin
10
10
  require 'fox12'
11
+ require 'fox12/colors'
11
12
  rescue LoadError => e
12
13
  $stderr.puts "Please install the FXRuby (FOX) library v1.2 or later."
13
14
  if $rubygems
@@ -130,6 +131,7 @@ class FXMapperWindow < FXMainWindow
130
131
  end
131
132
 
132
133
  map.copy(tmp)
134
+ map.fit
133
135
  map.create_pathmap
134
136
  map.verify_integrity
135
137
  map.window.create
@@ -134,6 +134,7 @@ class FXRoom < Room
134
134
  #
135
135
  def draw(dc, zoom, idx, opt, data)
136
136
  draw_box(dc, zoom, idx, opt)
137
+ return if zoom < 0.5
137
138
  dc.font = data['font']
138
139
  x, y = draw_name(dc, zoom)
139
140
  dc.font = data['objfont']
@@ -180,7 +181,7 @@ class FXRoom < Room
180
181
  dc.drawRectangle(x, y, w, h)
181
182
 
182
183
  # Draw grey square for index
183
- if opt['Location Numbers']
184
+ if opt['Location Numbers'] and zoom >= 0.5
184
185
  dc.foreground = opt['Box Number Color']
185
186
  x += w # Index goes at bottom right of square
186
187
  y += h
@@ -20,11 +20,10 @@ class TranscriptReader
20
20
  OTHERS = /^(read|inventory$|i$)/i
21
21
  UNSCRIPT = /^unscript$/i
22
22
  BLANK = /^\s*$/
23
- MOVE = /^(walk|run|go)\s+/i
24
23
  TAKE = /^(take|get)\s+(a\s+|the\s+)?(.*)/i
25
24
  DROP = /^(drop|leave)\s+()/i
26
25
  STARTUP = /(^[A-Z]+$|Copyright|\([cC]\)\s*\d|Trademark|Release|Version|[Ss]erial [Nn]umber|Written by)/
27
- DARKNESS = /dark/i
26
+ DARKNESS = /dark|It is pitch black/i
28
27
  DEAD = /(You die|You have died|You are dead)/i
29
28
 
30
29
  # Compass direction command -> direction mapping.
@@ -38,11 +37,15 @@ class TranscriptReader
38
37
  ODIRMAP = {"up" => 1, "u" => 1, "down" => 2, "d" => 2,
39
38
  "in" => 3, "out" => 4, 'enter' => 3, 'exit' => 4 }
40
39
 
40
+ DIR_REX = '(' + DIRMAP.keys.join('|') + '|' + ODIRMAP.keys.join('|') + ')'
41
+ GO = /^((walk|run|go)\s+)?#{DIR_REX}[.,\s]*\b/i
42
+
41
43
  # Direction list in order of positioning preference.
42
44
  DIRLIST = [ 0, 4, 2, 6, 1, 3, 5, 7 ]
43
45
 
44
46
  NAME_REMOVE = /(\s+\(.+\)|,\s+[io]n\s+.+)/ # remove things like (on the bed)
45
- NAME_INVALID = /[\[\]\.!\?]/
47
+ NAME_INVALID = /[\[\]!\.\?\000]/
48
+ SALUTATIONS = /\b(Mr|Mr?s|Miss|Jr|Sr)\./
46
49
  NAME_MAXWORDS = 20
47
50
  NAME_MAXUNCAP = 4 # so that lowercase room/end will be accepted
48
51
 
@@ -51,7 +54,7 @@ class TranscriptReader
51
54
 
52
55
 
53
56
  ## Change this to non-dil to print out debugging info
54
- @@debug = nil
57
+ @@debug = 1
55
58
 
56
59
 
57
60
  def debug(*msg)
@@ -63,7 +66,7 @@ class TranscriptReader
63
66
  ## Possible nessages indicating get/take succeeded
64
67
  TAKE_OK = [
65
68
  /taken/i,
66
- /you\s+now\s+have\s+(got\s+)?the/i,
69
+ /you\s+now\s+have\s+(got\s+)?/i,
67
70
  ]
68
71
 
69
72
  IT = /^(it|them)$/
@@ -147,22 +150,24 @@ class TranscriptReader
147
150
  EXITS_REGEX =
148
151
  [
149
152
  # You can go south or east
150
- /you\s+can\s+go\s+#{DIR}\s+#{OR}\s+#{DIR}[,\.\s+]/i,
153
+ /you\s+can\s+go\s+#{DIR}\s+#{OR}\s+#{DIR}\b/i,
151
154
  # You can go south
152
- /you\s+can\s+go\s+#{DIR}[,\.\s+]/i,
155
+ /you\s+can\s+go\s+#{DIR}\b/i,
153
156
  # to the east or west
154
- /to\s+the\s+#{DIR}\s+#{OR}\s+#{DIR}[,\.\s+]/i,
157
+ /to\s+the\s+#{DIR}\s+#{OR}\s+#{DIR}\b/i,
155
158
  # to the east
156
- /to\s+the\s+#{DIR}[,\.\s+]/i,
159
+ /to\s+the\s+#{DIR}\b/i,
157
160
  # paths lead west and north
158
- /(run|lead|wander|winds)\s+#{DIR}\s+#{OR}\s+#{DIR}[,\.\s+]/i,
161
+ /(run|lead|wander|winds)\s+#{DIR}\s+#{OR}\s+#{DIR}\b/i,
159
162
  # east-west corridor
160
- /[\.\s+]#{DIR}[\/-]#{DIR}[,\.\s+]/i,
163
+ /[\.\s+]#{DIR}[\/-]#{DIR}\b/i,
161
164
  # East is the postoffice
162
- /[,\.\s+]#{DIR}\s+is/i,
165
+ /\b#{DIR}\s+is/i,
166
+ # Directly north
167
+ /\bDirectly\s+#{DIR}/i,
163
168
  # continues|lies|etc... east
164
- /(runs|leads|heads|opens|winds|continues|branches|lies|wanders|bends|curves)\s+#{DIR}[,\.\s+]/i,
165
- /(running|leading|heading|opening|branching|lying|wandering|looking|bending)\s+#{DIR}[,\.\s+]/i,
169
+ /(runs|leads|heads|opens|winds|continues|branches|lies|wanders|bends|curves)\s+#{DIR}\b/i,
170
+ /(running|leading|heading|opening|branching|lying|wandering|looking|bending)\s+#{DIR}\b/i,
166
171
  ]
167
172
 
168
173
  EXITS_SPECIAL = {
@@ -348,7 +353,6 @@ class TranscriptReader
348
353
 
349
354
  desc = room[:desc]
350
355
  line = move[:line]
351
- cmd = move[:cmd]
352
356
 
353
357
  # If we teleported, try to find room
354
358
  if room[:tele]
@@ -369,28 +373,33 @@ class TranscriptReader
369
373
  there = find_room(name, desc)
370
374
  next if there == @here
371
375
 
372
- cmd.sub!(MOVE, '')
373
- if DIRMAP[cmd]
374
- dir = DIRMAP[cmd]
376
+ if not cmd
377
+ debug "Oops... run out of commands."
378
+ break
379
+ end
380
+ cmd.sub!(GO, '')
381
+ dir = $3
382
+ debug "MOVED IN DIRECTION: #{dir} CMD LEFT:#{cmd}"
383
+ if DIRMAP[dir]
384
+ dir = DIRMAP[dir]
375
385
  go = nil
376
- cmd = nil
377
- elsif ODIRMAP[cmd]
378
- go = ODIRMAP[cmd]
386
+ elsif ODIRMAP[dir]
387
+ go = ODIRMAP[dir]
379
388
  dir = choose_dir(@here, there, go)
380
- cmd = nil
381
389
  else
382
390
  # special move ---
383
391
  dir = choose_dir(@here, there)
384
392
  go = nil
385
393
  end
394
+ debug "MOVED IN DIR INDEX: #{dir}"
386
395
 
387
396
  @here.selected = false
388
397
  if not there
389
398
  # Unvisited -- new room
390
- @here = new_room(move, name, desc, dir, @here, go, cmd)
399
+ @here = new_room(move, name, desc, dir, @here, go)
391
400
  else
392
401
  # Visited before -- new link
393
- new_link(move, @here, there, dir, go, cmd)
402
+ break unless new_link(move, @here, there, dir, go)
394
403
  @here = there
395
404
  end
396
405
  }
@@ -460,15 +469,19 @@ class TranscriptReader
460
469
  # Remove unwanted stuff
461
470
  line.sub!(NAME_REMOVE, '')
462
471
 
472
+ # Remove periods from salutations
473
+ line.sub!(SALUTATIONS, '\1')
474
+
463
475
  # quick check for invalid format
464
476
  return false if line =~ NAME_INVALID
477
+ # Qucik check for word characters
465
478
  return false unless line =~ /\w/
466
479
 
467
- # Check word count
480
+ # Check word count (if too many, not a room)
468
481
  words = line.split(' ')
469
482
  return false if words.size > NAME_MAXWORDS
470
483
 
471
- # Check uncapitalized words
484
+ # Check if we start line with uncapitalized words or symbols
472
485
  return false if line =~ /^[ a-z\/\\\-\(\)]/
473
486
 
474
487
  words.each { |w|
@@ -480,7 +493,7 @@ class TranscriptReader
480
493
  #
481
494
  # Create a new room
482
495
  #
483
- def new_room( move, name, desc, dir = nil, from = nil, go = nil, cmd = nil )
496
+ def new_room( move, name, desc, dir = nil, from = nil, go = nil )
484
497
  if not from
485
498
  debug "FROM undefined. Increase section #{name}"
486
499
  @section += 1
@@ -571,19 +584,31 @@ class TranscriptReader
571
584
  end
572
585
  end
573
586
 
574
- def new_link(move, from, to, dir, go, cmd)
587
+
588
+ def new_link(move, from, to, dir, go)
575
589
  odir = (dir + 4) % 8
576
590
  c = nil
591
+ # If we have something in the from direction
577
592
  if from[dir]
578
593
  c = from[dir]
579
594
  debug "\tMOVE #{c} DIR: #{dir}"
580
- if not c.roomB
595
+ if c.stub?
581
596
  # Stub connection, fill it
582
597
  c.roomB = to
583
- debug "\tREMOVE #{to[odir]}"
584
- @map.delete_connection(to[odir]) if to[odir] and to[odir].stub?
598
+ # we still need to check the destination to[odir]...
599
+ if not to[odir]
600
+ # nothing to do
601
+ elsif to[odir].stub?
602
+ @map.delete_connection(to[odir])
603
+ debug "\tREMOVE #{to[odir]}"
604
+ else
605
+ # this end cannot be deleted. we need to shift odir
606
+ debug "\tCHOOSE NEW DIR for #{odir}"
607
+ odir = choose_dir(to, from, go, dir)
608
+ @map.delete_connection(to[odir]) if to[odir]
609
+ debug "\tSHIFTED DESTINATION TO EXIT #{odir}"
610
+ end
585
611
  to[odir] = c
586
- debug "\tREPLACED WITH #{c}"
587
612
  elsif c.roomB == to
588
613
  # We already went this way. Nothing to do.
589
614
  debug "\tWE ALREADY PASSED THRU HERE"
@@ -594,27 +619,34 @@ class TranscriptReader
594
619
  debug "\tSECTION: #{@map.section}"
595
620
  debug "\tVERIFIED EXIT BOTH WAYS"
596
621
  else
597
- if c.roomA == from
622
+ debug "\tOTHER"
623
+ if c.roomA == from and c.dir != Connection::BtoA
598
624
  b = c.roomB
599
625
  if b.name =~ DARKNESS
626
+ debug "*** REPLACING DARK ROOM ***"
600
627
  @map.delete_connection(c)
601
628
  @map.delete_room(b)
602
629
  to.darkness = true
603
630
  c = nil
604
631
  else
632
+ debug "*** CANNOT AUTOMAP --- MAZE ***"
605
633
  dir = Room::DIRECTIONS[dir]
606
634
  @map.cannot_automap "Maze detected.\n'#{from}' #{dir} leads to '#{c.roomB}',\nnot to this '#{to}'."
635
+ self.stop
607
636
  return nil
608
637
  end
609
638
  else
639
+ debug "SHIFT LINK #{from} #{dir}"
610
640
  # We have a connection that turns. Move the link around
611
641
  shift_link(from, dir)
612
642
  c = nil
613
643
  end
614
644
  end
615
- elsif to[odir]
645
+ end
646
+
647
+ if not c and to[odir]
616
648
  c = to[odir]
617
- if not c.roomB
649
+ if c.stub?
618
650
  debug "\tREMOVE #{to[odir]} and REPLACE with #{c}"
619
651
  # Stub connection, fill it
620
652
  c.roomB = from
@@ -626,8 +658,8 @@ class TranscriptReader
626
658
  c.exitBtext = go if go
627
659
  else
628
660
  # We need to change odir to something else
629
- # shift_link(to, odir)
630
- odir = choose_dir(to, from, go)
661
+ odir = choose_dir(to, from, go, dir)
662
+ @map.delete_connection(to[odir]) if to[odir] and to[odir].stub?
631
663
  c = nil
632
664
  end
633
665
  end
@@ -656,7 +688,8 @@ class TranscriptReader
656
688
  c = @map.new_connection( from, dir, to, odir )
657
689
  c.exitAtext = go if go
658
690
  c.dir = Connection::AtoB
659
- rescue
691
+ rescue => e
692
+ $stderr.puts e
660
693
  end
661
694
  end
662
695
 
@@ -665,9 +698,7 @@ class TranscriptReader
665
698
 
666
699
 
667
700
  # Choose a direction to represent up/down/in/out.
668
- def choose_dir(a, b, go = nil)
669
- best = nil
670
- bestscore = 0
701
+ def choose_dir(a, b, go = nil, exitB = nil)
671
702
  if go
672
703
  rgo = go % 2 == 0? go - 1 : go + 1
673
704
  debug "#{Connection::EXIT_TEXT[go]} <=> #{Connection::EXIT_TEXT[rgo]}"
@@ -686,34 +717,63 @@ class TranscriptReader
686
717
  }
687
718
  end
688
719
 
720
+ # We prefer directions that travel less... so we need to figure
721
+ # out where we start from...
722
+ if b
723
+ x = b.x
724
+ y = b.y
725
+ else
726
+ x = a.x
727
+ y = a.y
728
+ end
729
+ if exitB
730
+ dx, dy = Room::DIR_TO_VECTOR[exitB]
731
+ x += dx
732
+ y += dy
733
+ end
734
+
689
735
  # No such luck... Pick a direction.
736
+ best = nil
737
+ bestscore = nil
738
+
690
739
  DIRLIST.each { |dir|
691
740
  # We prefer straight directions to diagonal ones
692
- inc = dir % 2 == 1 ? 1 : 3
693
- rdir = (dir + 4) % 8
694
- score = 0
741
+ inc = dir % 2 == 1 ? 10 : 14
742
+ score = 1000
695
743
  # We prefer directions where both that dir and the opposite side
696
744
  # are empty.
697
- score += inc unless a[dir]
698
- score += 1 unless a[rdir]
699
- next if score <= bestscore
745
+ if (not a[dir]) or a[dir].stub?
746
+ score += inc
747
+ score += 4 if a[dir] #attaching to stubs is better
748
+ end
749
+ # rdir = (dir + 4) % 8
750
+ # score += 1 unless a[rdir]
751
+
752
+ # Measure distance for that exit, we prefer shorter
753
+ # paths
754
+ dx, dy = Room::DIR_TO_VECTOR[dir]
755
+ dx = (a.x + dx) - x
756
+ dy = (a.y + dy) - y
757
+ d = dx * dx + dy * dy
758
+ score -= d
759
+ next if bestscore and score <= bestscore
700
760
  bestscore = score
701
761
  best = dir
702
762
  }
703
763
 
704
- if bestscore == 0
705
- $stderr.puts "No free exit for up/down"
764
+ if not bestscore
765
+ raise "No free exit for choose_dir"
706
766
  end
707
767
 
708
768
  return best
709
769
  end
710
770
 
711
771
  def stop
712
- @t.stop
772
+ @t.stop if @t
713
773
  end
714
774
 
715
775
  def destroy
716
- @t.kill
776
+ @t.kill if @t
717
777
  @f.close
718
778
  GC.start
719
779
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.10
3
3
  specification_version: 1
4
4
  name: ifmapper
5
5
  version: !ruby/object:Gem::Version
6
- version: "0.8"
7
- date: 2005-08-20
6
+ version: 0.8.1
7
+ date: 2005-08-21
8
8
  summary: Interactive Fiction Mapping Tool.
9
9
  require_paths:
10
10
  - lib
@@ -32,18 +32,18 @@ files:
32
32
  - lib/IFMapper/Map.rb
33
33
  - lib/IFMapper/FXSpline.rb
34
34
  - lib/IFMapper/FXSection.rb
35
+ - lib/IFMapper/FXRoom.rb
35
36
  - lib/IFMapper/FXMapDialogBox.rb
36
37
  - lib/IFMapper/FXSectionDialogBox.rb
37
38
  - lib/IFMapper/FXMapperWindow.rb
38
39
  - lib/IFMapper/Room.rb
39
40
  - lib/IFMapper/Section.rb
41
+ - lib/IFMapper/FXConnection.rb
42
+ - lib/IFMapper/FXMapColorBox.rb
40
43
  - lib/IFMapper/IFMWriter.rb
41
44
  - lib/IFMapper/FXWarningBox.rb
42
- - lib/IFMapper/FXMapColorBox.rb
43
45
  - lib/IFMapper/PDFMapExporter.rb
44
46
  - lib/IFMapper/FXMapperSettings.rb
45
- - lib/IFMapper/FXRoom.rb
46
- - lib/IFMapper/FXConnection.rb
47
47
  - lib/IFMapper/AStar.rb
48
48
  - lib/IFMapper/Connection.rb
49
49
  - lib/IFMapper/MapPrinting.rb