slp-enforcer
Version:
Finds violations of the Melee Controller Ruleset by inspecting SLP files
189 lines (188 loc) • 12.2 kB
JavaScript
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const globals_1 = require("@jest/globals");
const index_1 = require("../index");
const sdi_1 = require("../sdi");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
globals_1.test('Test Region Sanity Check', () => {
// DZ - Dead Zone Test
globals_1.expect(sdi_1.getSDIRegion(0, 0)).toBe(sdi_1.SDIRegion.DZ);
globals_1.expect(sdi_1.getSDIRegion(0.2, 0.2)).toBe(sdi_1.SDIRegion.DZ);
globals_1.expect(sdi_1.getSDIRegion(-0.2, -0.2)).toBe(sdi_1.SDIRegion.DZ);
// NE - Northeast
globals_1.expect(sdi_1.getSDIRegion(0.8, 0.8)).toBe(sdi_1.SDIRegion.NE);
globals_1.expect(sdi_1.getSDIRegion(0.9, 0.7)).toBe(sdi_1.SDIRegion.NE);
// SE - Southeast
globals_1.expect(sdi_1.getSDIRegion(0.8, -0.8)).toBe(sdi_1.SDIRegion.SE);
globals_1.expect(sdi_1.getSDIRegion(0.9, -0.7)).toBe(sdi_1.SDIRegion.SE);
// SW - Southwest
globals_1.expect(sdi_1.getSDIRegion(-0.8, -0.8)).toBe(sdi_1.SDIRegion.SW);
globals_1.expect(sdi_1.getSDIRegion(-0.9, -0.7)).toBe(sdi_1.SDIRegion.SW);
// NW - Northwest
globals_1.expect(sdi_1.getSDIRegion(-0.8, 0.8)).toBe(sdi_1.SDIRegion.NW);
globals_1.expect(sdi_1.getSDIRegion(-0.9, 0.7)).toBe(sdi_1.SDIRegion.NW);
// N - North
globals_1.expect(sdi_1.getSDIRegion(0, 0.8)).toBe(sdi_1.SDIRegion.N);
globals_1.expect(sdi_1.getSDIRegion(0.2, 0.9)).toBe(sdi_1.SDIRegion.N);
// E - East
globals_1.expect(sdi_1.getSDIRegion(0.8, 0)).toBe(sdi_1.SDIRegion.E);
globals_1.expect(sdi_1.getSDIRegion(0.9, 0.2)).toBe(sdi_1.SDIRegion.E);
// S - South
globals_1.expect(sdi_1.getSDIRegion(0, -0.8)).toBe(sdi_1.SDIRegion.S);
globals_1.expect(sdi_1.getSDIRegion(0.2, -0.9)).toBe(sdi_1.SDIRegion.S);
// W - West
globals_1.expect(sdi_1.getSDIRegion(-0.8, 0)).toBe(sdi_1.SDIRegion.W);
globals_1.expect(sdi_1.getSDIRegion(-0.9, 0.2)).toBe(sdi_1.SDIRegion.W);
// TILT - Middle-ish area
globals_1.expect(sdi_1.getSDIRegion(0.4, 0.4)).toBe(sdi_1.SDIRegion.TILT);
globals_1.expect(sdi_1.getSDIRegion(-0.4, -0.4)).toBe(sdi_1.SDIRegion.TILT);
globals_1.expect(sdi_1.getSDIRegion(0.2, -0.3)).toBe(sdi_1.SDIRegion.TILT);
// Edge cases
// Testing near the edges of the DZ boundary (0.2875)
globals_1.expect(sdi_1.getSDIRegion(0.2876, 0)).toBe(sdi_1.SDIRegion.TILT);
globals_1.expect(sdi_1.getSDIRegion(0, 0.2876)).toBe(sdi_1.SDIRegion.TILT);
globals_1.expect(sdi_1.getSDIRegion(-0.2876, 0)).toBe(sdi_1.SDIRegion.TILT);
globals_1.expect(sdi_1.getSDIRegion(0, -0.2876)).toBe(sdi_1.SDIRegion.TILT);
// Test values on the boundary of magnitude 0.7 (diagonal)
globals_1.expect(sdi_1.getSDIRegion(0.7, 0.7)).toBe(sdi_1.SDIRegion.NE);
globals_1.expect(sdi_1.getSDIRegion(-0.7, 0.7)).toBe(sdi_1.SDIRegion.NW);
globals_1.expect(sdi_1.getSDIRegion(0.7, -0.7)).toBe(sdi_1.SDIRegion.SE);
globals_1.expect(sdi_1.getSDIRegion(-0.7, -0.7)).toBe(sdi_1.SDIRegion.SW);
// Boundary checks for cardinal directions (0.7)
globals_1.expect(sdi_1.getSDIRegion(0.7, 0)).toBe(sdi_1.SDIRegion.E);
globals_1.expect(sdi_1.getSDIRegion(0, 0.7)).toBe(sdi_1.SDIRegion.N);
globals_1.expect(sdi_1.getSDIRegion(-0.7, 0)).toBe(sdi_1.SDIRegion.W);
globals_1.expect(sdi_1.getSDIRegion(0, -0.7)).toBe(sdi_1.SDIRegion.S);
});
globals_1.test('Test SDI from legal digital file', () => {
let data = fs.readFileSync(path.join(__dirname, '../../test_data/legal/digital/potion_p3/potion_' + 2 + '.slp'), null);
let game = new index_1.SlippiGame(index_1.toArrayBuffer(data));
globals_1.expect(game).not.toBeNull();
let gameCoords = index_1.getCoordListFromGame(game, 2, true);
globals_1.expect(sdi_1.failsSDIRuleOne(gameCoords)).toEqual([]);
globals_1.expect(sdi_1.failsSDIRuleThree(gameCoords)).toEqual([]);
});
globals_1.test('Test isDiagonalAdjacent()', async () => {
globals_1.expect(sdi_1.isDiagonalAdjacent(sdi_1.SDIRegion.SE, sdi_1.SDIRegion.NW)).toEqual(false);
globals_1.expect(sdi_1.isDiagonalAdjacent(sdi_1.SDIRegion.SE, sdi_1.SDIRegion.SE)).toEqual(false);
globals_1.expect(sdi_1.isDiagonalAdjacent(sdi_1.SDIRegion.SE, sdi_1.SDIRegion.DZ)).toEqual(false);
globals_1.expect(sdi_1.isDiagonalAdjacent(sdi_1.SDIRegion.SE, sdi_1.SDIRegion.SW)).toEqual(true);
globals_1.expect(sdi_1.isDiagonalAdjacent(sdi_1.SDIRegion.NW, sdi_1.SDIRegion.NE)).toEqual(true);
globals_1.expect(sdi_1.isDiagonalAdjacent(sdi_1.SDIRegion.SW, sdi_1.SDIRegion.SE)).toEqual(true);
});
globals_1.test('Test SDI (manual coords)', async () => {
// Sanity check. No movement. No violation
let coords = [{ x: 0, y: 0 }, { x: 0, y: 0 }, { x: 0, y: 0 }, { x: 0, y: 0 }, { x: 0, y: 0 }, { x: 0, y: 0 }];
globals_1.expect(sdi_1.failsSDIRuleOne(coords)).toEqual([]);
// Easy case. Lots of SDI. Violation.
coords = [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 0, y: 0 }, { x: 1, y: 0 }, { x: 0, y: 0 }, { x: 1, y: 0 }];
globals_1.expect(sdi_1.failsSDIRuleOne(coords).length).toBeGreaterThanOrEqual(1);
// Too many frames in the tilt zone, doesn't count as SDI!
coords = [{ x: 0, y: 0 }, { x: 0.3, y: 0 }, { x: 0.32, y: 0 }, { x: 0.35, y: 0 }, { x: 0.4, y: 0 }, { x: 1, y: 0 }, { x: 0, y: 0 }, { x: 1, y: 0 }];
globals_1.expect(sdi_1.failsSDIRuleOne(coords)).toEqual([]);
// Slowest possible SDIs. Doesn't count as SDI since it has travel time
coords = [{ x: 0, y: 0 }, { x: 0.3, y: 0 }, { x: 0.35, y: 0 }, { x: 0.4, y: 0 }, { x: 1, y: 0 }, { x: 0, y: 0 }, { x: 0.35, y: 0 }, { x: 0.4, y: 0 }, { x: 1, y: 0 }];
globals_1.expect(sdi_1.failsSDIRuleOne(coords).length).toEqual(0);
// Doesn't count as SDI since it has travel time
coords = [{ x: 0, y: 0 }, { x: 0.3, y: 0 }, { x: 1, y: 0 }, { x: 0, y: 0 }, { x: 0.3, y: 0 }, { x: 1, y: 0 }];
globals_1.expect(sdi_1.failsSDIRuleOne(coords).length).toEqual(0);
// Violation. SDI, then put in a bunch of travel time after.
// IE: You don't get off the hook just because you have travel time after the SDI
coords = [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 0, y: 0 }, { x: 1, y: 0 }, { x: 0.3, y: 0 }, { x: 0.35, y: 0 }, { x: 0.4, y: 0 }];
globals_1.expect(sdi_1.failsSDIRuleOne(coords).length).toBeGreaterThanOrEqual(1);
});
globals_1.test('Test SDI (legal A)', async () => {
let data = fs.readFileSync(path.join(__dirname, '../../test_data/legal/digital/sdi/sdi_r18_v2.slp'), null);
let game = new index_1.SlippiGame(index_1.toArrayBuffer(data));
globals_1.expect(game).not.toBeNull();
let coords = index_1.getCoordListFromGame(game, 0, true);
// TODO: Re-enable these tests once we get an SLP that works
// expect(hasIllegalSDI(game, 0, coords)).toEqual([])
globals_1.expect(sdi_1.failsSDIRuleOne(coords)).toEqual([]);
// expect(failsSDIRuleTwo(coords)).toEqual([])
globals_1.expect(sdi_1.failsSDIRuleThree(coords)).toEqual([]);
});
globals_1.test('Test SDI (legal B)', async () => {
let data = fs.readFileSync(path.join(__dirname, '../../test_data/legal/digital/sdi/sdi_t20_cardinal_diagonal.slp'), null);
let game = new index_1.SlippiGame(index_1.toArrayBuffer(data));
globals_1.expect(game).not.toBeNull();
let coords = index_1.getCoordListFromGame(game, 0, true);
globals_1.expect(index_1.hasIllegalSDI(game, 0, coords).result).toEqual(false);
globals_1.expect(sdi_1.failsSDIRuleOne(coords)).toEqual([]);
globals_1.expect(sdi_1.failsSDIRuleTwo(coords)).toEqual([]);
globals_1.expect(sdi_1.failsSDIRuleThree(coords)).toEqual([]);
});
globals_1.test('Test SDI (legal C)', async () => {
let data = fs.readFileSync(path.join(__dirname, '../../test_data/legal/digital/sdi/sdi_mash.slp'), null);
let game = new index_1.SlippiGame(index_1.toArrayBuffer(data));
globals_1.expect(game).not.toBeNull();
let coords = index_1.getCoordListFromGame(game, 0, true);
globals_1.expect(index_1.hasIllegalSDI(game, 0, coords).result).toEqual(false);
globals_1.expect(sdi_1.failsSDIRuleOne(coords)).toEqual([]);
globals_1.expect(sdi_1.failsSDIRuleTwo(coords)).toEqual([]);
globals_1.expect(sdi_1.failsSDIRuleThree(coords)).toEqual([]);
});
globals_1.test('Test SDI (legal D)', async () => {
let data = fs.readFileSync(path.join(__dirname, '../../test_data/legal/digital/sdi/Game_20250201T233229.slp'), null);
let game = new index_1.SlippiGame(index_1.toArrayBuffer(data));
globals_1.expect(game).not.toBeNull();
let coords = index_1.getCoordListFromGame(game, 0, true);
globals_1.expect(sdi_1.failsSDIRuleOne(coords)).toEqual([]);
globals_1.expect(sdi_1.failsSDIRuleTwo(coords)).toEqual([]);
globals_1.expect(sdi_1.failsSDIRuleThree(coords)).toEqual([]);
});
globals_1.test('Test SDI (legal E)', async () => {
let data = fs.readFileSync(path.join(__dirname, '../../test_data/legal/digital/sdi/Game_20250201T232732.slp'), null);
let game = new index_1.SlippiGame(index_1.toArrayBuffer(data));
globals_1.expect(game).not.toBeNull();
let coords = index_1.getCoordListFromGame(game, 1, true);
globals_1.expect(sdi_1.failsSDIRuleOne(coords)).toEqual([]);
globals_1.expect(sdi_1.failsSDIRuleTwo(coords)).toEqual([]);
globals_1.expect(sdi_1.failsSDIRuleThree(coords)).toEqual([]);
});
globals_1.test('Test SDI (non legal A)', async () => {
let data = fs.readFileSync(path.join(__dirname, '../../test_data/nonlegal/digital/sdi/sdi_tas_neutral_cardinal.slp'), null);
let game = new index_1.SlippiGame(index_1.toArrayBuffer(data));
globals_1.expect(game).not.toBeNull();
let coords = index_1.getCoordListFromGame(game, 3, true);
// Fails rule #1
globals_1.expect(index_1.hasIllegalSDI(game, 3, coords).result).toEqual(true);
let violations = sdi_1.failsSDIRuleOne(coords);
globals_1.expect(violations.length).toEqual(195);
globals_1.expect(violations[10].reason).toEqual("Failed SDI rule #1");
globals_1.expect(violations[10].metric).toEqual(139);
globals_1.expect(violations[10].evidence).toEqual([{ "x": 0, "y": 0 }, { "x": 0, "y": 0 }, { "x": -1, "y": 0 }, { "x": 0, "y": 0 }, { "x": -1, "y": 0 }, { "x": 0, "y": 0 }, { "x": -1, "y": 0 }, { "x": 0, "y": 0 }, { "x": -1, "y": 0 }, { "x": 0, "y": 0 }]);
});
globals_1.test('Test SDI (non legal B)', async () => {
let data = fs.readFileSync(path.join(__dirname, '../../test_data/nonlegal/digital/sdi/sdi_tas_cardinal_diagonal.slp'), null);
let game = new index_1.SlippiGame(index_1.toArrayBuffer(data));
globals_1.expect(game).not.toBeNull();
let coords = index_1.getCoordListFromGame(game, 3, true);
let violations = sdi_1.failsSDIRuleTwo(coords);
globals_1.expect(violations.length).toEqual(36);
globals_1.expect(violations[10].reason).toEqual("Failed SDI rule #2");
globals_1.expect(violations[10].metric).toEqual(226);
globals_1.expect(violations[10].evidence).toEqual([{ "x": 1, "y": 0 }, { "x": 0.7, "y": 0.7 }, { "x": 1, "y": 0 }, { "x": 0.7, "y": 0.7 }, { "x": 1, "y": 0 }]);
});
globals_1.test('Test SDI (non legal C)', async () => {
let data = fs.readFileSync(path.join(__dirname, '../../test_data/nonlegal/digital/sdi/sdi_unnerfed.slp'), null);
let game = new index_1.SlippiGame(index_1.toArrayBuffer(data));
globals_1.expect(game).not.toBeNull();
let coords = index_1.getCoordListFromGame(game, 3, true);
// Fails rule #3 but not rule #1
globals_1.expect(index_1.hasIllegalSDI(game, 3, coords).result).toEqual(true);
globals_1.expect(sdi_1.failsSDIRuleOne(coords)).toEqual([]);
let violations = sdi_1.failsSDIRuleThree(coords);
globals_1.expect(violations.length).toEqual(8);
globals_1.expect(violations[4].reason).toEqual("Failed SDI rule #3");
globals_1.expect(violations[4].metric).toEqual(2535);
globals_1.expect(violations[4].evidence).toEqual([{ "x": 0.7, "y": 0.7 }, { "x": 0.7, "y": 0.7 }, { "x": 0, "y": 1 }, { "x": -0.7, "y": 0.7 }, { "x": 0.7, "y": 0.7 }]);
});