chiark / gitweb /
Release 1.1.6.
[rocl] / elite-cmdr
index 4c101df158c4bf68f36dc350aa40e4c71f71324b..b0d500c16c61850307943fdd60230b503cdb4674 100755 (executable)
@@ -1,45 +1,82 @@
 #! /usr/bin/tclsh
+###
+### Commander file inspector
+###
+### (c) 2003 Mark Wooding
+###
 
-package require "elite" "1.0.0"
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
-if {[llength $argv] < 1} {
-  puts stderr "usage: $argv0 \[-OPTION | ATTR | ATTR=VALUE\] ..."
-  exit 1
+package require "elite" "1.0.1"
+
+###--------------------------------------------------------------------------
+### Various type handlers.
+###
+### We associate a named type and some optional (type-specific) parameters
+### with each attribute in the commander file format.  For each TYPE, there
+### are Tcl procedures:
+###
+### get/TYPE [PARAM ...] A -- return presentation form of the attribute A
+### dump/TYPE [PARAM ...] A -- return an external form of the attribute A
+### set/TYPE [PARAM ...] A V -- convert V from presentation form and store
+###    as the attribute A
+
+proc dump-like-get {type} {
+  ## Define dump/TYPE as a synonym for get/TYPE.
+
+  proc dump/$type {args} [list uplevel 1 get/$type \$args]
 }
-jameson cmdr
 
+## string -- just a plain unconverted string.
 proc get/string {a} { global cmdr; return $cmdr($a) }
-proc dump/string {a} { global cmdr; return $cmdr($a) }
+dump-like-get string
 proc set/string {a v} { global cmdr; set cmdr($a) $v }
 
+## int MIN MAX -- an integer constrained to lie between the stated
+##     (inclusive) bounds.
 proc get/int {min max a} {
   global cmdr
   return [format "%d" [expr {$cmdr($a) + 0}]]
 }
-proc dump/int {min max a} {
-  global cmdr
-  return [format "%d" [expr {$cmdr($a) + 0}]]
-}
+dump-like-get int
 proc set/int {min max a v} {
   global cmdr
   if {$v < $min || $v > $max} { error "value out of range" }
   set cmdr($a) $v
 }
 
+## tenth MIN MAX -- a numerical value constrained to lie between the stated
+## inclusive bounds; the internal format is an integer containing ten times
+## the presentation value.
 proc get/tenth {min max a} {
   global cmdr
   return [format "%.1f" [expr {$cmdr($a)/10.0}]]
 }
-proc dump/tenth {min max a} {
-  global cmdr
-  return [format "%.1f" [expr {$cmdr($a)/10.0}]]
-}
+dump-like-get tenth
 proc set/tenth {min max a v} {
   global cmdr
   if {$v < $min || $v > $max} { error "value out of range" }
   set cmdr($a) [expr {int($v * 10)}]
 }
 
+## choice MIN MAX L -- the presentation form is either an integer between the
+##     given inclusive bounds, or a token matching one of the items in the
+##     list L; the internal form is the integer, or the index of the token
+##     in the list.
 proc get/choice {min max l a} {
   global cmdr
   set x "custom"
@@ -65,8 +102,10 @@ proc set/choice {min max l a v} {
   set cmdr($a) $v
 }
 
+## seed -- a galaxy seed; any valid galaxy spec is permitted as the
+##     presentation form.
 proc get/seed {a} { global cmdr; return $cmdr($a) }
-proc dump/seed {a} { global cmdr; return $cmdr($a) }
+dump-like-get seed
 proc set/seed {a v} {
   global cmdr
   set s [parse-galaxy-spec $v]
@@ -74,9 +113,12 @@ proc set/seed {a v} {
   destructure [list . cmdr($a)] $s
 }
 
+## world -- a planet identifier; on input, any planet spec is permitted
+##     (relative to the commander's established galaxy), and on output a
+##     summary description is produced.
 proc get/world {a} {
   global cmdr gov eco
-  set ww [worldinfo $cmdr(gal-seed)]
+  set ww [elite-galaxylist $cmdr(gal-seed)]
   set s [nearest-planet $ww \
       [expr {$cmdr(world-x) * 4}] [expr {$cmdr(world-y) * 2}]]
   elite-worldinfo p $s
@@ -90,37 +132,53 @@ proc dump/world {a} {
 }
 proc set/world {a v} {
   global cmdr
+  set ww [elite-galaxylist $cmdr(gal-seed)]
   set s [parse-planet-spec $cmdr(gal-seed) $v]
   if {[string equal $s ""]} { error "bad planet spec `$v'" }
   if {![in-galaxy-p $cmdr(gal-seed) $s]} {
     error "planet `[worldname $s]' not in galaxy $cmdr(gal-seed)"
   }
   elite-worldinfo p $s
+  set ss [nearest-planet $ww $p(x) $p(y)]
+  if {![string equal $s $ss]} {
+    set n $p(name)
+    elite-worldinfo p $ss
+    puts stderr "can't dock at $n: $p(name) is coincident"
+  }
   set cmdr(world-x) [expr {$p(x)/4}]
   set cmdr(world-y) [expr {$p(y)/2}]
 }
 
+## bool DFL -- internal form is either zero or DFL; external form is one of a
+##     number of standard boolean tokens.
 proc get/bool {dfl a} {
   global cmdr
   if {$cmdr($a)} { return "yes" } else { return "no" }
 }
-proc dump/bool {dfl a} {
-  global cmdr
-  if {$cmdr($a)} { return "yes" } else { return "no" }
-}  
+dump-like-get bool
 proc set/bool {dfl a v} {
   global cmdr
   switch -- [string tolower $v] {
-    "y" - "yes" - "true" - "on" { set v 1 }
-    "n" - "no" - "false" - "off" { set v 0 }
+    "y" - "yes" - "true" - "on" - "t" { set v 1 }
+    "n" - "no" - "false" - "off" - "nil" { set v 0 }
   }
   if {$v} { set cmdr($a) $dfl } else { set cmdr($a) 0 }
 }
 
+## comment -- a pseudo-type for discarding commnts in input files.
 proc set/comment {a v} { }
 
+###--------------------------------------------------------------------------
+### Attribute table.
+
+### The `attr' array maps commander attribute names to TYPE [PARAM ...]
+### lists; the `attrs' list contains the names in a canonical order.
 set attrs {}
+
+## Comment magic.
 set attr(\#) { comment }
+
+## Basic attributes.
 foreach {a type} {
   mission              { int 0 255 }
   score                        { choice 0 65535 {
@@ -129,6 +187,8 @@ foreach {a type} {
     "elite" 6400
   } }
   credits              { tenth 0 429496729.5 }
+  legal-status         { choice 0 255
+                         { "clean" 0 "offender" 1 "fugitive" 50 } }
   cargo                        { int 4 255 }
   gal-number           { int 1 8 }
   gal-seed             { seed }
@@ -141,6 +201,8 @@ foreach {a type} {
   set attr($a) $type
   lappend attrs $a
 }
+
+## Lasers.
 foreach l {front rear left right} {
   set attr($l-laser) {
     choice 0 255
@@ -148,12 +210,16 @@ foreach l {front rear left right} {
   }
   lappend attrs $l-laser
 }
+
+## Standard boolean properties.
 foreach i {
   ecm fuel-scoop energy-bomb escape-pod docking-computer gal-hyperdrive
 } {
   set attr($i) { bool 255 }
   lappend attrs $i
 }
+
+## Station and hold produce.
 foreach l {station hold} {
   foreach {t p} $products {
     set attr($l-$t) { int 0 255 }
@@ -161,27 +227,72 @@ foreach l {station hold} {
   }
 }
 
+###--------------------------------------------------------------------------
+### Main program.
+
+jameson cmdr
+
+## Parse the command-line.
+if {[llength $argv] < 1} {
+  puts stderr "usage: $argv0 \[-OPTION | ATTR | ATTR=VALUE\] ..."
+  exit 1
+}
+
+proc show-attrs {pat} {
+  ## Show the attributes whose names match the glob pattern PAT.  Return the
+  ## number of matches.
+
+  global attr attrs
+  set n 0
+  foreach a $attrs {
+    if {[string match $pat $a]} {
+      puts [format "%-20s %s" $a [eval \
+         get/[lindex $attr($a) 0] [lrange $attr($a) 1 end] [list $a]]]
+      incr n
+    }
+  }
+  return $n
+}
+
+proc load-file {file} {
+  ## Load FILE as a commander.
+
+  global argv0 cmdr
+  if {[catch { elite-unpackcmdr cmdr [read-file $file] } err]} {
+    puts stderr "$argv0: couldn't read `$file': $err"
+    exit 1
+  }
+}
+
 set acted 0
 for {set i 0} {$i < [llength $argv]} {incr i} {
   set a [lindex $argv $i]
   switch -regexp -- $a {
-    "^-reset$" { jameson cmdr }
+
+    "^-reset$" {
+      ## Reset the commander back to Jameson.
+
+      jameson cmdr
+    }
+
     "^-show$" {
-      foreach a $attrs {
-       puts [format "%-20s %s" $a [eval \
-           get/[lindex $attr($a) 0] [lrange $attr($a) 1 end] [list $a]]]
-      }
+      ## Produce a human-readable description of the commander.
+
+      show-attrs "*"
       set acted 1
     }
+
     "^-load$" {
+      ## Load a commander file.
+
       incr i
       set a [lindex $argv $i]
-      if {[catch { elite-unpackcmdr cmdr [read-file $a] } err]} {
-       puts stderr "$argv0: couldn't read `$a': $err"
-       exit 1
-      }
+      load-file $a
     }
+
     "^-save$" {
+      ## Write the commander to a file.
+
       incr i
       set a [lindex $argv $i]
       if {[catch { write-file $a [elite-packcmdr cmdr] } err]} {
@@ -190,7 +301,10 @@ for {set i 0} {$i < [llength $argv]} {incr i} {
       }
       set acted 1
     }
+
     "^-dump$" {
+      ## Dump a machine-readable textual description of the commander.
+
       puts "# {Elite commander dump}"
       puts ""
       foreach a $attrs {
@@ -199,7 +313,10 @@ for {set i 0} {$i < [llength $argv]} {incr i} {
       }
       set acted 1
     }
+
     "^-read$" {
+      ## Read back a description produced by `-dump'.
+
       incr i
       set a [lindex $argv $i]
       if {[catch {
@@ -214,11 +331,17 @@ for {set i 0} {$i < [llength $argv]} {incr i} {
        exit 1
       }
     }
+
     "^-" {
+      ## An unknown option.
+
       puts stderr "$argv0: unknown option `$a'"
       exit 1
     }
+
     "^[a-z][a-z-]*=" {
+      ## An assignment ATTR=VALUE.
+
       regexp {^([a-z][a-z-]*)=(.*)$} $a . a v
       if {![info exists attr($a)]} {
        puts stderr "$argv0: no such attribute `$a'"
@@ -231,25 +354,23 @@ for {set i 0} {$i < [llength $argv]} {incr i} {
        exit 1
       }
     }
-    "^[a-z][a-z-]*$" {
-      if {![info exists attr($a)]} {
-       puts stderr "$argv0: no such attribute `$a'"
-       exit 1
-      }
-      puts [format "%-20s %s" $a [eval \
-         get/[lindex $attr($a) 0] [lrange $attr($a) 1 end] [list $a]]]
-    }
+
     default {
-      if {[catch { elite-unpackcmdr cmdr [read-file $a] } err]} {
-       puts stderr "$argv0: couldn't read `$a': $err"
-       exit 1
+      ## If the argument matches any attribute names, then print the matching
+      ## attributes; otherwise load the named file.
+
+      if {[show-attrs $a]} {
+       set acted 1
+      } else {
+       load-file $a
       }
     }
   }
 }
+
+## If we didn't do anything, write out a description of the file.
 if {!$acted} {
-  foreach a $attrs {
-    puts [format "%-20s %s" $a [eval \
-       get/[lindex $attr($a) 0] [lrange $attr($a) 1 end] [list $a]]]
-  }
+  show-attrs "*"
 }
+
+###----- That's all, folks --------------------------------------------------