diff --git a/engine/content.go b/engine/content.go index 0cb8d65..e98dec8 100644 --- a/engine/content.go +++ b/engine/content.go @@ -237,6 +237,21 @@ func (c *Content) Validate() error { if len(m.Tiles) != m.Width*m.Height { return fmt.Errorf("map %s: %d tiles for %dx%d", m.ID, len(m.Tiles), m.Width, m.Height) } + + for y := 0; y < m.Height; y++ { + for x := 0; x < m.Width; x++ { + i := y*m.Width + x + rx, ry := m.Width-1-x, m.Height-1-y + ri := ry*m.Width + rx + + if m.Tiles[i] != m.Tiles[ri] { + return fmt.Errorf( + "map %s: tile (%d,%d) differs from its 180-degree counterpart (%d,%d)", + m.ID, x, y, rx, ry, + ) + } + } + } for _, o := range m.Objectives { for _, p := range o.Tiles { if p.X < 0 || p.Y < 0 || p.X >= m.Width || p.Y >= m.Height { diff --git a/engine/symmetry_test.go b/engine/symmetry_test.go index 5b70295..c08cf8b 100644 --- a/engine/symmetry_test.go +++ b/engine/symmetry_test.go @@ -102,3 +102,15 @@ func TestSummonKillGivesNoCredit(t *testing.T) { t.Fatalf("summon kill credited: team kills %d, hask xp %d", k, a.u(h.ID).XP) } } + +func TestValidateRejectsAsymmetricMap(t *testing.T) { + c := content(t) + + m := c.Maps["relay"] + m.Tiles[0].Terrain = m.Tiles[len(m.Tiles)-1].Terrain + "-changed" + c.Maps["relay"] = m + + if err := c.Validate(); err == nil { + t.Fatal("expected validation to reject an asymmetric map") + } +}