ifmapper 0.8 → 0.8.1

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