Programming with sub-models To enhance the support for chess variants with fairy pieces, several sub-models were created. fairy-moves-model.js This sub-model, when included in the model build with base-model.js, will provide various forms of support that chess variants featuring unorthodox pieces would often need. This ranges from new routines for generating move graphs of often encountered unorthodox pieces, move-mode flags for some common forms of locust capture (i.e. removal of pieces on other squares than the destination of the move), and anti-trading rules. Move graphs. Several new routines for creating the graphs for fairy pieces are available. These are (as they would be used in the game's model file for defining the piece moves): this.cbCamelGraph(geometry, confine); // [1,3] leaper this.cbZebraGraph(geometry, confine); // [2,3] leaper this.cbElephantGraph(geometry, confine); // [1,1] and [2,2] leaper this.cbWarMachineGraph(geometry, confine); // [2,0] and [1,0] leaper this.cbAlibabaGraph(geometry, confine); // [2,0] and [2,2] leaper this.cbWizardGraph(geometry, confine); // [1,1] and [1,3] leaper this.cbChampionGraph(geometry, confine); // [1,0],[1,1] and [2,0] leaper this.cbVaoGraph(geometry, confine); // diagonal XQ Cannon this.cbCardinalGraph(geometry, confine); // Knight-Bishop compound this.cbMarshallGraph(geometry, confine); // Knight-Rook compound this.cbAmazonGraph(geometry, confine); // Knight-Queen compound this.cbGriffonGraph(geometry, confine); // R after F bent slider this.cbRhinoGraph(geometry, confine); // B after W bent slider More general routines for creating graphs are: this.cbSkiGraph(geometry, stepSet, flag, bendAngle, iflag, range); This creates a two-leg trajectory, where the second leg can continue at an angle specified by bendAngle from the first. Here 0 means straight on, 1 a (symmetric) 45-degree bent, etc. The first step will use the iflag, the remaining trajectory the flag argument for its mode. this.cbAdvancerGraph(geometry, stepSet, range); This creates a graph for a rider in the given directions with the given range, which makes Advancer capture (stopping just before the piece on its trajectory that it wants to capture). These moves are implemented as e.p. captures, so the user won't have to click the intended capture target, just the destination. Locust and double captures There now is some automated support for moves that have set the (new) this.cbConstants.FLAG_FAIRY amongst their flags. Some flag bits that otherwise would be freely available to the user will then specify in which way moves that were pushed on the special- moves stack will be automatically processed and transferred to the array of pseudo-legal moves. The available flavors are: this.cbConstants.FLAG_RIFLE; // capture target without moving this.cbConstants.FLAG_HITRUN; // capture is followed by king move this.cbConstants.FLAG_CHECKER; // capture by jumping over enemy The latter should be used only by moves that step to the second square, and would only be allowed if that square is empty. But by combining it with FLAG_SPECIAL_CAPTURE it can be made to also work for a double capture. All these flags have FLAG_FAIRY set in their bit pattern. Without that, when using FLAG_SPECIAL, FLAG_SPECIAL_CAPTURE or FLAG_CAPTURE_SELF the move would be put in the array 'special' of candidate moves if the specified target square was empty, or occupied by a foe or friend, respectively. (Combinations thereof are possible.) This feature is already supported in base-model.js. One would then have to provide his own post-processing routine to convert these candidate moves to real moves, and push those to the 'moves' array. The move that is used to leave the capture square on hit & run capture can be controlled by assigning a graph to the variable Model.Game.neighbors (i.e. this.neighbors in the game definition). By default it would be the King graph. Entering these moves requires the capture victim to be clicked, after which the possible final destination(s) will get highlighted, and have to be clicked to complete the move. This way for entering moves requires that multi-leg-view.js is included in the view build. If the user wants to use custom code for processing special moves in combination with the fairy-move-model.js file, he can provide a routine this.customGen(moves, move, board, aGame) to convert the given move from the special moves stack into a real one, and push that to the moves array (or disgard it). The final two arguments are the game state (a Board object) and the Game object, which can be consulted to perform the transformation. Like always, the candidate will contain a field x (apart from the normal f, t, c and a fields for squares of origin and destination, index of the piece at the destination in the pieces array (or null), and abbreviated piece name, respectively), which contains the XOR of the destination square and the previously visited square on the path in the low 16 bits, and the mode flags in the high-order bits. Flying capture The base model already supports 'flying capture', i.e. the power to jump over arbitrary many pieces for capturing, as a special case of screen capture. Just for a reminder we describe it here. Flying capture is indicated by FLAG_SCREEN_CAPTURE, just like normal screen capture. What makes the difference is a non-zero value in the optional 'ranking' field of the piece definition: ranking: N, In that case the move along a ray is not terminated with the screen capture, but can also fly over it for capturing further down the ray. Whether a piece can be used as a screen at all is determined by the ranking of the latter. This must be lower than that of the piece making the capture, or equal if they are an even number. This allows implementation both of the case where equal pieces would block each other, and where they don't. Note that normal screen capture (which has N=0) can use all piece types as a screen, irrespective of the ranking of the latter. Anti-trade rules There also is support for some anti-trade rules. Pieces can be assigned to an 'anti-trade group' N with the aid of a field antiTrade: N, amongst the piece properties. Pieces in the same odd-numbered group will then not be able to capture each other, if recapture on the same square would be possible. (I.e., if the captured piece was protected.) If |N| > 100 (and odd) it is even forbidden to capture unprotected pieces of the same trade group. Pieces with an even antiTrade value can always be traded for each other, but cannot capture a protected piece with the next odd anti-trade group. If N < 0 'counter-strike' against the piece is also banned: in the move directly following the capture of a piece from such a group, pieces from the same group cannot be captured by pieces outside the group. The anti-trading provisions only get switched on by assigning a non-zero value M to Model.Game.minimumBridge=M; The actual value you use for this will be significant when anti-trading restrictions apply to a piece capable of double- capture: all pieces of a type >= M captured as 'side catch' to the trade will cause the ban on trading to be lifted. (Note that the ban only appied for capturing on the destination square to begin with.) To lift the ban for any side catch, you can take M = -1.