UNPKG

puzzlescript

Version:

Play PuzzleScript games in your terminal!

189 lines 10.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createTests = void 0; /* eslint-env jasmine */ const fs_1 = __importStar(require("fs")); const path_1 = __importDefault(require("path")); const engine_1 = require("../../src/engine"); const parser_1 = __importDefault(require("../../src/parser/parser")); const recordCoverage_1 = require("../../src/recordCoverage"); const util_1 = require("../../src/util"); // import TerminalUI from '../../src/ui/terminal' const CI_MAX_SOLUTION_LENGTH = 1000; // The length of 1 level of cyber-lasso const SKIP_GAMES = [ 'always-magnets', 'lil-purple' // "Match lengths differ. Expected 1 but found 0." ]; const describeFn = process.env.SKIP_SOLUTIONS ? describe.skip : describe; const SOLUTION_ROOT = path_1.default.join(__dirname, '../../game-solutions/'); const solutionFiles = fs_1.default.readdirSync(SOLUTION_ROOT); function parseEngine(code, levelNum = 0) { const { data } = parser_1.default.parse(code); const engine = new engine_1.GameEngine(data, new util_1.EmptyGameEngineHandler()); return { engine, data }; } function isShort() { return process.env.CI === 'true' || process.env.TEST_SHORT === 'true'; } function createTests(moduloNumber, moduloTotal) { if (process.env.SKIP_SOLUTIONS) { describe.skip('Skipping replay tests', () => { it.skip('skiping test'); }); console.log('Skipping Replay tests'); // tslint:disable-line:no-console return; } if (isShort() && (moduloNumber === 7 || moduloNumber === 8)) { describe.skip(`Skipping replaySolutions/${moduloNumber}.test because it causes Travis to time out`, () => { it.skip('skipping tests'); }); return; } describeFn('replays levels of games', () => { solutionFiles.forEach((solutionFilename, solutionIndex) => { // Skip the README.md file if (!solutionFilename.endsWith('.json')) { return; } // Only run 1/10 of all the games in each spec file. This is so JEST can run them concurrently if (solutionIndex % moduloTotal !== moduloNumber) { return; } const GIST_ID = path_1.default.basename(solutionFilename).replace('.json', ''); const testTitle = `plays ${isShort() ? '*a single level*' : '_the solved levels_'} of ${GIST_ID}`; if (SKIP_GAMES.indexOf(GIST_ID) >= 0) { it.skip(testTitle, () => { }); return; } it(testTitle, () => __awaiter(this, void 0, void 0, function* () { const gistFilename = path_1.default.join(__dirname, `../../games/${GIST_ID}/script.txt`); const { engine, data } = parseEngine(fs_1.default.readFileSync(gistFilename, 'utf-8')); const recordings = JSON.parse(fs_1.default.readFileSync(path_1.default.join(SOLUTION_ROOT, solutionFilename), 'utf-8')).solutions; let numPlayed = 0; let hasAtLeastOneSolution = 0; // play games in reverse order because it is likely that the harder levels will fail first for (let index = recordings.length - 1; index >= 0; index--) { // for (let index = 0; index < recordings.length; index++) { const recording = recordings[index]; if (!recording || !recording.solution) { continue; // skip message-only levels or levels that do not have a solution } // Some games (like Fish Friend) are a bunch of dialog and do not actually need to run // so if they only contain a "X" then skip them const trimmedSolution = recording.solution.replace(/,/g, '').replace(/\./g, '').replace(/!/g, ''); if (trimmedSolution === 'X' || trimmedSolution === '') { continue; } hasAtLeastOneSolution++; if (isShort() && recording.solution.length > CI_MAX_SOLUTION_LENGTH) { const msg = `CI-SKIP: Solution group: [${moduloNumber}/${moduloTotal}]. Level=${index}. Because the solution is too long: ${recording.solution.length} > ${CI_MAX_SOLUTION_LENGTH}. "${GIST_ID}"`; // tslint:disable-line:max-line-length console.log(msg); // tslint:disable-line:no-console continue; } if (isShort() && numPlayed > 0) { break; } numPlayed++; engine.setLevel(index, null /*no checkpoint*/); // UI.setGame(engine) const DID_NOT_WIN = 'DID_NOT_WIN'; let wonAtKeyIndex = DID_NOT_WIN; const keypresses = recording.solution.split(''); for (let i = 0; i < keypresses.length; i++) { const key = keypresses[i]; switch (key) { case 'W': engine.press(util_1.INPUT_BUTTON.UP); break; case 'S': engine.press(util_1.INPUT_BUTTON.DOWN); break; case 'A': engine.press(util_1.INPUT_BUTTON.LEFT); break; case 'D': engine.press(util_1.INPUT_BUTTON.RIGHT); break; case 'X': engine.press(util_1.INPUT_BUTTON.ACTION); break; case '!': // dismiss message prompt. not even a tick continue; case '.': case ',': break; default: throw new Error(`ERROR: Unsupported character "${key}"`); } let didWin = false; // do { // loop until we are done with animations const { didLevelChange, didWinGame } = yield engine.tick(); didWin = didWin || didWinGame || didLevelChange; // } while(engine.hasAgain()) // if (SHOW_STEPS) { // UI.renderScreen(false) // } if (didWin) { wonAtKeyIndex = i; break; } } if (wonAtKeyIndex === DID_NOT_WIN || (wonAtKeyIndex !== keypresses.length - 1)) { // console.error('Screendump of level') // TerminalUI.setGameEngine(engine) // TerminalUI.dumpScreen() // while (engine.canUndo()) { // engine.pressUndo() // engine.tick() // TerminalUI.dumpScreen() // } // UI.setGame(engine) // UI.dumpScreen() } expect({ title: data.title, levelNumber: index, wonAtKeyIndex }).toEqual({ title: data.title, levelNumber: index, wonAtKeyIndex: keypresses.length - 1 }); } if (hasAtLeastOneSolution > 1) { expect(numPlayed).toBeGreaterThanOrEqual(1); } const coverageFilenameSuffix = `${GIST_ID}-playgame`; const codeCoverageObj = (0, recordCoverage_1.saveCoverageFile)(data, gistFilename, (absPath) => path_1.default.relative(process.cwd(), absPath)); if ((0, fs_1.existsSync)(`coverage`)) { (0, fs_1.writeFileSync)(`coverage/coverage-${coverageFilenameSuffix}.json`, JSON.stringify(codeCoverageObj, null, 2)); // indent by 2 chars } })); }); }); } exports.createTests = createTests; //# sourceMappingURL=helper.js.map