diff --git a/lib/gameState.ts b/lib/gameState.ts index 83f1f7e..b5cf75d 100644 --- a/lib/gameState.ts +++ b/lib/gameState.ts @@ -1,8 +1,13 @@ -import PTNFileParser = require('ptn-file-parser') -import TakBoard = require('./takBoard') +import PTNFileParser = require('ptn-file-parser'); +import TakBoard = require('./takBoard'); +import Move = require('./move'); class GameState { public size: number; + public playerOne: string = "Unkown"; + public playerTwo: string = "Unkown"; + public isGameOver: boolean = false; + public result: string = ""; private _board: TakBoard; constructor(state: object = {size: 5}){ @@ -12,9 +17,27 @@ class GameState { static fromPtnFile(file: string): GameState { let ptnFile: any = PTNFileParser.parsePtnFile(file) - let size = new Number(ptnFile.tags['Size']) + let size = +ptnFile.tags['Size']; + let state = new GameState({size}) + if(ptnFile.tags['Player1']) state.playerOne = ptnFile.tags['Player1']; + if(ptnFile.tags['Player2']) state.playerTwo = ptnFile.tags['Player2']; + // possible outcomes are R-0/0-R (road win), F-0/0-F (flat win), 1-0/0-1 (resignation), and 1/2-1/2 (draw) + if(ptnFile.tags['Result'] && (ptnFile.tags['Result'] as string).search(/[RF1]/gi) >= 0) { + state.isGameOver = true; + state.result = ptnFile.tags['Result']; + } // ToDo! loop through moves and place pieces - return new GameState({size}) + let moveNr = 0; + while(ptnFile.whiteMoves[moveNr]) { + state.move(Move.fromPtn(ptnFile.whiteMoves[moveNr])) + if(!ptnFile.blackMoves[moveNr]) break; + state.move(Move.fromPtn(ptnFile.blackMoves[moveNr])) + } + return state; + } + + move(move: Move) { + throw new Error("Method not implemented."); } } diff --git a/lib/move.ts b/lib/move.ts new file mode 100644 index 0000000..b2b2700 --- /dev/null +++ b/lib/move.ts @@ -0,0 +1,48 @@ +const moveRegex = /(\d)?([CSF])?([a-h][1-8])(?:([<>+-])([1-8]+))?/g; + +class Move { + public file: string; + public rank: number; + public stone: string = "F"; + public direction: string = ""; + public placedPieces: string[] = []; + constructor(ptn: string) { + let parsed = ptn.match(moveRegex); + if(!parsed) throw new Error("Invalid PTN string (failed to parse)"); + if(!parsed[3]) throw new Error("Invalid PTN string (missing rank and file)"); + let fileAndRank = parsed[3].split(""); + this.rank = Number(fileAndRank[1]); + this.file = fileAndRank[0]; + if(!this.rank) throw new Error("Invalid PTN string (invalid rank)"); + if(parsed[2]) { + this.stone = parsed[2]; + } + if(parsed[4]) { + this.direction = parsed[4]; + if(!parsed[5]) throw new Error("Invalid PTN string (direction but no placed pieces)"); + if(!parsed[1]) throw new Error("Invalid PTN string (no pieces picked up)"); + this.placedPieces = parsed[5].split(""); + let count = 0; + for(let num of this.placedPieces) { + count += Number(num); + } + if(count !== Number(parsed[1])) throw new Error("Invalid PTN string (picked up != placed)"); + } + } + + static fromPtn(ptn: string): Move { + return new Move(ptn); + } + + public toObject(): object { + return { + file: this.file, + rank: this.rank, + stone: this.stone, + direction: this.direction, + placedPieces: this.placedPieces + } + } +} + +export = Move; diff --git a/test/gameStateTests.js b/test/gameStateTests.js index 1263c28..24a0bd1 100644 --- a/test/gameStateTests.js +++ b/test/gameStateTests.js @@ -1,10 +1,19 @@ "use strict"; const expect = require("chai").expect; const GameState = require("../dist/gameState") +const ptnFile = require('./resources/ptnFile') describe("GameState", () => { it("should assume a board size of 5", () => { var state = new GameState(); expect(state.size).to.equal(5); }); + it("should read data from PTN file", () => { + var state = GameState.fromPtnFile(ptnFile.simplePtnFile); + expect(state.size).to.equal(6); + expect(state.playerOne).to.equal("NohatCoder"); + expect(state.playerTwo).to.equal("fwwwwibib"); + expect(state.isGameOver).to.be.true; + expect(state.result).to.equal("R-0"); + }); }); diff --git a/test/resources/ptnFile.js b/test/resources/ptnFile.js new file mode 100644 index 0000000..32ec0a9 --- /dev/null +++ b/test/resources/ptnFile.js @@ -0,0 +1,20 @@ +exports.simplePtnFile = `[Site "PlayTak.com"] +[Event "Online Play"] +[Date "2018.10.28"] +[Time "16:10:44"] +[Player1 "NohatCoder"] +[Player2 "fwwwwibib"] +[Clock "10:0 +20"] +[Result "R-0"] +[Size "6"] + +1. a6 f6 +2. d4 c4 +3. d3 c3 +4. d5 c5 +5. d2 Ce4 +6. c2 e3 +7. e2 b2 +8. Cb3 1e4<1 +9. 1d3<1 Sd1 +10. a3 1d1+1` \ No newline at end of file