chiark / gitweb /
Release 1.1.6.
[rocl] / elite-reach
... / ...
CommitLineData
1#! /usr/bin/tclsh
2###
3### Determine the connected components of the various galaxies
4###
5### (c) 2003 Mark Wooding
6###
7
8###----- Licensing notice ---------------------------------------------------
9###
10### This program is free software; you can redistribute it and/or modify
11### it under the terms of the GNU General Public License as published by
12### the Free Software Foundation; either version 2 of the License, or
13### (at your option) any later version.
14###
15### This program is distributed in the hope that it will be useful,
16### but WITHOUT ANY WARRANTY; without even the implied warranty of
17### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18### GNU General Public License for more details.
19###
20### You should have received a copy of the GNU General Public License
21### along with this program; if not, write to the Free Software Foundation,
22### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24package require "elite" "1.0.1"
25
26###--------------------------------------------------------------------------
27### Support functions.
28
29proc reach {dist seed} {
30 ## Given a hyperspace range DIST and a galaxy SEED, determine and print the
31 ## connected components of the reachability graph.
32
33 ## Determine the graph. Throughout, we use world seeds as indices: a(W)
34 ## maintains a list of worlds adjacent to W. p(W) is set (to an
35 ## uninteresting value) if it's awaiting tracing. The algorithm is simple:
36 ## repeatedly pick a world awaiting tracing, do a depth-first search of
37 ## graph starting from the chosen world adding each one encountered to the
38 ## current component and removing it from the waiting list.
39 set ww [elite-galaxylist $seed]
40 elite-adjacency a $ww $dist
41 foreach {s x w} $ww { set p($s) 1 }
42
43 ## Initially there are no components.
44 set pp {}
45
46 ## Iterate over the untraced worlds.
47 while 1 {
48
49 ## Find an untraced world. If there are none left then we're done.
50 set ps [array startsearch p]
51 if {![array anymore p $ps]} { array donesearch p $ps; break }
52 set cc [array nextelement p $ps]
53 array donesearch p $ps
54
55 ## Now we do the depth-first search. For each world in $trace,
56 ## accumulate the untraced worlds reachable from it, and add them to the
57 ## component. Do this until we stop tracing new worlds.
58 set trace $cc
59 unset p($cc)
60 while {[llength $trace]} {
61 set tt $trace; set trace {}
62 foreach c $tt {
63 foreach w $a($c) {
64 if {[info exists p($w)]} {
65 unset p($w)
66 lappend trace $w
67 }
68 }
69 }
70 set cc [concat $cc $trace]
71 }
72
73 ## We've finished the component. Add it to the list.
74 lappend pp $cc
75 }
76
77 ## Output the components.
78 foreach cc $pp {
79
80 ## Firstly, accumulate the summary data for all the worlds in the
81 ## component. Also, do dead-end analysis: if there's no world in the
82 ## component with tech level 10 or higher then the component as a whole
83 ## is a `dead end', and can't be escaped by buying a galactic hyperdrive
84 ## (and you can't have one of those already, because you must have used
85 ## it to reach the component in the first pace).
86 set de 1
87 set l {}
88 foreach c $cc {
89 elite-worldinfo i $c
90 if {$i(techlevel) >= 10} { set de 0 }
91 lappend l [world-summary $i(seed)]
92 }
93
94 ## Secondly, output the component information. Separate components using
95 ## blank lines.
96 foreach n $l {
97 if {$de} { append n " *" }
98 puts $n
99 }
100 puts ""
101 }
102}
103
104###--------------------------------------------------------------------------
105### Main program.
106
107## Parse the command line. The default will be to scan all of the standard
108## galaxies.
109if {[llength $argv] == 0} {
110 set argv {1 2 3 4 5 6 7 8}
111}
112set gg {}
113set d 70
114for {set i 0} {$i < [llength $argv]} {incr i} {
115 set a [lindex $argv $i]
116 switch -glob -- $a {
117 "-d" {
118 incr i
119 set d [expr {int([lindex $argv $i] * 10)}]
120 }
121 "-*" {
122 puts stderr "usage: $argv0 \[-d DIST\] \[GALAXY ...\]"
123 exit 1
124 }
125 default {
126 set g [parse-galaxy-spec $a]
127 if {[string equal $g ""]} {
128 puts stderr "$argv0: bad galaxy spec `$a'"
129 exit 1
130 }
131 destructure {ng g} $g
132 lappend gg $d $ng $g
133 }
134 }
135}
136
137## Analyse the requested galaxies.
138foreach {d ng g} $gg {
139 puts "*** GALAXY $ng ***"
140 reach $d $g
141}
142
143###----- That's all, folks --------------------------------------------------