From 73d0a88dedae72d01b26e8714d5de404f64e074c Mon Sep 17 00:00:00 2001 From: Niklas Eicker Date: Tue, 29 Oct 2019 14:13:39 +0100 Subject: [PATCH 1/4] read player names and result/status from PTN file --- lib/gameState.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/gameState.ts b/lib/gameState.ts index 83f1f7e..c490a38 100644 --- a/lib/gameState.ts +++ b/lib/gameState.ts @@ -3,6 +3,10 @@ import TakBoard = require('./takBoard') 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 +16,17 @@ 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}) + return state; } } From 7c7a5f7d633c2d9ed9b0439c3f4ed54211767aca Mon Sep 17 00:00:00 2001 From: Niklas Eicker Date: Tue, 29 Oct 2019 14:14:17 +0100 Subject: [PATCH 2/4] test game state taking player names and result/status from PTN file --- test/gameStateTests.js | 9 +++++++++ test/resources/ptnFile.js | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 test/resources/ptnFile.js 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 From eb282bc456d1aa6d8d1e6e556dde0b4f60990f08 Mon Sep 17 00:00:00 2001 From: Niklas Eicker Date: Mon, 2 Dec 2019 14:48:24 +0100 Subject: [PATCH 3/4] start reading in and parsing moves --- lib/gameState.ts | 15 +++++++++++++-- lib/move.ts | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 lib/move.ts diff --git a/lib/gameState.ts b/lib/gameState.ts index c490a38..b5cf75d 100644 --- a/lib/gameState.ts +++ b/lib/gameState.ts @@ -1,5 +1,6 @@ -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; @@ -26,8 +27,18 @@ class GameState { state.result = ptnFile.tags['Result']; } // ToDo! loop through moves and place pieces + 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."); + } } export = GameState; diff --git a/lib/move.ts b/lib/move.ts new file mode 100644 index 0000000..d7a0f6e --- /dev/null +++ b/lib/move.ts @@ -0,0 +1,19 @@ +const moveRegex = /(\d)?([CSF])?([a-h][1-8])(?:([<>+-])([1-8]+))?/g; + +class Move { + private stone: string = "F"; + constructor(ptn: string) { + let parsed = ptn.match(moveRegex); + if(!parsed) throw new Error("Invalid PTN string"); + if(parsed[2]) { + this.stone = parsed[2]; + } + + } + + static fromPtn(ptn: string): Move { + return new Move(ptn); + } +} + +export = Move; From c0e9526f255448a5914423ba0771d3074306fb32 Mon Sep 17 00:00:00 2001 From: Niklas Eicker Date: Wed, 4 Dec 2019 21:04:02 +0100 Subject: [PATCH 4/4] parse move from ptn --- lib/move.ts | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/move.ts b/lib/move.ts index d7a0f6e..b2b2700 100644 --- a/lib/move.ts +++ b/lib/move.ts @@ -1,19 +1,48 @@ const moveRegex = /(\d)?([CSF])?([a-h][1-8])(?:([<>+-])([1-8]+))?/g; class Move { - private stone: string = "F"; + 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"); + 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;