diff --git a/src/games/chessbase/index.js b/src/games/chessbase/index.js
index f2b7933..9afde63 100644
--- a/src/games/chessbase/index.js
+++ b/src/games/chessbase/index.js
@@ -5166,6 +5166,128 @@ exports.games = (function () {
},
"viewScripts": config_view_js_giga
},
+ {
+ "name": "leychessalpha-chess",
+ "modelScripts": modelScripts_lca,
+ "config": {
+ "status": true,
+ "model": {
+ "title-en": "LeyChessAlpha",
+ "summary": "Chess on 12x12 with fairy pieces",
+ "rules": {
+ "en": "leychessalpha-rules.html"
+ },
+ "module": "chessbase",
+ "plazza": "true",
+ "thumbnail": "leychessalpha-thumb.png",
+ "released": 1402412178,
+ "credits": {
+ "en": "leychessalpha-credits.html"
+ },
+ "gameOptions": config_model_gameOptions,
+ "obsolete": false,
+ "js": modelScripts_lca,
+ "description": {
+ "en": "leychessalpha-description.html"
+ },
+ "levels": config_model_levels_15
+ },
+ "view": {
+ "title-en": "Chessbase view",
+ "visuals": {
+ "600x600": [
+ "res/visuals/leychessalpha-600x600-3d.jpg",
+ "res/visuals/leychessalpha-600x600-2d.jpg"
+ ]
+ },
+ "xdView": true,
+ "css": config_view_css,
+ "preferredRatio": 1,
+ "useShowMoves": true,
+ "useNotation": true,
+ "module": "chessbase",
+ "defaultOptions": config_view_defaultOptions,
+ "skins": [
+ {
+ "name": "skin3d",
+ "title": "3D Classic",
+ "3d": true,
+ "preload": [
+ "smoothedfilegeo|0|/res/ring-target.js",
+ "image|/res/images/cancel.png",
+ "image|/res/images/wikipedia.png",
+ "smoothedfilegeo|0|/res/fairy/pawn/pawn.js",
+ "image|/res/fairy/pawn/pawn-diffusemap.jpg",
+ "image|/res/fairy/pawn/pawn-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/knight/knight.js",
+ "image|/res/fairy/knight/knight-diffusemap.jpg",
+ "image|/res/fairy/knight/knight-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/bishop/bishop.js",
+ "image|/res/fairy/bishop/bishop-diffusemap.jpg",
+ "image|/res/fairy/bishop/bishop-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/queen/queen.js",
+ "image|/res/fairy/queen/queen-diffusemap.jpg",
+ "image|/res/fairy/queen/queen-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/king/king.js",
+ "image|/res/fairy/king/king-diffusemap.jpg",
+ "image|/res/fairy/king/king-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/rook/rook.js",
+ "image|/res/fairy/rook/rook-diffusemap.jpg",
+ "image|/res/fairy/rook/rook-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/cannon2/cannon2.js",
+ "image|/res/fairy/cannon2/cannon2-diffusemap.jpg",
+ "image|/res/fairy/cannon2/cannon2-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/elephant/elephant.js",
+ "image|/res/fairy/elephant/elephant-diffusemap.jpg",
+ "image|/res/fairy/elephant/elephant-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/admiral/admiral.js",
+ "image|/res/fairy/admiral/admiral-diffusemap.jpg",
+ "image|/res/fairy/admiral/admiral-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/camel/camel.js",
+ "image|/res/fairy/camel/camel-diffusemap.jpg",
+ "image|/res/fairy/camel/camel-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/lion/lion.js",
+ "image|/res/fairy/lion/lion-diffusemap.jpg",
+ "image|/res/fairy/lion/lion-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/eagle/eagle.js",
+ "image|/res/fairy/eagle/eagle-diffusemap.jpg",
+ "image|/res/fairy/eagle/eagle-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/unicorn/unicorn.js",
+ "image|/res/fairy/unicorn/unicorn-diffusemap.jpg",
+ "image|/res/fairy/unicorn/unicorn-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/lighthouse/lighthouse.js",
+ "image|/res/fairy/lighthouse/lighthouse-diffusemap.jpg",
+ "image|/res/fairy/lighthouse/lighthouse-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/amazon/amazon.js",
+ "image|/res/fairy/amazon/amazon-diffusemap.jpg",
+ "image|/res/fairy/amazon/amazon-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/cardinal/cardinal.js",
+ "image|/res/fairy/cardinal/cardinal-diffusemap.jpg",
+ "image|/res/fairy/cardinal/cardinal-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/marshall/marshall.js",
+ "image|/res/fairy/marshall/marshall-diffusemap.jpg",
+ "image|/res/fairy/marshall/marshall-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/dragon/dragon.js",
+ "image|/res/fairy/dragon/dragon-diffusemap.jpg",
+ "image|/res/fairy/dragon/dragon-normalmap.jpg",
+ "smoothedfilegeo|0|/res/fairy/crowned-rook/crowned-rook.js",
+ "image|/res/fairy/crowned-rook/crowned-rook-diffusemap.jpg",
+ "image|/res/fairy/crowned-rook/crowned-rook-normalmap.jpg",
+ ],
+ "world": config_view_skins_world,
+ "camera": config_view_skins_camera
+ },
+ config_view_skins_9
+ ],
+ "animateSelfMoves": false,
+ "switchable": true,
+ "sounds": config_view_sounds,
+ "js": config_view_js_lca,
+ "useAutoComplete": true
+ }
+ },
+ "viewScripts": config_view_js_lca
+ },
{
"name": "knightet-chess",
"modelScripts": modelScripts_k,
diff --git a/src/games/chessbase/leychessalpha-description.html b/src/games/chessbase/leychessalpha-description.html
new file mode 100644
index 0000000..dea2b87
--- /dev/null
+++ b/src/games/chessbase/leychessalpha-description.html
@@ -0,0 +1 @@
+
LeyChessAlpha is a 12*12 Chess Variant with Fairy Pieces based on Metamachy.
diff --git a/src/games/chessbase/leychessalpha-model.js b/src/games/chessbase/leychessalpha-model.js
new file mode 100644
index 0000000..17a8324
--- /dev/null
+++ b/src/games/chessbase/leychessalpha-model.js
@@ -0,0 +1,574 @@
+/*
+ * Copyright(c) 2013-2017 - jocly.com
+ *
+ * You are allowed to use and modify this source code as long as it is exclusively for use in the Jocly API.
+ *
+ * Original authors: Jocly team
+ *
+ */
+
+
+
+
+(function() {
+
+ var geometry = Model.Game.cbBoardGeometryGrid(12,12);
+
+ Model.Game.cbDefine = function() {
+
+ var $this = this;
+
+ /*
+ * Movement/capture graph for the prince
+ */
+ function PrinceGraph(side) {
+ var graph={};
+ for(var pos=0;pos0)
+ graph[pos].push($this.cbTypedArray(away));
+ }
+ }
+ });
+ }
+ return $this.cbMergeGraphs(geometry,
+ $this.cbShortRangeGraph(geometry,[[-1,-1],[-1,1],[1,-1],[1,1]]),
+ graph
+ );
+ }
+
+ return {
+
+ geometry: geometry,
+
+ pieceTypes: {
+
+ 0: {
+ name: 'pawn-w',
+ aspect: 'fr-pawn',
+ graph: this.cbPawnGraph(geometry,1),
+ value: 1,
+ abbrev: '',
+ fenAbbrev: 'P',
+ epCatch: false,
+ },
+
+ 1: {
+ name: 'ipawn-w',
+ aspect: 'fr-pawn',
+ graph: this.cbInitialPawnGraph(geometry,1),
+ value: 1,
+ abbrev: '',
+ fenAbbrev: 'P',
+ initial: [{s:1,p:24},{s:1,p:25},{s:1,p:26},{s:1,p:27},{s:1,p:28},{s:1,p:29},{s:1,p:30},{s:1,p:31},{s:1,p:32},{s:1,p:33},{s:1,p:34},{s:1,p:35}],
+ epTarget: true,
+ epCatch: false,
+ },
+
+ 2: {
+ name: 'pawn-b',
+ aspect: 'fr-pawn',
+ graph: this.cbPawnGraph(geometry,-1),
+ value: 1,
+ abbrev: '',
+ fenAbbrev: 'P',
+ epCatch: false,
+
+ },
+
+ 3: {
+ name: 'ipawn-b',
+ aspect: 'fr-pawn',
+ graph: this.cbInitialPawnGraph(geometry,-1),
+ value: 1,
+ abbrev: '',
+ fenAbbrev: 'P',
+ initial: [{s:-1,p:108},{s:-1,p:109},{s:-1,p:110},{s:-1,p:111},{s:-1,p:112},{s:-1,p:113},{s:-1,p:114},{s:-1,p:115},{s:-1,p:116},{s:-1,p:117},{s:-1,p:118},{s:-1,p:119}],
+ epTarget: true,
+ epCatch: false,
+ },
+
+ 4: {
+ name: 'knight',
+ aspect: 'fr-knight',
+ graph: this.cbKnightGraph(geometry),
+ value: 2.9,
+ abbrev: 'N',
+ initial: [{s:1,p:14},{s:1,p:21},{s:-1,p:122},{s:-1,p:129}],
+ },
+
+ 5: {
+ name: 'bishop',
+ aspect: 'fr-bishop',
+ graph: this.cbBishopGraph(geometry),
+ value: 3.1,
+ abbrev: 'B',
+ initial: [{s:1,p:15},{s:1,p:20},{s:-1,p:123},{s:-1,p:128}],
+ },
+
+ 6: {
+ name: 'rook',
+ aspect: 'fr-rook',
+ graph: this.cbRookGraph(geometry),
+ value: 5,
+ abbrev: 'R',
+ initial: [{s:1,p:13},{s:1,p:22},{s:-1,p:121},{s:-1,p:130}],
+ castle: true,
+ },
+
+ 7: {
+ name: 'queen',
+ aspect: 'fr-queen',
+ graph: this.cbQueenGraph(geometry),
+ value: 9,
+ abbrev: 'Q',
+ initial: [{s:1,p:18},{s:-1,p:126}],
+ },
+
+ 8: {
+ name: 'king',
+ aspect: 'fr-king',
+ isKing: true,
+ graph: this.cbKingGraph(geometry),
+ abbrev: 'K',
+ initial: [{s:1,p:17},{s:-1,p:125}],
+ },
+
+ 9: {
+ name: 'cannon',
+ aspect: 'fr-cannon2',
+ graph: this.cbXQCannonGraph(geometry),
+ value: 3.5,
+ abbrev: 'C',
+ initial: [{s:1,p:0},{s:1,p:11},{s:-1,p:132},{s:-1,p:143}],
+ },
+
+ 10: {
+ name: 'elephant',
+ aspect: 'fr-elephant',
+ graph: this.cbShortRangeGraph(geometry,[[-1,-1],[-1,1],[1,-1],[1,1],[-2,-2],[-2,2],[2,-2],[2,2]]),
+ value: 2.5,
+ abbrev: 'E',
+ initial: [{s:1,p:12},{s:1,p:23},{s:-1,p:120},{s:-1,p:131}],
+ },
+
+ 11: {
+ name: 'prince-w',
+ aspect: 'fr-admiral',
+ graph: PrinceGraph(1),
+ value: 3,
+ epTarget: true,
+ abbrev: 'I',
+ initial: [{s:1,p:16},{s:1,p:19}],
+ },
+
+ 12: {
+ name: 'prince-b',
+ aspect: 'fr-admiral',
+ graph: PrinceGraph(-1),
+ epTarget: true,
+ value: 3,
+ abbrev: 'I',
+ initial: [{s:-1,p:124},{s:-1,p:127}],
+ },
+
+
+ 13: {
+ name: 'camel',
+ aspect: 'fr-camel',
+ graph: this.cbShortRangeGraph(geometry,[[-3,-1],[-3,1],[3,-1],[3,1],[1,3],[1,-3],[-1,3],[-1,-3]]),
+ value: 2,
+ abbrev: 'M',
+ initial: [{s:1,p:1},{s:1,p:10},{s:-1,p:133},{s:-1,p:142}],
+ },
+
+ 14: {
+ name: 'lion',
+ aspect: 'fr-lion',
+ graph: this.cbShortRangeGraph(geometry,[
+ [-1,-1],[-1,1],[1,-1],[1,1],[1,0],[0,1],[-1,0],[0,-1],
+ [-2,0],[-2,-1],[-2,-2],[-1,-2],[0,-2],
+ [1,-2],[2,-2],[2,-1],[2,0],[2,1],
+ [2,2],[1,2],[0,2],[-1,2],[-2,2],[-2,1]]),
+ value: 7.5,
+ abbrev: 'L',
+ initial: [{s:1,p:5},{s:-1,p:137}],
+ },
+ 15: {
+ name: 'eagle',
+ aspect: 'fr-eagle',
+ graph: EagleGraph(),
+ value: 8,
+ abbrev: 'A',
+ initial: [{s:1,p:6},{s:-1,p:138}],
+ },
+ 16: {
+ name: 'unicorn',
+ aspect: 'fr-unicorn',
+ graph: this.cbMergeGraphs(geometry,
+ this.cbShortRangeGraph(geometry,[
+ [-2,-2],[-2,0],[-2,2],[0,2],[2,2],[2,0],[2,-2],[0,-2],
+ [-3,-3],[-3,0],[-3,3],[0,3],[3,3],[3,0],[3,-3],[0,-3]]),
+ this.cbKingGraph(geometry),
+ this.cbKnightGraph(geometry),
+ this.cbLongRangeGraph(geometry,[[2,-1],[2,1],[-2,-1],[-2,1],[-1,2],[-1,-2],[1,2],[1,-2]]),
+ this.cbShortRangeGraph(geometry,[[-3,-1],[-3,1],[3,-1],[3,1],[1,3],[1,-3],[-1,3],[-1,-3]])
+ ),
+ value: 13,
+ abbrev: 'Pa',
+ initial: [{s:1,p:2},{s:-1,p:134}],
+ },
+ 17: {
+ name: 'dragon',
+ aspect: 'fr-dragon',
+ graph: this.cbMergeGraphs(geometry,
+ this.cbQueenGraph(geometry),
+ EagleGraph()),
+ value: 14,
+ abbrev: 'D',
+ initial: [{s:1,p:4},{s:-1,p:136}],
+ },
+ 18: {
+ name: 'lighthouse',
+ aspect: 'fr-lighthouse',
+ graph: this.cbMergeGraphs(geometry,
+ this.cbQueenGraph(geometry),
+ this.cbXQCannonGraph(geometry),
+ this.cbLongRangeGraph(geometry,[[1,-1],[-1,-1],[-1,1],[1,1]],null,this.cbConstants.FLAG_MOVE | this.cbConstants.FLAG_SCREEN_CAPTURE)),
+ value: 12,
+ abbrev: 'LH',
+ initial: [{s:1,p:3},{s:-1,p:135}],
+ },
+ 19: {
+ name: 'emperor',
+ aspect: 'fr-crowned-rook',
+ graph: this.cbMergeGraphs(geometry,
+ this.cbQueenGraph(geometry),
+ this.cbXQCannonGraph(geometry),
+ this.cbLongRangeGraph(geometry,[[1,-1],[-1,-1],[-1,1],[1,1]],null,this.cbConstants.FLAG_MOVE | this.cbConstants.FLAG_SCREEN_CAPTURE),
+ EagleGraph(),
+ this.cbShortRangeGraph(geometry,[
+ [-2,-2],[-2,0],[-2,2],[0,2],[2,2],[2,0],[2,-2],[0,-2],
+ [-3,-3],[-3,0],[-3,3],[0,3],[3,3],[3,0],[3,-3],[0,-3]]),
+ this.cbKnightGraph(geometry),
+ this.cbLongRangeGraph(geometry,[[2,-1],[2,1],[-2,-1],[-2,1],[-1,2],[-1,-2],[1,2],[1,-2]]),
+ this.cbShortRangeGraph(geometry,[[-3,-1],[-3,1],[3,-1],[3,1],[1,3],[1,-3],[-1,3],[-1,-3]])),
+ value: 20,
+ abbrev: 'EM',
+ },
+ 20: {
+ name: 'commander',
+ aspect: 'fr-amazon',
+ graph: this.cbMergeGraphs(geometry,
+ this.cbQueenGraph(geometry),
+ this.cbKnightGraph(geometry)),
+ value: 13,
+ abbrev: 'Co',
+ initial: [{s:1,p:7},{s:-1,p:139}],
+ },
+
+ 21: {
+ name: 'cardinal',
+ aspect: 'fr-cardinal',
+ graph: this.cbMergeGraphs(geometry,
+ this.cbBishopGraph(geometry),
+ this.cbKnightGraph(geometry)),
+ value: 6,
+ abbrev: 'Ca',
+ initial: [{s:1,p:9},{s:-1,p:141}],
+ },
+
+ 22: {
+ name: 'chancellor',
+ aspect: 'fr-marshall',
+ graph: this.cbMergeGraphs(geometry,
+ this.cbRookGraph(geometry),
+ this.cbKnightGraph(geometry)),
+ value: 9,
+ abbrev: 'Ch',
+ initial: [{s:1,p:8},{s:-1,p:140}],
+ castle: true,
+ },
+ },
+
+ promote: function(aGame,piece,move) {
+ if(piece.t==1 && geometry.R(move.t)==11)
+ return [14,15,20,16,17,18];
+ else if(piece.t==3 && geometry.R(move.t)==0)
+ return [14,15,20,16,17,18];
+ else if(piece.t==11 && geometry.R(move.t)==11)
+ return [19];
+ else if(piece.t==12 && geometry.R(move.t)==0)
+ return [19];
+ return [];
+ },
+
+ };
+ }
+
+ /*
+ * Model.Board.GenerateMoves:
+ * - handle setup phase
+ * - handle king special move: a kind of castle involving only the king
+ */
+ var kingLongMoves={
+ "1": {
+ 17: [ [15,16],[19,18],[41,29],[39,28],[43,30],[3,4,16],[27,16,28],[40,28,29],[42,29,30],[31,18,30],[7,18,6] ],
+ 5: [ [3,4],[7,8],[29,17],[27,16],[31,18],[15,4,6],[28,16,17],[30,17,18],[19,6,18] ],
+ },
+ "-1": {
+ 125: [ [127,126],[123,124],[101,113],[99,112],[103,114],[135,124,136],[111,112,124],[100,112,113],[102,113,114],[115,114,126],[139,126,138] ],
+ 137: [ [139,138],[135,136],[113,125],[115,126],[111,124],[127,126,138],[114,125,126],[112,124,125],[123,124,136] ],
+ },
+ }
+ var SuperModelBoardGenerateMoves=Model.Board.GenerateMoves;
+ Model.Board.GenerateMoves = function(aGame) {
+ // first moves (white and black) are managed specifically to setup K,Q,E,L initial position
+ if(this.setupState===undefined) {
+ this.mMoves=[{}];
+ return;
+ }
+ if(this.setupState=="setup") {
+ this.mMoves=[];
+ for(var i=0;i<12;i++)
+ this.mMoves.push({setup:i});
+ return;
+ }
+ SuperModelBoardGenerateMoves.apply(this,arguments); // call regular GenerateMoves method
+ // now consider special 2 cases king moves
+ var kPiece=this.pieces[this.board[this.kings[this.mWho]]];
+ if(!kPiece.m && !this.check) {
+ var lMoves=kingLongMoves[this.mWho][kPiece.p];
+ for(var i=0;i=0)
+ continue;
+ var canMove=true;
+ var oppInCheck=false;
+ for(var j=0;j0;
+ if(!inCheck && j==0)
+ oppInCheck=this.cbGetAttackers(aGame,this.kings[-this.mWho],-this.mWho,true).length>0;
+ this.cbQuickUnapply(aGame,undo);
+ this.board[pos]=tmpOut;
+ this.cbIntegrity(aGame);
+ if(inCheck) {
+ canMove=false;
+ break;
+ }
+ }
+ if(canMove)
+ this.mMoves.push({
+ f: kPiece.p,
+ t: lMove[0],
+ c: null,
+ ck: oppInCheck,
+ a: 'K',
+ });
+ }
+ }
+ }
+
+ /*
+ * Model.Board.CopyFrom overriding to copy setupState property
+ */
+ var SuperModelBoardCopyFrom = Model.Board.CopyFrom;
+ Model.Board.CopyFrom = function(aBoard) {
+ SuperModelBoardCopyFrom.apply(this,arguments);
+ this.setupState = aBoard.setupState;
+ }
+
+ /*
+ * Model.Board.Evaluate overriding: in setup phase, no evaluation
+ */
+ var SuperModelBoardEvaluate = Model.Board.Evaluate;
+ Model.Board.Evaluate = function(aGame) {
+ if(this.setupState===undefined || this.setupState=="setup")
+ return;
+ SuperModelBoardEvaluate.apply(this,arguments);
+ }
+
+ /*
+ * Model.Board.ApplyMove overriding: setup phase and king special move
+ */
+ var SuperModelBoardApplyMove=Model.Board.ApplyMove;
+ Model.Board.ApplyMove = function(aGame,move) {
+ if(this.setupState===undefined)
+ this.setupState="setup";
+ else if(this.setupState=="setup") {
+ var $this=this, piece;
+ // at this point, KQLE have arbitrary positions. remember those piece indexes so we can move them
+ var starting={
+ "1": { K: 17, Q: 18, L: 5, E: 6 },
+ "-1": { K: 125, Q: 126, L: 137, E: 138 },
+ }
+ var indexes={ "1": {}, "-1": {} };
+ ["1","-1"].forEach(function(side) {
+ for(var p in starting[side])
+ indexes[side][p]=$this.board[starting[side][p]];
+ });
+ // remove KQLE from the board
+ [5,6,17,18,125,126,137,138].forEach(function(pos) {
+ var pIndex=$this.board[pos];
+ $this.board[pos]=-1;
+ piece = $this.pieces[pIndex];
+ piece.p=-1;
+ $this.zSign=aGame.zobrist.update($this.zSign,"board",piece.t,pos);
+ });
+ // setup KQLE positions according to the setup
+ var setup=move.setup;
+ var remaining={};
+ if(setup/6<1) {
+ this.board[17]=indexes[1].K;
+ piece = this.pieces[indexes[1].K];
+ piece.p=17;
+ $this.zSign=aGame.zobrist.update($this.zSign,"board",piece.t,17);
+ this.kings[1]=17;
+ remaining[1]=[18,5,6];
+ this.board[125]=indexes[-1].K;
+ piece = this.pieces[indexes[-1].K];
+ piece.p=125;
+ $this.zSign=aGame.zobrist.update($this.zSign,"board",piece.t,125);
+ this.kings[-1]=125;
+ remaining[-1]=[126,137,138];
+ } else {
+ this.board[5]=indexes[1].K;
+ piece = this.pieces[indexes[1].K];
+ piece.p=5;
+ $this.zSign=aGame.zobrist.update($this.zSign,"board",piece.t,5);
+ this.kings[1]=5;
+ remaining[1]=[17,18,6];
+ this.board[137]=indexes[-1].K;
+ piece = this.pieces[indexes[-1].K];
+ piece.p=137;
+ $this.zSign=aGame.zobrist.update($this.zSign,"board",piece.t,137);
+ this.kings[-1]=137;
+ remaining[-1]=[125,126,138];
+ }
+ setup%=6;
+ var queen=Math.floor(setup/2);
+ this.board[remaining[1][queen]]=indexes[1].Q;
+ piece = this.pieces[indexes[1].Q];
+ piece.p=remaining[1][queen];
+ $this.zSign=aGame.zobrist.update($this.zSign,"board",piece.t,remaining[1][queen]);
+ remaining[1].splice(queen,1);
+ this.board[remaining[-1][queen]]=indexes[-1].Q;
+ piece = this.pieces[indexes[-1].Q];
+ piece.p=remaining[-1][queen];
+ $this.zSign=aGame.zobrist.update($this.zSign,"board",piece.t,remaining[-1][queen]);
+ remaining[-1].splice(queen,1);
+ var eagle,lion;
+ setup%=2;
+ if(setup==0) {
+ eagle=0;
+ lion=1;
+ } else {
+ eagle=1;
+ lion=0;
+ }
+ this.board[remaining[1][eagle]]=indexes[1].E;
+ piece = this.pieces[indexes[1].E];
+ piece.p=remaining[1][eagle];
+ $this.zSign=aGame.zobrist.update($this.zSign,"board",piece.t,remaining[1][eagle]);
+ this.board[remaining[1][lion]]=indexes[1].L;
+ piece = this.pieces[indexes[1].L];
+ piece.p=remaining[1][lion];
+ $this.zSign=aGame.zobrist.update($this.zSign,"board",piece.t,remaining[1][lion]);
+
+ this.board[remaining[-1][eagle]]=indexes[-1].E;
+ piece = this.pieces[indexes[-1].E];
+ piece.p=remaining[-1][eagle];
+ $this.zSign=aGame.zobrist.update($this.zSign,"board",piece.t,remaining[-1][eagle]);
+ this.board[remaining[-1][lion]]=indexes[-1].L;
+ piece = this.pieces[indexes[-1].L];
+ piece.p=remaining[-1][lion];
+ $this.zSign=aGame.zobrist.update($this.zSign,"board",piece.t,remaining[1][lion]);
+
+ this.setupState="done";
+ } else
+ SuperModelBoardApplyMove.apply(this,arguments);
+ }
+
+ /*
+ * Model.Move.ToString overriding for setup notation
+ */
+ var SuperModelMoveToString = Model.Move.ToString;
+ Model.Move.ToString = function() {
+ if(this.f===undefined) {
+ if(this.setup===undefined)
+ return "--";
+ else
+ return "#"+this.setup;
+ }
+ return SuperModelMoveToString.apply(this,arguments);
+ }
+
+ /*
+ * Model.Board.CompactMoveString overriding to help reading PJN game transcripts
+ */
+ var SuperModelBoardCompactMoveString = Model.Board.CompactMoveString;
+ Model.Board.CompactMoveString = function(aGame,aMove,allMoves) {
+ if(typeof aMove.ToString!="function") // ensure proper move object, if necessary
+ aMove=aGame.CreateMove(aMove);
+ if(this.setupState===undefined || this.setupState=="setup")
+ return aMove.ToString();
+ return SuperModelBoardCompactMoveString.apply(this,arguments);
+ }
+
+ /*
+ * Model.Board.StaticGenerateMoves overriding to prevent using AI during the setup phase
+ */
+ Model.Board.StaticGenerateMoves = function(aGame) {
+ if(this.setupState=="setup")
+ return [aGame.CreateMove({setup:Math.floor(Math.random()*12)})];
+ return null;
+ }
+
+})();
diff --git a/src/games/chessbase/leychessalpha-view.js b/src/games/chessbase/leychessalpha-view.js
new file mode 100644
index 0000000..4a17bb5
--- /dev/null
+++ b/src/games/chessbase/leychessalpha-view.js
@@ -0,0 +1,220 @@
+/*
+ * Copyright(c) 2013-2017 - jocly.com
+ *
+ * You are allowed to use and modify this source code as long as it is exclusively for use in the Jocly API.
+ *
+ * Original authors: Jocly team
+ *
+ */
+
+
+
+
+(function() {
+
+ View.Game.cbDefineView = function() {
+
+ var metamachyBoardDelta = {
+ //notationMode: 'in',
+ //notationDebug: true,
+ };
+ var metamachyBoard3d = $.extend(true,{},this.cbGridBoardClassic3DMargin,metamachyBoardDelta);
+ var metamachyBoard2d = $.extend(true,{},this.cbGridBoardClassic2DNoMargin,metamachyBoardDelta);
+
+ return {
+ coords: {
+ "2d": this.cbGridBoard.coordsFn.call(this,metamachyBoard2d),
+ "3d": this.cbGridBoard.coordsFn.call(this,metamachyBoard3d),
+ },
+ boardLayout: [
+ ".#.#.#.#.#.#",
+ "#.#.#.#.#.#.",
+ ".#.#.#.#.#.#",
+ "#.#.#.#.#.#.",
+ ".#.#.#.#.#.#",
+ "#.#.#.#.#.#.",
+ ".#.#.#.#.#.#",
+ "#.#.#.#.#.#.",
+ ".#.#.#.#.#.#",
+ "#.#.#.#.#.#.",
+ ".#.#.#.#.#.#",
+ "#.#.#.#.#.#.",
+ ],
+ board: {
+ "2d": {
+ draw: this.cbDrawBoardFn(metamachyBoard2d),
+ },
+ "3d": {
+ display: this.cbDisplayBoardFn(metamachyBoard3d),
+ },
+ },
+ clicker: {
+ "2d": {
+ width: 1000,
+ height: 1000,
+ },
+ "3d": {
+ scale: [.6,.6,.6],
+ },
+ },
+ pieces: this.cbFairyPieceStyle({
+ "default": {
+ "3d": {
+ scale: [.4,.4,.4],
+ },
+ "2d": {
+ width: 900,
+ height: 900,
+ },
+ },
+ }),
+ };
+ }
+
+ /*
+ * Make the knight & the camel jump when moving, the elephant & the lion when moving 2 squares, the cannon when capturing
+ */
+ View.Board.cbMoveMidZ = function(aGame,aMove,zFrom,zTo) {
+ if(aMove.a=='N' || aMove.a=='M' || (aMove.a=='E' && aGame.g.distGraph[aMove.f][aMove.t]==2) || (aMove.a=='L' && aGame.g.distGraph[aMove.f][aMove.t]==2) || (aMove.a=='K' && aGame.g.distGraph[aMove.f][aMove.t]==2) || (aMove.a=='C' && aMove.c!=null))
+ return Math.max(zFrom,zTo)+1500;
+ else
+ return (zFrom+zTo)/2;
+ }
+
+ /*
+ * View.Game.xdInit overriding to create initial setup gadgets
+ */
+ var SuperViewGameXdInit = View.Game.xdInit;
+ View.Game.xdInit = function(xdv) {
+ var $this=this;
+ SuperViewGameXdInit.apply(this,arguments);
+ var size=600;
+ xdv.createGadget("setup-board",{
+ base: {
+ type: "element",
+ x: 0,
+ y: 0,
+ width: size*12,
+ height: size*9,
+ z: 108,
+ css: {
+ "background-color": "White",
+ },
+ },
+ });
+ var setups={
+ 0: "KQEL",
+ 1: "KQLE",
+ 2: "KEQL",
+ 3: "KLQE",
+ 4: "KELQ",
+ 5: "KLEQ",
+ 6: "QEKL",
+ 7: "QLKE",
+ 8: "EQKL",
+ 9: "LQKE",
+ 10: "ELKQ",
+ 11: "LEKQ",
+ }
+ var imageOffsets={
+ K: 500, Q: 400, E: 1100, L: 1200,
+ }
+ for(var setup in setups) {
+ (function(setup) {
+ var x=((setup%4)-1.5)*3*size;
+ var y=(Math.floor(setup/4)-1)*3*size;
+ xdv.createGadget("setup#"+setup,{
+ base: {
+ type: "canvas",
+ x: x,
+ y: y,
+ width: 2*size,
+ height: 2*size,
+ z: 109,
+ draw: function(ctx) {
+ ctx.fillStyle="#c0c0c0";
+ ctx.rect(-size,-size,size*2,size*2);
+ ctx.fill();
+ ctx.save();
+ this.getResource("image|"+$this.g.fullPath+"/res/fairy/wikipedia-fairy-sprites.png",function(image) {
+ for(var i=0;i<4;i++) {
+ var x=i%2, y=Math.floor(i/2), p=setups[setup].charAt(i);
+ ctx.drawImage(image,imageOffsets[p],0,100,100,(x-1)*size,(y-1)*size,size,size);
+ }
+ ctx.restore();
+ });
+ }
+ },
+ });
+ })(setup);
+ }
+ }
+
+ /*
+ * View.Board.xdInput overriding to handle setup phase
+ */
+ var SuperViewBoardxdInput = View.Board.xdInput;
+ View.Board.xdInput = function(xdv, aGame) {
+ if(this.setupState===undefined) {
+ return {
+ initial: {},
+ getActions: function(moves,currentInput) { return null; },
+ }
+ } else if(this.setupState=="setup") {
+ return {
+ initial: {
+ setupDone: false,
+ },
+ getActions: function(moves,currentInput) {
+ var actions={};
+ if(!currentInput.setupDone) {
+ moves.forEach(function(move) {
+ actions[move.setup]={
+ view: ["setup#"+move.setup],
+ click: ["setup#"+move.setup],
+ moves: [move],
+ validate: { setupDone: true },
+ }
+ });
+ }
+ return actions;
+ },
+ furnitures: ["setup-board"],
+ }
+ } else
+ return SuperViewBoardxdInput.apply(this,arguments);
+ }
+
+ /*
+ * View.Board.cbAnimate overriding to prevent animation on setup
+ */
+ var SuperViewBoardcbAnimate = View.Board.cbAnimate;
+ View.Board.cbAnimate = function(xdv,aGame,aMove,callback) {
+ if(this.setupState===undefined || this.setupState=="setup")
+ callback();
+ else
+ SuperViewBoardcbAnimate.apply(this,arguments);
+ }
+
+ /*
+ * View.Board.xdDisplay overriding to prevent displaying KQEL before setup
+ */
+ var SuperViewBoardxdDisplay = View.Board.xdDisplay;
+ View.Board.xdDisplay = function(xdv, aGame) {
+ if(this.setupState===undefined || this.setupState=="setup") {
+ var $this=this;
+ var hidden={};
+ [5,6,17,18,125,126,137,138].forEach(function(pos) {
+ var pIndex=$this.board[pos];
+ hidden[pos]=pIndex;
+ $this.pieces[pIndex].p=-1;
+ });
+ SuperViewBoardxdDisplay.apply(this,arguments);
+ for(var pos in hidden)
+ this.pieces[hidden[pos]].p=parseInt(pos);
+ } else
+ SuperViewBoardxdDisplay.apply(this,arguments);
+ }
+
+})();
+