OK, test this.
After a bit of research I have found an easy way to modify the fast route-finding algorithm so that it weights diagonal moves and orthogonal moves (by default, 7 & 5 respectively- but you can change this by changing global variables diagonal-length and orthogonal-length (integers only)). Setting both diagonal-length and orthogonal-length to 1 will replicate normal fast route-finding behaviour.
NB 1: if compiling for Z-machine, this will limit the maximum path length you can trace to a few hundred rooms (choosing smaller values for diagonal-length and orthogonal-length will increase this, and vice versa).
NB 2: ‘the number of moves from X to Y’ will now return (orthogonal_length x orthogonal moves) + (diagonal_length x diagonal_moves) rather than the number of discrete moves from room to room.
NB 3: This presently has an uncomfortable hard-coded dependency on diagonal directions being the 2nd, 3rd, 5th & 6th to be declared in the template, which is true for 6M62, but may break with updates or modification to “Output.i6t: Object Tree”.
With a bit more work this dependency could be removed, and a system even set up whereby named directions had individual and/or dynamically updateable weightings- for example, to dissuade from route-finding in northerly directions in a snowstorm…
"________Diagonals" by PB
AA is a Room. AB is east of AA. AC is east of AB. AD is east of AC.
BA is a Room. BB is east of BA. BC is east of BB. BD is east of BC.
BA is north of AA. BB is north of AB. BC is north of AC. BD is north of AD.
CA is a Room. CB is east of CA. CC is east of CB. CD is east of CC.
CA is north of BA. CB is north of BB. CC is north of BC. CD is north of BD.
DA is a Room. DB is east of DA. DC is east of DB. DD is east of DC.
DA is north of CA. DB is north of CB. DC is north of CC. DD is north of CD.
BB is northeast of AA. BB is northwest of AC.
BC is northeast of AB. BC is northwest of AD.
CB is northeast of BA. CB is northwest of BC.
CC is northeast of BB. CC is northwest of BD.
DB is northeast of CA. DB is northwest of CC.
DC is northeast of CB. DC is northwest of CD.
DA is northwest of CB. DD is northeast of CC.
BA is northwest of AB. BD is northeast of AC.
CA is northwest of BB. CD is northeast of BC.
TARGET is initially DD.[set this variable to the room you want the game to track you towards.]
Section - Testing
When play begins:
follow the distance meter rule;
Every turn (this is the distance meter rule):
say "the best way to [TARGET] is [best route from the location to TARGET] in [the number of moves from the location to TARGET] paces.";
Chapter - Setup
Section - I7
Use fast route-finding.
Diagonal-length is a number that varies.
The diagonal-length variable translates into I6 as "diagonal_length".
Orthogonal-length is a number that varies.
The orthogonal-length variable translates into I6 as "orthogonal_length".
Section - I6
Include (-
Global diagonal_length = 7;
Global orthogonal_length = 5;
-) after "Definitions.i6t".
Include (-
Replace MapRouteTo;
-) after "Definitions.i6t".
Include (-
[ MapRouteTo from to filter use_doors count oy oyi ds;
! print "^ (new MapRouteTo called with count=",count,")...^";
!for (ds=0: ds<No_Directions: ds++) {
! oyi=0; objectloop (oy ofclass K3_direction) {
! if (oyi== ds) print ds, ": ",(name) oy;
! oyi++;
! }
!}
if (from == nothing) return nothing;
if (to == nothing) return nothing;
if (from == to) return nothing;
if ((filter) && (filter(from) == 0)) return nothing;
if ((filter) && (filter(to) == 0)) return nothing;
if ((last_filter ~= filter) || (last_use_doors ~= use_doors)) map_has_changed = true;
oyi = 0;
objectloop (oy has mark_as_room) {
if ((filter == 0) || (filter(oy))) {
if (oy.room_index == -1) map_has_changed = true;
oy.room_index = oyi++;
} else {
if (oy.room_index >= 0) map_has_changed = true;
oy.room_index = -1;
}
}
oyi = 0;
objectloop (oy ofclass K4_door) {
ds = false;
if ((use_doors & 2) ||
(oy has open) || ((oy has openable) && (oy hasnt locked))) ds = true;
if (DoorRoutingViable->oyi ~= ds) map_has_changed = true;
DoorRoutingViable->oyi = ds;
oyi++;
}
if (map_has_changed) {
#ifdef FAST_ROUTE_FINDING; ComputeFWMatrix(filter, use_doors); #endif;
map_has_changed = false; last_filter = filter; last_use_doors = use_doors;
}
#ifdef FAST_ROUTE_FINDING;
if (count) return FastCountRouteTo(from, to, filter, use_doors);
return FastRouteTo(from, to, filter, use_doors);
#ifnot;
if (count) return SlowCountRouteTo(from, to, filter, use_doors);
return SlowRouteTo(from, to, filter, use_doors);
#endif;
];
-) after "Output.i6t".
Include (-
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
! Relations.i6t: Fast Route-Finding
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
#ifdef FAST_ROUTE_FINDING;
Array FWMatrix --> NUM_ROOMS*NUM_ROOMS;
[ FastRouteTo from to filter use_doors diri i dir oy;
if (from == to) return nothing;
i = (FWMatrix-->(from.room_index*NUM_ROOMS + to.room_index))/No_Directions;
if (i == 0) return nothing;
diri = (FWMatrix-->(from.room_index*NUM_ROOMS + to.room_index))%No_Directions;
i=0; objectloop (dir ofclass K3_direction) {
if (i == diri) return dir;
i++;
}
return nothing;
];
[ FastCountRouteTo from to filter use_doors k;
if (from == to) return 0;
k = (FWMatrix-->(from.room_index*NUM_ROOMS + to.room_index))/No_Directions;
if (k == 0) return -1;
return k;
];
[ ComputeFWMatrix filter use_doors oy ox oj axy ayj axj dir diri nd row w; ! #### w for weighting direc tions
objectloop (oy has mark_as_room) if (oy.room_index >= 0)
objectloop (ox has mark_as_room) if (ox.room_index >= 0)
FWMatrix-->(oy.room_index*NUM_ROOMS + ox.room_index) = 0;
objectloop (oy has mark_as_room) if (oy.room_index >= 0) {
row = (oy.IK1_Count)*No_Directions;
for (diri=0: diri<No_Directions: diri++) {
ox = Map_Storage-->(row+diri);
if ((ox) && (ox has mark_as_room) && (ox.room_index >= 0)) {
!##### modifed code begins
if (diri == 1 || diri == 2 || diri == 4 || diri == 5) w=diagonal_length; else w=orthogonal_length;
!##### this depends on diagonal directions being the 2nd, 3rd, 5th & 6th to be declared
FWMatrix-->(oy.room_index*NUM_ROOMS + ox.room_index) = No_Directions*w + diri;
!#### modified code ends
continue;
}
if (use_doors && (ox ofclass K4_door) &&
((use_doors & 2) || (DoorRoutingViable->(ox.IK4_Count)))) {
@push location; location = oy;
ox = ox.door_to();
@pull location;
if ((ox) && (ox has mark_as_room) && (ox.room_index >= 0)) {
!##### modifed code begins
if (diri == 1 || diri == 2 || diri == 4 || diri == 5) w=diagonal_length; else w=orthogonal_length;
!##### this depends on diagonal directions being the 2nd, 3rd, 5th & 6th to be declared
FWMatrix-->(oy.room_index*NUM_ROOMS + ox.room_index) = No_Directions*w + diri;
!#### modified code ends
continue;
}
}
}
}
objectloop (oy has mark_as_room) if (oy.room_index >= 0)
objectloop (ox has mark_as_room) if (ox.room_index >= 0) {
axy = (FWMatrix-->(ox.room_index*NUM_ROOMS + oy.room_index))/No_Directions;
if (axy > 0)
objectloop (oj has mark_as_room) if (oj.room_index >= 0) {
ayj = (FWMatrix-->(oy.room_index*NUM_ROOMS + oj.room_index))/No_Directions;
if (ayj > 0) {
!print "Is it faster to go from ", (name) ox, " to ",
! (name) oj, " via ", (name) oy, "?^";
axj = (FWMatrix-->(ox.room_index*NUM_ROOMS + oj.room_index))/
No_Directions;
if ((axj == 0) || (axy + ayj < axj)) {
!print "Yes^";
FWMatrix-->(ox.room_index*NUM_ROOMS + oj.room_index) =
(axy + ayj)*No_Directions +
(FWMatrix-->(ox.room_index*NUM_ROOMS + oy.room_index))%
No_Directions;
}
}
}
}
];
#ENDIF;
-) instead of "Fast Route-Finding" in "Relations.i6t".