From d6e91af7e8455136aabf4195452881a499d30514 Mon Sep 17 00:00:00 2001 From: Leonardo Val Date: Fri, 27 Mar 2015 10:14:31 -0300 Subject: [PATCH] Advanced to v0.1.3 --- build/ludorum.js | 1125 +------------------------------------- build/ludorum.js.map | 6 +- build/ludorum.min.js | 6 +- build/ludorum.min.js.map | 2 +- package.json | 2 +- 5 files changed, 36 insertions(+), 1105 deletions(-) diff --git a/build/ludorum.js b/build/ludorum.js index 11db190..f9bef55 100644 --- a/build/ludorum.js +++ b/build/ludorum.js @@ -2338,6 +2338,7 @@ var MonteCarloPlayer = players.MonteCarloPlayer = declare(HeuristicPlayer, { + `simulationCount=30`: Maximum amount of simulations performed for each available move at each decision. + `timeCap=1000ms`: Time limit for the player to decide. + + `horizon=500`: Maximum amount of moves performed in simulations. + `agent`: Player instance used in the simulations. If undefined moves are chosen at random. Agents with asynchronous decisions are not supported. */ @@ -2346,7 +2347,7 @@ var MonteCarloPlayer = players.MonteCarloPlayer = declare(HeuristicPlayer, { initialize(this, params) .number('simulationCount', { defaultValue: 30, coerce: true }) .number('timeCap', { defaultValue: 1000, coerce: true }) - .number('horizon', { defaultValue: Infinity, coerce: true }); + .number('horizon', { defaultValue: 500, coerce: true }); if (params) switch (typeof params.agent) { case 'function': this.agent = new HeuristicPlayer({ heuristic: params.agent }); break; case 'object': this.agent = params.agent; break; @@ -3335,327 +3336,6 @@ games.ToadsAndFrogs = declare(Game, { }); // declare ToadsAndFrogs -/** # Mancala - -Implementation of the [Kalah](http://en.wikipedia.org/wiki/Kalah) member of the -[Mancala family of games](http://en.wikipedia.org/wiki/Mancala). -*/ -games.Mancala = declare(Game, { - name: 'Mancala', - - /** The constructor takes the `activePlayer` (`"North"` by default) and the board as an array of - integers (initial board by default). - */ - constructor: function Mancala(activePlayer, board){ - Game.call(this, activePlayer); - this.board = board || this.makeBoard(); - }, - - /** `makeBoard(seeds, houses)` builds an array for the given amounts of houses and seeds per - house. By default 4 seeds and 6 houses per player are assumed. - */ - makeBoard: function makeBoard(seeds, houses){ - seeds = isNaN(seeds) ? 4 : +seeds; - houses = isNaN(houses) ? 6 : +houses; - var result = []; - for(var j = 0; j < 2; j++){ - for(var i = 0; i < houses; i++){ - result.push(seeds); - } - result.push(0); - } - return result; - }, - - /** The players' roles in a Mancala match are `"North"` and `"South"`. - */ - players: ["North", "South"], - - /** If `emptyCapture` is true, making a capture only moves the active player's seed to his - store, and the opponents seeds are not captured. By default this is false. - */ - emptyCapture: false, - - /** If `countRemainingSeeds` is true, at the end of the game if a player has seeds on his - houses, those seeds are included in his score. This is the default behaviour. - */ - countRemainingSeeds: true, - - // ## Game state information ################################################################### - - /** `store(player)` returns the index in this game's board of the player's store. - */ - store: function store(player){ - switch (this.players.indexOf(player)) { - case 0: return this.board.length / 2 - 1; // Store of North. - case 1: return this.board.length - 1; // Store of South. - default: throw new Error("Invalid player "+ player +"."); - } - }, - - /** `houses(player)` returns an array with the indexes of the player's houses in this game's - board. - */ - houses: function houses(player){ - switch (this.players.indexOf(player)) { - case 0: return Iterable.range(0, this.board.length / 2 - 1).toArray(); // Store of North. - case 1: return Iterable.range(this.board.length / 2, this.board.length - 1).toArray(); // Store of South. - default: throw new Error("Invalid player "+ player +"."); - } - }, - - /** The house in front of a players house is calculated by `oppositeHouse(player, i)`. It - returns the index of the opposite house of `i` for the given player, or a negative if `i` is not - a house of the given player. This is necessary for resolving captures. - */ - oppositeHouse: function oppositeHouse(player, i) { - var playerHouses = this.houses(player), - opponentHouses = this.houses(this.opponent(player)), - index = playerHouses.indexOf(i); - return index < 0 ? index : opponentHouses.reverse()[index]; - }, - - /** The flow of seeds on the board is defined by `nextSquare(player, i)`. It returns the index - of the square following `i` for the given player. - */ - nextSquare: function nextSquare(player, i){ - do { - i = (i + 1) % this.board.length; - } while (i === this.store(this.opponent(player))); - return i; - }, - - // ## Game logic ############################################################################### - - /** A move for a Mancala player is an index of the square in the board. - */ - moves: function moves(){ - if (this.result()) { - return null; - } else { - var board = this.board, - result = {}, - activePlayer = this.activePlayer(); - result[activePlayer] = this.houses(activePlayer).filter(function(house){ - return board[house] > 0; // The house has seeds. - }); - return result[activePlayer].length > 0 ? result : null; - } - }, - - /** The game ends when the active player cannot move. The `score()` for each player is the seed - count of its store and (if `countRemainingSeeds` is true) the houses on its side of the board. - */ - scores: function scores() { - var game = this, - board = this.board, - sides = this.players.map(function (player) { - return iterable(game.houses(player)).map(function (h) { - return board[h]; - }).sum(); - }); - if (sides[0] > 0 && sides[1] > 0) { // Both sides have seeds. - return null; - } else { // One side has no seeds. - var _scores = {}; - this.players.forEach(function (player, i) { - _scores[player] = board[game.store(player)] + game.countRemainingSeeds * sides[i]; - }); - return _scores; - } - }, - - /** The result for each player is the difference between its score and the opponent's. - */ - result: function result() { - var scores = this.scores(), - players = this.players; - return scores && this.zerosumResult(scores[players[0]] - scores[players[1]], players[0]); - }, - - /** The `next(moves)` game state implies taking all seeds from the selected house and moving - them across the board, placing one seed at each step. A player can pass through its store but - not through the opponent's. If the move ends at the active player's store, then it has another - move. If it ends at an empty house, capture may occur. - */ - next: function next(moves) { - var activePlayer = this.activePlayer(), - move = +moves[activePlayer], - newBoard = this.board.slice(0), - seeds = newBoard[move], - freeTurn = false, - store, oppositeHouse; - raiseIf(seeds < 1, "Invalid move ", move, " for game ", this); - // Move. - newBoard[move] = 0; - for (; seeds > 0; seeds--) { - move = this.nextSquare(activePlayer, move); - newBoard[move]++; - } - // Free turn if last square of the move is the player's store. - freeTurn = move == this.store(activePlayer); - // Capture. - if (!freeTurn) { - oppositeHouse = this.oppositeHouse(activePlayer, move); - if (oppositeHouse >= 0 && newBoard[move] == 1 && newBoard[oppositeHouse] > 0) { - store = this.store(activePlayer); - newBoard[store]++; - newBoard[move] = 0; - if (!this.emptyCapture) { - newBoard[store] += newBoard[oppositeHouse]; - newBoard[oppositeHouse] = 0; - } - } - } - return new this.constructor(freeTurn ? activePlayer : this.opponent(), newBoard); - }, - - /** The `resultBounds` for a Mancala game are estimated with the total number of seeds in the - board. It is very unlikely to get these result though. - */ - resultBounds: function resultBounds() { - var stoneCount = iterable(this.board).sum(); - return [-stoneCount,+stoneCount]; - }, - - // ## Utility methods ########################################################################## - - /** Serialization is used in the `toString()` method, but it is also vital for sending the game - state across a network or the marshalling between the rendering thread and a webworker. - */ - __serialize__: function __serialize__() { - return [this.name, this.activePlayer(), this.board.slice()]; - }, - - identifier: function identifier() { - return this.activePlayer().charAt(0) + this.board.map(function (n) { - return ('00'+ n.toString(36)).substr(-2); - }).join(''); - }, - - // ## User intefaces ########################################################################### - - /** `printBoard()` creates a text (ASCII) version of the board. - */ - printBoard: function printBoard() { - var game = this, - lpad = base.Text.lpad, - north = this.players[0], - northHouses = this.houses(north).map(function (h) { - return lpad(''+ game.board[h], 2, '0'); - }).reverse(), - northStore = lpad(''+ this.board[this.store(north)], 2, '0'), - south = this.players[1], - southHouses = this.houses(south).map(function (h) { - return lpad(''+ game.board[h], 2, '0'); - }), - southStore = lpad(''+ this.board[this.store(south)], 2, '0'); - return " "+ northHouses.join(" | ") +" \n"+ - northStore +" ".repeat(northHouses.length * 2 + (northHouses.length - 1) * 3 + 2) + southStore +"\n"+ - " "+ southHouses.join(" | ") +" "; - }, - - /** The `display(ui)` method is called by a `UserInterface` to render the game state. The only - supported user interface type is `BasicHTMLInterface`. The look can be configured using CSS - classes. - */ - display: function display(ui) { - raiseIf(!ui || !(ui instanceof UserInterface.BasicHTMLInterface), "Unsupported UI!"); - return this.__displayHTML__(ui); - }, - - /** Board is displayed in HTML as a table with two rows: north and south. The north row has the - two stores on each side, as `TD`s with `rowspan=2`. Each table cell (houses and stores) contains - the number of seeds inside it. - */ - __displayHTML__: function __displayHTML__(ui) { - var table, tr, td, data, - mancala = this, - north = this.players[0], - south = this.players[1], - activePlayer = this.activePlayer(), - moves = this.moves(), - boardSquare = function boardSquare(td, i, isStore) { - var data = { - id: "ludorum-square-"+ i, - className: isStore ? "ludorum-square-store" : "ludorum-square-house", - square: mancala.board[i], - innerHTML: base.Text.escapeXML(mancala.board[i]) - }; - if (!isStore && moves && moves[activePlayer] && moves[activePlayer].indexOf(i) >= 0) { - data.move = i; - data.activePlayer = activePlayer; - data.className = "ludorum-square-move"; - td.onclick = data.onclick = ui.perform.bind(ui, data.move, activePlayer); - } - td['ludorum-data'] = data; - td.id = data.id; - td.className = data.className; - td.innerHTML = data.innerHTML; - td.setAttribute("rowspan", isStore ? 2 : 1); - return td; - }; - ui.container.appendChild(table = document.createElement('table')); - table.appendChild(tr = document.createElement('tr')); - tr.appendChild(boardSquare(document.createElement('td'), this.store(north), true)); - this.houses(north).reverse().forEach(function (h) { - tr.appendChild(boardSquare(document.createElement('td'), h, false)); - }); - tr.appendChild(boardSquare(document.createElement('td'), this.store(south), true)); - table.appendChild(tr = document.createElement('tr')); - this.houses(south).forEach(function (h) { - tr.appendChild(boardSquare(document.createElement('td'), h, false)); - }); - return ui; - }, - - // ## Heuristics and AI ######################################################################## - - /** `Mancala.heuristics` is a bundle of helper functions to build heuristic evaluation functions - for this game. - */ - 'static heuristics': { - /** + `heuristicFromWeights(weights=default weights)` builds an heuristic evaluation - function from weights for each square in the board. The result of the function is the - normalized weighted sum. - */ - heuristicFromWeights: function heuristicFromWeights(weights) { - var weightSum = iterable(weights).map(Math.abs).sum(); - function __heuristic__(game, player) { - var seedSum = 0, signum; - switch (game.players.indexOf(player)) { - case 0: signum = 1; break; // North. - case 1: signum = -1; break; // South. - default: throw new Error("Invalid player "+ player +"."); - } - return iterable(game.board).map(function (seeds, i) { - seedSum += seeds; - return seeds * weights[i]; //TODO Normalize weights before. - }).sum() / weightSum / seedSum * signum; - } - __heuristic__.weights = weights; - return __heuristic__; - } - }, - - // ## Mancala type initialization ############################################################## - - '': function () { - /** The `makeBoard` can also be used without an instance of Mancala. - */ - this.makeBoard = this.prototype.makeBoard; - - /** The `defaultHeuristic `for Mancala is based on weights for each square. Stores are worth - 5 and houses 1, own possitive and the opponent's negative. - */ - this.heuristics.defaultHeuristic = this.heuristics.heuristicFromWeights( - [+1,+1,+1,+1,+1,+1,+5, - -1,-1,-1,-1,-1,-1,-5] - ); - } -}); // declare Mancala. - - /** # Pig. [Pig](http://en.wikipedia.org/wiki/Pig_%28dice_game%29) is a simple dice betting game, used as an @@ -3755,110 +3435,6 @@ games.Pig = declare(Game, { }); // Pig. -/** # ConnectFour. - -Implementation of the [Connect Four game](http://en.wikipedia.org/wiki/Connect_Four), -based on [`ConnectionGame`](ConnectionGame.js.html). -*/ -games.ConnectFour = declare(games.ConnectionGame, { - name: 'ConnectFour', - - /** The default `height` of the board is 6 ... - */ - height: 6, - - /** ... and the default `width` of the board is 7. - */ - width: 7, - - /** The default `lineLength` to win the game is 4. - */ - lineLength: 4, - - /** The game's players are Yellow and Red, since these are the classic - colours of the pieces. - */ - players: ['Yellow', 'Red'], - - /** The active players `moves()` are the indexes of every column that has - not reached the top height. - */ - moves: function moves() { - var result = null; - if (!this.result()) { - var ms = [], - board = this.board.string, - offset = (this.height - 1) * this.width; - for (var i = 0; i < board.length; ++i) { - if (board.charAt(offset + i) === '.') { - ms.push(i); - } - } - if (ms.length > 0) { - result = {}; - result[this.activePlayer()] = ms; - } - } - return result; - }, - - /** The `next(moves)` game state drops a piece at the column with the index - of the active player's move. - */ - next: function next(moves) { - var activePlayer = this.activePlayer(), - board = this.board.string, - column = +moves[activePlayer], - height = this.height, - width = this.width; - for (var row = 0; row < height; ++row) { - if (board.charAt(row * width + column) === '.') { - return new this.constructor(this.opponent(), - this.board.place([row, column], activePlayer === this.players[0] ? '0' : '1')); - } - } - throw new Error('Invalid move '+ JSON.stringify(moves) +'!'); - }, - - // ## User intefaces ####################################################### - - /** The `display(ui)` method is called by a `UserInterface` to render the - game state. The only supported user interface type is `BasicHTMLInterface`. - The look can be configured using CSS classes. - */ - display: function display(ui) { - raiseIf(!ui || !(ui instanceof UserInterface.BasicHTMLInterface), "Unsupported UI!"); - var moves = this.moves(), - activePlayer = this.activePlayer(), - board = this.board; - moves = moves && moves[activePlayer]; - var table = this.board.renderAsHTMLTable(ui.document, ui.container, function (data) { - data.className = data.square === '.' ? 'ludorum-empty' : 'ludorum-player'+ data.square; - data.innerHTML = data.square === '.' ? " " : "●"; - if (moves && moves.indexOf(data.coord[1]) >= 0) { - data.move = data.coord[1]; - data.activePlayer = activePlayer; - data.onclick = ui.perform.bind(ui, data.move, activePlayer); - } - }); - table.insertBefore( - ui.build(ui.document.createElement('colgroup'), - Iterable.repeat(['col'], this.board.width).toArray()), - table.firstChild - ); - return ui; - }, - - // ## Utility methods ###################################################### - - /** The serialization of the game is a representation of a call to its - constructor (inherited from [`ConnectionGame`](ConnectionGame.js.html)). - */ - __serialize__: function __serialize__() { - return [this.name, this.activePlayer(), this.board.string]; - } -}); // declare ConnectFour. - /** # Mutropas Mutropas is a game invented for Ludorum as a simple example of a game of hidden (a.k.a. incomplete) @@ -4033,281 +3609,6 @@ games.Mutropas = declare(Game, { }); // declare Mutropas -/** # Othello - -Implementation of [Othello (aka Reversi)](http://en.wikipedia.org/wiki/Reversi) -for Ludorum. -*/ -games.Othello = declare(Game, { - /** The constructor takes the `activePlayer` (`"Black"` by default) and a - board (initial board by default). The board is represented by an array of - two integers and a string: `[rows, columns, string]`. The string must have: - - + `'W'` for every square occupied by a white piece. - + `'B'` for every square occupied by a black piece. - + `'.'` for every empty square. - */ - constructor: function Othello(activePlayer, board){ - Game.call(this, activePlayer); - this.board = this.makeBoard.apply(this, board || []); - if (!this.moves()) { - var opponent = this.opponent(); - if (this.moves(opponent)) { - this.activePlayers = [opponent]; - } - } - }, - - /** `makeBoard(rows=8, columns=8, string)` is used to build the initial - board. - */ - makeBoard: function makeBoard(rows, columns, string){ - rows = isNaN(rows) ? 8 : +rows; - columns = isNaN(columns) ? 8 : +columns; - raiseIf(rows < 4 || columns < 4 || rows % 2 || columns % 2, "An Othello board must have even dimensions greater than 3."); - if (typeof string === 'string') { - return new CheckerboardFromString(rows, columns, string); - } else { - return new CheckerboardFromString(rows, columns) - .__place__([rows / 2, columns / 2 - 1], "W") - .__place__([rows / 2 - 1, columns / 2], "W") - .__place__([rows / 2, columns / 2], "B") - .__place__([rows / 2 - 1, columns / 2 - 1], "B"); - } - }, - - /** The game's name is `'Othello'`. - */ - name: 'Othello', - - /** The game is played by two players: Black and White. Black moves first. - */ - players: ["Black", "White"], - - /** Much of the move calculations are based on the possible lines in the - board. These are calculated and cached by the `lines(rows, cols)` function. - */ - lines: (function (cache) { - return function lines(rows, cols) { - var key = rows +'x'+ cols, - result = cache[key]; - if (typeof result === 'undefined') { - result = cache[key] = new utils.Checkerboard(rows, cols).lines().map(function(line) { - return line.toArray(); - }, function(line){ - return line.length > 2; - }).toArray(); - } - return result; - }; - })({}), - - /** Another optimization in the move logic uses regular expressions to match - patterns in the board. These are predefined as a _class_ member. - */ - __MOVE_REGEXPS__: { - "Black": [/\.W+B/g, /BW+\./g], - "White": [/\.B+W/g, /WB+\./g] - }, - - /** A move always places a piece in an empty square, if and only if by doing - so one or more lines of the opponent's pieces get enclosed between pieces of - the active player. - */ - moves: function moves(player){ - if (!player && this.__moves__) { - return this.__moves__; - } - player = player || this.activePlayer(); - var board = this.board, - coords = {}, - regexps = this.__MOVE_REGEXPS__[player]; - this.lines(board.height, board.width).forEach(function(line){ - regexps.forEach(function (regexp) { - board.asString(line).replace(regexp, function(m, i){ - var coord = m.charAt(0) === "." ? line[i] : line[m.length - 1 + i]; - coords[coord] = coord; - return m; - }); - }); - }); - var _moves = []; - for (var id in coords) { - _moves.push(coords[id]); - } - return this.__moves__ = (_moves.length > 0 ? obj(player, _moves) : null); - }, - - /** When the active player encloses one or more lines of opponent's pieces - between two of its own, all those are turned into active player's pieces. - */ - next: function next(moves) { - var board = this.board.clone(), - activePlayer = this.activePlayer(), - piece, valid; - if (!moves.hasOwnProperty(activePlayer) || !board.isValidCoord(moves[activePlayer])) { - throw new Error("Invalid moves "+ JSON.stringify(moves) +"!"); - } else if (activePlayer == this.players[0]) { - piece = "B"; - valid = /^W+B/; - } else { - piece = "W"; - valid = /^B+W/; - } - board.walks(moves[activePlayer], Checkerboard.DIRECTIONS.EVERY).forEach(function (walk){ - var match = valid.exec(board.asString(walk).substr(1)); - if (match){ - walk.toArray().slice(0, match[0].length).forEach(function(coord){ - board.__place__(coord, piece); - }); - } - }); - return new this.constructor(this.opponent(), [board.height, board.width, board.string]); - }, - - /** A match ends when the active player cannot move. The winner is the one - with more pieces of its color in the board at the end. - */ - result: function result() { - if (this.moves()) { - return null; - } else { - var weight = {"W": -1, "B": 1}, - res_b = iterable(this.board.string).map(function(m){ - return weight[m] || 0; - }).sum(); - return this.zerosumResult(res_b, "Black"); - } - }, - - /** The actual score is calculated as the difference in piece count. This - means that the maximum victory (maybe impossible) is to fill the board with - pieces of only one colour. - */ - resultBounds: function resultBounds() { - var squareCount = this.board.width * this.board.height; - return [-squareCount, +squareCount]; - }, - - // ## User intefaces ####################################################### - - /** The `display(ui)` method is called by a `UserInterface` to render the - game state. The only supported user interface type is `BasicHTMLInterface`. - The look can be configured using CSS classes. - */ - display: function display(ui) { - raiseIf(!ui || !(ui instanceof UserInterface.BasicHTMLInterface), "Unsupported UI!"); - var moves = this.moves(), - activePlayer = this.activePlayer(), - board = this.board, - classNames = { - 'B': "ludorum-square-Black", - 'W': "ludorum-square-White", - '.': "ludorum-square-empty" - }; - moves = moves && moves[activePlayer].map(JSON.stringify); - board.renderAsHTMLTable(ui.document, ui.container, function (data) { - data.className = classNames[data.square]; - data.innerHTML = ' '; - var move = JSON.stringify(data.coord); - if (moves && moves.indexOf(move) >= 0) { - data.move = data.coord; - data.activePlayer = activePlayer; - data.className = "ludorum-square-move"; - data.onclick = ui.perform.bind(ui, data.move, activePlayer); - } - }); - return ui; - }, - - // ## Utility methods ###################################################### - - /** The game state serialization simply contains the constructor arguments. - */ - __serialize__: function __serialize__() { - var board = this.board; - return [this.name, this.activePlayer(), [board.height, board.width, board.string]]; - }, - - // ## Heuristics ########################################################### - - /** `Othello.heuristics` is a bundle of helper functions to build heuristic - evaluation functions for this game. - */ - 'static heuristics': { - /** `heuristicFromWeights(weights)` returns an heuristic function that - may be used with any [heuristic based player](../players/HeuristicPlayer.js.html). - Weights are normalized, so the result is in (-1,+1) (exclusively). - */ - heuristicFromWeights: function heuristicFromWeights(weights) { - var weightCount = weights.length, - weightSum = iterable(weights).map(Math.abs).sum(); // Used to normalize the sum. - var heuristic = function __heuristic__(game, player) { - var board = game.board; - raiseIf(board.height * board.width !== weightCount, "Wrong amount of weights!"); - return board.weightedSum(weights, { - 'W': player.charAt(0) === 'W' ? 1 : -1, - 'B': player.charAt(0) === 'B' ? 1 : -1 - }) / weightSum; - }; - heuristic.weights = weights; - return heuristic; - }, - - /** `heuristicFromSymmetricWeights(weights)` is similar to - `heuristicFromWeights()` but instead of demanding a weight for every - square in the board, it uses only the upper left quadrant and builds - the rest by symmetry. Hence only a quarter of the weights is required. - */ - heuristicFromSymmetricWeights: function heuristicFromSymmetricWeights(weights, rows, columns) { - rows = isNaN(rows) ? 8 : rows | 0; - columns = isNaN(columns) ? 8 : columns | 0; - var width = Math.ceil(rows / 2); - raiseIf(width * Math.ceil(columns / 2) > weights.length, "Not enough weights!"); - weights = Iterable.range(columns).map(function (column) { - var i = column < columns / 2 ? column : columns - column - 1, - left = i * width, - right = (i + 1) * width; - return weights.slice(left, right) - .concat(weights.slice(left, right - rows % 2).reverse()); - }).flatten().toArray(); - return this.heuristicFromWeights(weights); - }, - - /** `pieceRatio(game, player)` is an heuristic criteria based on the - difference of the piece counts of both players. - */ - pieceRatio: function pieceRatio(game, player) { - var playerPieceCount = 0, opponentPieceCount = 0; - iterable(game.board.string).forEach(function (sq) { - if (sq !== '.') { - if (sq === player.charAt(0)) { - ++playerPieceCount; - } else { - ++opponentPieceCount; - } - } - }); - return (playerPieceCount - opponentPieceCount) / (playerPieceCount + opponentPieceCount) || 0; - }, - - /** `mobilityRatio(game, player)` is an heuristic criteria based on the - difference of the move counts of both players. - */ - mobilityRatio: function mobilityRatio(game, player) { - var opponent = game.opponent(player), - playerMoves = game.moves(player), - opponentMoves = game.moves(opponent), - playerMoveCount = playerMoves && playerMoves[player] && playerMoves[player].length || 0, - opponentMoveCount = opponentMoves && opponentMoves[opponent] && opponentMoves[opponent].length || 0; - return (playerMoveCount - opponentMoveCount) / (playerMoveCount + opponentMoveCount) || 0; - } - } -}); // declare Othello. - -games.Othello.makeBoard = games.Othello.prototype.makeBoard; - - /** # Bahab Bahab is a chess-like board game originally designed for Ludorum. @@ -4319,8 +3620,8 @@ games.Bahab = declare(Game, { */ players: ['Uppercase', 'Lowercase'], - /** The constructor takes the `activePlayer` (Uppercase by default) and the - `board` as a string (`initialBoard` by default). + /** The constructor takes the `activePlayer` (Uppercase by default) and the `board` as a string + (`initialBoard` by default). */ constructor: function Bahab(activePlayer, board) { Game.call(this, activePlayer); @@ -4328,22 +3629,21 @@ games.Bahab = declare(Game, { : new CheckerboardFromString(5, 5, board || this.initialBoard); }, - /** The `initialBoard` has two ranks of pieces for each player. All B pieces - except one A piece at the center of the first rank. + /** The `initialBoard` has two ranks of pieces for each player. All B pieces except one A piece + at the center of the first rank. */ initialBoard: ['BBABB', 'BBBBB', '.....', 'bbbbb', 'bbabb'].join(''), - /** `__PLAYER_ENDGAME_RE__` regular expressions are used to optimize result - calculations. They match if the player has no A piece or if its opponent has - an A piece in its rank. + /** `__PLAYER_ENDGAME_RE__` regular expressions are used to optimize result calculations. They + match if the player has no A piece or if its opponent has an A piece in its rank. */ __PLAYER_ENDGAME_RE__: { Uppercase: /^[.Bab]+$|^.{0,4}[a]/, Lowercase: /^[.bAB]+$|[A].{0,4}$/ }, - /** A player wins when it moves its A piece to the opponent's first rank, - and loses when its A piece is captured by the opponent. + /** A player wins when it moves its A piece to the opponent's first rank, and loses when its A + piece is captured by the opponent. */ result: function result() { var board = this.board.string, player; @@ -4356,18 +3656,17 @@ games.Bahab = declare(Game, { return this.moves() ? null : this.defeat(this.activePlayer()); }, - /** `__PLAYER_PIECES_RE__` regular expressions are used to optimize move - calculations. + /** `__PLAYER_PIECES_RE__` regular expressions are used to optimize move calculations. */ __PLAYER_PIECES_RE__: { Uppercase: /[AB]/g, Lowercase: /[ab]/g }, - /** All pieces move one square forward. A pieces can move straight forward - or diagonally, and B pieces move only diagonally. Pieces can move to any - square that is empty or occupied by an opponent's piece. If the piece moves - to an occupied square, it captures the piece in it. + /** All pieces move one square forward. Piece A can move straight backwards or diagonally + forward, and B pieces move only diagonally forward. Pieces can move to any square that is empty + or occupied by an opponent's piece of the same type. If the piece moves to an occupied square, + it captures the piece in it. */ moves: function moves() { var activePlayer = this.activePlayer(), @@ -4377,16 +3676,16 @@ games.Bahab = declare(Game, { board.string.replace(pieceRegExp, function (piece, i) { var coord = [(i / 5)|0, i % 5], pieceMoves; switch (piece) { - case 'A': pieceMoves = [[+1,-1], [+1, 0], [+1,+1]]; break; + case 'A': pieceMoves = [[+1,-1], [-1, 0], [+1,+1]]; break; case 'B': pieceMoves = [[+1,-1], [+1,+1]]; break; - case 'a': pieceMoves = [[-1,-1], [-1, 0], [-1,+1]]; break; + case 'a': pieceMoves = [[-1,-1], [+1, 0], [-1,+1]]; break; case 'b': pieceMoves = [[-1,-1], [-1,+1]]; break; } iterable(pieceMoves).forEachApply(function (dx, dy) { var coordTo = [coord[0] + dx, coord[1] + dy], squareTo = board.square(coordTo); if (board.isValidCoord(coordTo) && !squareTo.match(pieceRegExp) && - (piece.toLowerCase() != 'b' || squareTo.toLowerCase() != 'a')) { + (squareTo == '.' || piece.toLowerCase() == squareTo.toLowerCase())) { _moves.push([coord, coordTo]); // Valid coordinate and not occupied by a friendly piece. } }); @@ -4395,9 +3694,8 @@ games.Bahab = declare(Game, { return _moves.length > 0 ? obj(activePlayer, _moves) : null; }, - /** Valid move for this game are pairs of coordinates (`[row, column]`), the - first one being where the moving piece starts, and the second one being - where the moving piece ends. + /** Valid move for this game are pairs of coordinates (`[row, column]`), the first one being + where the moving piece starts, and the second one being where the moving piece ends. */ next: function next(moves) { if (!moves) { @@ -4411,19 +3709,18 @@ games.Bahab = declare(Game, { return new this.constructor(this.opponent(), this.board.move(move[0], move[1])); }, - // ## User intefaces ####################################################### + // ## User intefaces ########################################################################### - /** The `display(ui)` method is called by a `UserInterface` to render the - game state. The only supported user interface type is `BasicHTMLInterface`. - The look can be configured using CSS classes. + /** The `display(ui)` method is called by a `UserInterface` to render the game state. The only + supported user interface type is `BasicHTMLInterface`. The look can be configured using CSS + classes. */ display: function display(ui) { raiseIf(!ui || !(ui instanceof UserInterface.BasicHTMLInterface), "Unsupported UI!"); return this.__displayHTML__(ui); }, - /** The game board is rendered in HTML as a table. The look can be customized - with CSS classes. + /** The game board is rendered in HTML as a table. The look can be customized with CSS classes. */ __displayHTML__: function __displayHTML__(ui) { var game = this, @@ -4447,14 +3744,15 @@ games.Bahab = declare(Game, { data.innerHTML = data.square == '.' ? ' ' : data.square; if (ui.selectedPiece) { if (selectedMoves && selectedMoves.indexOf(JSON.stringify(data.coord)) >= 0) { - data.className = "ludorum-square-move"; + data.className = "ludorum-square-"+ activePlayer +"-move"; data.onclick = function () { var selectedPiece = ui.selectedPiece; ui.selectedPiece = (void 0); ui.perform([selectedPiece, data.coord], activePlayer); - }; + }; } - } else if (movesByFrom.hasOwnProperty(JSON.stringify(data.coord))) { + } + if (movesByFrom.hasOwnProperty(JSON.stringify(data.coord))) { data.onclick = function () { ui.selectedPiece = data.coord; ui.display(game); // Redraw the game state. @@ -4464,7 +3762,7 @@ games.Bahab = declare(Game, { return ui; }, - // ## Utility methods ###################################################### + // ## Utility methods ########################################################################## /** The game state serialization simply contains the constructor arguments. */ @@ -4473,369 +3771,6 @@ games.Bahab = declare(Game, { } }); // declare Bahab. -/** # Colograph - -Implementation of the game Colograph, a competitive version of the classic -[graph colouring problem](http://en.wikipedia.org/wiki/Graph_coloring). -*/ -games.Colograph = declare(Game, { - /** The constructor takes the following arguments: - */ - constructor: function Colograph(args) { - /** + `activePlayer`: There is only one active player per turn, and it - is the first player by default. - */ - Game.call(this, args ? args.activePlayer : undefined); - initialize(this, args) - /** + `colours`: The colour of each node in the graph is given by an - array of integers, each being the node's player index in the players - array, or -1 for uncoloured nodes. By default all nodes are not - coloured, which is the initial game state. - */ - .object('colours', { defaultValue: {} }) - /** + `edges`: The edges of the graph are represented by an array of - arrays of integers, acting as an adjacency list. - */ - .array('edges', { defaultValue: [[1,3],[2],[3],[]] }) - /** + `shapes`: Each of the graph's nodes can have a certain shape. This - is specified by an array of strings, one for each node. - */ - .array('shapes', { defaultValue: ['circle', 'triangle', 'square', 'star'] }) - /** + `scoreSameShape=-1`: Score added by each coloured edge that binds - two nodes of the same shape. - */ - .number('scoreSameShape', { defaultValue: -1, coerce: true }) - /** + `scoreDifferentShape=-1`: Score added by each coloured edge that - binds two nodes of different shapes. - */ - .number('scoreDifferentShape', { defaultValue: -1, coerce: true }); - }, - - name: 'Colograph', - - /** There are two roles in this game: Red and Blue. - */ - players: ['Red', 'Blue'], - - /** Scores are calculated for each player with the edges of their colour. An - edge connecting two nodes of the same colour is considered to be of that - colour. - */ - score: function score() { - var points = {}, - shapes = this.shapes, - colours = this.colours, - scoreSameShape = this.scoreSameShape, - scoreDifferentShape = this.scoreDifferentShape, - startingPoints = this.edges.length; - this.players.forEach(function (player) { - points[player] = startingPoints; - }); - iterable(this.edges).forEach(function (n1_edges, n1) { - n1_edges.forEach(function (n2) { - var k = n1 +','+ n2; - if (colours.hasOwnProperty(k)) { - points[colours[k]] += shapes[n1] === shapes[n2] ? scoreSameShape : scoreDifferentShape; - } - }); - }); - return points; - }, - - /** The game ends when the active player has no moves, i.e. when all nodes - in the graph have been coloured. The match is won by the player with the - greatest score. - */ - result: function result() { - if (!this.moves()) { // If the active player cannot move, the game is over. - var points = this.score(), - players = this.players; - return this.zerosumResult(points[players[0]] - points[players[1]], players[0]); - } else { - return null; // The game continues. - } - }, - - /** Every non coloured node is a possible move for the active player. - */ - moves: function moves() { - var colours = this.colours, - uncoloured = []; - for (var i = 0; i < this.edges.length; i++) { - if (!this.colours.hasOwnProperty(i)) { - uncoloured.push(i); - } - } - return uncoloured.length < 1 ? null : obj(this.activePlayer(), uncoloured); - }, - - /** The result of any move is the colouring of one previously uncoloured - node with the active players's colour. - */ - next: function next(moves) { - var activePlayer = this.activePlayer(), - move = +moves[activePlayer] >> 0; - raiseIf(move < 0 || move >= this.colours.length, - 'Invalid move: node ', move, ' does not exist in ', this, '.'); - raiseIf(this.colours[move] >= 0, - 'Invalid move: node ', move, ' has already been coloured in ', this, '.'); - var newColours = copy(obj(move, activePlayer), this.colours); - this.edges[move].forEach(function (n2) { // Colour edges from the one coloured in this move. - if (newColours[n2] === activePlayer) { - newColours[move +','+ n2] = activePlayer; - } - }); - this.edges.forEach(function (adjs, n1) { // Colour edges to the one coloured in this move. - if (n1 !== move && adjs.indexOf(move) >= 0 && newColours[n1] === activePlayer) { - newColours[n1 +','+ move] = activePlayer; - } - }); - return new this.constructor({ - activePlayer: this.opponent(activePlayer), - colours: newColours, - edges: this.edges, - shapes: this.shapes, - scoreSameShape: this.scoreSameShape, - scoreDifferentShape: this.scoreDifferentShape - }); - }, - - __serialize__: function __serialize__() { - return [this.name, { - activePlayer: this.activePlayer(), - colours: this.colours, - edges: this.edges, - shapes: this.shapes, - scoreSameShape: this.scoreSameShape, - scoreDifferentShape: this.scoreDifferentShape - }]; - }, - - // ## Game properties. ##################################################### - - /** `edgeColour(node1, node2)` returns a colour (player index) if the nodes - are joined by an edge, and both have that same colour. - */ - edgeColour: function edgeColour(node1, node2) { - var connected = this.edges[node1].indexOf(node2) >= 0 || this.edges[node2].indexOf(node1) >= 0, - colour1 = this.colours[node1], - colour2 = this.colours[node2]; - return connected && colour1 >= 0 && colour1 === colour2 ? colour1 : -1; - }, - - // ## Heuristics. ########################################################## - - /** `heuristics` is a namespace for heuristic evaluation functions to be - used with artificial intelligence methods such as Minimax. - */ - 'static heuristics': { - /** + `scoreDifference(game, player)` is a simple heuristic that uses - the current score. - */ - scoreDifference: function scoreDifference(game, player) { - var score = game.score(), - result = 0; - for (var p in score) { - result += p === player ? score[p] : -score[p]; - } - return result / game.edges.length / 2; - } - }, - - // ## Graph generation. #################################################### - - /** One of the nice features of this game is the variety that comes from - chaning the graph on which the game is played. `randomGraph` can be used to - generate graphs to experiment with. - */ - 'static randomGraph': function randomGraph(nodeCount, edgeCount, random) { - nodeCount = Math.max(2, +nodeCount >> 0); - edgeCount = Math.max(nodeCount - 1, +edgeCount >> 0); - var edges = basis.iterables.range(nodeCount - 1).map(function (i) { - return random.split(1, basis.iterables.range(i + 1, nodeCount).toArray()); - }).toArray(); - for (var n = edgeCount - (nodeCount - 1), pair, pair2; n > 0; n--) { - pair = random.choice(edges); - if (pair[1].length > 0) { - pair2 = random.split(1, pair[1]); - pair[0].push(pair2[0][0]); - pair[1] = pair2[1]; - n--; - } - } - edges = edges.map(function (pair) { - return pair[0]; - }); - edges.push([]); // Last node has no edges. - return edges; - }, - - /** `randomGame(params)` will generates a random Colograph game with a - random graph. - */ - 'static randomGame': function randomGame(args) { - params = base.initialize({}, params) - .object('random', { defaultValue: randomness.DEFAULT }) - .integer('nodeCount', { defaultValue: 8, coerce: true }) - .integer('edgeCount', { defaultValue: 11, coerce: true }) - .integer('shapeCount', { defaultValue: 4, coerce: true, minimum: 1, maximum: 4 }) - .subject; - var SHAPES = ['circle', 'triangle', 'square', 'star']; - return new Colograph({ - edges: this.randomGraph(params.nodeCount, params.edgeCount, params.random), - shapes: params.random.randoms(params.nodeCount, 0, params.shapeCount).map(function (r) { - return SHAPES[r|0]; - }), - scoreSameShape: 1 - }); - }, - - // ## Human interface based on KineticJS. ################################## - - /** This legacy code is an implementation of a UI for Colograph using - [KineticJS](http://kineticjs.com/). Not entirely compatible yet. - */ - 'static KineticUI': declare(UserInterface, { - constructor: function KineticUI(args) { - UserInterface.call(this, args); - initialize(this, args) - .string("container", { defaultValue: "colograph-container" }) - .object("Kinetic", { defaultValue: window.Kinetic }) - .integer('canvasRadius', { defaultValue: NaN, coerce: true }) - .integer('nodeRadius', { defaultValue: 15, coerce: true }) - .array('playerColours', { defaultValue: ['red', 'blue'] }); - if (isNaN(this.canvasRadius)) { - this.canvasRadius = (Math.min(screen.width, screen.height) * 0.6) >> 1; - } - var stage = this.stage = new Kinetic.Stage({ - container: this.container, - width: this.canvasRadius * 2, - height: this.canvasRadius * 2 - }), - layer = this.layer = new Kinetic.Layer({ - clearBeforeDraw: true, - offsetX: -this.canvasRadius, - offsetY: -this.canvasRadius - }), - game = this.match.state(); - stage.add(layer); - setInterval(stage.draw.bind(stage), 1000 / 30); - layer.destroyChildren(); - this.edges = {}; - this.nodes = {}; - this.drawEdges(game); - this.drawNodes(game); - }, - - drawEdges: function drawEdges(game) { - var angle = 2 * Math.PI / game.edges.length, - radius = this.canvasRadius - this.nodeRadius * 2, - ui = this; - game.edges.forEach(function (n2s, n1) { // Create lines. - n2s.forEach(function (n2) { - var line = new ui.Kinetic.Line({ - points: [radius * Math.cos(angle * n1), radius * Math.sin(angle * n1), - radius * Math.cos(angle * n2), radius * Math.sin(angle * n2)], - stroke: "black", strokeWidth: 2 - }); - ui.edges[n1+','+n2] = line; - ui.layer.add(line); - }); - }); - }, - - drawNodes: function drawNodes(game) { - var angle = 2 * Math.PI / game.edges.length, - radius = this.canvasRadius - this.nodeRadius * 2, - ui = this; - game.edges.forEach(function (adjs, n) { - var shape, - x = radius * Math.cos(angle * n), - y = radius * Math.sin(angle * n); - switch (game.shapes[n]) { - case 'square': - shape = ui.drawSquare(x, y, ui.nodeRadius, n); break; - case 'triangle': - shape = ui.drawTriangle(x, y, ui.nodeRadius, n); break; - case 'star': - shape = ui.drawStar(x, y, ui.nodeRadius, n); break; - default: - shape = ui.drawCircle(x, y, ui.nodeRadius, n); - } - shape.on('mouseover', function () { - shape.setScale(1.2); - }); - shape.on('mouseout', function () { - shape.setScale(1); - }); - shape.on('click tap', function () { - ui.perform(n); - }); - shape.setRotation(Math.random() * 2 * Math.PI);//FIXME - ui.nodes[n] = shape; - ui.layer.add(shape); - }); - }, - - drawCircle: function drawCircle(x, y, r, n) { - return new this.Kinetic.Circle({ - x: x, y: y, radius: r, - fill: "white", stroke: "black", strokeWidth: 2 - }); - }, - - drawSquare: function drawSquare(x, y, r, n) { - return new this.Kinetic.Rect({ - x: x, y: y, width: r * 2, height: r * 2, - offsetX: r, offsetY: r, - fill: "white", stroke: "black", strokeWidth: 2 - }); - }, - - drawStar: function drawStar(x, y, r, n) { - return new Kinetic.Star({ numPoints: 5, - x: x, y: y, innerRadius: r * 0.6, outerRadius: r * 1.5, - fill: 'white', stroke: 'black', strokeWidth: 2 - }); - }, - - drawTriangle: function drawTriangle(x, y, r, n) { - return new Kinetic.RegularPolygon({ sides: 3, - x: x, y: y, radius: r * 1.25, - fill: 'white', stroke: 'black', strokeWidth: 2 - }); - }, - - display: function display(game) { - this.updateEdges(game); - this.updateNodes(game); - }, - - updateEdges: function updateEdges(game) { - var ui = this; - game.edges.forEach(function (n2s, n1) { - n2s.forEach(function (n2) { - var k = n1+','+n2; - ui.edges[k].setStroke(game.colours[k] || "black"); - }); - }); - }, - - updateNodes: function updateNodes(game) { - var ui = this; - game.edges.forEach(function (adjs, n) { - var colour = game.colours[n]; - if (colour) { - ui.nodes[n].setFill(colour); - ui.nodes[n].off('mouseover mouseout click tap'); - } - }); - } - }) // KineticJSCircleUI. - -}); // declare Colograph. - - /** # RoundRobin [Round-robins](http://en.wikipedia.org/wiki/Round-robin_tournament) are diff --git a/build/ludorum.js.map b/build/ludorum.js.map index 7e0b236..845fd69 100644 --- a/build/ludorum.js.map +++ b/build/ludorum.js.map @@ -31,18 +31,14 @@ "src/games/OddsAndEvens.js", "src/games/TicTacToe.js", "src/games/ToadsAndFrogs.js", - "src/games/Mancala.js", "src/games/Pig.js", - "src/games/ConnectFour.js", "src/games/Mutropas.js", - "src/games/Othello.js", "src/games/Bahab.js", - "src/games/Colograph.js", "src/tournaments/RoundRobin.js", "src/tournaments/Measurement.js", "src/tournaments/Elimination.js", "src/__epilogue__.js" ], "names": [], - "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACjZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mC;;ACvEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACzMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2C;;ACxJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACtJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACnTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC3IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uB;;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC9BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AChJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACnFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC1EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACrHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACvEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC7KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8B;;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qB;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC3DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8B;;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC3JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC1EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC9TA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2B;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC3KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AChRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qB;;ACnKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACxWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC5CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACpFA;AACA;AACA,G" + "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACjZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mC;;ACvEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACzMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2C;;ACxJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACtJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACnTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC3IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACrEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACxIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uB;;ACtEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC9BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AChJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACnFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC1EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACtDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACvEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC7KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8B;;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qB;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC3DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8B;;AC7IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC3JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC1EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AChGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC3KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qB;;AChKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;AC5CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;ACpFA;AACA;AACA,G" } \ No newline at end of file diff --git a/build/ludorum.min.js b/build/ludorum.min.js index 72b50c1..06d703d 100644 --- a/build/ludorum.min.js +++ b/build/ludorum.min.js @@ -1,5 +1,5 @@ -//! ludorum 0.1.3-alpha +//! ludorum 0.1.3 -!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["creatartis-base"],b):"object"==typeof module&&module.exports?module.exports=b(require("creatartis-base")):a.ludorum=b(a.base)}(this,function a(b){"use strict";{var c=b.declare,d=b.objects.unimplemented,e=b.obj,f=b.copy,g=b.raise,h=b.raiseIf,i=b.Iterable,j=b.iterable,k=b.Future,l=b.Randomness,m=b.initialize,n=b.Statistics,o=b.Events,p={__name__:"ludorum",__init__:a,__dependencies__:[b]},q=p.utils={},r=p.Game=c({constructor:function(a){this.activePlayers=a?Array.isArray(a)?a:[a]:[this.players[0]]},name:"?",players:[],moves:d("Game","moves"),next:d("Game","next"),result:d("Game","result"),scores:function(){return this.results()},view:function(){return this},isActive:function(){for(var a=0;aa,"There is no active player."),h(a>1,"More than one player is active."),this.activePlayers[0]},opponents:function(a){return a=a||this.activePlayers,this.players.filter(function(b){return a.indexOf(b)<0})},opponent:function(a){var b=this.players.indexOf(a||this.activePlayer());return this.players[(b+1)%this.players.length]},perform:function(){for(var a,b={},c=0;c+a?this.ply()+ +a:+a,this.history[0|a]},result:function(){return this.state().result()},decisions:function(a){a=a||this.state();var b=this,c=this.players,d=a.activePlayers;return k.all(d.map(function(b){return c[b].decision(a.view(b),b)})).then(function(c){var e=j(d).zip(c).toObject();return b.onMove(a,e),e})},run:function(a){if(a=isNaN(a)?1/0:+a,1>a)return k.when(this);var b,c=this.ply(),d=this.state();if(1>c&&this.onBegin(d),d=this.__advanceAleatories__(d),b=d.result())return this.onEnd(d,b),k.when(this);var e=this;return this.decisions(d).then(function(b){return e.__advance__(d,b)?e.run(a-1):e})},__advanceAleatories__:function(a){for(var b;a instanceof y;a=b)b=a.next(),this.history.push(b),this.onNext(a,b);return a},__advance__:function(a,b){var c=this,d=a.activePlayers.filter(function(a){return b[a]instanceof v.CommandQuit});if(d.length>0)return c.onQuit(a,d[0]),!1;var e=a.next(b);return this.history.push(e),this.onNext(a,e),!0},"static CommandQuit":function(){},onBegin:function(a){this.events.emit("begin",a,this),this.logger&&this.logger.info("Match begins with ",j(this.players).map(function(a){return a[1]+" as "+a[0]}).join(", "),"; for ",a,".")},onMove:function(a,b){this.events.emit("move",a,b,this),this.logger&&this.logger.info("Players move: ",JSON.stringify(b)," in ",a)},onNext:function(a,b){this.events.emit("next",a,b,this),this.logger&&this.logger.info("Match advances from ",a," to ",b)},onEnd:function(a,b){this.events.emit("end",a,b,this),this.logger&&this.logger.info("Match for ",a,"ends with ",JSON.stringify(b))},onQuit:function(a,b){this.events.emit("quit",a,b,this),this.logger&&this.logger.info("Match for ",a," aborted because player "+b+" quitted.")},toString:function(){return"Match("+this.game+", "+JSON.stringify(this.players)+")"}}),w=p.Tournament=c({constructor:function(a,b){this.game=a,this.players=Array.isArray(b)?b:iterables.iterable(b).toArray(),this.statistics=new n,this.events=new o({events:["begin","beforeMatch","afterMatch","end"]})},__advance__:d("Tournament","__advance__"),run:function(){this.onBegin();var a=this;return k.doWhile(function(){return k.then(a.__advance__(),function(b){return b?(a.beforeMatch(b),a.__runMatch__(b).then(function(b){return a.account(b),a.afterMatch(b),b})):null})}).then(this.onEnd.bind(this))},__runMatch__:function(a){return a.run()},account:function(a){var b=this.game,c=a.result(),d=this.statistics;h(!c,"Match doesn't have results. Has it finished?"),j(a.players).forEach(function(e){var f=e[0],g=e[1],h=c[e[0]];d.add({key:"results",game:b.name,role:f,player:g.name},h),d.add({key:h>0?"victories":0>h?"defeats":"draws",game:b.name,role:f,player:g.name},h),d.add({key:"length",game:b.name,role:f,player:g.name},a.ply()),a.history.forEach(function(a){if("function"==typeof a.moves){var c=a.moves();c&&c.hasOwnProperty(f)&&c[f].length>0&&d.add({key:"width",game:b.name,role:f,player:g.name},c[f].length)}})})},onBegin:function(){this.events.emit("begin",this),this.logger&&this.logger.info("Tournament begins for game ",game.name,".")},beforeMatch:function(a){this.events.emit("beforeMatch",a,this),this.logger&&this.logger.debug("Beginning match with ",JSON.stringify(a.players),".")},afterMatch:function(a){this.events.emit("afterMatch",a,this),this.logger&&this.logger.debug("Finishing match with ",JSON.stringify(a.players),".")},onEnd:function(){this.events.emit("end",this.statistics,this),this.logger&&this.logger.info("Tournament ends for game ",game.name,":\n",this.statistics,"\n")}}),x=p.tournaments={},y=p.Aleatory=c({constructor:function(a,b){this.random=b||l.DEFAULT,"function"==typeof a&&(this.next=a)},value:function(){var a,b=this.random.random();if(j(this.distribution()).forEach(function(c){if(b-=c[1],0>=b)throw a=c[0],i.STOP_ITERATION}),"undefined"==typeof a)throw new Error("Random value could not be obtained.");return a},next:d("Aleatory","next"),distribution:d("Aleatory","distribution"),"static fromDistribution":function(a,b,c){var d=new y(b,c);return d.distribution=function(){return a},d},"static withDistribution":function(a){return c(y,{distribution:function(){return a}})},"static fromValues":function(a,b,c){a=j(a).toArray();var d=1/a.length,e=new y(b,c);return e.value=function(){return this.random.choice(a)},e.distribution=function(){return a.map(function(a){return[a,d]})},e},"static withValues":function(a){a=j(a).toArray();var b=1/a.length;return c(y,{value:function(){return this.random.choice(a)},distribution:function(){return a.map(function(a){return[a,b]})}})},"static fromRange":function(a,b,c,d){var e=new y(c,d);return e.value=function(){return this.random.randomInt(a,b+1)},e.distribution=function(){return i.range(a,b+1).map(function(c){return[c,1/(b+1-a)]})},e},"static withRange":function(a,b){return c(y,{value:function(){return this.random.randomInt(a,b+1)},distribution:function(){return i.range(a,b+1).map(function(c){return[c,1/(b+1-a)]})}})}}),z=p.aleatories={},A=q.Checkerboard=c({constructor:function(a,b){isNaN(a)||(this.height=0|a),isNaN(b)||(this.width=0|b)},emptySquare:null,isValidCoord:function(a){return Array.isArray(a)&&!isNaN(a[0])&&!isNaN(a[1])&&a[0]>=0&&a[0]=0&&a[1]=b}).map(function(a){return i.range(0,a.length-b+1).map(function(c){return a.slice(c,c+b)})}).flatten()},walk:function(a,b){var c=this;return new i(function(){var d=a.slice();return function(){if(c.isValidCoord(d)){var a=d.slice();return d[0]+=b[0],d[1]+=b[1],a}throw i.STOP_ITERATION}})},walks:function(a,b){var c=this;return b.map(function(b){return c.walk(a,b)})},"static DIRECTIONS":{HORIZONTAL:[[0,-1],[0,1]],VERTICAL:[[-1,0],[1,0]],ORTHOGONAL:[[0,-1],[0,1],[-1,0],[1,0]],DIAGONAL:[[-1,-1],[-1,1],[1,-1],[1,1]],EVERY:[[0,-1],[0,1],[-1,0],[1,0],[-1,-1],[-1,1],[1,-1],[1,1]]},clone:d("utils.Checkerboard","clone"),__place__:d("utils.Checkerboard","place"),place:function(a,b){return this.clone().__place__(a,b)},__move__:function(a,b,c){return this.__place__(b,this.square(a)).__place__(a,"undefined"==typeof c?this.emptySquare:c)},move:function(a,b,c){return this.clone().__move__(a,b,c)},__swap__:function(a,b){var c=this.square(b);return this.__place__(b,this.square(a)).__place__(a,c)},swap:function(a,b){return this.clone().__swap__(a,b)},renderAsHTMLTable:function(a,c,d){var e=this,f=a.createElement("table");return c.appendChild(f),e.horizontals().reverse().forEach(function(c){var g=a.createElement("tr");f.appendChild(g),c.forEach(function(c){var f=e.square(c),h=a.createElement("td"),i={id:"ludorum-square-"+c.join("-"),className:"ludorum-square",square:f,coord:c,innerHTML:b.Text.escapeXML(f)};d&&(i=d(i)||i),h["ludorum-data"]=i,h.id=i.id,h.className=i.className,h.innerHTML=i.innerHTML,i.onclick&&(h.onclick=i.onclick),g.appendChild(h)})}),f},weightedSum:function(a,b){var c=this;return this.coordinates().zip(a).mapApply(function(a,d){return b[c.square(a)]*d||0}).sum()}}),B=q.CheckerboardFromString=c(A,{constructor:function(a,b,c,d){if(A.call(this,a,b),d&&(this.emptySquare=(d+this.emptySquare).charAt(0)),c&&c.length!==a*b)throw new Error("Given string "+JSON.stringify(c)+" does not match board dimensions.");this.string=c||this.emptySquare.repeat(a*b)},emptySquare:".",toString:function(){var a=this.string,b=this.height,c=this.width;return i.range(b).map(function(d){return a.substr((b-d-1)*c,c)}).join("\n")},square:function(a,b){var c=a[0],d=a[1],e=this.width;return c>=0&&c=0&&e>d?this.string.charAt(c*e+d):b},asString:function(a){var b=this;return a.map(function(a){return b.square(a)}).join("")},asStrings:function(a){var b=this;return a.map(function(a){return b.asString(a)})},asRegExp:function(a,b,c){c=c||".";var d=this.width,e=i.repeat(!1,d*this.height).toArray();a.forEach(function(a){e[a[0]*d+a[1]]=!0});for(var f,g="",h=0,j=0;jh?f?b:c:(f?b:c)+"{"+h+"}"}return g},asRegExps:function(a,b,c){var d=this;return a.map(function(a){return d.asRegExp(a,b,c)}).join("|")},clone:function(){return new this.constructor(this.height,this.width,this.string,this.hasOwnProperty("emptySquare")?this.emptySquare:void 0)},__place__:function(a,b){h(!this.isValidCoord(a),"Invalid coordinate ",a,"."),b=(b+this.emptySquare).charAt(0);var c=a[0]*this.width+a[1];return this.string=this.string.substr(0,c)+b+this.string.substr(c+1),this}});q.CheckerboardFromPieces=c(A,{constructor:function(a,b,c,d){A.call(this,a,b),arguments.length>3&&(this.emptySquare=d),this.pieces=j(c||[]).map(function(a){var c=a.position;return[c[0]*b+c[1],a]}).toObject()},emptySquare:null,toString:function(){return"["+j(this.pieces).select(1).join(", ")+"]"},square:function(a,b){var c=a[0]*this.width+a[1];return this.pieces.hasOwnProperty(c)?this.pieces[c]:b},clone:function(){var a=[].concat(this.pieces);return this.hasOwnProperty("emptySquare")?new this.constructor(this.height,this.width,a,this.emptySquare):new this.constructor(this.height,this.width,a)},__place__:function(a,b){h(!this.isValidCoord(a),"Invalid coordinate ",a,"!");var c=a[0]*this.width+a[1];return delete this.pieces[c],b&&(this.pieces[c]=b),this}})}p.utils.Scanner=c({constructor:function(a){m(this,a).object("game",{ignore:!0}).integer("maxWidth",{defaultValue:1e3,coerce:!0}).integer("maxLength",{defaultValue:50,coerce:!0}).object("random",{defaultValue:l.DEFAULT}).object("statistics",{defaultValue:new n})},scan:function(a){var b=this,c=arguments.length<2?this.game?[this.game]:[]:Array.prototype.slice.call(arguments,1),d=0;return k.whileDo(function(){return c.length>0&&dg?(e.add({key:"defeat.result",game:b.name,role:f,player:h},g,b),e.add({key:"defeat.length",game:b.name,role:f,player:h},c,b)):g>0?(e.add({key:"victory.result",game:b.name,role:f,player:h},g,b),e.add({key:"victory.length",game:b.name,role:f,player:h},c,b)):e.add({key:"draw.length",game:b.name,role:f,player:h},c,b)}),!0;var f=b.moves();return j(b.activePlayers).forEach(function(a){e.add({key:"game.width",game:b.name,role:a},f[a].length)}),!1}}),q.Cache=c({constructor:function(a){this.clear(),a&&this.root(a)},stateIdentifier:function(a){return a.identifier()},moveIdentifier:function(a){return JSON.stringify(a)},has:function(a){var b="string"==typeof a?a:this.stateIdentifier(a);return this.__entries__.hasOwnProperty(b)},get:function(a){var b="string"==typeof a?a:this.stateIdentifier(a);return this.__entries__[b]},size:function(){return Object.keys(this.__entries__).length},entry:function(a,b){if(b=b||this.stateIdentifier(a),this.has(b))return this.get(b);var c={id:b,state:a,precursors:[],descendants:{}};return this.__entries__[b]=c,c},descendant:function(a,b){var c=this.moveIdentifier(b),d=a.descendants;if(d.hasOwnProperty(c))return d[c][1];var e=a.state.next(b),f=this.stateIdentifier(e),g=this.get(f)||this.entry(e,f);return d[c]=[b,g],g.precursors.push([b,a]),g},descendants:function(a){var b=this.descendant.bind(this,a);return arguments.length>1?Array.prototype.slice.call(arguments,1).map(b):a.state.possibleMoves().map(b)},clear:function(){this.__entries__={},this.__root__=null},root:function(a){if(arguments.length>0){var b=this.stateIdentifier(a);this.__root__=this.get(b)||this.entry(a,b),this.prune(b)}return this.__root__},prune:function(a){for(var b,c=[a||this.__root__.id],d={};a=c.shift();)d.hasOwnProperty(a)||(b=this.get(a),d[a]=b,c.push.apply(c,j(b.descendants).mapApply(function(a,b){return b[1][a]}).toArray()));return this.__entries__=d}});var C=c({constructor:function(a,b,c){this.parent=a,this.state=b,this.transition=c,this.children={}},childrenCount:function(){return Object.keys(this.children).length},__childSerialization__:function(a){return JSON.stringify(a)},expand:function(a){var b,c=this.__childSerialization__(a),d=this.children[c];if(!d){try{b=this.state.next(a)}catch(e){g("Node expansion for ",this.state," with ",JSON.stringify(a)," failed with: ",e)}d=new this.constructor(this,b,a),this.children[c]=d}return d},possibleTransitions:function(){return this.state instanceof y?this.state.distribution():this.state instanceof r?this.state.possibleMoves():void g("Cannot get possible transitions from ("+this.state+")! Is it a Game or Aleatory?")},expandAll:function(){var a=this;return this.possibleTransitions().map(function(b){return a.expand(b)})}});u.RandomPlayer=c(t,{constructor:function(a){t.call(this,a),m(this,a).object("random",{defaultValue:l.DEFAULT})},decision:function(a,b){return this.random.choice(this.movesFor(a,b))}}),u.TracePlayer=c(t,{constructor:function(a){t.call(this,a),this.trace=j(a.trace),this.__iter__=this.trace.__iter__(),this.__decision__=this.__iter__()},decision:function(){try{this.__decision__=this.__iter__()}catch(a){i.prototype.catchStop(a)}return this.__decision__},__serialize__:function(){return["TracePlayer",{name:this.name,trace:this.trace.toArray()}]}});var D=u.HeuristicPlayer=c(t,{constructor:function(a){t.call(this,a),m(this,a).object("random",{defaultValue:l.DEFAULT}).func("heuristic",{ignore:!0})},moveEvaluation:function(a,b,c){if(Object.keys(a).length<2)return this.stateEvaluation(b.next(a),c);var d=0,g=0;return a=f(e(c,[a[c]]),a),b.possibleMoves(a).forEach(function(a){d+=this.stateEvaluation(b.next(a),c),++g}),g>0?d/g:0},stateEvaluation:function(a,b){var c=a.result();return c?c[b]:this.heuristic(a,b)},heuristic:function(){return this.random.random(-.5,.5)},bestMoves:function(a){return j(a).greater(function(a){return a[1]}).map(function(a){return a[0]})},selectMoves:function(a,b,c){var d=this,e=!1,f=a.map(function(a){var f=d.moveEvaluation(a,b,c);return f instanceof k?(e=e||!0,f.then(function(b){return[a,b]})):[a,f]});return e?k.all(f).then(this.bestMoves):this.bestMoves(f)},decision:function(a,b){var c=this,d=a.moves();h(!d||!d.hasOwnProperty(b),"Player "+b+" is not active (moves= "+JSON.stringify(d)+")!");var g=d[b];if(h(!Array.isArray(g)||g.length<1,"Player "+b+" has no moves ("+g+")!"),1==g.length)return g[0];d=g.map(function(a){return f(e(b,a),d)});var i=c.selectMoves(d,a,b);return k.then(i,function(d){return h(!d||!d.length,"No moves where selected at ",a," for player ",b,"!"),c.random.choice(d)[b]})},"static composite":function(){var a=Array.prototype.slice.call(arguments);h(a.length<1,"HeuristicPlayer.composite() cannot take an odd number of arguments!");for(var b=0;b1,"HeuristicPlayer.composite() argument ",b+1," (",a[b+1],") is not a valid weight!");return function(b,c){for(var d=0,e=0;e+1=this.horizon?this.heuristics(a):null},maxN:function(a,b,c){var d=this.quiescence(a,b,c);if(!d){var f,g,h=a.activePlayer(),i=this.movesFor(a,h);if(d={},i.length<1)throw new Error("No moves for unfinished game "+a+".");for(var j=0;j(d[h]||-1/0)&&(d=f)}return d},toString:function(){return(this.constructor.name||"MaxNPlayer")+"("+JSON.stringify({name:this.name,horizon:this.horizon})+")"}}),u.MiniMaxPlayer=c(D,{constructor:function(a){D.call(this,a),m(this,a).integer("horizon",{defaultValue:4,coerce:!0})},stateEvaluation:function(a,b){return this.minimax(a,b,0)},quiescence:function(a,b,c){var d=a.result();return d?d[b]:c>=this.horizon?this.heuristic(a,b):0/0},minimax:function(a,b,c){var d=this.quiescence(a,b,c);if(isNaN(d)){var f,g,h=a.activePlayer(),i=this.movesFor(a,h);if(i.length<1)throw new Error("No moves for unfinished game "+a+".");h==b?(d=-1/0,f=Math.max):(d=+1/0,f=Math.min);for(var j=0;jd&&(d=g):f>g&&(f=g),!(d>=f));l++);return j?d:f}});var F=u.MonteCarloPlayer=c(D,{constructor:function(a){if(D.call(this,a),m(this,a).number("simulationCount",{defaultValue:30,coerce:!0}).number("timeCap",{defaultValue:1e3,coerce:!0}).number("horizon",{defaultValue:1/0,coerce:!0}),a)switch(typeof a.agent){case"function":this.agent=new D({heuristic:a.agent});break;case"object":this.agent=a.agent;break;default:this.agent=null}},selectMoves:function(a,b,c){for(var d=this,g=Date.now()+this.timeCap,i=b.next.bind(b),k=a.map(function(a){return{move:a,nexts:Object.keys(a).length<2?[b.next(a)]:b.possibleMoves(f(e(c,[a[c]]),a)).map(i),sum:0,count:0}}),l=0;l0})});return k=j(k).greater(function(a){return h(isNaN(a.sum),"State evaluation is NaN for move ",a.move,"!"),a.count>0?a.sum/a.count:0}).map(function(a){return a.move})},stateEvaluation:function(a,b){for(var c,d=0,e=this.simulationCount,f=0;e>f&&(c=this.simulation(a,b),d+=c.result[b],!(c.plies<1));++f);return e>0?d/e:0},simulation:function(a,b){var c,d,f,h=this;for(c=0;!0;++c)if(a instanceof y)a=a.next();else{if(f=a.moves(),!f)return{game:a,result:a.result(),plies:c};if(c>this.horizon)return{game:a,result:e(b,this.heuristic(a,b)),plies:c};d={},a.activePlayers.forEach(function(b){d[b]=h.agent?h.agent.decision(a,b):h.random.choice(f[b])}),a=a.next(d)}g("Simulation ended unexpectedly for player ",b," in game ",a,"!")},__serialize__:function(){return[this.constructor.name,{name:this.name,simulationCount:this.simulationCount,timeCap:this.timeCap,agent:this.agent}]}});u.UCTPlayer=c(F,{constructor:function(a){F.call(this,a),m(this,a).number("explorationConstant",{defaultValue:Math.sqrt(2),coerce:!0})},selectNode:function(a,b,c){return c=isNaN(c)?this.explorationConstant:+c,this.random.choice(j(a.children).select(1).greater(function(a){return a.uct.rewards/a.uct.visits+c*Math.sqrt(Math.log(b)/a.uct.visits)}))},selectMoves:function(a,b,c){var d,e,f=new C(null,b),g=Date.now()+this.timeCap;f.uct={pending:this.random.shuffle(f.possibleTransitions()),visits:0,rewards:0};for(var h=0;h0;)d=this.selectNode(d,h+1,this.explorationConstant);for(d.uct.pending.length>0&&(d=d.expand(d.uct.pending.pop()),d.uct={pending:this.random.shuffle(d.possibleTransitions()),visits:0,rewards:0}),e=this.simulation(d.state,c);d;d=d.parent)++d.uct.visits,d.uct.rewards+=(b.normalizedResult(e.result)[c]+1)/2}return a=j(f.children).select(1).greater(function(a){return a.uct.visits}).map(function(a){return a.transition})},__serialize__:function(){return[this.constructor.name,{name:this.name,simulationCount:this.simulationCount,timeCap:this.timeCap,explorationConstant:this.explorationConstant}]}});var G=u.UserInterfacePlayer=c(t,{constructor:function(a){t.call(this,a)},participate:function(a,b){return this.role=b,this},decision:function(){return this.__future__&&this.__future__.isPending()&&this.__future__.resolve(new v.CommandQuit),this.__future__=new k,this.__future__},perform:function(a){var b=this.__future__;return b&&(this.__future__=null,b.resolve(a)),!!b}}),H=u.UserInterface=c({constructor:function(a){this.onBegin=this.onBegin.bind(this),this.onNext=this.onNext.bind(this),this.onEnd=this.onEnd.bind(this),a.match&&this.show(a.match)},show:function(a){this.match&&(a.events.off("begin",this.onBegin),a.events.off("next",this.onNext),a.events.off("end",this.onEnd)),this.match=a,a.events.on("begin",this.onBegin),a.events.on("next",this.onNext),a.events.on("end",this.onEnd)},onBegin:function(a){this.display(a)},onNext:function(a,b){this.display(b)},onEnd:function(a,b){this.results=b,this.display(a)},display:d("UserInterface","display"),perform:function(a,b){j(this.match.players).forEach(function(c){var d=(c[0],c[1]);d instanceof G&&(!b||d.role===b)&&d.perform(a)})}});H.BasicHTMLInterface=c(H,{constructor:function(a){H.call(this,a),this.document=a.document||b.global.document,this.container=a.container,"string"==typeof this.container&&(this.container=this.document.getElementById(this.container))},display:function(a){for(var b,c=this.container;b=c.firstChild;)c.removeChild(b);a.display(this)},build:function(a,b){var c=this;return b.forEach(function(b){var d;if(Array.isArray(b)){if(d=c.document.createElement(b[0]),b.length>2&&b[1]){var e=b[1];for(var f in e)attr.hasOwnProperty(f)&&d.setAttribute(f,e[f])}b.length>1&&b[b.length-1]&&c.build(d,b[b.length-1])}else"string"==typeof b&&(d=c.document.createTextNode(b));d&&a&&a.appendChild(d)}),a}});u.WebWorkerPlayer=c(t,{constructor:function(a){t.call(this,a),m(this,a).object("worker"),this.worker.onmessage=b.Parallel.prototype.__onmessage__.bind(this)},"static createWorker":function(a){h("string function".indexOf(typeof a)<0,"Invalid player builder: "+a+"!");var c=new b.Parallel;return c.run("self.ludorum = ("+p.__init__+')(self.base), "OK"').then(function(){return c.run("self.PLAYER = ("+a+').call(self), "OK"')}).then(function(){return c.worker})},"static create":function(a){var b=this;return b.createWorker(a.playerBuilder).then(function(a){return new b({name:name,worker:a})})},decision:function(a,b){return this.__future__&&this.__future__.isPending()&&this.__future__.resolve(v.commandQuit),this.__future__=new k,this.worker.postMessage("PLAYER.decision(ludorum.Game.fromJSON("+a.toJSON()+"), "+JSON.stringify(b)+")"),this.__future__}});return z.dice={D4:y.withRange(1,4),D6:y.withRange(1,6),D8:y.withRange(1,8),D10:y.withRange(1,10),D12:y.withRange(1,12),D20:y.withRange(1,20),D100:y.withRange(1,100)},s.Predefined=c(r,{constructor:function(a,b,c,d){b&&(this.__results__=b,this.players=Object.keys(b)),r.call(this,a),this.height=isNaN(c)?5:+c,this.width=isNaN(d)?5:+d},name:"Predefined",players:["A","B"],__results__:{A:0,B:0},moves:function(){return this.height>0?e(this.activePlayer(),i.range(1,this.width+1).toArray()):void 0},result:function(){return this.height>0?null:this.__results__},next:function(){return new this.constructor(this.opponent(),this.__results__,this.height-1,this.width)},__serialize__:function(){return[this.name,this.activePlayer(),this.results,this.height,this.width]}}),s.Choose2Win=c(r,{constructor:function(a,b,c){r.call(this,b),this.__turns__=isNaN(a)?1/0:+a,this.__winner__=c},name:"Choose2Win",players:["This","That"],moves:function(){return!this.__winner__&&this.__turns__>0?e(this.activePlayer(),["win","lose","pass"]):void 0},result:function(){return this.__winner__?this.victory(this.__winner__):this.__turns__<1?this.draw():null},next:function(a){var b=this.activePlayer(),c=this.opponent(b);switch(h(!a.hasOwnProperty(b),"No move for active player ",b," at ",this,"!"),a[b]){case"win":return new this.constructor(this.__turns__-1,c,b);case"lose":return new this.constructor(this.__turns__-1,c,c);case"pass":return new this.constructor(this.__turns__-1,c);default:g("Invalid move ",a[b]," for player ",b," at ",this,"!")}},__serialize__:function(){return[this.name,this.__turns__,this.activePlayer(),this.__winner__]}}),s.ConnectionGame=c(r,{height:9,width:9,lineLength:5,constructor:function(a,b){r.call(this,a),this.board=b instanceof B?b:new B(this.height,this.width,(b||".".repeat(this.height*this.width))+"")},name:"ConnectionGame",players:["First","Second"],__lines__:function(){function a(a,c,d){var e=a+"x"+c+"/"+d;if(!b.hasOwnProperty(e)){var f=new B(a,c,".".repeat(a*c));b[e]=f.lines().map(function(a){return a.toArray()},function(a){return a.length>=d}).toArray()}return b[e]}var b={};return a.CACHE=b,a}(),result:function(){if(this.hasOwnProperty("__result__"))return this.__result__;for(var a=this.lineLength,b=this.board.asStrings(this.__lines__(this.height,this.width,a)).join(" "),c=0;c=0)return this.__result__=this.victory([this.players[c]]);return this.__result__=b.indexOf(".")<0?this.draw():null},moves:function(){return this.hasOwnProperty("__moves__")?this.__moves__:this.__moves__=this.result()?null:e(this.activePlayer(),j(this.board.string).filter(function(a){return"."===a},function(a,b){return b}).toArray())},next:function(a){var b=this.activePlayer(),c=this.players.indexOf(b),d=+a[b],e=d/this.width>>0,f=d%this.width; -return new this.constructor((c+1)%this.players.length,this.board.place([e,f],c.toString(36)))},display:function(a){h(!(a&&a instanceof H.BasicHTMLInterface),"Unsupported UI!");var b=this.moves(),c=this.activePlayer(),d=this.board;b=b&&b[c];this.board.renderAsHTMLTable(a.document,a.container,function(e){e.className="."===e.square?"ludorum-empty":"ludorum-player"+e.square,e.innerHTML="."===e.square?" ":"●";var f=e.coord[0]*d.height+e.coord[1];b&&b.indexOf(f)>=0&&(e.move=f,e.activePlayer=c,e.onclick=a.perform.bind(a,e.move,c))});return a},__serialize__:function(){return[this.name,this.activePlayer(),this.board.string]}}),s.OddsAndEvens=c(r,{constructor:function(a,b){r.call(this,this.players),this.turns=isNaN(a)?1:+a,this.points=b||{Evens:0,Odds:0}},name:"OddsAndEvens",players:["Evens","Odds"],moves:function(){return this.turns<1?null:{Evens:[1,2],Odds:[1,2]}},result:function(){var a=this.points.Evens-this.points.Odds;return this.turns>0?null:{Evens:+a,Odds:-a}},next:function(a){h("number"!=typeof a.Evens||"number"!=typeof a.Odds,"Invalid moves "+(JSON.stringify(a)||a)+"!");var b=(a.Evens+a.Odds)%2===0;return new this.constructor(this.turns-1,{Evens:this.points.Evens+(b?1:0),Odds:this.points.Odds+(b?0:1)})},__serialize__:function(){return[this.name,this.turns,this.points]}}),s.TicTacToe=c(r,{name:"TicTacToe",constructor:function(a,b){r.call(this,a),this.board=b||"_________"},players:["Xs","Os"],result:function(){return function(){return this.board.match(this.WIN_X)?this.victory(["Xs"]):this.board.match(this.WIN_O)?this.victory(["Os"]):this.board.indexOf("_")<0?this.draw():null}}(),moves:function(){if(this.result())return null;var a={};return a[this.activePlayer()]=j(this.board).filter(function(a){return"_"===a},function(a,b){return b}).toArray(),a},next:function(a){var b=this.activePlayer(),c=+a[b];if(isNaN(c)||"_"!==this.board.charAt(c))throw new Error("Invalid move "+JSON.stringify(a)+" for board "+this.board+" (moves= "+JSON.stringify(a)+").");var d=this.board.substring(0,c)+b.charAt(0)+this.board.substring(c+1);return new this.constructor(this.opponent(b),d)},__serialize__:function(){return[this.name,this.activePlayer(),this.board]},printBoard:function(){var a=this.board;return[a.substr(0,3).split("").join("|"),"-+-+-",a.substr(3,3).split("").join("|"),"-+-+-",a.substr(6,3).split("").join("|")].join("\n")},display:function(a){h(!(a&&a instanceof H.BasicHTMLInterface),"Unsupported UI!");var b=this.activePlayer(),c=this.moves(),d=(this.board,{X:"ludorum-square-Xs",O:"ludorum-square-Os",_:"ludorum-square-empty"}),e={X:"X",O:"O",_:" "};return c=c&&c[b]&&c[b].length>0,new B(3,3,this.board,"_").renderAsHTMLTable(a.document,a.container,function(f){f.className=d[f.square],f.innerHTML=e[f.square],c&&"_"===f.square&&(f.move=3*f.coord[0]+f.coord[1],f.activePlayer=b,f.onclick=a.perform.bind(a,f.move,b))}),a},"static heuristics":{heuristicFromWeights:function(a){function b(b,d){var e=d.charAt(0);return j(b.board).map(function(b,c){return"_"===b?0:a[c]*(b===e?1:-1)}).sum()/c}var c=j(a).map(Math.abs).sum();return b.weights=a,b}},"":function(){var a=new B(3,3,"_".repeat(9)),b=a.sublines(a.lines(),3);this.prototype.WIN_X=new RegExp(a.asRegExps(b,"X",".")),this.prototype.WIN_O=new RegExp(a.asRegExps(b,"O",".")),this.heuristics.defaultHeuristic=this.heuristics.heuristicFromWeights([2,1,2,1,5,1,2,1,2])}}),s.ToadsAndFrogs=c(r,{constructor:function I(a,b){r.call(this,a),this.board=b||I.board()},"static board":function(a,b){return a=isNaN(a)?3:+a,b=isNaN(b)?2:+b,"T".repeat(a)+"_".repeat(b)+"F".repeat(a)},name:"ToadsAndFrogs",players:["Toads","Frogs"],result:function(){return this.moves()?null:this.defeat()},moves:function(){var a=this.activePlayer(),b={},c=b[a]=[];return this.board.replace(a==this.players[0]?/TF?_/g:/_T?F/g,function(a,b){return c.push(b),a}),c.length>0?b:null},next:function(a){var b=this.activePlayer(),c=a[b],d=(b.charAt(0),this.board);if("T_"==d.substr(c,2))d=d.substring(0,c)+"_T"+d.substring(c+2);else if("_F"==d.substr(c,2))d=d.substring(0,c)+"F_"+d.substring(c+2);else if("TF_"==d.substr(c,3))d=d.substring(0,c)+"_FT"+d.substring(c+3);else{if("_TF"!=d.substr(c,3))throw new Error("Invalid move ",c," for board <",d,">.");d=d.substring(0,c)+"FT_"+d.substring(c+3)}return new this.constructor(this.opponent(),d)},__serialize__:function(){return[this.name,this.activePlayer,this.board]}}),s.Mancala=c(r,{name:"Mancala",constructor:function(a,b){r.call(this,a),this.board=b||this.makeBoard()},makeBoard:function(a,b){a=isNaN(a)?4:+a,b=isNaN(b)?6:+b;for(var c=[],d=0;2>d;d++){for(var e=0;b>e;e++)c.push(a);c.push(0)}return c},players:["North","South"],emptyCapture:!1,countRemainingSeeds:!0,store:function(a){switch(this.players.indexOf(a)){case 0:return this.board.length/2-1;case 1:return this.board.length-1;default:throw new Error("Invalid player "+a+".")}},houses:function(a){switch(this.players.indexOf(a)){case 0:return i.range(0,this.board.length/2-1).toArray();case 1:return i.range(this.board.length/2,this.board.length-1).toArray();default:throw new Error("Invalid player "+a+".")}},oppositeHouse:function(a,b){var c=this.houses(a),d=this.houses(this.opponent(a)),e=c.indexOf(b);return 0>e?e:d.reverse()[e]},nextSquare:function(a,b){do b=(b+1)%this.board.length;while(b===this.store(this.opponent(a)));return b},moves:function(){if(this.result())return null;var a=this.board,b={},c=this.activePlayer();return b[c]=this.houses(c).filter(function(b){return a[b]>0}),b[c].length>0?b:null},scores:function(){var a=this,b=this.board,c=this.players.map(function(c){return j(a.houses(c)).map(function(a){return b[a]}).sum()});if(c[0]>0&&c[1]>0)return null;var d={};return this.players.forEach(function(e,f){d[e]=b[a.store(e)]+a.countRemainingSeeds*c[f]}),d},result:function(){var a=this.scores(),b=this.players;return a&&this.zerosumResult(a[b[0]]-a[b[1]],b[0])},next:function(a){var b,c,d=this.activePlayer(),e=+a[d],f=this.board.slice(0),g=f[e],i=!1;for(h(1>g,"Invalid move ",e," for game ",this),f[e]=0;g>0;g--)e=this.nextSquare(d,e),f[e]++;return i=e==this.store(d),i||(c=this.oppositeHouse(d,e),c>=0&&1==f[e]&&f[c]>0&&(b=this.store(d),f[b]++,f[e]=0,this.emptyCapture||(f[b]+=f[c],f[c]=0))),new this.constructor(i?d:this.opponent(),f)},resultBounds:function(){var a=j(this.board).sum();return[-a,+a]},__serialize__:function(){return[this.name,this.activePlayer(),this.board.slice()]},identifier:function(){return this.activePlayer().charAt(0)+this.board.map(function(a){return("00"+a.toString(36)).substr(-2)}).join("")},printBoard:function(){var a=this,c=b.Text.lpad,d=this.players[0],e=this.houses(d).map(function(b){return c(""+a.board[b],2,"0")}).reverse(),f=c(""+this.board[this.store(d)],2,"0"),g=this.players[1],h=this.houses(g).map(function(b){return c(""+a.board[b],2,"0")}),i=c(""+this.board[this.store(g)],2,"0");return" "+e.join(" | ")+" \n"+f+" ".repeat(2*e.length+3*(e.length-1)+2)+i+"\n "+h.join(" | ")+" "},display:function(a){return h(!(a&&a instanceof H.BasicHTMLInterface),"Unsupported UI!"),this.__displayHTML__(a)},__displayHTML__:function(a){var c,d,e=this,f=this.players[0],g=this.players[1],h=this.activePlayer(),i=this.moves(),j=function(c,d,f){var g={id:"ludorum-square-"+d,className:f?"ludorum-square-store":"ludorum-square-house",square:e.board[d],innerHTML:b.Text.escapeXML(e.board[d])};return!f&&i&&i[h]&&i[h].indexOf(d)>=0&&(g.move=d,g.activePlayer=h,g.className="ludorum-square-move",c.onclick=g.onclick=a.perform.bind(a,g.move,h)),c["ludorum-data"]=g,c.id=g.id,c.className=g.className,c.innerHTML=g.innerHTML,c.setAttribute("rowspan",f?2:1),c};return a.container.appendChild(c=document.createElement("table")),c.appendChild(d=document.createElement("tr")),d.appendChild(j(document.createElement("td"),this.store(f),!0)),this.houses(f).reverse().forEach(function(a){d.appendChild(j(document.createElement("td"),a,!1))}),d.appendChild(j(document.createElement("td"),this.store(g),!0)),c.appendChild(d=document.createElement("tr")),this.houses(g).forEach(function(a){d.appendChild(j(document.createElement("td"),a,!1))}),a},"static heuristics":{heuristicFromWeights:function(a){function b(b,d){var e,f=0;switch(b.players.indexOf(d)){case 0:e=1;break;case 1:e=-1;break;default:throw new Error("Invalid player "+d+".")}return j(b.board).map(function(b,c){return f+=b,b*a[c]}).sum()/c/f*e}var c=j(a).map(Math.abs).sum();return b.weights=a,b}},"":function(){this.makeBoard=this.prototype.makeBoard,this.heuristics.defaultHeuristic=this.heuristics.heuristicFromWeights([1,1,1,1,1,1,5,-1,-1,-1,-1,-1,-1,-5])}}),s.Pig=c(r,{constructor:function(a,b,c,d){r.call(this,a),this.goal=isNaN(b)?100:+b,this.__scores__=c||j(this.players).zip([0,0]).toObject(),this.__rolls__=d||[]},name:"Pig",players:["One","Two"],moves:function(){if(!this.result()){var a=this.activePlayer(),b=this.__scores__[a]+j(this.__rolls__).sum();return e(a,this.__rolls__.length<1?["roll"]:b>=this.goal?["hold"]:["roll","hold"])}},result:function(){var a=this.__scores__[this.players[0]],b=this.__scores__[this.players[1]];if(a>=this.goal||b>=this.goal){var c={};return c[this.players[0]]=Math.min(this.goal,a)-Math.min(this.goal,b),c[this.players[1]]=-c[this.players[0]],c}},next:function(a){var b=this.activePlayer(),c=a[b];if(h("undefined"==typeof c,"No move for active player ",b," at ",this,"!"),"hold"===c){var d=f(this.__scores__);return d[b]+=j(this.__rolls__).sum(),new this.constructor(this.opponent(),this.goal,d,[])}if("roll"===c){var e=this;return new z.dice.D6(function(a){return a=isNaN(a)?this.value():+a,a>1?new e.constructor(b,e.goal,e.__scores__,e.__rolls__.concat(a)):new e.constructor(e.opponent(),e.goal,e.__scores__,[])})}g("Invalid moves ",JSON.stringify(a)," at ",this,"!")},resultBounds:function(){return[-this.goal,+this.goal]},__serialize__:function(){return[this.name,this.activePlayer(),this.goal,this.__scores__,this.__rolls__]}}),s.ConnectFour=c(s.ConnectionGame,{name:"ConnectFour",height:6,width:7,lineLength:4,players:["Yellow","Red"],moves:function(){var a=null;if(!this.result()){for(var b=[],c=this.board.string,d=(this.height-1)*this.width,e=0;e0&&(a={},a[this.activePlayer()]=b)}return a},next:function(a){for(var b=this.activePlayer(),c=this.board.string,d=+a[b],e=this.height,f=this.width,g=0;e>g;++g)if("."===c.charAt(g*f+d))return new this.constructor(this.opponent(),this.board.place([g,d],b===this.players[0]?"0":"1"));throw new Error("Invalid move "+JSON.stringify(a)+"!")},display:function(a){h(!(a&&a instanceof H.BasicHTMLInterface),"Unsupported UI!");{var b=this.moves(),c=this.activePlayer();this.board}b=b&&b[c];var d=this.board.renderAsHTMLTable(a.document,a.container,function(d){d.className="."===d.square?"ludorum-empty":"ludorum-player"+d.square,d.innerHTML="."===d.square?" ":"●",b&&b.indexOf(d.coord[1])>=0&&(d.move=d.coord[1],d.activePlayer=c,d.onclick=a.perform.bind(a,d.move,c))});return d.insertBefore(a.build(a.document.createElement("colgroup"),i.repeat(["col"],this.board.width).toArray()),d.firstChild),a},__serialize__:function(){return[this.name,this.activePlayer(),this.board.string]}}),s.Mutropas=c(r,{name:"Mutropas",players:["Left","Right"],constructor:function(a){r.call(this,this.players),a=a||{},this.random=a.random||l.DEFAULT,this.playedPieces=a.playedPieces||[],this.pieces=a.pieces||this.dealPieces(),this.__scores__=a.scores||e(this.players[0],0,this.players[1],0)},allPieces:i.range(9).toArray(),dealPieces:function(a){a=a||this.random;var b=this.allPieces.length/2|0,c=a.split(b,this.allPieces),d=a.split(b,c[1]);return e(this.players[0],c[0],this.players[1],d[0])},moves:function(){return this.result()?null:f({},this.pieces)},moveResult:function(a,b){var c=j(this.allPieces).max(0)+1;return b>a?c/2>=b-a?1:-1:a>b?a-b>=c/2+1?1:-1:0},next:function(a){var b=this.players[0],c=this.players[1],d=a[b],f=a[c],g=this.pieces;h(g[b].indexOf(d)<0,"Invalid move ",JSON.stringify(d)," for player ",b,"! (moves= ",JSON.stringify(a),")"),h(g[c].indexOf(f)<0,"Invalid move ",JSON.stringify(f)," for player ",c,"! (moves= ",JSON.stringify(a),")");var i=this.moveResult(d,f);return new this.constructor({random:this.random,playedPieces:this.playedPieces.concat([d,f]),pieces:e(b,g[b].filter(function(a){return a!==d}),c,g[c].filter(function(a){return a!==f})),scores:e(b,this.__scores__[b]+i,c,this.__scores__[c]-i)})},scores:function(){return f({},this.__scores__)},result:function(){var a=this.players;if(this.playedPieces.length>=this.allPieces.length-1){var b=this.scores();return this.zerosumResult(b[a[0]]-b[a[1]],a[0])}return null},__possiblePieces__:function(a){var b=this.playedPieces,c=this.pieces[this.opponent(a)],d=j(this.allPieces).filter(function(a){return b.indexOf(a)<0&&c.indexOf(a)<0});return d.combinations(d.count()-1)},view:function(a){var b=this,c=this.opponent(a),d=this.random;return y.withValues(this.__possiblePieces__(c),d,function(f){return f=f||this.value(),new b.constructor({random:d,playedPieces:b.playedPieces,scores:b.scores(),pieces:e(a,b.pieces[a],c,f)})})},__serialize__:function(){return[this.name,{pieces:this.__pieces__,scores:this.__scores__}]}}),s.Othello=c(r,{constructor:function(a,b){if(r.call(this,a),this.board=this.makeBoard.apply(this,b||[]),!this.moves()){var c=this.opponent();this.moves(c)&&(this.activePlayers=[c])}},makeBoard:function(a,b,c){return a=isNaN(a)?8:+a,b=isNaN(b)?8:+b,h(4>a||4>b||a%2||b%2,"An Othello board must have even dimensions greater than 3."),"string"==typeof c?new B(a,b,c):new B(a,b).__place__([a/2,b/2-1],"W").__place__([a/2-1,b/2],"W").__place__([a/2,b/2],"B").__place__([a/2-1,b/2-1],"B")},name:"Othello",players:["Black","White"],lines:function(a){return function(b,c){var d=b+"x"+c,e=a[d];return"undefined"==typeof e&&(e=a[d]=new q.Checkerboard(b,c).lines().map(function(a){return a.toArray()},function(a){return a.length>2}).toArray()),e}}({}),__MOVE_REGEXPS__:{Black:[/\.W+B/g,/BW+\./g],White:[/\.B+W/g,/WB+\./g]},moves:function(a){if(!a&&this.__moves__)return this.__moves__;a=a||this.activePlayer();var b=this.board,c={},d=this.__MOVE_REGEXPS__[a];this.lines(b.height,b.width).forEach(function(a){d.forEach(function(d){b.asString(a).replace(d,function(b,d){var e="."===b.charAt(0)?a[d]:a[b.length-1+d];return c[e]=e,b})})});var f=[];for(var g in c)f.push(c[g]);return this.__moves__=f.length>0?e(a,f):null},next:function(a){var b,c,d=this.board.clone(),e=this.activePlayer();if(!a.hasOwnProperty(e)||!d.isValidCoord(a[e]))throw new Error("Invalid moves "+JSON.stringify(a)+"!");return e==this.players[0]?(b="B",c=/^W+B/):(b="W",c=/^B+W/),d.walks(a[e],A.DIRECTIONS.EVERY).forEach(function(a){var e=c.exec(d.asString(a).substr(1));e&&a.toArray().slice(0,e[0].length).forEach(function(a){d.__place__(a,b)})}),new this.constructor(this.opponent(),[d.height,d.width,d.string])},result:function(){if(this.moves())return null;var a={W:-1,B:1},b=j(this.board.string).map(function(b){return a[b]||0}).sum();return this.zerosumResult(b,"Black")},resultBounds:function(){var a=this.board.width*this.board.height;return[-a,+a]},display:function(a){h(!(a&&a instanceof H.BasicHTMLInterface),"Unsupported UI!");var b=this.moves(),c=this.activePlayer(),d=this.board,e={B:"ludorum-square-Black",W:"ludorum-square-White",".":"ludorum-square-empty"};return b=b&&b[c].map(JSON.stringify),d.renderAsHTMLTable(a.document,a.container,function(d){d.className=e[d.square],d.innerHTML=" ";var f=JSON.stringify(d.coord);b&&b.indexOf(f)>=0&&(d.move=d.coord,d.activePlayer=c,d.className="ludorum-square-move",d.onclick=a.perform.bind(a,d.move,c))}),a},__serialize__:function(){var a=this.board;return[this.name,this.activePlayer(),[a.height,a.width,a.string]]},"static heuristics":{heuristicFromWeights:function(a){var b=a.length,c=j(a).map(Math.abs).sum(),d=function(d,e){var f=d.board;return h(f.height*f.width!==b,"Wrong amount of weights!"),f.weightedSum(a,{W:"W"===e.charAt(0)?1:-1,B:"B"===e.charAt(0)?1:-1})/c};return d.weights=a,d},heuristicFromSymmetricWeights:function(a,b,c){b=isNaN(b)?8:0|b,c=isNaN(c)?8:0|c;var d=Math.ceil(b/2);return h(d*Math.ceil(c/2)>a.length,"Not enough weights!"),a=i.range(c).map(function(e){var f=c/2>e?e:c-e-1,g=f*d,h=(f+1)*d;return a.slice(g,h).concat(a.slice(g,h-b%2).reverse())}).flatten().toArray(),this.heuristicFromWeights(a)},pieceRatio:function(a,b){var c=0,d=0;return j(a.board.string).forEach(function(a){"."!==a&&(a===b.charAt(0)?++c:++d)}),(c-d)/(c+d)||0},mobilityRatio:function(a,b){var c=a.opponent(b),d=a.moves(b),e=a.moves(c),f=d&&d[b]&&d[b].length||0,g=e&&e[c]&&e[c].length||0;return(f-g)/(f+g)||0}}}),s.Othello.makeBoard=s.Othello.prototype.makeBoard,s.Bahab=c(r,{name:"Bahab",players:["Uppercase","Lowercase"],constructor:function(a,b){r.call(this,a),this.board=b instanceof B?b:new B(5,5,b||this.initialBoard)},initialBoard:["BBABB","BBBBB",".....","bbbbb","bbabb"].join(""),__PLAYER_ENDGAME_RE__:{Uppercase:/^[.Bab]+$|^.{0,4}[a]/,Lowercase:/^[.bAB]+$|[A].{0,4}$/},result:function(){for(var a,b=this.board.string,c=0;2>c;++c)if(a=this.players[c],b.match(this.__PLAYER_ENDGAME_RE__[a]))return this.defeat(a);return this.moves()?null:this.defeat(this.activePlayer())},__PLAYER_PIECES_RE__:{Uppercase:/[AB]/g,Lowercase:/[ab]/g},moves:function(){var a=this.activePlayer(),b=this.__PLAYER_PIECES_RE__[a],c=this.board,d=[];return c.string.replace(b,function(a,e){var f,g=[e/5|0,e%5];switch(a){case"A":f=[[1,-1],[1,0],[1,1]];break;case"B":f=[[1,-1],[1,1]];break;case"a":f=[[-1,-1],[-1,0],[-1,1]];break;case"b":f=[[-1,-1],[-1,1]]}return j(f).forEachApply(function(e,f){var h=[g[0]+e,g[1]+f],i=c.square(h);!c.isValidCoord(h)||i.match(b)||"b"==a.toLowerCase()&&"a"==i.toLowerCase()||d.push([g,h])}),a}),d.length>0?e(a,d):null},next:function(a){if(!a)throw new Error("Invalid moves "+a+"!");var b=this.activePlayer(),c=a[b];if(!Array.isArray(a[b]))throw new Error("Invalid moves "+JSON.stringify(a)+"!");return new this.constructor(this.opponent(),this.board.move(c[0],c[1]))},display:function(a){return h(!(a&&a instanceof H.BasicHTMLInterface),"Unsupported UI!"),this.__displayHTML__(a)},__displayHTML__:function(a){var b=this,c=this.moves(),d=this.activePlayer(),e=this.board,f={A:"ludorum-square-Uppercase-A",B:"ludorum-square-Uppercase-B",a:"ludorum-square-Lowercase-A",b:"ludorum-square-Lowercase-B",".":"ludorum-square-empty"},g=c?j(c[d]).groupAll(function(a){return JSON.stringify(a[0])}):{},h=a.selectedPiece&&g[JSON.stringify(a.selectedPiece)].map(function(a){return JSON.stringify(a[1])});return e.renderAsHTMLTable(a.document,a.container,function(c){c.className=f[c.square],c.innerHTML="."==c.square?" ":c.square,a.selectedPiece?h&&h.indexOf(JSON.stringify(c.coord))>=0&&(c.className="ludorum-square-move",c.onclick=function(){var b=a.selectedPiece;a.selectedPiece=void 0,a.perform([b,c.coord],d)}):g.hasOwnProperty(JSON.stringify(c.coord))&&(c.onclick=function(){a.selectedPiece=c.coord,a.display(b)})}),a},__serialize__:function(){return[this.name,this.activePlayer(),this.board.string]}}),s.Colograph=c(r,{constructor:function(a){r.call(this,a?a.activePlayer:void 0),m(this,a).object("colours",{defaultValue:{}}).array("edges",{defaultValue:[[1,3],[2],[3],[]]}).array("shapes",{defaultValue:["circle","triangle","square","star"]}).number("scoreSameShape",{defaultValue:-1,coerce:!0}).number("scoreDifferentShape",{defaultValue:-1,coerce:!0})},name:"Colograph",players:["Red","Blue"],score:function(){var a={},b=this.shapes,c=this.colours,d=this.scoreSameShape,e=this.scoreDifferentShape,f=this.edges.length;return this.players.forEach(function(b){a[b]=f}),j(this.edges).forEach(function(f,g){f.forEach(function(f){var h=g+","+f;c.hasOwnProperty(h)&&(a[c[h]]+=b[g]===b[f]?d:e)})}),a},result:function(){if(this.moves())return null;var a=this.score(),b=this.players;return this.zerosumResult(a[b[0]]-a[b[1]],b[0])},moves:function(){for(var a=(this.colours,[]),b=0;b>0;h(0>c||c>=this.colours.length,"Invalid move: node ",c," does not exist in ",this,"."),h(this.colours[c]>=0,"Invalid move: node ",c," has already been coloured in ",this,".");var d=f(e(c,b),this.colours);return this.edges[c].forEach(function(a){d[a]===b&&(d[c+","+a]=b)}),this.edges.forEach(function(a,e){e!==c&&a.indexOf(c)>=0&&d[e]===b&&(d[e+","+c]=b)}),new this.constructor({activePlayer:this.opponent(b),colours:d,edges:this.edges,shapes:this.shapes,scoreSameShape:this.scoreSameShape,scoreDifferentShape:this.scoreDifferentShape})},__serialize__:function(){return[this.name,{activePlayer:this.activePlayer(),colours:this.colours,edges:this.edges,shapes:this.shapes,scoreSameShape:this.scoreSameShape,scoreDifferentShape:this.scoreDifferentShape}]},edgeColour:function(a,b){var c=this.edges[a].indexOf(b)>=0||this.edges[b].indexOf(a)>=0,d=this.colours[a],e=this.colours[b];return c&&d>=0&&d===e?d:-1},"static heuristics":{scoreDifference:function(a,b){var c=a.score(),d=0;for(var e in c)d+=e===b?c[e]:-c[e];return d/a.edges.length/2}},"static randomGraph":function(a,b,c){a=Math.max(2,+a>>0),b=Math.max(a-1,+b>>0);for(var d,e,f=basis.iterables.range(a-1).map(function(b){return c.split(1,basis.iterables.range(b+1,a).toArray())}).toArray(),g=b-(a-1);g>0;g--)d=c.choice(f),d[1].length>0&&(e=c.split(1,d[1]),d[0].push(e[0][0]),d[1]=e[1],g--);return f=f.map(function(a){return a[0]}),f.push([]),f},"static randomGame":function(){params=b.initialize({},params).object("random",{defaultValue:randomness.DEFAULT}).integer("nodeCount",{defaultValue:8,coerce:!0}).integer("edgeCount",{defaultValue:11,coerce:!0}).integer("shapeCount",{defaultValue:4,coerce:!0,minimum:1,maximum:4}).subject;var a=["circle","triangle","square","star"];return new Colograph({edges:this.randomGraph(params.nodeCount,params.edgeCount,params.random),shapes:params.random.randoms(params.nodeCount,0,params.shapeCount).map(function(b){return a[0|b]}),scoreSameShape:1})},"static KineticUI":c(H,{constructor:function(a){H.call(this,a),m(this,a).string("container",{defaultValue:"colograph-container"}).object("Kinetic",{defaultValue:window.Kinetic}).integer("canvasRadius",{defaultValue:0/0,coerce:!0}).integer("nodeRadius",{defaultValue:15,coerce:!0}).array("playerColours",{defaultValue:["red","blue"]}),isNaN(this.canvasRadius)&&(this.canvasRadius=.6*Math.min(screen.width,screen.height)>>1);var b=this.stage=new Kinetic.Stage({container:this.container,width:2*this.canvasRadius,height:2*this.canvasRadius}),c=this.layer=new Kinetic.Layer({clearBeforeDraw:!0,offsetX:-this.canvasRadius,offsetY:-this.canvasRadius}),d=this.match.state();b.add(c),setInterval(b.draw.bind(b),1e3/30),c.destroyChildren(),this.edges={},this.nodes={},this.drawEdges(d),this.drawNodes(d)},drawEdges:function(a){var b=2*Math.PI/a.edges.length,c=this.canvasRadius-2*this.nodeRadius,d=this;a.edges.forEach(function(a,e){a.forEach(function(a){var f=new d.Kinetic.Line({points:[c*Math.cos(b*e),c*Math.sin(b*e),c*Math.cos(b*a),c*Math.sin(b*a)],stroke:"black",strokeWidth:2});d.edges[e+","+a]=f,d.layer.add(f)})})},drawNodes:function(a){var b=2*Math.PI/a.edges.length,c=this.canvasRadius-2*this.nodeRadius,d=this;a.edges.forEach(function(e,f){var g,h=c*Math.cos(b*f),i=c*Math.sin(b*f);switch(a.shapes[f]){case"square":g=d.drawSquare(h,i,d.nodeRadius,f);break;case"triangle":g=d.drawTriangle(h,i,d.nodeRadius,f);break;case"star":g=d.drawStar(h,i,d.nodeRadius,f);break;default:g=d.drawCircle(h,i,d.nodeRadius,f)}g.on("mouseover",function(){g.setScale(1.2)}),g.on("mouseout",function(){g.setScale(1)}),g.on("click tap",function(){d.perform(f)}),g.setRotation(2*Math.random()*Math.PI),d.nodes[f]=g,d.layer.add(g)})},drawCircle:function(a,b,c){return new this.Kinetic.Circle({x:a,y:b,radius:c,fill:"white",stroke:"black",strokeWidth:2})},drawSquare:function(a,b,c){return new this.Kinetic.Rect({x:a,y:b,width:2*c,height:2*c,offsetX:c,offsetY:c,fill:"white",stroke:"black",strokeWidth:2})},drawStar:function(a,b,c){return new Kinetic.Star({numPoints:5,x:a,y:b,innerRadius:.6*c,outerRadius:1.5*c,fill:"white",stroke:"black",strokeWidth:2})},drawTriangle:function(a,b,c){return new Kinetic.RegularPolygon({sides:3,x:a,y:b,radius:1.25*c,fill:"white",stroke:"black",strokeWidth:2})},display:function(a){this.updateEdges(a),this.updateNodes(a)},updateEdges:function(a){var b=this;a.edges.forEach(function(c,d){c.forEach(function(c){var e=d+","+c;b.edges[e].setStroke(a.colours[e]||"black")})})},updateNodes:function(a){var b=this;a.edges.forEach(function(c,d){var e=a.colours[d];e&&(b.nodes[d].setFill(e),b.nodes[d].off("mouseover mouseout click tap"))})}})}),x.RoundRobin=c(w,{constructor:function(a,b,c){w.call(this,a,b),this.matchCount=isNaN(c)?a.players.length:+c,this.__advance__=this.__matches__().chain(i.repeat(null)).__iter__()},__matches__:function(){var a=this.game,b=j(this.players);return b=b.product.apply(b,i.repeat(this.players,a.players.length-1).toArray()),b.filter(function(a){for(var b=1;bc;c++)if(a[b]===a[c])return!1;return!0}).product(i.range(this.matchCount)).map(function(b){return new v(a,b[0])})}}),x.Measurement=c(w,{constructor:function(a,b,c,d){w.call(this,a,Array.isArray(b)?b:[b]),this.opponents=Array.isArray(c)?c:[c],h(this.opponents.length2?c.product.apply(c,i.repeat(this.opponents,b-2).toArray()):c.map(function(a){return[a]}),j(this.players).product(i.range(b),c,i.range(this.matchCount)).map(function(b){var c=b[2].slice(0);return c.splice(b[1],0,b[0]),new v(a,c)})}}),x.Elimination=c(w,{constructor:function(a,b,c){w.call(this,a,b),this.matchCount=isNaN(c)?1:+c>>0},__bracket__:function(a){var b=this.game,c=this.matchCount,d=this.game.players.length;return a=a||this.players,a.lengtha,"There is no active player."),h(a>1,"More than one player is active."),this.activePlayers[0]},opponents:function(a){return a=a||this.activePlayers,this.players.filter(function(b){return a.indexOf(b)<0})},opponent:function(a){var b=this.players.indexOf(a||this.activePlayer());return this.players[(b+1)%this.players.length]},perform:function(){for(var a,b={},c=0;c+a?this.ply()+ +a:+a,this.history[0|a]},result:function(){return this.state().result()},decisions:function(a){a=a||this.state();var b=this,c=this.players,d=a.activePlayers;return k.all(d.map(function(b){return c[b].decision(a.view(b),b)})).then(function(c){var e=j(d).zip(c).toObject();return b.onMove(a,e),e})},run:function(a){if(a=isNaN(a)?1/0:+a,1>a)return k.when(this);var b,c=this.ply(),d=this.state();if(1>c&&this.onBegin(d),d=this.__advanceAleatories__(d),b=d.result())return this.onEnd(d,b),k.when(this);var e=this;return this.decisions(d).then(function(b){return e.__advance__(d,b)?e.run(a-1):e})},__advanceAleatories__:function(a){for(var b;a instanceof y;a=b)b=a.next(),this.history.push(b),this.onNext(a,b);return a},__advance__:function(a,b){var c=this,d=a.activePlayers.filter(function(a){return b[a]instanceof v.CommandQuit});if(d.length>0)return c.onQuit(a,d[0]),!1;var e=a.next(b);return this.history.push(e),this.onNext(a,e),!0},"static CommandQuit":function(){},onBegin:function(a){this.events.emit("begin",a,this),this.logger&&this.logger.info("Match begins with ",j(this.players).map(function(a){return a[1]+" as "+a[0]}).join(", "),"; for ",a,".")},onMove:function(a,b){this.events.emit("move",a,b,this),this.logger&&this.logger.info("Players move: ",JSON.stringify(b)," in ",a)},onNext:function(a,b){this.events.emit("next",a,b,this),this.logger&&this.logger.info("Match advances from ",a," to ",b)},onEnd:function(a,b){this.events.emit("end",a,b,this),this.logger&&this.logger.info("Match for ",a,"ends with ",JSON.stringify(b))},onQuit:function(a,b){this.events.emit("quit",a,b,this),this.logger&&this.logger.info("Match for ",a," aborted because player "+b+" quitted.")},toString:function(){return"Match("+this.game+", "+JSON.stringify(this.players)+")"}}),w=p.Tournament=c({constructor:function(a,b){this.game=a,this.players=Array.isArray(b)?b:iterables.iterable(b).toArray(),this.statistics=new n,this.events=new o({events:["begin","beforeMatch","afterMatch","end"]})},__advance__:d("Tournament","__advance__"),run:function(){this.onBegin();var a=this;return k.doWhile(function(){return k.then(a.__advance__(),function(b){return b?(a.beforeMatch(b),a.__runMatch__(b).then(function(b){return a.account(b),a.afterMatch(b),b})):null})}).then(this.onEnd.bind(this))},__runMatch__:function(a){return a.run()},account:function(a){var b=this.game,c=a.result(),d=this.statistics;h(!c,"Match doesn't have results. Has it finished?"),j(a.players).forEach(function(e){var f=e[0],g=e[1],h=c[e[0]];d.add({key:"results",game:b.name,role:f,player:g.name},h),d.add({key:h>0?"victories":0>h?"defeats":"draws",game:b.name,role:f,player:g.name},h),d.add({key:"length",game:b.name,role:f,player:g.name},a.ply()),a.history.forEach(function(a){if("function"==typeof a.moves){var c=a.moves();c&&c.hasOwnProperty(f)&&c[f].length>0&&d.add({key:"width",game:b.name,role:f,player:g.name},c[f].length)}})})},onBegin:function(){this.events.emit("begin",this),this.logger&&this.logger.info("Tournament begins for game ",game.name,".")},beforeMatch:function(a){this.events.emit("beforeMatch",a,this),this.logger&&this.logger.debug("Beginning match with ",JSON.stringify(a.players),".")},afterMatch:function(a){this.events.emit("afterMatch",a,this),this.logger&&this.logger.debug("Finishing match with ",JSON.stringify(a.players),".")},onEnd:function(){this.events.emit("end",this.statistics,this),this.logger&&this.logger.info("Tournament ends for game ",game.name,":\n",this.statistics,"\n")}}),x=p.tournaments={},y=p.Aleatory=c({constructor:function(a,b){this.random=b||l.DEFAULT,"function"==typeof a&&(this.next=a)},value:function(){var a,b=this.random.random();if(j(this.distribution()).forEach(function(c){if(b-=c[1],0>=b)throw a=c[0],i.STOP_ITERATION}),"undefined"==typeof a)throw new Error("Random value could not be obtained.");return a},next:d("Aleatory","next"),distribution:d("Aleatory","distribution"),"static fromDistribution":function(a,b,c){var d=new y(b,c);return d.distribution=function(){return a},d},"static withDistribution":function(a){return c(y,{distribution:function(){return a}})},"static fromValues":function(a,b,c){a=j(a).toArray();var d=1/a.length,e=new y(b,c);return e.value=function(){return this.random.choice(a)},e.distribution=function(){return a.map(function(a){return[a,d]})},e},"static withValues":function(a){a=j(a).toArray();var b=1/a.length;return c(y,{value:function(){return this.random.choice(a)},distribution:function(){return a.map(function(a){return[a,b]})}})},"static fromRange":function(a,b,c,d){var e=new y(c,d);return e.value=function(){return this.random.randomInt(a,b+1)},e.distribution=function(){return i.range(a,b+1).map(function(c){return[c,1/(b+1-a)]})},e},"static withRange":function(a,b){return c(y,{value:function(){return this.random.randomInt(a,b+1)},distribution:function(){return i.range(a,b+1).map(function(c){return[c,1/(b+1-a)]})}})}}),z=p.aleatories={},A=q.Checkerboard=c({constructor:function(a,b){isNaN(a)||(this.height=0|a),isNaN(b)||(this.width=0|b)},emptySquare:null,isValidCoord:function(a){return Array.isArray(a)&&!isNaN(a[0])&&!isNaN(a[1])&&a[0]>=0&&a[0]=0&&a[1]=b}).map(function(a){return i.range(0,a.length-b+1).map(function(c){return a.slice(c,c+b)})}).flatten()},walk:function(a,b){var c=this;return new i(function(){var d=a.slice();return function(){if(c.isValidCoord(d)){var a=d.slice();return d[0]+=b[0],d[1]+=b[1],a}throw i.STOP_ITERATION}})},walks:function(a,b){var c=this;return b.map(function(b){return c.walk(a,b)})},"static DIRECTIONS":{HORIZONTAL:[[0,-1],[0,1]],VERTICAL:[[-1,0],[1,0]],ORTHOGONAL:[[0,-1],[0,1],[-1,0],[1,0]],DIAGONAL:[[-1,-1],[-1,1],[1,-1],[1,1]],EVERY:[[0,-1],[0,1],[-1,0],[1,0],[-1,-1],[-1,1],[1,-1],[1,1]]},clone:d("utils.Checkerboard","clone"),__place__:d("utils.Checkerboard","place"),place:function(a,b){return this.clone().__place__(a,b)},__move__:function(a,b,c){return this.__place__(b,this.square(a)).__place__(a,"undefined"==typeof c?this.emptySquare:c)},move:function(a,b,c){return this.clone().__move__(a,b,c)},__swap__:function(a,b){var c=this.square(b);return this.__place__(b,this.square(a)).__place__(a,c)},swap:function(a,b){return this.clone().__swap__(a,b)},renderAsHTMLTable:function(a,c,d){var e=this,f=a.createElement("table");return c.appendChild(f),e.horizontals().reverse().forEach(function(c){var g=a.createElement("tr");f.appendChild(g),c.forEach(function(c){var f=e.square(c),h=a.createElement("td"),i={id:"ludorum-square-"+c.join("-"),className:"ludorum-square",square:f,coord:c,innerHTML:b.Text.escapeXML(f)};d&&(i=d(i)||i),h["ludorum-data"]=i,h.id=i.id,h.className=i.className,h.innerHTML=i.innerHTML,i.onclick&&(h.onclick=i.onclick),g.appendChild(h)})}),f},weightedSum:function(a,b){var c=this;return this.coordinates().zip(a).mapApply(function(a,d){return b[c.square(a)]*d||0}).sum()}}),B=q.CheckerboardFromString=c(A,{constructor:function(a,b,c,d){if(A.call(this,a,b),d&&(this.emptySquare=(d+this.emptySquare).charAt(0)),c&&c.length!==a*b)throw new Error("Given string "+JSON.stringify(c)+" does not match board dimensions.");this.string=c||this.emptySquare.repeat(a*b)},emptySquare:".",toString:function(){var a=this.string,b=this.height,c=this.width;return i.range(b).map(function(d){return a.substr((b-d-1)*c,c)}).join("\n")},square:function(a,b){var c=a[0],d=a[1],e=this.width;return c>=0&&c=0&&e>d?this.string.charAt(c*e+d):b},asString:function(a){var b=this;return a.map(function(a){return b.square(a)}).join("")},asStrings:function(a){var b=this;return a.map(function(a){return b.asString(a)})},asRegExp:function(a,b,c){c=c||".";var d=this.width,e=i.repeat(!1,d*this.height).toArray();a.forEach(function(a){e[a[0]*d+a[1]]=!0});for(var f,g="",h=0,j=0;jh?f?b:c:(f?b:c)+"{"+h+"}"}return g},asRegExps:function(a,b,c){var d=this;return a.map(function(a){return d.asRegExp(a,b,c)}).join("|")},clone:function(){return new this.constructor(this.height,this.width,this.string,this.hasOwnProperty("emptySquare")?this.emptySquare:void 0)},__place__:function(a,b){h(!this.isValidCoord(a),"Invalid coordinate ",a,"."),b=(b+this.emptySquare).charAt(0);var c=a[0]*this.width+a[1];return this.string=this.string.substr(0,c)+b+this.string.substr(c+1),this}});q.CheckerboardFromPieces=c(A,{constructor:function(a,b,c,d){A.call(this,a,b),arguments.length>3&&(this.emptySquare=d),this.pieces=j(c||[]).map(function(a){var c=a.position;return[c[0]*b+c[1],a]}).toObject()},emptySquare:null,toString:function(){return"["+j(this.pieces).select(1).join(", ")+"]"},square:function(a,b){var c=a[0]*this.width+a[1];return this.pieces.hasOwnProperty(c)?this.pieces[c]:b},clone:function(){var a=[].concat(this.pieces);return this.hasOwnProperty("emptySquare")?new this.constructor(this.height,this.width,a,this.emptySquare):new this.constructor(this.height,this.width,a)},__place__:function(a,b){h(!this.isValidCoord(a),"Invalid coordinate ",a,"!");var c=a[0]*this.width+a[1];return delete this.pieces[c],b&&(this.pieces[c]=b),this}})}p.utils.Scanner=c({constructor:function(a){m(this,a).object("game",{ignore:!0}).integer("maxWidth",{defaultValue:1e3,coerce:!0}).integer("maxLength",{defaultValue:50,coerce:!0}).object("random",{defaultValue:l.DEFAULT}).object("statistics",{defaultValue:new n})},scan:function(a){var b=this,c=arguments.length<2?this.game?[this.game]:[]:Array.prototype.slice.call(arguments,1),d=0;return k.whileDo(function(){return c.length>0&&dg?(e.add({key:"defeat.result",game:b.name,role:f,player:h},g,b),e.add({key:"defeat.length",game:b.name,role:f,player:h},c,b)):g>0?(e.add({key:"victory.result",game:b.name,role:f,player:h},g,b),e.add({key:"victory.length",game:b.name,role:f,player:h},c,b)):e.add({key:"draw.length",game:b.name,role:f,player:h},c,b)}),!0;var f=b.moves();return j(b.activePlayers).forEach(function(a){e.add({key:"game.width",game:b.name,role:a},f[a].length)}),!1}}),q.Cache=c({constructor:function(a){this.clear(),a&&this.root(a)},stateIdentifier:function(a){return a.identifier()},moveIdentifier:function(a){return JSON.stringify(a)},has:function(a){var b="string"==typeof a?a:this.stateIdentifier(a);return this.__entries__.hasOwnProperty(b)},get:function(a){var b="string"==typeof a?a:this.stateIdentifier(a);return this.__entries__[b]},size:function(){return Object.keys(this.__entries__).length},entry:function(a,b){if(b=b||this.stateIdentifier(a),this.has(b))return this.get(b);var c={id:b,state:a,precursors:[],descendants:{}};return this.__entries__[b]=c,c},descendant:function(a,b){var c=this.moveIdentifier(b),d=a.descendants;if(d.hasOwnProperty(c))return d[c][1];var e=a.state.next(b),f=this.stateIdentifier(e),g=this.get(f)||this.entry(e,f);return d[c]=[b,g],g.precursors.push([b,a]),g},descendants:function(a){var b=this.descendant.bind(this,a);return arguments.length>1?Array.prototype.slice.call(arguments,1).map(b):a.state.possibleMoves().map(b)},clear:function(){this.__entries__={},this.__root__=null},root:function(a){if(arguments.length>0){var b=this.stateIdentifier(a);this.__root__=this.get(b)||this.entry(a,b),this.prune(b)}return this.__root__},prune:function(a){for(var b,c=[a||this.__root__.id],d={};a=c.shift();)d.hasOwnProperty(a)||(b=this.get(a),d[a]=b,c.push.apply(c,j(b.descendants).mapApply(function(a,b){return b[1][a]}).toArray()));return this.__entries__=d}});var C=c({constructor:function(a,b,c){this.parent=a,this.state=b,this.transition=c,this.children={}},childrenCount:function(){return Object.keys(this.children).length},__childSerialization__:function(a){return JSON.stringify(a)},expand:function(a){var b,c=this.__childSerialization__(a),d=this.children[c];if(!d){try{b=this.state.next(a)}catch(e){g("Node expansion for ",this.state," with ",JSON.stringify(a)," failed with: ",e)}d=new this.constructor(this,b,a),this.children[c]=d}return d},possibleTransitions:function(){return this.state instanceof y?this.state.distribution():this.state instanceof r?this.state.possibleMoves():void g("Cannot get possible transitions from ("+this.state+")! Is it a Game or Aleatory?")},expandAll:function(){var a=this;return this.possibleTransitions().map(function(b){return a.expand(b)})}});u.RandomPlayer=c(t,{constructor:function(a){t.call(this,a),m(this,a).object("random",{defaultValue:l.DEFAULT})},decision:function(a,b){return this.random.choice(this.movesFor(a,b))}}),u.TracePlayer=c(t,{constructor:function(a){t.call(this,a),this.trace=j(a.trace),this.__iter__=this.trace.__iter__(),this.__decision__=this.__iter__()},decision:function(){try{this.__decision__=this.__iter__()}catch(a){i.prototype.catchStop(a)}return this.__decision__},__serialize__:function(){return["TracePlayer",{name:this.name,trace:this.trace.toArray()}]}});var D=u.HeuristicPlayer=c(t,{constructor:function(a){t.call(this,a),m(this,a).object("random",{defaultValue:l.DEFAULT}).func("heuristic",{ignore:!0})},moveEvaluation:function(a,b,c){if(Object.keys(a).length<2)return this.stateEvaluation(b.next(a),c);var d=0,g=0;return a=f(e(c,[a[c]]),a),b.possibleMoves(a).forEach(function(a){d+=this.stateEvaluation(b.next(a),c),++g}),g>0?d/g:0},stateEvaluation:function(a,b){var c=a.result();return c?c[b]:this.heuristic(a,b)},heuristic:function(){return this.random.random(-.5,.5)},bestMoves:function(a){return j(a).greater(function(a){return a[1]}).map(function(a){return a[0]})},selectMoves:function(a,b,c){var d=this,e=!1,f=a.map(function(a){var f=d.moveEvaluation(a,b,c);return f instanceof k?(e=e||!0,f.then(function(b){return[a,b]})):[a,f]});return e?k.all(f).then(this.bestMoves):this.bestMoves(f)},decision:function(a,b){var c=this,d=a.moves();h(!d||!d.hasOwnProperty(b),"Player "+b+" is not active (moves= "+JSON.stringify(d)+")!");var g=d[b];if(h(!Array.isArray(g)||g.length<1,"Player "+b+" has no moves ("+g+")!"),1==g.length)return g[0];d=g.map(function(a){return f(e(b,a),d)});var i=c.selectMoves(d,a,b);return k.then(i,function(d){return h(!d||!d.length,"No moves where selected at ",a," for player ",b,"!"),c.random.choice(d)[b]})},"static composite":function(){var a=Array.prototype.slice.call(arguments);h(a.length<1,"HeuristicPlayer.composite() cannot take an odd number of arguments!");for(var b=0;b1,"HeuristicPlayer.composite() argument ",b+1," (",a[b+1],") is not a valid weight!");return function(b,c){for(var d=0,e=0;e+1=this.horizon?this.heuristics(a):null},maxN:function(a,b,c){var d=this.quiescence(a,b,c);if(!d){var f,g,h=a.activePlayer(),i=this.movesFor(a,h);if(d={},i.length<1)throw new Error("No moves for unfinished game "+a+".");for(var j=0;j(d[h]||-1/0)&&(d=f)}return d},toString:function(){return(this.constructor.name||"MaxNPlayer")+"("+JSON.stringify({name:this.name,horizon:this.horizon})+")"}}),u.MiniMaxPlayer=c(D,{constructor:function(a){D.call(this,a),m(this,a).integer("horizon",{defaultValue:4,coerce:!0})},stateEvaluation:function(a,b){return this.minimax(a,b,0)},quiescence:function(a,b,c){var d=a.result();return d?d[b]:c>=this.horizon?this.heuristic(a,b):0/0},minimax:function(a,b,c){var d=this.quiescence(a,b,c);if(isNaN(d)){var f,g,h=a.activePlayer(),i=this.movesFor(a,h);if(i.length<1)throw new Error("No moves for unfinished game "+a+".");h==b?(d=-1/0,f=Math.max):(d=+1/0,f=Math.min);for(var j=0;jd&&(d=g):f>g&&(f=g),!(d>=f));l++);return j?d:f}});var F=u.MonteCarloPlayer=c(D,{constructor:function(a){if(D.call(this,a),m(this,a).number("simulationCount",{defaultValue:30,coerce:!0}).number("timeCap",{defaultValue:1e3,coerce:!0}).number("horizon",{defaultValue:500,coerce:!0}),a)switch(typeof a.agent){case"function":this.agent=new D({heuristic:a.agent});break;case"object":this.agent=a.agent;break;default:this.agent=null}},selectMoves:function(a,b,c){for(var d=this,g=Date.now()+this.timeCap,i=b.next.bind(b),k=a.map(function(a){return{move:a,nexts:Object.keys(a).length<2?[b.next(a)]:b.possibleMoves(f(e(c,[a[c]]),a)).map(i),sum:0,count:0}}),l=0;l0})});return k=j(k).greater(function(a){return h(isNaN(a.sum),"State evaluation is NaN for move ",a.move,"!"),a.count>0?a.sum/a.count:0}).map(function(a){return a.move})},stateEvaluation:function(a,b){for(var c,d=0,e=this.simulationCount,f=0;e>f&&(c=this.simulation(a,b),d+=c.result[b],!(c.plies<1));++f);return e>0?d/e:0},simulation:function(a,b){var c,d,f,h=this;for(c=0;!0;++c)if(a instanceof y)a=a.next();else{if(f=a.moves(),!f)return{game:a,result:a.result(),plies:c};if(c>this.horizon)return{game:a,result:e(b,this.heuristic(a,b)),plies:c};d={},a.activePlayers.forEach(function(b){d[b]=h.agent?h.agent.decision(a,b):h.random.choice(f[b])}),a=a.next(d)}g("Simulation ended unexpectedly for player ",b," in game ",a,"!")},__serialize__:function(){return[this.constructor.name,{name:this.name,simulationCount:this.simulationCount,timeCap:this.timeCap,agent:this.agent}]}});u.UCTPlayer=c(F,{constructor:function(a){F.call(this,a),m(this,a).number("explorationConstant",{defaultValue:Math.sqrt(2),coerce:!0})},selectNode:function(a,b,c){return c=isNaN(c)?this.explorationConstant:+c,this.random.choice(j(a.children).select(1).greater(function(a){return a.uct.rewards/a.uct.visits+c*Math.sqrt(Math.log(b)/a.uct.visits)}))},selectMoves:function(a,b,c){var d,e,f=new C(null,b),g=Date.now()+this.timeCap;f.uct={pending:this.random.shuffle(f.possibleTransitions()),visits:0,rewards:0};for(var h=0;h0;)d=this.selectNode(d,h+1,this.explorationConstant);for(d.uct.pending.length>0&&(d=d.expand(d.uct.pending.pop()),d.uct={pending:this.random.shuffle(d.possibleTransitions()),visits:0,rewards:0}),e=this.simulation(d.state,c);d;d=d.parent)++d.uct.visits,d.uct.rewards+=(b.normalizedResult(e.result)[c]+1)/2}return a=j(f.children).select(1).greater(function(a){return a.uct.visits}).map(function(a){return a.transition})},__serialize__:function(){return[this.constructor.name,{name:this.name,simulationCount:this.simulationCount,timeCap:this.timeCap,explorationConstant:this.explorationConstant}]}});var G=u.UserInterfacePlayer=c(t,{constructor:function(a){t.call(this,a)},participate:function(a,b){return this.role=b,this},decision:function(){return this.__future__&&this.__future__.isPending()&&this.__future__.resolve(new v.CommandQuit),this.__future__=new k,this.__future__},perform:function(a){var b=this.__future__;return b&&(this.__future__=null,b.resolve(a)),!!b}}),H=u.UserInterface=c({constructor:function(a){this.onBegin=this.onBegin.bind(this),this.onNext=this.onNext.bind(this),this.onEnd=this.onEnd.bind(this),a.match&&this.show(a.match)},show:function(a){this.match&&(a.events.off("begin",this.onBegin),a.events.off("next",this.onNext),a.events.off("end",this.onEnd)),this.match=a,a.events.on("begin",this.onBegin),a.events.on("next",this.onNext),a.events.on("end",this.onEnd)},onBegin:function(a){this.display(a)},onNext:function(a,b){this.display(b)},onEnd:function(a,b){this.results=b,this.display(a)},display:d("UserInterface","display"),perform:function(a,b){j(this.match.players).forEach(function(c){var d=(c[0],c[1]);d instanceof G&&(!b||d.role===b)&&d.perform(a)})}});H.BasicHTMLInterface=c(H,{constructor:function(a){H.call(this,a),this.document=a.document||b.global.document,this.container=a.container,"string"==typeof this.container&&(this.container=this.document.getElementById(this.container))},display:function(a){for(var b,c=this.container;b=c.firstChild;)c.removeChild(b);a.display(this)},build:function(a,b){var c=this;return b.forEach(function(b){var d;if(Array.isArray(b)){if(d=c.document.createElement(b[0]),b.length>2&&b[1]){var e=b[1];for(var f in e)attr.hasOwnProperty(f)&&d.setAttribute(f,e[f])}b.length>1&&b[b.length-1]&&c.build(d,b[b.length-1])}else"string"==typeof b&&(d=c.document.createTextNode(b));d&&a&&a.appendChild(d)}),a}});u.WebWorkerPlayer=c(t,{constructor:function(a){t.call(this,a),m(this,a).object("worker"),this.worker.onmessage=b.Parallel.prototype.__onmessage__.bind(this)},"static createWorker":function(a){h("string function".indexOf(typeof a)<0,"Invalid player builder: "+a+"!");var c=new b.Parallel;return c.run("self.ludorum = ("+p.__init__+')(self.base), "OK"').then(function(){return c.run("self.PLAYER = ("+a+').call(self), "OK"')}).then(function(){return c.worker})},"static create":function(a){var b=this;return b.createWorker(a.playerBuilder).then(function(a){return new b({name:name,worker:a})})},decision:function(a,b){return this.__future__&&this.__future__.isPending()&&this.__future__.resolve(v.commandQuit),this.__future__=new k,this.worker.postMessage("PLAYER.decision(ludorum.Game.fromJSON("+a.toJSON()+"), "+JSON.stringify(b)+")"),this.__future__}});return z.dice={D4:y.withRange(1,4),D6:y.withRange(1,6),D8:y.withRange(1,8),D10:y.withRange(1,10),D12:y.withRange(1,12),D20:y.withRange(1,20),D100:y.withRange(1,100)},s.Predefined=c(r,{constructor:function(a,b,c,d){b&&(this.__results__=b,this.players=Object.keys(b)),r.call(this,a),this.height=isNaN(c)?5:+c,this.width=isNaN(d)?5:+d},name:"Predefined",players:["A","B"],__results__:{A:0,B:0},moves:function(){return this.height>0?e(this.activePlayer(),i.range(1,this.width+1).toArray()):void 0},result:function(){return this.height>0?null:this.__results__},next:function(){return new this.constructor(this.opponent(),this.__results__,this.height-1,this.width)},__serialize__:function(){return[this.name,this.activePlayer(),this.results,this.height,this.width]}}),s.Choose2Win=c(r,{constructor:function(a,b,c){r.call(this,b),this.__turns__=isNaN(a)?1/0:+a,this.__winner__=c},name:"Choose2Win",players:["This","That"],moves:function(){return!this.__winner__&&this.__turns__>0?e(this.activePlayer(),["win","lose","pass"]):void 0},result:function(){return this.__winner__?this.victory(this.__winner__):this.__turns__<1?this.draw():null},next:function(a){var b=this.activePlayer(),c=this.opponent(b);switch(h(!a.hasOwnProperty(b),"No move for active player ",b," at ",this,"!"),a[b]){case"win":return new this.constructor(this.__turns__-1,c,b);case"lose":return new this.constructor(this.__turns__-1,c,c);case"pass":return new this.constructor(this.__turns__-1,c);default:g("Invalid move ",a[b]," for player ",b," at ",this,"!")}},__serialize__:function(){return[this.name,this.__turns__,this.activePlayer(),this.__winner__]}}),s.ConnectionGame=c(r,{height:9,width:9,lineLength:5,constructor:function(a,b){r.call(this,a),this.board=b instanceof B?b:new B(this.height,this.width,(b||".".repeat(this.height*this.width))+"")},name:"ConnectionGame",players:["First","Second"],__lines__:function(){function a(a,c,d){var e=a+"x"+c+"/"+d;if(!b.hasOwnProperty(e)){var f=new B(a,c,".".repeat(a*c));b[e]=f.lines().map(function(a){return a.toArray()},function(a){return a.length>=d}).toArray()}return b[e]}var b={};return a.CACHE=b,a}(),result:function(){if(this.hasOwnProperty("__result__"))return this.__result__;for(var a=this.lineLength,b=this.board.asStrings(this.__lines__(this.height,this.width,a)).join(" "),c=0;c=0)return this.__result__=this.victory([this.players[c]]);return this.__result__=b.indexOf(".")<0?this.draw():null},moves:function(){return this.hasOwnProperty("__moves__")?this.__moves__:this.__moves__=this.result()?null:e(this.activePlayer(),j(this.board.string).filter(function(a){return"."===a},function(a,b){return b}).toArray())},next:function(a){var b=this.activePlayer(),c=this.players.indexOf(b),d=+a[b],e=d/this.width>>0,f=d%this.width; +return new this.constructor((c+1)%this.players.length,this.board.place([e,f],c.toString(36)))},display:function(a){h(!(a&&a instanceof H.BasicHTMLInterface),"Unsupported UI!");var b=this.moves(),c=this.activePlayer(),d=this.board;b=b&&b[c];this.board.renderAsHTMLTable(a.document,a.container,function(e){e.className="."===e.square?"ludorum-empty":"ludorum-player"+e.square,e.innerHTML="."===e.square?" ":"●";var f=e.coord[0]*d.height+e.coord[1];b&&b.indexOf(f)>=0&&(e.move=f,e.activePlayer=c,e.onclick=a.perform.bind(a,e.move,c))});return a},__serialize__:function(){return[this.name,this.activePlayer(),this.board.string]}}),s.OddsAndEvens=c(r,{constructor:function(a,b){r.call(this,this.players),this.turns=isNaN(a)?1:+a,this.points=b||{Evens:0,Odds:0}},name:"OddsAndEvens",players:["Evens","Odds"],moves:function(){return this.turns<1?null:{Evens:[1,2],Odds:[1,2]}},result:function(){var a=this.points.Evens-this.points.Odds;return this.turns>0?null:{Evens:+a,Odds:-a}},next:function(a){h("number"!=typeof a.Evens||"number"!=typeof a.Odds,"Invalid moves "+(JSON.stringify(a)||a)+"!");var b=(a.Evens+a.Odds)%2===0;return new this.constructor(this.turns-1,{Evens:this.points.Evens+(b?1:0),Odds:this.points.Odds+(b?0:1)})},__serialize__:function(){return[this.name,this.turns,this.points]}}),s.TicTacToe=c(r,{name:"TicTacToe",constructor:function(a,b){r.call(this,a),this.board=b||"_________"},players:["Xs","Os"],result:function(){return function(){return this.board.match(this.WIN_X)?this.victory(["Xs"]):this.board.match(this.WIN_O)?this.victory(["Os"]):this.board.indexOf("_")<0?this.draw():null}}(),moves:function(){if(this.result())return null;var a={};return a[this.activePlayer()]=j(this.board).filter(function(a){return"_"===a},function(a,b){return b}).toArray(),a},next:function(a){var b=this.activePlayer(),c=+a[b];if(isNaN(c)||"_"!==this.board.charAt(c))throw new Error("Invalid move "+JSON.stringify(a)+" for board "+this.board+" (moves= "+JSON.stringify(a)+").");var d=this.board.substring(0,c)+b.charAt(0)+this.board.substring(c+1);return new this.constructor(this.opponent(b),d)},__serialize__:function(){return[this.name,this.activePlayer(),this.board]},printBoard:function(){var a=this.board;return[a.substr(0,3).split("").join("|"),"-+-+-",a.substr(3,3).split("").join("|"),"-+-+-",a.substr(6,3).split("").join("|")].join("\n")},display:function(a){h(!(a&&a instanceof H.BasicHTMLInterface),"Unsupported UI!");var b=this.activePlayer(),c=this.moves(),d=(this.board,{X:"ludorum-square-Xs",O:"ludorum-square-Os",_:"ludorum-square-empty"}),e={X:"X",O:"O",_:" "};return c=c&&c[b]&&c[b].length>0,new B(3,3,this.board,"_").renderAsHTMLTable(a.document,a.container,function(f){f.className=d[f.square],f.innerHTML=e[f.square],c&&"_"===f.square&&(f.move=3*f.coord[0]+f.coord[1],f.activePlayer=b,f.onclick=a.perform.bind(a,f.move,b))}),a},"static heuristics":{heuristicFromWeights:function(a){function b(b,d){var e=d.charAt(0);return j(b.board).map(function(b,c){return"_"===b?0:a[c]*(b===e?1:-1)}).sum()/c}var c=j(a).map(Math.abs).sum();return b.weights=a,b}},"":function(){var a=new B(3,3,"_".repeat(9)),b=a.sublines(a.lines(),3);this.prototype.WIN_X=new RegExp(a.asRegExps(b,"X",".")),this.prototype.WIN_O=new RegExp(a.asRegExps(b,"O",".")),this.heuristics.defaultHeuristic=this.heuristics.heuristicFromWeights([2,1,2,1,5,1,2,1,2])}}),s.ToadsAndFrogs=c(r,{constructor:function I(a,b){r.call(this,a),this.board=b||I.board()},"static board":function(a,b){return a=isNaN(a)?3:+a,b=isNaN(b)?2:+b,"T".repeat(a)+"_".repeat(b)+"F".repeat(a)},name:"ToadsAndFrogs",players:["Toads","Frogs"],result:function(){return this.moves()?null:this.defeat()},moves:function(){var a=this.activePlayer(),b={},c=b[a]=[];return this.board.replace(a==this.players[0]?/TF?_/g:/_T?F/g,function(a,b){return c.push(b),a}),c.length>0?b:null},next:function(a){var b=this.activePlayer(),c=a[b],d=(b.charAt(0),this.board);if("T_"==d.substr(c,2))d=d.substring(0,c)+"_T"+d.substring(c+2);else if("_F"==d.substr(c,2))d=d.substring(0,c)+"F_"+d.substring(c+2);else if("TF_"==d.substr(c,3))d=d.substring(0,c)+"_FT"+d.substring(c+3);else{if("_TF"!=d.substr(c,3))throw new Error("Invalid move ",c," for board <",d,">.");d=d.substring(0,c)+"FT_"+d.substring(c+3)}return new this.constructor(this.opponent(),d)},__serialize__:function(){return[this.name,this.activePlayer,this.board]}}),s.Pig=c(r,{constructor:function(a,b,c,d){r.call(this,a),this.goal=isNaN(b)?100:+b,this.__scores__=c||j(this.players).zip([0,0]).toObject(),this.__rolls__=d||[]},name:"Pig",players:["One","Two"],moves:function(){if(!this.result()){var a=this.activePlayer(),b=this.__scores__[a]+j(this.__rolls__).sum();return e(a,this.__rolls__.length<1?["roll"]:b>=this.goal?["hold"]:["roll","hold"])}},result:function(){var a=this.__scores__[this.players[0]],b=this.__scores__[this.players[1]];if(a>=this.goal||b>=this.goal){var c={};return c[this.players[0]]=Math.min(this.goal,a)-Math.min(this.goal,b),c[this.players[1]]=-c[this.players[0]],c}},next:function(a){var b=this.activePlayer(),c=a[b];if(h("undefined"==typeof c,"No move for active player ",b," at ",this,"!"),"hold"===c){var d=f(this.__scores__);return d[b]+=j(this.__rolls__).sum(),new this.constructor(this.opponent(),this.goal,d,[])}if("roll"===c){var e=this;return new z.dice.D6(function(a){return a=isNaN(a)?this.value():+a,a>1?new e.constructor(b,e.goal,e.__scores__,e.__rolls__.concat(a)):new e.constructor(e.opponent(),e.goal,e.__scores__,[])})}g("Invalid moves ",JSON.stringify(a)," at ",this,"!")},resultBounds:function(){return[-this.goal,+this.goal]},__serialize__:function(){return[this.name,this.activePlayer(),this.goal,this.__scores__,this.__rolls__]}}),s.Mutropas=c(r,{name:"Mutropas",players:["Left","Right"],constructor:function(a){r.call(this,this.players),a=a||{},this.random=a.random||l.DEFAULT,this.playedPieces=a.playedPieces||[],this.pieces=a.pieces||this.dealPieces(),this.__scores__=a.scores||e(this.players[0],0,this.players[1],0)},allPieces:i.range(9).toArray(),dealPieces:function(a){a=a||this.random;var b=this.allPieces.length/2|0,c=a.split(b,this.allPieces),d=a.split(b,c[1]);return e(this.players[0],c[0],this.players[1],d[0])},moves:function(){return this.result()?null:f({},this.pieces)},moveResult:function(a,b){var c=j(this.allPieces).max(0)+1;return b>a?c/2>=b-a?1:-1:a>b?a-b>=c/2+1?1:-1:0},next:function(a){var b=this.players[0],c=this.players[1],d=a[b],f=a[c],g=this.pieces;h(g[b].indexOf(d)<0,"Invalid move ",JSON.stringify(d)," for player ",b,"! (moves= ",JSON.stringify(a),")"),h(g[c].indexOf(f)<0,"Invalid move ",JSON.stringify(f)," for player ",c,"! (moves= ",JSON.stringify(a),")");var i=this.moveResult(d,f);return new this.constructor({random:this.random,playedPieces:this.playedPieces.concat([d,f]),pieces:e(b,g[b].filter(function(a){return a!==d}),c,g[c].filter(function(a){return a!==f})),scores:e(b,this.__scores__[b]+i,c,this.__scores__[c]-i)})},scores:function(){return f({},this.__scores__)},result:function(){var a=this.players;if(this.playedPieces.length>=this.allPieces.length-1){var b=this.scores();return this.zerosumResult(b[a[0]]-b[a[1]],a[0])}return null},__possiblePieces__:function(a){var b=this.playedPieces,c=this.pieces[this.opponent(a)],d=j(this.allPieces).filter(function(a){return b.indexOf(a)<0&&c.indexOf(a)<0});return d.combinations(d.count()-1)},view:function(a){var b=this,c=this.opponent(a),d=this.random;return y.withValues(this.__possiblePieces__(c),d,function(f){return f=f||this.value(),new b.constructor({random:d,playedPieces:b.playedPieces,scores:b.scores(),pieces:e(a,b.pieces[a],c,f)})})},__serialize__:function(){return[this.name,{pieces:this.__pieces__,scores:this.__scores__}]}}),s.Bahab=c(r,{name:"Bahab",players:["Uppercase","Lowercase"],constructor:function(a,b){r.call(this,a),this.board=b instanceof B?b:new B(5,5,b||this.initialBoard)},initialBoard:["BBABB","BBBBB",".....","bbbbb","bbabb"].join(""),__PLAYER_ENDGAME_RE__:{Uppercase:/^[.Bab]+$|^.{0,4}[a]/,Lowercase:/^[.bAB]+$|[A].{0,4}$/},result:function(){for(var a,b=this.board.string,c=0;2>c;++c)if(a=this.players[c],b.match(this.__PLAYER_ENDGAME_RE__[a]))return this.defeat(a);return this.moves()?null:this.defeat(this.activePlayer())},__PLAYER_PIECES_RE__:{Uppercase:/[AB]/g,Lowercase:/[ab]/g},moves:function(){var a=this.activePlayer(),b=this.__PLAYER_PIECES_RE__[a],c=this.board,d=[];return c.string.replace(b,function(a,e){var f,g=[e/5|0,e%5];switch(a){case"A":f=[[1,-1],[-1,0],[1,1]];break;case"B":f=[[1,-1],[1,1]];break;case"a":f=[[-1,-1],[1,0],[-1,1]];break;case"b":f=[[-1,-1],[-1,1]]}return j(f).forEachApply(function(e,f){var h=[g[0]+e,g[1]+f],i=c.square(h);!c.isValidCoord(h)||i.match(b)||"."!=i&&a.toLowerCase()!=i.toLowerCase()||d.push([g,h])}),a}),d.length>0?e(a,d):null},next:function(a){if(!a)throw new Error("Invalid moves "+a+"!");var b=this.activePlayer(),c=a[b];if(!Array.isArray(a[b]))throw new Error("Invalid moves "+JSON.stringify(a)+"!");return new this.constructor(this.opponent(),this.board.move(c[0],c[1]))},display:function(a){return h(!(a&&a instanceof H.BasicHTMLInterface),"Unsupported UI!"),this.__displayHTML__(a)},__displayHTML__:function(a){var b=this,c=this.moves(),d=this.activePlayer(),e=this.board,f={A:"ludorum-square-Uppercase-A",B:"ludorum-square-Uppercase-B",a:"ludorum-square-Lowercase-A",b:"ludorum-square-Lowercase-B",".":"ludorum-square-empty"},g=c?j(c[d]).groupAll(function(a){return JSON.stringify(a[0])}):{},h=a.selectedPiece&&g[JSON.stringify(a.selectedPiece)].map(function(a){return JSON.stringify(a[1])});return e.renderAsHTMLTable(a.document,a.container,function(c){c.className=f[c.square],c.innerHTML="."==c.square?" ":c.square,a.selectedPiece&&h&&h.indexOf(JSON.stringify(c.coord))>=0&&(c.className="ludorum-square-"+d+"-move",c.onclick=function(){var b=a.selectedPiece;a.selectedPiece=void 0,a.perform([b,c.coord],d)}),g.hasOwnProperty(JSON.stringify(c.coord))&&(c.onclick=function(){a.selectedPiece=c.coord,a.display(b)})}),a},__serialize__:function(){return[this.name,this.activePlayer(),this.board.string]}}),x.RoundRobin=c(w,{constructor:function(a,b,c){w.call(this,a,b),this.matchCount=isNaN(c)?a.players.length:+c,this.__advance__=this.__matches__().chain(i.repeat(null)).__iter__()},__matches__:function(){var a=this.game,b=j(this.players);return b=b.product.apply(b,i.repeat(this.players,a.players.length-1).toArray()),b.filter(function(a){for(var b=1;bc;c++)if(a[b]===a[c])return!1;return!0}).product(i.range(this.matchCount)).map(function(b){return new v(a,b[0])})}}),x.Measurement=c(w,{constructor:function(a,b,c,d){w.call(this,a,Array.isArray(b)?b:[b]),this.opponents=Array.isArray(c)?c:[c],h(this.opponents.length2?c.product.apply(c,i.repeat(this.opponents,b-2).toArray()):c.map(function(a){return[a]}),j(this.players).product(i.range(b),c,i.range(this.matchCount)).map(function(b){var c=b[2].slice(0);return c.splice(b[1],0,b[0]),new v(a,c)})}}),x.Elimination=c(w,{constructor:function(a,b,c){w.call(this,a,b),this.matchCount=isNaN(c)?1:+c>>0},__bracket__:function(a){var b=this.game,c=this.matchCount,d=this.game.players.length;return a=a||this.players,a.length