Finish the Set/ implementation
This commit is contained in:
@@ -122,12 +122,9 @@ func loadSets() {
|
||||
}
|
||||
|
||||
for key, mapSet := range mapSets {
|
||||
fmt.Printf(" * `%s`: Defs=%#v len(palette)=%d\n", key, mapSet.Defs, len(mapSet.Palette))
|
||||
if key == "map01.set" {
|
||||
for i, objName := range mapSet.Palette {
|
||||
fmt.Printf(" %d. %s\n", i, objName)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf(" * `%s`: surface expected=%d actual=%d\n", key, mapSet.SurfaceCount, len(mapSet.SurfacePalette))
|
||||
fmt.Printf(" * `%s`: left expected=%d actual=%d\n", key, mapSet.LeftCount, len(mapSet.LeftPalette))
|
||||
fmt.Printf(" * `%s`: right expected=%d actual=%d\n", key, mapSet.RightCount, len(mapSet.RightPalette))
|
||||
fmt.Printf(" * `%s`: center expected=%d actual=%d\n", key, mapSet.CenterCount, len(mapSet.CenterPalette))
|
||||
}
|
||||
}
|
||||
|
@@ -293,7 +293,7 @@ func runStep(win *pixelgl.Window, state *runState) *runState {
|
||||
log.Printf(
|
||||
"x=%d y=%d z=%d SurfaceTile=%d (%s) SurfaceFrame=%d SquadRelated=%d",
|
||||
x, y, state.zIdx,
|
||||
cell.Surface.Index(), state.env.set.Palette[int(cell.Surface.Index())], cell.Surface.Frame(),
|
||||
cell.Surface.Index(), state.env.set.SurfacePalette[int(cell.Surface.Index())], cell.Surface.Frame(),
|
||||
cell.SquadRelated,
|
||||
)
|
||||
log.Printf("CellIdx%d=%d. Full cell data: %#v", state.cellIdx, cell.At(state.cellIdx), cell)
|
||||
|
@@ -81,7 +81,7 @@ remake.
|
||||
* `*.TXT`
|
||||
* [`Obj/`](obj.md)
|
||||
* `*.obj` # must be visual data of some sort, one per placeable map object?
|
||||
* `Pic/`
|
||||
* [✓] `Pic/`
|
||||
* `*.pcx` # Standard .pcx format
|
||||
* `RandomMaps/`
|
||||
* `*.chk` # multiplayer. worry about these another day
|
||||
@@ -89,7 +89,7 @@ remake.
|
||||
* `Save_G/`
|
||||
* `*.sav` # savedata, gzip-compressed, custom format
|
||||
* `*.txt` # Seems to be a copy of one of Maps/*.txt
|
||||
* [`Sets/`](sets.md)
|
||||
* [✓] [`Sets/`](sets.md)
|
||||
* `Data.chk` # checksums? Mentions all the .set files
|
||||
* `*.set` # plain text, related to maps. Editor has a concept of map sets, which these must be
|
||||
* [✓] `SMK/`
|
||||
@@ -119,4 +119,4 @@ Phew.
|
||||
* [`Maps/*.txt`](maps.md#associated-txt-file)
|
||||
* [`Sets/*.set`](sets.md)
|
||||
* [`Sounds/wh40k.ds`](sounds.md)
|
||||
* `Wav/*.wav`
|
||||
* `Wav/*.wav`
|
||||
|
@@ -6,11 +6,11 @@ The map file loads a set, and can then reference objects by a small number.
|
||||
Since a maximally-filled map file seems to be able to reference 91,000 * 4
|
||||
objects, this is a necessary optimization for 1998-era hardware.
|
||||
|
||||
Complete parser implementation [here](../../internal/sets.md).
|
||||
|
||||
## Structure
|
||||
|
||||
These files are plain-text.
|
||||
|
||||
We handily have a `template.set`, which looks like:
|
||||
These files are plain-text. A `template.set` is handily included:
|
||||
|
||||
```
|
||||
set template
|
||||
@@ -45,25 +45,26 @@ blank
|
||||
The files are of varying lengths. `template.set` is 220 lines, `map10.set` only
|
||||
83.
|
||||
|
||||
So it's a line-based format that goes:
|
||||
Whitespace and comments (`#`) are ignored. We have the following lines:
|
||||
|
||||
* Set description
|
||||
* Blank line (optional, missing in `GEN_JUN.set`, `GEN_WAS.set`, others)
|
||||
* `Defs`
|
||||
* Blank line
|
||||
* 4 space-separated numbers, variable between sets
|
||||
* At least one blank line, sometimes 2
|
||||
* A list of object names, sometimes with # comments on the right hand side
|
||||
* Set description (informational only)
|
||||
* `Defs` literal
|
||||
* 4 space-separated numbers - count of entries in each of four subsections:
|
||||
* Surface
|
||||
* Left
|
||||
* Right
|
||||
* Center
|
||||
* A list of sum(counts) .asn/.obj filename prefixes, sometimes with comments
|
||||
* They all seem to end with a comment of some sort, e.g. `# meaningless comment`
|
||||
|
||||
Questions:
|
||||
The groups in the `Defs` section are equivalent to the four types of object
|
||||
referenced in each map cell.
|
||||
|
||||
What are the `Defs` for? Is it `Defaults` or `Definitions`? The values are
|
||||
quite variable between files.
|
||||
The `.MAP` files reference these tiles as palette entries. Each cell in the map
|
||||
has an object index and frame number. I *suspect* the object index is relative
|
||||
to the correct section of the palette. TODO: check this.
|
||||
|
||||
Is whitespace significant in the list of objects? First assumption is no.
|
||||
|
||||
Is it a simple 0-indexed palette or do maps embed an absolute line number?
|
||||
## Remaining questions
|
||||
|
||||
Do positions in the palette have special meaning? e.g. is a particular range
|
||||
always reserved for walls?
|
||||
@@ -74,4 +75,3 @@ Are there any special values that don't appear as files in the `Obj/` directory?
|
||||
Once the map format is fleshed out a little more, can investigate by creating a
|
||||
map with a single object from the set in it and seeing what line that works out
|
||||
to be.
|
||||
|
||||
|
@@ -2,7 +2,6 @@ package sets
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@@ -13,10 +12,17 @@ import (
|
||||
|
||||
type MapSet struct {
|
||||
Description string
|
||||
Defs [4]byte // TODO: work out what these are for
|
||||
|
||||
SurfaceCount int
|
||||
LeftCount int
|
||||
RightCount int
|
||||
CenterCount int
|
||||
|
||||
// TODO: is there any more structure than this? Should I preserve empty lines?
|
||||
Palette []string
|
||||
SurfacePalette []string
|
||||
LeftPalette []string
|
||||
RightPalette []string
|
||||
CenterPalette []string
|
||||
}
|
||||
|
||||
func LoadSets(dir string) (map[string]*MapSet, error) {
|
||||
@@ -63,57 +69,77 @@ func LoadSet(filename string) (*MapSet, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out.Defs, err = consumeDefs(s)
|
||||
if err != nil {
|
||||
if err := consumeDefs(s, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for {
|
||||
str, err := s.ConsumeString()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out.Palette = append(out.Palette, str)
|
||||
if err := consumePalette(s, out.SurfaceCount, &out.SurfacePalette); err != nil {
|
||||
return nil, fmt.Errorf("Failed to read surface palette: %v", err)
|
||||
}
|
||||
if err := consumePalette(s, out.LeftCount, &out.LeftPalette); err != nil {
|
||||
return nil, fmt.Errorf("Failed to read left palette: %v", err)
|
||||
}
|
||||
if err := consumePalette(s, out.RightCount, &out.RightPalette); err != nil {
|
||||
return nil, fmt.Errorf("Failed to read right palette: %v", err)
|
||||
}
|
||||
if err := consumePalette(s, out.CenterCount, &out.CenterPalette); err != nil {
|
||||
return nil, fmt.Errorf("Failed to read center palette: %v", err)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func consumeDefs(scanner *asciiscan.Scanner) ([4]byte, error) {
|
||||
var out [4]byte
|
||||
|
||||
func consumeDefs(scanner *asciiscan.Scanner, in *MapSet) error {
|
||||
expectDefs, err := scanner.ConsumeString()
|
||||
if err != nil {
|
||||
return out, err
|
||||
return err
|
||||
}
|
||||
|
||||
if expectDefs != "Defs" {
|
||||
return out, fmt.Errorf("Couldn't find Defs section")
|
||||
return fmt.Errorf("Couldn't find Defs section")
|
||||
}
|
||||
|
||||
defs, err := scanner.ConsumeString()
|
||||
if err != nil {
|
||||
return out, err
|
||||
return err
|
||||
}
|
||||
|
||||
parts := strings.SplitN(defs, " ", -1)
|
||||
if len(parts) != 4 {
|
||||
return out, fmt.Errorf("Defs section did not have 4 components")
|
||||
return fmt.Errorf("Defs section did not have 4 components")
|
||||
}
|
||||
|
||||
ints := make([]int, 4)
|
||||
|
||||
for i, part := range parts {
|
||||
n, err := strconv.ParseInt(part, 10, 8)
|
||||
if err != nil {
|
||||
return out, err
|
||||
return err
|
||||
}
|
||||
|
||||
out[i] = byte(n) // safe as we specify 8 bits to ParseInt
|
||||
ints[i] = int(n) // safe as we specify 8 bits to ParseInt
|
||||
}
|
||||
|
||||
return out, nil
|
||||
in.SurfaceCount = ints[0]
|
||||
in.LeftCount = ints[1]
|
||||
in.RightCount = ints[2]
|
||||
in.CenterCount = ints[3]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func consumePalette(scanner *asciiscan.Scanner, n int, in *[]string) error {
|
||||
out := make([]string, 0, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
str, err := scanner.ConsumeString()
|
||||
if err != nil {
|
||||
return err // EOF is bad: the number of entries is explicit
|
||||
}
|
||||
|
||||
out = append(out, str)
|
||||
}
|
||||
|
||||
*in = out
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user