import { assert } from 'chai'; import { Point, Hexagon, OffsetCoord, DoubledCoord, Layout } from '../../../../lib/graphics/grids/Hexagon'; const hexagon = Hexagon.create; const point = Point.create; describe('graphics.grids.Hexgon', () => { describe('Hexagon', () => { describe('constructor', () => { it('constructor#default', () => { const hex = hexagon(); assert.isTrue(hex instanceof Hexagon); assert.strictEqual(hex.q, 0); assert.strictEqual(hex.r, 0); assert.strictEqual(hex.s, 0); }); it('constructor#args', () => { const hex = hexagon(1, 2, 3); assert.isTrue(hex instanceof Hexagon); assert.strictEqual(hex.q, 1); assert.strictEqual(hex.r, 2); assert.strictEqual(hex.s, 3); }); }); describe('toHash', () => { test.each([ [hexagon(), 1394771295, undefined], [hexagon(), 3817169758, 17], [hexagon(1, 2, 3), 487941079, undefined], [hexagon(1, 2, 3), 2645506267, 17], ])('toHash#%#', (hex: Hexagon, result: number, seed?: number) => { assert.strictEqual(hex.toHash(seed), result); assert.strictEqual(Hexagon.hash(hex, seed), result); }); }); describe('equals', () => { test.each([ [hexagon(), hexagon(), true], [hexagon(), hexagon(1, 2, 3), false], [hexagon(1, 2, 3), hexagon(1, 2, 3), true], ])('equals#%#', (lhs: Hexagon, rhs: Hexagon, result: boolean) => { assert.strictEqual(lhs.equals(rhs), result); assert.strictEqual(Hexagon.equal(lhs, rhs), result); }); }); it('plus', () => { assert.isTrue(hexagon(3, -7, 4).plus(hexagon(1, -3, 2)).equals(hexagon(4, -10, 6))); }) it('minus', () => { assert.isTrue(hexagon(1, -3, 2).minus(hexagon(3, -7, 4)).equals(hexagon(-2, 4, -2))); }); describe('mul', () => { it('mul#number', () => { assert.isTrue(hexagon(1, -2, 3).mul(2).equals(hexagon(2, -4, 6))); }); it('mul#hexagon', () => { assert.isTrue(hexagon(1, -2, 3).mul(hexagon(3, -1, 2)).equals(hexagon(3, 2, 6))); }); it('mul#other', () => { assert.isTrue(hexagon(1, -2, 3).mul('2').equals(hexagon())); }); }); describe('div', () => { it('div#number', () => { assert.isTrue(hexagon(2, -4, 6).div(2).equals(hexagon(1, -2, 3))); }); it('div#hexagon', () => { assert.isTrue(hexagon(3, 2, 6).div(hexagon(3, -1, 2)).equals(hexagon(1, -2, 3))); }); it('div#other', () => { assert.isTrue(hexagon(1, -2, 3).div('2').equals(hexagon())); }); }); it('rotatedLeft', () => { assert.isTrue(hexagon(1, -3, 2).rotatedLeft().equals(hexagon(-2, -1, 3))); }); it('rotatedRight', () => { assert.isTrue(hexagon(1, -3, 2).rotatedRight().equals(hexagon(3, -2, -1))); }); it('neighbor', () => { const h = hexagon(1, -2, 1); const results = [hexagon(2, -2, 0), hexagon(2, -3, 1), hexagon(1, -3, 2), hexagon(0, -2, 2), hexagon(0, -1, 1), hexagon(1, -1, 0)]; for (let i = 0; i <= 5; i++) assert.isTrue(h.neighbor(i).equals(results[i])); }); it('diagonalNeighbor', () => { const h = hexagon(1, -2, 1); const results = [hexagon(3, -3, 0), hexagon(2, -4, 2), hexagon(0, -3, 3), hexagon(-1, -1, 2), hexagon(0, 0, 0), hexagon(2, -1, -1)]; for (let i = 0; i <= 5; i++) assert.isTrue(h.diagonalNeighbor(i).equals(results[i])); }); it('length', () => { assert.strictEqual(hexagon(1, 2, -2).length(), 3); }); it('manhattanLength', () => { assert.strictEqual(hexagon(1, 2, -2).manhattanLength(), 5); }); describe('distance', () => { test.each([ [hexagon(), hexagon(), 0], [hexagon(1, 2, -2), hexagon(), 3], [hexagon(), hexagon(1, 2, -2), 3], ])('distance#%#', (from: Hexagon, to: Hexagon, result: number) => { assert.strictEqual(from.distance(to), result); }); }); describe('rounded', () => { const a = hexagon(0, 0, 0); const b = hexagon(1, -1, 0); const c = hexagon(0, -1, 1); test.each([ [hexagon(0.0, 0.0, 0.0).interpolated(hexagon(10.0, -20.0, 10.0), 0.5), hexagon(5, -10, 5)], [a.interpolated(b, 0.499), a], [a.interpolated(b, 0.501), b], [hexagon(a.q * 0.4 + b.q * 0.3 + c.q * 0.3, a.r * 0.4 + b.r * 0.3 + c.r * 0.3, a.s * 0.4 + b.s * 0.3 + c.s * 0.3), a], [hexagon(a.q * 0.3 + b.q * 0.3 + c.q * 0.4, a.r * 0.3 + b.r * 0.3 + c.r * 0.4, a.s * 0.3 + b.s * 0.3 + c.s * 0.4), c] ])('rounded#%#', (hex: Hexagon, result: Hexagon) => { assert.isTrue(hex.rounded().equals(result)); }); }); describe('trace', () => { test.each([ [hexagon(0, 0, 0), hexagon(1, -5, 4), [hexagon(0, 0, 0), hexagon(0, -1, 1), hexagon(0, -2, 2), hexagon(1, -3, 2), hexagon(1, -4, 3), hexagon(1, -5, 4)]], ])('trace#%#', (a: Hexagon, b: Hexagon, result: Hexagon[]) => { assert.isTrue(Hexagon.trace(a, b).every((hex, index) => hex.equals(result[index]))); }); }); describe('compare', () => { test.each([ [hexagon(), hexagon(), 0], [hexagon(1, 2, 3), hexagon(), 1], [hexagon(), hexagon(1, 2, 3), -1], [hexagon(1, 2, 3), hexagon(1, 2, 3), 0], ])('compare#%#', (lhs: Hexagon, rhs: Hexagon, result: number) => { assert.strictEqual(Math.sign(Hexagon.compare(lhs, rhs)), result); }); }); describe('fromAxial', () => { test.each([ [0, 0, hexagon()], [1, 2, hexagon(1, 2, -3)], [2, 1, hexagon(2, 1, -3)], ])('fromAxial#%#', (q: number, r: number, result: Hexagon) => { assert.isTrue(Hexagon.fromAxial(q, r).equals(result)); }); }); }); describe('Layout', () => { it('flat', () => { const h = hexagon(3, 4, -7); const flat = new Layout(Layout.flat, point(10, 15), point(35, 71)); assert.isTrue(flat.pointToHex(flat.hexToPoint(h)).rounded().equals(h)); }); it('pointy', () => { const h = hexagon(3, 4, -7); const pointy = new Layout(Layout.pointy, point(10, 15), point(35, 71)); assert.isTrue(pointy.pointToHex(pointy.hexToPoint(h)).rounded().equals(h)); }); describe('polygonCorners', () => { const layout = new Layout(Layout.flat, point(16, 16)); test.each([ [layout, hexagon(), [point(16, 0), point(8, -13.85641), point(-8, -13.85641), point(-16, 0), point(-8, 13.85641), point(8, 13.85641)]], [layout, hexagon(1, 0, -1), [point(40, 13.85641), point(32, 0), point(16, 0), point(8, 13.85641), point(16, 27.71281), point(32, 27.71281)]], [layout, hexagon(1, 2, -3), [point(40, 69.28203), point(32, 55.42563), point(16, 55.42563), point(8, 69.28203), point(16, 83.13844), point(32, 83.13844)]], ])('polygonCorners#%#', (layout: Layout, hex: Hexagon, result: Point[]) => { assert.isTrue(layout.polygonCorners(hex).every((point, index) => point.fuzzyEquals(result[index]))); }); }); }); describe('OffsetCoord', () => { const a = hexagon(3, 4, -7); const b = new OffsetCoord(1, -3); describe('offsetToCube', () => { test.each([ // roundtrip [OffsetCoord.qoffsetToCube(OffsetCoord.EVEN, OffsetCoord.qoffsetFromCube(OffsetCoord.EVEN, a)), a], [OffsetCoord.qoffsetToCube(OffsetCoord.ODD, OffsetCoord.qoffsetFromCube(OffsetCoord.ODD, a)), a], [OffsetCoord.roffsetToCube(OffsetCoord.EVEN, OffsetCoord.roffsetFromCube(OffsetCoord.EVEN, a)), a], [OffsetCoord.roffsetToCube(OffsetCoord.ODD, OffsetCoord.roffsetFromCube(OffsetCoord.ODD, a)), a], // normal [OffsetCoord.qoffsetToCube(OffsetCoord.EVEN, new OffsetCoord(1, 3)), hexagon(1, 2, -3)], [OffsetCoord.qoffsetToCube(OffsetCoord.ODD, new OffsetCoord(1, 2)), hexagon(1, 2, -3)], ])('offsetToCube#%#', (actual: Hexagon, expected: Hexagon) => { assert.isTrue(actual.equals(expected)); }); }); describe('offsetFromCube', () => { test.each([ // roundtrip [OffsetCoord.qoffsetFromCube(OffsetCoord.EVEN, OffsetCoord.qoffsetToCube(OffsetCoord.EVEN, b)), b], [OffsetCoord.qoffsetFromCube(OffsetCoord.ODD, OffsetCoord.qoffsetToCube(OffsetCoord.ODD, b)), b], [OffsetCoord.roffsetFromCube(OffsetCoord.EVEN, OffsetCoord.roffsetToCube(OffsetCoord.EVEN, b)), b], [OffsetCoord.roffsetFromCube(OffsetCoord.ODD, OffsetCoord.roffsetToCube(OffsetCoord.ODD, b)), b], [OffsetCoord.roffsetFromCube(OffsetCoord.ODD, OffsetCoord.roffsetToCube(OffsetCoord.ODD, new OffsetCoord())), new OffsetCoord()], [OffsetCoord.qoffsetFromCube(OffsetCoord.EVEN, OffsetCoord.qoffsetToCube(OffsetCoord.EVEN, new OffsetCoord())), new OffsetCoord()], // normal [OffsetCoord.qoffsetFromCube(OffsetCoord.EVEN, hexagon(1, 2, -3)), new OffsetCoord(1, 3)], [OffsetCoord.qoffsetFromCube(OffsetCoord.ODD, hexagon(1, 2, -3)), new OffsetCoord(1, 2)], ])('offsetFromCube#%#', (actual: OffsetCoord, expected: OffsetCoord) => { assert.isTrue(actual.equals(expected)); }); }); }); describe('DoubledCoord', () => { const a = hexagon(3, 4, -7); const b = new DoubledCoord(1, -3); describe('doubledToCube', () => { test.each([ // roundtrip [DoubledCoord.qdoubledFromCube(a).qdoubledToCube(), a], [DoubledCoord.rdoubledFromCube(a).rdoubledToCube(), a], // normal [new DoubledCoord(1, 5).qdoubledToCube(), hexagon(1, 2, -3)], [new DoubledCoord(4, 2).rdoubledToCube(), hexagon(1, 2, -3)], ])('offsetToCube#%#', (actual: Hexagon, expected: Hexagon) => { assert.isTrue(actual.equals(expected)); }); }); describe('doubledFromCube', () => { test.each([ // roundtrip [DoubledCoord.qdoubledFromCube(b.qdoubledToCube()), b], [DoubledCoord.rdoubledFromCube(b.rdoubledToCube()), b], [DoubledCoord.rdoubledFromCube(new DoubledCoord().rdoubledToCube()), new DoubledCoord()], // normal [DoubledCoord.qdoubledFromCube(hexagon(1, 2, -3)), new DoubledCoord(1, 5)], [DoubledCoord.rdoubledFromCube(hexagon(1, 2, -3)), new DoubledCoord(4, 2)], ])('offsetFromCube#%#', (actual: DoubledCoord, expected: DoubledCoord) => { assert.isTrue(actual.equals(expected)); }); }); }); });