5 package require "elite-bits" "1.0.1"
7 set galaxy1 "4a5a480253b7" ;# Seed for standard galaxy 1
9 # --- tab ARR NAME NAME ... ---
11 # Construct an array mapping integers 0, 1, ... to the given NAMEs, in order.
22 # --- Various standard tables ---
25 "anarchy" "feudal" "multi-government" "dictatorship" \
26 "communist" "confederacy" "democracy" "corporate state"
29 "rich industrial" "average industrial" "poor industrial" \
30 "mainly industrial" "mainly agricultural" "rich agricultural" \
31 "average agricultural" "poor agricultural"
34 anarchy feudal multi-gov dictator \
35 communist confed democracy corp-state
38 rich-ind avg-ind poor-ind mainly-ind \
39 mainly-agri rich-agri avg-agri poor-agri
41 tab gv Ay Fl MG Dp Ct Cy Dy CS
42 tab ec RI AI PI MI MA RA AA PA
47 radioactives "Radioactives"
49 liquor-wines "Liquor & wines"
60 gem-stones "Gem-stones"
61 alien-items "Alien items"
64 foreach p $products { set unit($p) t }
65 foreach p {gold platinum} { set unit($p) kg }
66 set unit(gem-stones) g
69 # --- galaxy N [GAL] ---
71 # Compute the seed of the Nth galaxy, if GAL is the seed of galaxy 1. By
72 # default, GAL is the standard galaxy 1 seed.
74 proc galaxy [list n [list g $galaxy1]] {
75 for {set i 1} {$i < $n} {incr i} {
76 set g [elite-nextgalaxy $g]
81 # --- foreach-world GAL ARR SCRIPT ---
83 # For each world in galaxy GAL (a seed), set ARR to the world information
84 # and evaluate SCRIPT. The usual loop control commands can be used in
87 proc foreach-world {g p act} {
89 for {set i 0} {$i < 256} {incr i; set g [elite-nextworld $g]} {
95 # --- find-world GAL PAT ---
97 # Return a list of seeds for the worlds in galaxy GAL (a seed) whose names
98 # match the glob pattern PAT.
100 proc find-world {g pat} {
103 if {[string match -nocase $pat $p(name)]} {
110 # --- destructure PAT LIST ---
112 # Destrcture LIST according to PAT. If PAT is a single name, set the
113 # variable PAT to LIST; otherwise, if PAT is a list, each of its elements
114 # must correspond to an element of LIST, so recursively destructure the
115 # corresponding elements of each. It is not an error if the PAT list is
116 # shorter than LIST. The special variable name `.' indicates that no
117 # assignment is to be made.
119 proc destructure {pp xx} {
120 if {![string compare $pp "."]} {
122 } elseif {[llength $pp] == 0} {
124 } elseif {[llength $pp] == 1} {
128 foreach p $pp x $xx {
129 uplevel 1 [list destructure $p $x]
134 # --- write-file NAME CONTENTS [TRANS] ---
136 # Write file NAME, storing CONTENTS translated according to TRANS (default
137 # `binary'. The write is safe against errors -- we don't destroy the old
138 # data until the file is written.
140 proc write-file {name contents {trans binary}} {
141 if {[file exists $name]} {
142 if {[set rc [catch { file copy -force $name "$name.old" } err]]} {
143 return -code $rc $err
148 fconfigure $f -translation $trans
149 puts -nonewline $f $contents
153 catch { file rename -force "$name.old" $name }
154 return -code $rc $err
159 # --- read-file NAME [TRANS] ---
161 # Read the contents of the file NAME, translating it according to TRANS
162 # (default `binary').
164 proc read-file {name {trans binary}} {
166 fconfigure $f -translation $trans
172 # --- nearest-planet WW X Y ---
174 # Returns the seed of the `nearest' planet given in the worldinfo list WW to
175 # the point X Y (in decilightyears).
177 proc nearest-planet {ww x y} {
179 foreach {ss xx yy} $ww {
180 set dx [expr {abs($x - $xx)/4}]
181 set dy [expr {abs($y - $yy)/2}]
183 set d [expr {($dx * 2 + $dy)/2}]
185 set d [expr {($dx + $dy * 2)/2}]
195 # --- worldname W ---
197 # Returns the name of the world with seed W.
204 # --- shortest-path ADJ FROM TO WEIGHT ---
206 # Computes the shortest path and shortest distance between the worlds wose
207 # seeds are FROM and TO respectively. ADJ must be an adjacency table for the
208 # galaxy containing FROM and TO. WEIGHT is a command such that WEIGHT A B
209 # returns the `distance' for the simple path between A and B. The return
210 # value is a list P D, where D is the weight of the path found, and P is a
211 # simple list of seeds for the worlds on the path. P starts with FROM and
214 proc shortest-path {adjvar from to weight} {
216 if {[string equal $from $to]} { return [list $to 0] }
221 foreach {n x y} $adj($c) {
222 if {[info exists l($n)]} {
225 set w [expr {$l($c) + [uplevel 1 $weight [list $c $n]]}]
226 if {![info exists ll($n)] || $w < $ll($n)} {
228 set p($n) [concat $p($c) [list $n]]
231 set s [array startsearch ll]
232 if {![array anymore ll $s]} {
235 set c [array nextelement ll $s]
237 while {[array anymore ll $s]} {
238 set n [array nextelement ll $s]
244 if {[string equal $c $to]} { return [list $p($to) $ll($to)] }
250 # --- weight-hops A B ---
252 # shortest-path weight function giving each hop the same weight.
254 proc weight-hops {from to} {
258 # --- weight-fuel A B ---
260 # shortest-path weight function measuring the distance between FROM and TO.
262 proc weight-fuel {from to} {
263 elite-worldinfo f $from
264 elite-worldinfo t $to
265 return [elite-distance $f(x) $f(y) $t(x) $t(y)]
268 # --- weight-safety A B ---
270 # shortest-path weight function attempting to maximize safety of the journey
271 # by giving high weight (square-law) to worlds with unstable governments.
273 proc weight-safety {from to} {
274 elite-worldinfo t $to
275 set w [expr {8 - $t(government)}]
276 return [expr {$w * $w}]
279 # --- weight-encounters A B ---
281 # shortest-path weight function attempting to maximize encounters on the
282 # journey by giving high weight (square law) to worlds with stable
285 proc weight-encounters {from to} {
286 elite-worldinfo f $from
287 elite-worldinfo t $to
288 set w [expr {1 + $t(government)}]
289 return [expr {$w * $w}]
292 # --- weight-trading A B ---
294 # shortest-path weight function attempting to maximize trading opportunities
295 # along the journey by giving high weight (square law) to pairs of worlds
296 # with small differences between their economic statuses.
298 proc weight-trading {from to} {
299 elite-worldinfo f $from
300 elite-worldinfo t $to
301 set w [expr {8 - abs($f(economy) - $t(economy))}]
302 return [expr {$w * $w}]
305 # --- parse-galaxy-spec G ---
307 # Parses a galaxy spec and returns a list containing a description of the
308 # galaxy and the corresponding galaxy seed. A galaxy spec is one of:
310 # * a number between 1 and 8, corresponding to one of the standard
313 # * a 12-digit hex string, which is a galaxy seed (and is returned
316 # * a string of the form S:N where S is a 12-hex-digit seed and N is a
317 # galaxy number, corresponding to the Nth galaxy starting with S as
320 # If the string is unrecognized, an empty list is returned.
322 proc parse-galaxy-spec {g} {
323 switch -regexp -- $g {
324 {^[1-8]$} { return [list $g [galaxy $g]] }
325 {^[0-9a-fA-F]{12}$} { return [list $g $g] }
327 if {[regexp {^([0-9a-fA-F]{12}):([1-8])$} $g . b n]} {
328 return [list $g [galaxy $n $b]]
335 # --- parse-planet-spec G P ---
337 # Parses a planet spec and returns the planet seed. The planet spec P is
338 # interpreted relative to galaxy G. A planet spec is one of:
340 # * a simple integer, corresponding to a planet number;
342 # * a 12-hex-digit seed, which is returned unchanged;
344 # * a pair of integers separated by commas, corresponding to the nearest
345 # planet to those coordinates;
347 # * a glob pattern, corresponding to the lowest-numbered planet in the
348 # galaxy whose name matches the pattern case-insensitively; or
350 # * a string of the form G.P where G is a galaxy spec and P is a planet
351 # spec, corresponding to the planet specified by P relative to galaxy G.
353 # If the string is unrecognized, an empty string is returned.
355 proc parse-planet-spec {g p} {
356 if {[regexp {^[0-9a-fA-F]{12}$} $p]} { return $p }
357 if {[regexp {^(.+)\.(.+)$} $p . g p]} {
358 set g [parse-galaxy-spec $g]
359 if {[string equal $g ""]} { return {} }
361 return [parse-planet-spec $g $p]
363 if {[regexp {^(0x[0-9a-fA-F]+|[0-9]+)$} $p]} {
364 for {set s $g; set i 0} {$i < $p} {incr i; set s [elite-nextworld $s]} {}
367 if {[regexp {^(0x[0-9a-fA-F]+|[0-9]+),\s*(0x[0-9a-fA-F]+|[0-9]+)$} \
369 return [nearest-planet [elite-galaxylist $g] $x $y]
371 if {[regexp {^([^/]*)(?:/([1-9]\d*))?$} $p . p i]} {
372 if {[string equal $i ""]} { set i 1 }
373 set l [find-world $g $p]
374 if {$i <= [llength $l]} { return [lindex $l [expr {$i - 1}]] }
379 # --- in-galaxy-p G PP ---
381 # Returns nonzero if the planets (seeds) listed in PP are in galaxy G.
382 # Doesn't mind if the planet seeds are invalid.
384 proc in-galaxy-p {g pp} {
385 foreach-world $g i { set x($i(seed)) 1 }
386 foreach p $pp { if {![info exists x($p)]} { return 0 } }
390 # --- world-summary PLANET ---
392 # Return a one-line summary string for PLANET.
394 proc world-summary {s {ind 0} {spc 0}} {
397 set is [string repeat " " $ind]
398 set ss [string repeat " " $spc]
399 return [format "%s%-8s%s %4d %4d %-11s %-10s %2d %s" \
400 $is $p(name) $ss $p(x) $p(y) \
401 $eco($p(economy)) $gov($p(government)) $p(techlevel) $p(seed)]
404 # --- world-brief PLANET ---
406 # Return a very brief summary string for PLANET.
408 proc world-brief {s} {
411 return [format "%-8s (%s, %s, %2d)" \
412 $p(name) $ec($p(economy)) $gv($p(government)) $p(techlevel)]
415 # --- jameson ARR ---
417 # Fill ARR with the information about commander JAMESON.
420 global galaxy1 products
437 set cmdr(gal-seed) $galaxy1
439 ecm fuel-scoop energy-bomb energy-unit docking-computer
440 gal-hyperdrive escape-pod
442 elite-worldinfo lave [find-world $galaxy1 "Lave"]
443 set cmdr(world-x) [expr {$lave(x)/4}]
444 set cmdr(world-y) [expr {$lave(y)/2}]
445 elite-market mkt $lave(seed) 0
446 foreach {t n} $products {
447 destructure [list . cmdr(station-$t)] $mkt($t)
450 set cmdr(station-alien-items) 0
453 #----- That's all, folks ----------------------------------------------------
455 package provide "elite" "1.0.1"