How to use p4 method in fast-check-monorepo

Best JavaScript code snippet using fast-check-monorepo

engine.js

Source:engine.js Github

copy

Full Screen

1/* p4wn, AKA 5k chess - by Douglas Bagnall <douglas@paradise.net.nz>2 *3 * This code is in the public domain, or as close to it as various4 * laws allow. No warranty; no restrictions.5 *6 * lives at http://p4wn.sf.net/7 */8/*Compatibility tricks:9 * backwards for old MSIEs (to 5.5)10 * sideways for seed command-line javascript.*/11var p4_log;12if (this.imports !== undefined &&13 this.printerr !== undefined){//seed or gjs14 p4_log = function(){15 var args = Array.prototype.slice.call(arguments);16 printerr(args.join(', '));17 };18}19else if (this.console === undefined){//MSIE20 p4_log = function(){};21}22else {23 // disable the console24 p4_log = function(){};25 //p4_log = function(){console.log.apply(console, arguments);};26}27/*MSIE Date.now backport */28if (Date.now === undefined)29 Date.now = function(){return (new Date).getTime();};30/* The pieces are stored as numbers between 2 and 13, inclusive.31 * Empty squares are stored as 0, and off-board squares as 16.32 * There is some bitwise logic to it:33 * piece & 1 -> colour (white: 0, black: 1)34 * piece & 2 -> single move piece (including pawn)35 * if (piece & 2) == 0:36 * piece & 4 -> row and column moves37 * piece & 8 -> diagonal moves38 */39var P4_PAWN = 2, P4_ROOK = 4, P4_KNIGHT = 6, P4_BISHOP = 8, P4_QUEEN = 12, P4_KING = 10;40var P4_EDGE = 16;41/* in order, even indices: <nothing>, pawn, rook, knight, bishop, king, queen. Only the42 * even indices are used.*/43var P4_MOVES = [[], [],44 [], [],45 [1,10,-1,-10], [],46 [21,19,12,8,-21,-19,-12,-8], [],47 [11,9,-11,-9], [],48 [1,10,11,9,-1,-10,-11,-9], [],49 [1,10,11,9,-1,-10,-11,-9], []50 ];51/*P4_VALUES defines the relative value of various pieces.52 *53 * It follows the 1,3,3,5,9 pattern you learn as a kid, multiplied by54 * 20 to give sub-pawn resolution to other factors, with bishops given55 * a wee boost over knights.56 */57var P4_VALUES=[0, 0, //Piece values58 20, 20, //pawns59 100, 100, //rooks60 60, 60, //knights61 61, 61, //bishops62 8000, 8000,//kings63 180, 180, //queens64 0];65/* A score greater than P4_WIN indicates a king has been taken. It is66 * less than the value of a king, in case someone finds a way to, say,67 * sacrifice two queens in order to checkmate.68 */69var P4_KING_VALUE = P4_VALUES[10];70var P4_WIN = P4_KING_VALUE >> 1;71/* every move, a winning score decreases by this much */72var P4_WIN_DECAY = 300;73var P4_WIN_NOW = P4_KING_VALUE - 250;74/* P4_{MAX,MIN}_SCORE should be beyond any possible evaluated score */75var P4_MAX_SCORE = 9999; // extremes of evaluation range76var P4_MIN_SCORE = -P4_MAX_SCORE;77/*initialised in p4_initialise_state */78var P4_CENTRALISING_WEIGHTS;79var P4_BASE_PAWN_WEIGHTS;80var P4_KNIGHT_WEIGHTS;81/*P4_DEBUG turns on debugging features */82var P4_DEBUG = 0;83var P4_INITIAL_BOARD = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 1 1";84/*use javascript typed arrays rather than plain arrays85 * (faster in some browsers, unsupported in others, possibly slower elsewhere) */86var P4_USE_TYPED_ARRAYS = this.Int32Array !== undefined;87var P4_PIECE_LUT = { /*for FEN, PGN interpretation */88 P: 2,89 p: 3,90 R: 4,91 r: 5,92 N: 6,93 n: 7,94 B: 8,95 b: 9,96 K: 10,97 k: 11,98 Q: 12,99 q: 13100};101var P4_ENCODE_LUT = ' PPRRNNBBKKQQ';102function p4_alphabeta_treeclimber(state, count, colour, score, s, e, alpha, beta){103 var move = p4_make_move(state, s, e, P4_QUEEN);104 var i;105 var ncolour = 1 - colour;106 var movelist = p4_parse(state, colour, move.ep, -score);107 var movecount = movelist.length;108 if(count){109 //branch nodes110 var t;111 for(i = 0; i < movecount; i++){112 var mv = movelist[i];113 var mscore = mv[0];114 var ms = mv[1];115 var me = mv[2];116 if (mscore > P4_WIN){ //we won! Don't look further.117 alpha = P4_KING_VALUE;118 break;119 }120 t = -p4_alphabeta_treeclimber(state, count - 1, ncolour, mscore, ms, me,121 -beta, -alpha);122 if (t > alpha){123 alpha = t;124 }125 if (alpha >= beta){126 break;127 }128 }129 if (alpha < -P4_WIN_NOW && ! p4_check_check(state, colour)){130 /* Whatever we do, we lose the king.131 * But if it is not check then this is stalemate, and the132 * score doesn't apply.133 */134 alpha = state.stalemate_scores[colour];135 }136 if (alpha < -P4_WIN){137 /*make distant checkmate seem less bad */138 alpha += P4_WIN_DECAY;139 }140 }141 else{142 //leaf nodes143 while(beta > alpha && --movecount != -1){144 if(movelist[movecount][0] > alpha){145 alpha = movelist[movecount][0];146 }147 }148 }149 p4_unmake_move(state, move);150 return alpha;151}152/* p4_prepare() works out weightings for assessing various moves,153 * favouring centralising moves early, for example.154 *155 * It is called before each tree search, not for each parse(), so it156 * is OK for it to be a little bit slow. But that also means it drifts157 * out of sync with the real board state, especially on deep searches.158 */159function p4_prepare(state){160 var i, j, x, y, a;161 var pieces = state.pieces = [[], []];162 /*convert state.moveno half move count to move cycle count */163 var moveno = state.moveno >> 1;164 var board = state.board;165 /* high earliness_weight indicates a low move number. The formula166 * should work above moveno == 50, but this is javascript.167 */168 var earliness_weight = (moveno > 50) ? 0 : parseInt(6 * Math.exp(moveno * -0.07));169 var king_should_hide = moveno < 12;170 var early = moveno < 5;171 /* find the pieces, kings, and weigh material*/172 var kings = [0, 0];173 var material = [0, 0];174 var best_pieces = [0, 0];175 for(i = 20; i < 100; i++){176 a = board[i];177 var piece = a & 14;178 var colour = a & 1;179 if(piece){180 pieces[colour].push([a, i]);181 if (piece == P4_KING){182 kings[colour] = i;183 }184 else{185 material[colour] += P4_VALUES[piece];186 best_pieces[colour] = Math.max(best_pieces[colour], P4_VALUES[piece]);187 }188 }189 }190 /*does a draw seem likely soon?*/191 var draw_likely = (state.draw_timeout > 90 || state.current_repetitions >= 2);192 if (draw_likely)193 p4_log("draw likely", state.current_repetitions, state.draw_timeout);194 state.values = [[], []];195 var qvalue = P4_VALUES[P4_QUEEN]; /*used as ballast in various ratios*/196 var material_sum = material[0] + material[1] + 2 * qvalue;197 var wmul = 2 * (material[1] + qvalue) / material_sum;198 var bmul = 2 * (material[0] + qvalue) / material_sum;199 var multipliers = [wmul, bmul];200 var emptiness = 4 * P4_QUEEN / material_sum;201 state.stalemate_scores = [parseInt(0.5 + (wmul - 1) * 2 * qvalue),202 parseInt(0.5 + (bmul - 1) * 2 * qvalue)];203 //p4_log("value multipliers (W, B):", wmul, bmul,204 // "stalemate scores", state.stalemate_scores);205 for (i = 0; i < P4_VALUES.length; i++){206 var v = P4_VALUES[i];207 if (v < P4_WIN){//i.e., not king208 state.values[0][i] = parseInt(v * wmul + 0.5);209 state.values[1][i] = parseInt(v * bmul + 0.5);210 }211 else {212 state.values[0][i] = v;213 state.values[1][i] = v;214 }215 }216 /*used for pruning quiescence search */217 state.best_pieces = [parseInt(best_pieces[0] * wmul + 0.5),218 parseInt(best_pieces[1] * bmul + 0.5)];219 var kx = [kings[0] % 10, kings[1] % 10];220 var ky = [parseInt(kings[0] / 10), parseInt(kings[1] / 10)];221 /* find the frontmost pawns in each file */222 var pawn_cols = [[], []];223 for (y = 3; y < 9; y++){224 for (x = 1; x < 9; x++){225 i = y * 10 + x;226 a = board[i];227 if ((a & 14) != P4_PAWN)228 continue;229 if ((a & 1) == 0){230 pawn_cols[0][x] = y;231 }232 else if (pawn_cols[1][x] === undefined){233 pawn_cols[1][x] = y;234 }235 }236 }237 var target_king = (moveno >= 20 || material_sum < 5 * qvalue);238 var weights = state.weights;239 for (y = 2; y < 10; y++){240 for (x = 1; x < 9; x++){241 i = y * 10 + x;242 var early_centre = P4_CENTRALISING_WEIGHTS[i] * earliness_weight;243 var plateau = P4_KNIGHT_WEIGHTS[i];244 for (var c = 0; c < 2; c++){245 var dx = Math.abs(kx[1 - c] - x);246 var dy = Math.abs(ky[1 - c] - y);247 var our_dx = Math.abs(kx[c] - x);248 var our_dy = Math.abs(ky[c] - y);249 var d = Math.max(Math.sqrt(dx * dx + dy * dy), 1) + 1;250 var mul = multipliers[c]; /*(mul < 1) <==> we're winning*/251 var mul3 = mul * mul * mul;252 var at_home = y == 2 + c * 7;253 var pawn_home = y == 3 + c * 5;254 var row4 = y == 5 + c;255 var promotion_row = y == 9 - c * 7;256 var get_out = (early && at_home) * -5;257 var knight = parseInt(early_centre * 0.3) + 2 * plateau + get_out;258 var rook = parseInt(early_centre * 0.3);259 var bishop = parseInt(early_centre * 0.6) + plateau + get_out;260 if (at_home){261 rook += (x == 4 || x == 5) * (earliness_weight + ! target_king);262 rook += (x == 1 || x == 8) * (moveno > 10 && moveno < 20) * -3;263 rook += (x == 2 || x == 7) * (moveno > 10 && moveno < 20) * -1;264 }265 /*Queen wants to stay home early, then jump right in*/266 /*keep kings back on home row for a while*/267 var queen = parseInt(plateau * 0.5 + early_centre * (0.5 - early));268 var king = (king_should_hide && at_home) * 2 * earliness_weight;269 /*empty board means pawn advancement is more urgent*/270 var get_on_with_it = Math.max(emptiness * 2, 1);271 var pawn = get_on_with_it * P4_BASE_PAWN_WEIGHTS[c ? 119 - i : i];272 if (early){273 /* Early pawn weights are slightly randomised, so each game is different.274 */275 if (y >= 4 && y <= 7){276 var boost = 1 + 3 * (y == 5 || y == 6);277 pawn += parseInt((boost + p4_random_int(state, 4)) * 0.1 *278 early_centre);279 }280 if (x == 4 || x == 5){281 //discourage middle pawns from waiting at home282 pawn -= 3 * pawn_home;283 pawn += 3 * row4;284 }285 }286 /*pawn promotion row is weighted as a queen minus a pawn.*/287 if (promotion_row)288 pawn += state.values[c][P4_QUEEN] - state.values[c][P4_PAWN];289 /*pawns in front of a castled king should stay there*/290 pawn += 4 * (y == 3 && ky[c] == 2 && Math.abs(our_dx) < 2 &&291 kx[c] != 5 && x != 4 && x != 5);292 /*passed pawns (having no opposing pawn in front) are encouraged. */293 var cols = pawn_cols[1 - c];294 if (cols[x] == undefined ||295 (c == 0 && cols[x] < y) ||296 (c == 1 && cols[x] > y))297 pawn += 2;298 /* After a while, start going for opposite king. Just299 * attract pieces into the area so they can mill about in300 * the area, waiting for an opportunity.301 *302 * As prepare is only called at the beginning of each tree303 * search, the king could wander out of the targetted area304 * in deep searches. But that's OK. Heuristics are305 * heuristics.306 */307 if (target_king){308 knight += 2 * parseInt(8 * mul / d);309 rook += 2 * ((dx < 2) + (dy < 2));310 bishop += 3 * (Math.abs((dx - dy)) < 2);311 queen += 2 * parseInt(8 / d) + (dx * dy == 0) + (dx - dy == 0);312 /* The losing king wants to stay in the middle, while313 the winning king goes in for the kill.*/314 var king_centre_wt = 8 * emptiness * P4_CENTRALISING_WEIGHTS[i];315 king += parseInt(150 * emptiness / (mul3 * d) + king_centre_wt * mul3);316 }317 weights[P4_PAWN + c][i] = pawn;318 weights[P4_KNIGHT + c][i] = knight;319 weights[P4_ROOK + c][i] = rook;320 weights[P4_BISHOP + c][i] = bishop;321 weights[P4_QUEEN + c][i] = queen;322 weights[P4_KING + c][i] = king;323 if (draw_likely && mul < 1){324 /*The winning side wants to avoid draw, so adds jitter to its weights.*/325 var range = 3 / mul3;326 for (j = 2 + c; j < 14; j += 2){327 weights[j][i] += p4_random_int(state, range);328 }329 }330 }331 }332 }333 state.prepared = true;334}335function p4_maybe_prepare(state){336 if (! state.prepared)337 p4_prepare(state);338}339function p4_parse(state, colour, ep, score) {340 var board = state.board;341 var s, e; //start and end position342 var E, a; //E=piece at end place, a= piece moving343 var i, j;344 var other_colour = 1 - colour;345 var dir = (10 - 20 * colour); //dir= 10 for white, -10 for black346 var movelist = [];347 var captures = [];348 var weight;349 var pieces = state.pieces[colour];350 var castle_flags = (state.castles >> (colour * 2)) & 3;351 var values = state.values[other_colour];352 var all_weights = state.weights;353 for (j = pieces.length - 1; j >= 0; j--){354 s = pieces[j][1]; // board position355 a = board[s]; //piece number356 var weight_lut = all_weights[a];357 weight = score - weight_lut[s];358 a &= 14;359 if(a > 2){ //non-pawns360 var moves = P4_MOVES[a];361 if(a & 2){362 for(i = 0; i < 8; i++){363 e = s + moves[i];364 E = board[e];365 if(!E){366 movelist.push([weight + values[E] + weight_lut[e], s, e]);367 }368 else if((E&17)==other_colour){369 captures.push([weight + values[E] + weight_lut[e] + all_weights[E][e], s, e]);370 }371 }372 if(a == P4_KING && castle_flags){373 if((castle_flags & 1) &&374 (board[s-1] + board[s-2] + board[s-3] == 0) &&375 p4_check_castling(board, s - 2,other_colour,dir,-1)){//Q side376 movelist.push([weight + 12, s, s - 2]); //no analysis, just encouragement377 }378 if((castle_flags & 2) && (board[s+1]+board[s+2] == 0)&&379 p4_check_castling(board, s, other_colour, dir, 1)){//K side380 movelist.push([weight + 13, s, s + 2]);381 }382 }383 }384 else{//rook, bishop, queen385 var mlen = moves.length;386 for(i=0;i<mlen;){ //goeth thru list of moves387 var m = moves[i++];388 e=s;389 do {390 e+=m;391 E=board[e];392 if(!E){393 movelist.push([weight + values[E] + weight_lut[e], s, e]);394 }395 else if((E&17)==other_colour){396 captures.push([weight + values[E] + weight_lut[e] + all_weights[E][e], s, e]);397 }398 }while(!E);399 }400 }401 }402 else{ //pawns403 e=s+dir;404 if(!board[e]){405 movelist.push([weight + weight_lut[e], s, e]);406 /* s * (120 - s) < 3200 true for outer two rows on either side.*/407 var e2 = e + dir;408 if(s * (120 - s) < 3200 && (!board[e2])){409 movelist.push([weight + weight_lut[e2], s, e2]);410 }411 }412 /* +/-1 for pawn capturing */413 E = board[--e];414 if(E && (E & 17) == other_colour){415 captures.push([weight + values[E] + weight_lut[e] + all_weights[E][e], s, e]);416 }417 e += 2;418 E = board[e];419 if(E && (E & 17) == other_colour){420 captures.push([weight + values[E] + weight_lut[e] + all_weights[E][e], s, e]);421 }422 }423 }424 if(ep){425 var pawn = P4_PAWN | colour;426 var taken;427 /* Some repetitive calculation here could be hoisted out, but that would428 probably slow things: the common case is no pawns waiting to capture429 enpassant, not 2.430 */431 s = ep - dir - 1;432 if (board[s] == pawn){433 taken = values[P4_PAWN] + all_weights[P4_PAWN | other_colour][ep - dir];434 captures.push([score - weight_lut[s] + weight_lut[ep] + taken, s, ep]);435 }436 s += 2;437 if (board[s] == pawn){438 taken = values[P4_PAWN] + all_weights[P4_PAWN | other_colour][ep - dir];439 captures.push([score - weight_lut[s] + weight_lut[ep] + taken, s, ep]);440 }441 }442 return captures.concat(movelist);443}444/*Explaining the bit tricks used in check_castling and check_check:445 *446 * in binary: 16 8 4 2 1447 * empty448 * pawn 1 c449 * rook 1 c450 * knight 1 1 c451 * bishop 1 c452 * king 1 1 c453 * queen 1 1 c454 * wall 1455 *456 * so:457 *458 * piece & (16 | 4 | 2 | 1) is:459 * 2 + c for kings and pawns460 * 4 + c for rooks and queens461 * 6 + c for knights462 * 0 + c for bishops463 * 16 for walls464 *465 * thus:466 * ((piece & 23) == 4 | colour) separates the rooks and queens out467 * from the rest.468 * ((piece & 27) == 8 | colour) does the same for queens and bishops.469 */470/* check_castling471 *472 * s - "start" location (either king home square, or king destination)473 * the checks are done left to right.474 * * dir - direction of travel (White: 10, Black: -10)475 * side: -1 means Q side; 1, K side476 */477function p4_check_castling(board, s, colour, dir, side){478 var e;479 var E;480 var m, p;481 var knight = colour + P4_KNIGHT;482 var diag_slider = P4_BISHOP | colour;483 var diag_mask = 27;484 var grid_slider = P4_ROOK | colour;485 var king_pawn = 2 | colour;486 var grid_mask = 23;487 /* go through 3 positions, checking for check in each488 */489 for(p = s; p < s + 3; p++){490 //bishops, rooks, queens491 e = p;492 do{493 e += dir;494 E=board[e];495 } while (! E);496 if((E & grid_mask) == grid_slider)497 return 0;498 e = p;499 var delta = dir - 1;500 do{501 e += delta;502 E=board[e];503 } while (! E);504 if((E & diag_mask) == diag_slider)505 return 0;506 e = p;507 delta += 2;508 do{509 e += delta;510 E=board[e];511 } while (! E);512 if((E & diag_mask) == diag_slider)513 return 0;514 /*knights on row 7. (row 6 is handled below)*/515 if (board[p + dir - 2] == knight ||516 board[p + dir + 2] == knight)517 return 0;518 }519 /* a pawn or king in any of 5 positions on row 7.520 * or a knight on row 6. */521 for(p = s + dir - 1; p < s + dir + 4; p++){522 E = board[p] & grid_mask;523 if(E == king_pawn || board[p + dir] == knight)524 return 0;525 }526 /* scan back row for rooks, queens on the other side.527 * Same side check is impossible, because the castling rook is there528 */529 e = (side < 0) ? s + 2 : s;530 do {531 e -= side;532 E=board[e];533 } while (! E);534 if((E & grid_mask) == grid_slider)535 return 0;536 return 1;537}538function p4_check_check(state, colour){539 var board = state.board;540 /*find the king. The pieces list updates from the end,541 * so the last-most king is correctly placed.*/542 var pieces = state.pieces[colour];543 var p;544 var i = pieces.length;545 do {546 p = pieces[--i];547 } while (p[0] != (P4_KING | colour));548 var s = p[1];549 var other_colour = 1 - colour;550 var dir = 10 - 20 * colour;551 if (board[s + dir - 1] == (P4_PAWN | other_colour) ||552 board[s + dir + 1] == (P4_PAWN | other_colour))553 return true;554 var knight_moves = P4_MOVES[P4_KNIGHT];555 var king_moves = P4_MOVES[P4_KING];556 var knight = P4_KNIGHT | other_colour;557 var king = P4_KING | other_colour;558 for (i = 0; i < 8; i++){559 if (board[s + knight_moves[i]] == knight ||560 board[s + king_moves[i]] == king)561 return true;562 }563 var diagonal_moves = P4_MOVES[P4_BISHOP];564 var grid_moves = P4_MOVES[P4_ROOK];565 /* diag_mask ignores rook moves of queens,566 * grid_mask ignores the bishop moves*/567 var diag_slider = P4_BISHOP | other_colour;568 var diag_mask = 27;569 var grid_slider = P4_ROOK | other_colour;570 var grid_mask = 23;571 for (i = 0; i < 4; i++){572 var m = diagonal_moves[i];573 var e = s;574 var E;575 do {576 e += m;577 E = board[e];578 } while (!E);579 if((E & diag_mask) == diag_slider)580 return true;581 m = grid_moves[i];582 e = s;583 do {584 e += m;585 E = board[e];586 } while (!E);587 if((E & grid_mask) == grid_slider)588 return true;589 }590 return false;591}592function p4_optimise_piece_list(state){593 var i, p, s, e;594 var movelists = [595 p4_parse(state, 0, 0, 0),596 p4_parse(state, 1, 0, 0)597 ];598 var weights = state.weights;599 var board = state.board;600 for (var colour = 0; colour < 2; colour++){601 var our_values = state.values[colour];602 var pieces = state.pieces[colour];603 var movelist = movelists[colour];604 var threats = movelists[1 - colour];605 /* sparse array to index by score. */606 var scores = [];607 for (i = 0; i < pieces.length; i++){608 p = pieces[i];609 scores[p[1]] = {610 score: 0,611 piece: p[0],612 pos: p[1],613 threatened: 0614 };615 }616 /* Find the best score for each piece by pure static weights,617 * ignoring captures, which have their own path to the top. */618 for(i = movelist.length - 1; i >= 0; i--){619 var mv = movelist[i];620 var score = mv[0];621 s = mv[1];622 e = mv[2];623 if(! board[e]){624 var x = scores[s];625 x.score = Math.max(x.score, score);626 }627 }628 /* moving out of a threat is worth considering, especially629 * if it is a pawn and you are not.*/630 for(i = threats.length - 1; i >= 0; i--){631 var mv = threats[i];632 var x = scores[mv[2]];633 if (x !== undefined){634 var S = board[mv[1]];635 var r = (1 + x.piece > 3 + S < 4) * 0.01;636 if (x.threatened < r)637 x.threatened = r;638 }639 }640 var pieces2 = [];641 for (i = 20; i < 100; i++){642 p = scores[i];643 if (p !== undefined){644 p.score += p.threatened * our_values[p.piece];645 pieces2.push(p);646 }647 }648 pieces2.sort(function(a, b){return a.score - b.score;});649 for (i = 0; i < pieces2.length; i++){650 p = pieces2[i];651 pieces[i] = [p.piece, p.pos];652 }653 }654}655function p4_findmove(state, level, colour, ep){656 p4_prepare(state);657 p4_optimise_piece_list(state);658 var board = state.board;659 if (arguments.length == 2){660 colour = state.to_play;661 ep = state.enpassant;662 }663 var movelist = p4_parse(state, colour, ep, 0);664 var alpha = P4_MIN_SCORE;665 var mv, t, i;666 var bs = 0;667 var be = 0;668 if (level <= 0){669 for (i = 0; i < movelist.length; i++){670 mv = movelist[i];671 if(movelist[i][0] > alpha){672 alpha = mv[0];673 bs = mv[1];674 be = mv[2];675 }676 }677 return [bs, be, alpha];678 }679 for(i = 0; i < movelist.length; i++){680 mv = movelist[i];681 var mscore = mv[0];682 var ms = mv[1];683 var me = mv[2];684 if (mscore > P4_WIN){685 p4_log("XXX taking king! it should never come to this");686 alpha = P4_KING_VALUE;687 bs = ms;688 be = me;689 break;690 }691 t = -state.treeclimber(state, level - 1, 1 - colour, mscore, ms, me,692 P4_MIN_SCORE, -alpha);693 if (t > alpha){694 alpha = t;695 bs = ms;696 be = me;697 }698 }699 if (alpha < -P4_WIN_NOW && ! p4_check_check(state, colour)){700 alpha = state.stalemate_scores[colour];701 }702 return [bs, be, alpha];703}704/*p4_make_move changes the state and returns an object containing705 * everything necesary to undo the change.706 *707 * p4_unmake_move uses the p4_make_move return value to restore the708 * previous state.709 */710function p4_make_move(state, s, e, promotion){711 var board = state.board;712 var S = board[s];713 var E = board[e];714 board[e] = S;715 board[s] = 0;716 var piece = S & 14;717 var moved_colour = S & 1;718 var end_piece = S; /* can differ from S in queening*/719 //now some stuff to handle queening, castling720 var rs = 0, re, rook;721 var ep_taken = 0, ep_position;722 var ep = 0;723 if(piece == P4_PAWN){724 if((60 - e) * (60 - e) > 900){725 /*got to end; replace the pawn on board and in pieces cache.*/726 promotion |= moved_colour;727 board[e] = promotion;728 end_piece = promotion;729 }730 else if (((s ^ e) & 1) && E == 0){731 /*this is a diagonal move, but the end spot is empty, so we surmise enpassant */732 ep_position = e - 10 + 20 * moved_colour;733 ep_taken = board[ep_position];734 board[ep_position] = 0;735 }736 else if ((s - e) * (s - e) == 400){737 /*delta is 20 --> two row jump at start*/738 ep = (s + e) >> 1;739 }740 }741 else if (piece == P4_KING && ((s - e) * (s - e) == 4)){ //castling - move rook too742 rs = s - 4 + (s < e) * 7;743 re = (s + e) >> 1; //avg of s,e=rook's spot744 rook = moved_colour + P4_ROOK;745 board[rs] = 0;746 board[re] = rook;747 //piece_locations.push([rook, re]);748 }749 var old_castle_state = state.castles;750 if (old_castle_state){751 var mask = 0;752 var shift = moved_colour * 2;753 var side = moved_colour * 70;754 var s2 = s - side;755 var e2 = e + side;756 //wipe both our sides if king moves757 if (s2 == 25)758 mask |= 3 << shift;759 //wipe one side on any move from rook points760 else if (s2 == 21)761 mask |= 1 << shift;762 else if (s2 == 28)763 mask |= 2 << shift;764 //or on any move *to* opposition corners765 if (e2 == 91)766 mask |= 4 >> shift;767 else if (e2 == 98)768 mask |= 8 >> shift;769 state.castles &= ~mask;770 }771 var old_pieces = state.pieces.concat();772 var our_pieces = old_pieces[moved_colour];773 var dest = state.pieces[moved_colour] = [];774 for (var i = 0; i < our_pieces.length; i++){775 var x = our_pieces[i];776 var pp = x[0];777 var ps = x[1];778 if (ps != s && ps != rs){779 dest.push(x);780 }781 }782 dest.push([end_piece, e]);783 if (rook)784 dest.push([rook, re]);785 if (E || ep_taken){786 var their_pieces = old_pieces[1 - moved_colour];787 dest = state.pieces[1 - moved_colour] = [];788 var gone = ep_taken ? ep_position : e;789 for (i = 0; i < their_pieces.length; i++){790 var x = their_pieces[i];791 if (x[1] != gone){792 dest.push(x);793 }794 }795 }796 return {797 /*some of these (e.g. rook) could be recalculated during798 * unmake, possibly more cheaply. */799 s: s,800 e: e,801 S: S,802 E: E,803 ep: ep,804 castles: old_castle_state,805 rs: rs,806 re: re,807 rook: rook,808 ep_position: ep_position,809 ep_taken: ep_taken,810 pieces: old_pieces811 };812}813function p4_unmake_move(state, move){814 var board = state.board;815 if (move.ep_position){816 board[move.ep_position] = move.ep_taken;817 }818 board[move.s] = move.S;819 board[move.e] = move.E;820 //move.piece_locations.length--;821 if(move.rs){822 board[move.rs] = move.rook;823 board[move.re] = 0;824 //move.piece_locations.length--;825 }826 state.pieces = move.pieces;827 state.castles = move.castles;828}829function p4_insufficient_material(state){830 var knights = false;831 var bishops = undefined;832 var i;833 var board = state.board;834 for(i = 20; i < 100; i++){835 var piece = board[i] & 14;836 if(piece == 0 || piece == P4_KING){837 continue;838 }839 if (piece == P4_KNIGHT){840 /* only allow one knight of either colour, never with a bishop */841 if (knights || bishops !== undefined){842 return false;843 }844 knights = true;845 }846 else if (piece == P4_BISHOP){847 /*any number of bishops, but on only one colour square */848 var x = i & 1;849 var y = parseInt(i / 10) & 1;850 var parity = x ^ y;851 if (knights){852 return false;853 }854 else if (bishops === undefined){855 bishops = parity;856 }857 else if (bishops != parity){858 return false;859 }860 }861 else {862 return false;863 }864 }865 return true;866}867/* p4_move(state, s, e, promotion)868 * s, e are start and end positions869 *870 * promotion is the desired pawn promotion if the move gets a pawn to the other871 * end.872 *873 * return value contains bitwise flags874*/875var P4_MOVE_FLAG_OK = 1;876var P4_MOVE_FLAG_CHECK = 2;877var P4_MOVE_FLAG_MATE = 4;878var P4_MOVE_FLAG_CAPTURE = 8;879var P4_MOVE_FLAG_CASTLE_KING = 16;880var P4_MOVE_FLAG_CASTLE_QUEEN = 32;881var P4_MOVE_FLAG_DRAW = 64;882var P4_MOVE_ILLEGAL = 0;883var P4_MOVE_MISSED_MATE = P4_MOVE_FLAG_CHECK | P4_MOVE_FLAG_MATE;884var P4_MOVE_CHECKMATE = P4_MOVE_FLAG_OK | P4_MOVE_FLAG_CHECK | P4_MOVE_FLAG_MATE;885var P4_MOVE_STALEMATE = P4_MOVE_FLAG_OK | P4_MOVE_FLAG_MATE;886function p4_move(state, s, e, promotion){887 var board = state.board;888 var colour = state.to_play;889 var other_colour = 1 - colour;890 if (s != parseInt(s)){891 if (e === undefined){892 var mv = p4_interpret_movestring(state, s);893 s = mv[0];894 e = mv[1];895 if (s == 0)896 return {flags: P4_MOVE_ILLEGAL, ok: false};897 promotion = mv[2];898 }899 else {/*assume two point strings: 'e2', 'e4'*/900 s = p4_destringify_point(s);901 e = p4_destringify_point(e);902 }903 }904 if (promotion === undefined)905 promotion = P4_QUEEN;906 var E=board[e];907 var S=board[s];908 /*See if this move is even slightly legal, disregarding check.909 */910 var i;911 var legal = false;912 p4_maybe_prepare(state);913 var moves = p4_parse(state, colour, state.enpassant, 0);914 for (i = 0; i < moves.length; i++){915 if (e == moves[i][2] && s == moves[i][1]){916 legal = true;917 break;918 }919 }920 if (! legal) {921 return {flags: P4_MOVE_ILLEGAL, ok: false};922 }923 /*Try the move, and see what the response is.*/924 var changes = p4_make_move(state, s, e, promotion);925 /*is it check? */926 if (p4_check_check(state, colour)){927 p4_unmake_move(state, changes);928 p4_log('in check', changes);929 return {flags: P4_MOVE_ILLEGAL, ok: false, string: "in check!"};930 }931 /*The move is known to be legal. We won't be undoing it.*/932 var flags = P4_MOVE_FLAG_OK;933 state.enpassant = changes.ep;934 state.history.push([s, e, promotion]);935 /*draw timeout: 50 moves without pawn move or capture is a draw */936 if (changes.E || changes.ep_position){937 state.draw_timeout = 0;938 flags |= P4_MOVE_FLAG_CAPTURE;939 }940 else if ((S & 14) == P4_PAWN){941 state.draw_timeout = 0;942 }943 else{944 state.draw_timeout++;945 }946 if (changes.rs){947 flags |= (s > e) ? P4_MOVE_FLAG_CASTLE_QUEEN : P4_MOVE_FLAG_CASTLE_KING;948 }949 var shortfen = p4_state2fen(state, true);950 var repetitions = (state.position_counts[shortfen] || 0) + 1;951 state.position_counts[shortfen] = repetitions;952 state.current_repetitions = repetitions;953 if (state.draw_timeout > 100 || repetitions >= 3 ||954 p4_insufficient_material(state)){955 flags |= P4_MOVE_FLAG_DRAW;956 }957 state.moveno++;958 state.to_play = other_colour;959 if (p4_check_check(state, other_colour)){960 flags |= P4_MOVE_FLAG_CHECK;961 }962 /* check for (stale|check)mate, by seeing if there is a move for963 * the other side that doesn't result in check. (In other words,964 * reduce the pseudo-legal-move list down to a legal-move list,965 * and check it isn't empty).966 *967 * We don't need to p4_prepare because other colour pieces can't968 * have moved (just disappeared) since previous call. Also,969 * setting the promotion piece is unnecessary, because all970 * promotions block check equally well.971 */972 var is_mate = true;973 var replies = p4_parse(state, other_colour, changes.ep, 0);974 for (i = 0; i < replies.length; i++){975 var m = replies[i];976 var change2 = p4_make_move(state, m[1], m[2], P4_QUEEN);977 var check = p4_check_check(state, other_colour);978 p4_unmake_move(state, change2);979 if (!check){980 is_mate = false;981 break;982 }983 }984 if (is_mate)985 flags |= P4_MOVE_FLAG_MATE;986 var movestring = p4_move2string(state, s, e, S, promotion, flags, moves);987 p4_log("successful move", s, e, movestring, flags);988 state.prepared = false;989 return {990 flags: flags,991 string: movestring,992 ok: true993 };994}995function p4_move2string(state, s, e, S, promotion, flags, moves){996 var piece = S & 14;997 var src, dest;998 var mv, i;999 var capture = flags & P4_MOVE_FLAG_CAPTURE;1000 src = p4_stringify_point(s);1001 dest = p4_stringify_point(e);1002 if (piece == P4_PAWN){1003 if (capture){1004 mv = src.charAt(0) + 'x' + dest;1005 }1006 else1007 mv = dest;1008 if (e > 90 || e < 30){ //end row, queening1009 if (promotion === undefined)1010 promotion = P4_QUEEN;1011 mv += '=' + P4_ENCODE_LUT.charAt(promotion);1012 }1013 }1014 else if (piece == P4_KING && (s-e) * (s-e) == 4) {1015 if (e < s)1016 mv = 'O-O-O';1017 else1018 mv = 'O-O';1019 }1020 else {1021 var row_qualifier = '';1022 var col_qualifier = '';1023 var pstr = P4_ENCODE_LUT.charAt(S);1024 var sx = s % 10;1025 var sy = parseInt(s / 10);1026 /* find any other pseudo-legal moves that would put the same1027 * piece in the same place, for which we'd need1028 * disambiguation. */1029 var co_landers = [];1030 for (i = 0; i < moves.length; i++){1031 var m = moves[i];1032 if (e == m[2] && s != m[1] && state.board[m[1]] == S){1033 co_landers.push(m[1]);1034 }1035 }1036 if (co_landers.length){1037 for (i = 0; i < co_landers.length; i++){1038 var c = co_landers[i];1039 var cx = c % 10;1040 var cy = parseInt(c / 10);1041 if (cx == sx)/*same column, so qualify by row*/1042 row_qualifier = src.charAt(1);1043 if (cy == sy)1044 col_qualifier = src.charAt(0);1045 }1046 if (row_qualifier == '' && col_qualifier == ''){1047 /*no co-landers on the same rank or file, so one or the other will do.1048 * By convention, use the column (a-h) */1049 col_qualifier = src.charAt(0);1050 }1051 }1052 mv = pstr + col_qualifier + row_qualifier + (capture ? 'x' : '') + dest;1053 }1054 if (flags & P4_MOVE_FLAG_CHECK){1055 if (flags & P4_MOVE_FLAG_MATE)1056 mv += '#';1057 else1058 mv += '+';1059 }1060 else if (flags & P4_MOVE_FLAG_MATE)1061 mv += ' stalemate';1062 return mv;1063}1064function p4_jump_to_moveno(state, moveno){1065 p4_log('jumping to move', moveno);1066 if (moveno === undefined || moveno > state.moveno)1067 moveno = state.moveno;1068 else if (moveno < 0){1069 moveno = state.moveno + moveno;1070 }1071 var state2 = p4_fen2state(state.beginning);1072 var i = 0;1073 while (state2.moveno < moveno){1074 var m = state.history[i++];1075 p4_move(state2, m[0], m[1], m[2]);1076 }1077 /* copy the replayed state across, not all that deeply, but1078 * enough to cover, eg, held references to board. */1079 var attr, dest;1080 for (attr in state2){1081 var src = state2[attr];1082 if (attr instanceof Array){1083 dest = state[attr];1084 dest.length = 0;1085 for (i = 0; i < src.length; i++){1086 dest[i] = src[i];1087 }1088 }1089 else {1090 state[attr] = src;1091 }1092 }1093 state.prepared = false;1094}1095/* write a standard FEN notation1096 * http://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation1097 * */1098function p4_state2fen(state, reduced){1099 var piece_lut = ' PpRrNnBbKkQq';1100 var board = state.board;1101 var fen = '';1102 //fen does Y axis backwards, X axis forwards */1103 for (var y = 9; y > 1; y--){1104 var count = 0;1105 for (var x = 1; x < 9; x++){1106 var piece = board[y * 10 + x];1107 if (piece == 0)1108 count++;1109 else{1110 if (count)1111 fen += count.toString();1112 fen += piece_lut.charAt(piece);1113 count = 0;1114 }1115 }1116 if (count)1117 fen += count;1118 if (y > 2)1119 fen += '/';1120 }1121 /*white or black */1122 fen += ' ' + 'wb'.charAt(state.to_play) + ' ';1123 /*castling */1124 if (state.castles){1125 var lut = [2, 'K', 1, 'Q', 8, 'k', 4, 'q'];1126 for (var i = 0; i < 8; i += 2){1127 if (state.castles & lut[i]){1128 fen += lut[i + 1];1129 }1130 }1131 }1132 else1133 fen += '-';1134 /*enpassant */1135 if (state.enpassant !== 0){1136 fen += ' ' + p4_stringify_point(state.enpassant);1137 }1138 else1139 fen += ' -';1140 if (reduced){1141 /*if the 'reduced' flag is set, the move number and draw1142 *timeout are not added. This form is used to detect draws by1143 *3-fold repetition.*/1144 return fen;1145 }1146 fen += ' ' + state.draw_timeout + ' ';1147 fen += (state.moveno >> 1) + 1;1148 return fen;1149}1150function p4_stringify_point(p){1151 var letters = " abcdefgh";1152 var x = p % 10;1153 var y = (p - x) / 10 - 1;1154 return letters.charAt(x) + y;1155}1156function p4_destringify_point(p){1157 var x = parseInt(p.charAt(0), 19) - 9; //a-h <-> 10-18, base 191158 var y = parseInt(p.charAt(1)) + 1;1159 if (y >= 2 && y < 10 && x >= 1 && x < 9)1160 return y * 10 + x;1161 return undefined;1162}1163/* read a standard FEN notation1164 * http://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation1165 * */1166function p4_fen2state(fen, state){1167 if (state === undefined)1168 state = p4_initialise_state();1169 var board = state.board;1170 var fenbits = fen.split(' ');1171 var fen_board = fenbits[0];1172 var fen_toplay = fenbits[1];1173 var fen_castles = fenbits[2];1174 var fen_enpassant = fenbits[3];1175 var fen_timeout = fenbits[4];1176 var fen_moveno = fenbits[5];1177 if (fen_timeout === undefined)1178 fen_timeout = 0;1179 //fen does Y axis backwards, X axis forwards */1180 var y = 90;1181 var x = 1;1182 var i;1183 for (var j = 0; j < fen_board.length; j++){1184 var c = fen_board.charAt(j);1185 if (c == '/'){1186 x = 1;1187 y -= 10;1188 if (y < 20)1189 break;1190 continue;1191 }1192 var piece = P4_PIECE_LUT[c];1193 if (piece && x < 9){1194 board[y + x] = piece;1195 x++;1196 }1197 else {1198 var end = Math.min(x + parseInt(c), 9);1199 for (; x < end; x++){1200 board[y + x] = 0;1201 }1202 }1203 }1204 state.to_play = (fen_toplay.toLowerCase() == 'b') ? 1 : 0;1205 state.castles = 0;1206 for (i = 0; i < fen_castles.length; i++){1207 var bit = {k: 8, q: 4, K: 2, Q: 1}[fen_castles.charAt(i)];1208 state.castles |= (bit || 0);1209 }1210 state.enpassant = (fen_enpassant != '-') ? p4_destringify_point(fen_enpassant) : 0;1211 state.draw_timeout = parseInt(fen_timeout);1212 if (fen_moveno === undefined){1213 /*have a guess based on entropy and pieces remaining*/1214 var pieces = 0;1215 var mix = 0;1216 var p, q, r;1217 for (y = 20; y < 100; y+=10){1218 for (x = 1; x < 9; x++){1219 p = board[y + x] & 15;1220 pieces += (!!p);1221 if (x < 8){1222 q = board[y + x + 1];1223 mix += (!q) != (!p);1224 }1225 if (y < 90){1226 q = board[y + x + 10];1227 mix += (!q) != (!p);1228 }1229 }1230 }1231 fen_moveno = Math.max(1, parseInt((32 - pieces) * 1.3 + (4 - fen_castles.length) * 1.5 + ((mix - 16) / 5)));1232 //p4_log("pieces", pieces, "mix", mix, "estimate", fen_moveno);1233 }1234 state.moveno = 2 * (parseInt(fen_moveno) - 1) + state.to_play;1235 state.history = [];1236 state.beginning = fen;1237 state.prepared = false;1238 state.position_counts = {};1239 /* Wrap external functions as methods. */1240 state.move = function(s, e, promotion){1241 return p4_move(this, s, e, promotion);1242 };1243 state.findmove = function(level){1244 return p4_findmove(this, level);1245 };1246 state.jump_to_moveno = function(moveno){1247 return p4_jump_to_moveno(this, moveno);1248 };1249 return state;1250}1251/*1252Weights would all fit within an Int8Array *except* for the last row1253for pawns, which is close to the queen value (180, max is 127).1254Int8Array seems slightly quicker in Chromium 18, no different in1255Firefox 12.1256Int16Array is no faster, perhaps slower than Int32Array.1257Int32Array is marginally slower than plain arrays with Firefox 12, but1258significantly quicker with Chromium.1259 */1260var P4_ZEROS = [];1261function p4_zero_array(){1262 if (P4_USE_TYPED_ARRAYS)1263 return new Int32Array(120);1264 if (P4_ZEROS.length == 0){1265 for(var i = 0; i < 120; i++){1266 P4_ZEROS[i] = 0;1267 }1268 }1269 return P4_ZEROS.slice();1270}1271/* p4_initialise_state() creates the board and initialises weight1272 * arrays etc. Some of this is really only needs to be done once.1273 */1274function p4_initialise_state(){1275 var board = p4_zero_array();1276 P4_CENTRALISING_WEIGHTS = p4_zero_array();1277 P4_BASE_PAWN_WEIGHTS = p4_zero_array();1278 P4_KNIGHT_WEIGHTS = p4_zero_array();1279 for(var i = 0; i < 120; i++){1280 var y = parseInt(i / 10);1281 var x = i % 10;1282 var dx = Math.abs(x - 4.5);1283 var dy = Math.abs(y - 5.5);1284 P4_CENTRALISING_WEIGHTS[i] = parseInt(6 - Math.pow((dx * dx + dy * dy) * 1.5, 0.6));1285 //knights have a flat topped centre (bishops too, but less so).1286 P4_KNIGHT_WEIGHTS[i] = parseInt(((dx < 2) + (dy < 2) * 1.5)1287 + (dx < 3) + (dy < 3)) - 2;1288 P4_BASE_PAWN_WEIGHTS[i] = parseInt('000012347000'.charAt(y));1289 if (y > 9 || y < 2 || x < 1 || x > 8)1290 board[i] = 16;1291 }1292 var weights = [];1293 for (i = 0; i < 14; i++){1294 weights[i] = p4_zero_array();1295 }1296 var state = {1297 board: board,1298 weights: weights,1299 history: [],1300 treeclimber: p4_alphabeta_treeclimber1301 };1302 p4_random_seed(state, P4_DEBUG ? 1 : Date.now());1303 return state;1304}1305function p4_new_game(){1306 return p4_fen2state(P4_INITIAL_BOARD);1307}1308/*convert an arbitrary movestring into a pair of integers offsets into1309 * the board. The string might be in any of these forms:1310 *1311 * "d2-d4" "d2d4" "d4" -- moving a pawn1312 *1313 * "b1-c3" "b1c3" "Nc3" "N1c3" "Nbc3" "Nb1c3" -- moving a knight1314 *1315 * "b1xc3" "b1xc3" "Nxc3" -- moving a knight, also happens to capture.1316 *1317 * "O-O" "O-O-O" -- special cases for castling ("e1-c1", etc, also work)1318 *1319 * Note that for the "Nc3" (pgn) format, some knowledge of the board1320 * is necessary, so the state parameter is required. If it is1321 * undefined, the other forms will still work.1322 */1323function p4_interpret_movestring(state, str){1324 /* Ignore any irrelevant characters, then tokenise.1325 *1326 */1327 var FAIL = [0, 0];1328 var algebraic_re = /^\s*([RNBQK]?[a-h]?[1-8]?)[ :x-]*([a-h][1-8]?)(=[RNBQ])?[!?+#e.p]*\s*$/;1329 var castle_re = /^\s*([O0o]-[O0o](-[O0o])?)\s*$/;1330 var position_re = /^[a-h][1-8]$/;1331 var m = algebraic_re.exec(str);1332 if (m == null){1333 /*check for castling notation (O-O, O-O-O) */1334 m = castle_re.exec(str);1335 if (m){1336 s = 25 + state.to_play * 70;1337 if (m[2])/*queenside*/1338 e = s - 2;1339 else1340 e = s + 2;1341 }1342 else1343 return FAIL;1344 }1345 var src = m[1];1346 var dest = m[2];1347 var queen = m[3];1348 var s, e, q;1349 var moves, i;1350 if (src == '' || src == undefined){1351 /* a single coordinate pawn move */1352 e = p4_destringify_point(dest);1353 s = p4_find_source_point(state, e, 'P' + dest.charAt(0));1354 }1355 else if (/^[RNBQK]/.test(src)){1356 /*pgn format*/1357 e = p4_destringify_point(dest);1358 s = p4_find_source_point(state, e, src);1359 }1360 else if (position_re.test(src) && position_re.test(dest)){1361 s = p4_destringify_point(src);1362 e = p4_destringify_point(dest);1363 }1364 else if (/^[a-h]$/.test(src)){1365 e = p4_destringify_point(dest);1366 s = p4_find_source_point(state, e, 'P' + src);1367 }1368 if (s == 0)1369 return FAIL;1370 if (queen){1371 /* the chosen queen piece */1372 q = P4_PIECE_LUT[queen.charAt(1)];1373 }1374 return [s, e, q];1375}1376function p4_find_source_point(state, e, str){1377 var colour = state.to_play;1378 var piece = P4_PIECE_LUT[str.charAt(0)];1379 piece |= colour;1380 var s, i;1381 var row, column;1382 /* can be specified as Na, Na3, N3, and who knows, N3a? */1383 for (i = 1; i < str.length; i++){1384 var c = str.charAt(i);1385 if (/[a-h]/.test(c)){1386 column = str.charCodeAt(i) - 96;1387 }1388 else if (/[1-8]/.test(c)){1389 /*row goes 2 - 9 */1390 row = 1 + parseInt(c);1391 }1392 }1393 var possibilities = [];1394 p4_prepare(state);1395 var moves = p4_parse(state, colour,1396 state.enpassant, 0);1397 for (i = 0; i < moves.length; i++){1398 var mv = moves[i];1399 if (e == mv[2]){1400 s = mv[1];1401 if (state.board[s] == piece &&1402 (column === undefined || column == s % 10) &&1403 (row === undefined || row == parseInt(s / 10))1404 ){1405 var change = p4_make_move(state, s, e, P4_QUEEN);1406 if (! p4_check_check(state, colour))1407 possibilities.push(s);1408 p4_unmake_move(state, change);1409 }1410 }1411 }1412 p4_log("finding", str, "that goes to", e, "got", possibilities);1413 if (possibilities.length == 0){1414 return 0;1415 }1416 else if (possibilities.length > 1){1417 p4_log("p4_find_source_point seems to have failed",1418 state, e, str,1419 possibilities);1420 }1421 return possibilities[0];1422}1423/*random number generator based on1424 * http://burtleburtle.net/bob/rand/smallprng.html1425 */1426function p4_random_seed(state, seed){1427 seed &= 0xffffffff;1428 state.rng = (P4_USE_TYPED_ARRAYS) ? new Uint32Array(4) : [];1429 state.rng[0] = 0xf1ea5eed;1430 state.rng[1] = seed;1431 state.rng[2] = seed;1432 state.rng[3] = seed;1433 for (var i = 0; i < 20; i++)1434 p4_random31(state);1435}1436function p4_random31(state){1437 var rng = state.rng;1438 var b = rng[1];1439 var c = rng[2];1440 /* These shifts amount to rotates.1441 * Note the three-fold right shift '>>>', meaning an unsigned shift.1442 * The 0xffffffff masks are needed to keep javascript to 32bit. (supposing1443 * untyped arrays).1444 */1445 var e = rng[0] - ((b << 27) | (b >>> 5));1446 rng[0] = b ^ ((c << 17) | (c >>> 15));1447 rng[1] = (c + rng[3]) & 0xffffffff;1448 rng[2] = (rng[3] + e) & 0xffffffff;1449 rng[3] = (e + rng[0]) & 0xffffffff;1450 return rng[3] & 0x7fffffff;1451}1452function p4_random_int(state, top){1453 /* uniform integer in range [0 < n < top), supposing top < 2 ** 311454 *1455 * This method is slightly (probably pointlessly) more accurate1456 * than converting to 0-1 float, multiplying and truncating, and1457 * considerably more accurate than a simple modulus.1458 * Obviously it is a bit slower.1459 */1460 /* mask becomes one less than the next highest power of 2 */1461 var mask = top;1462 mask--;1463 mask |= mask >>> 1;1464 mask |= mask >>> 2;1465 mask |= mask >>> 4;1466 mask |= mask >>> 8;1467 mask |= mask >>> 16;1468 var r;1469 do{1470 r = p4_random31(state) & mask;1471 } while (r >= top);1472 return r;...

Full Screen

Full Screen

view_utils.d.ts

Source:view_utils.d.ts Github

copy

Full Screen

1import { SanitizationService } from '../security';2import { RootRenderer, RenderComponentType, Renderer } from '../render/api';3import { ViewEncapsulation } from '../metadata/view';4export declare class ViewUtils {5 private _renderer;6 private _appId;7 sanitizer: SanitizationService;8 private _nextCompTypeId;9 constructor(_renderer: RootRenderer, _appId: string, sanitizer: SanitizationService);10 /**11 * Used by the generated code12 */13 createRenderComponentType(templateUrl: string, slotCount: number, encapsulation: ViewEncapsulation, styles: Array<string | any[]>): RenderComponentType;14 /** @internal */15 renderComponent(renderComponentType: RenderComponentType): Renderer;16}17export declare function flattenNestedViewRenderNodes(nodes: any[]): any[];18export declare function ensureSlotCount(projectableNodes: any[][], expectedSlotCount: number): any[][];19export declare const MAX_INTERPOLATION_VALUES: number;20export declare function interpolate(valueCount: number, c0: string, a1: any, c1: string, a2?: any, c2?: string, a3?: any, c3?: string, a4?: any, c4?: string, a5?: any, c5?: string, a6?: any, c6?: string, a7?: any, c7?: string, a8?: any, c8?: string, a9?: any, c9?: string): string;21export declare function checkBinding(throwOnChange: boolean, oldValue: any, newValue: any): boolean;22export declare function arrayLooseIdentical(a: any[], b: any[]): boolean;23export declare function mapLooseIdentical<V>(m1: {24 [key: string]: V;25}, m2: {26 [key: string]: V;27}): boolean;28export declare function castByValue<T>(input: any, value: T): T;29export declare const EMPTY_ARRAY: any[];30export declare const EMPTY_MAP: {};31export declare function pureProxy1<P0, R>(fn: (p0: P0) => R): (p0: P0) => R;32export declare function pureProxy2<P0, P1, R>(fn: (p0: P0, p1: P1) => R): (p0: P0, p1: P1) => R;33export declare function pureProxy3<P0, P1, P2, R>(fn: (p0: P0, p1: P1, p2: P2) => R): (p0: P0, p1: P1, p2: P2) => R;34export declare function pureProxy4<P0, P1, P2, P3, R>(fn: (p0: P0, p1: P1, p2: P2, p3: P3) => R): (p0: P0, p1: P1, p2: P2, p3: P3) => R;35export declare function pureProxy5<P0, P1, P2, P3, P4, R>(fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) => R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) => R;36export declare function pureProxy6<P0, P1, P2, P3, P4, P5, R>(fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) => R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) => R;37export declare function pureProxy7<P0, P1, P2, P3, P4, P5, P6, R>(fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) => R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) => R;38export declare function pureProxy8<P0, P1, P2, P3, P4, P5, P6, P7, R>(fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) => R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) => R;39export declare function pureProxy9<P0, P1, P2, P3, P4, P5, P6, P7, P8, R>(fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) => R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) => R;...

Full Screen

Full Screen

test.js

Source:test.js Github

copy

Full Screen

1//测试用2//搭建舞台3var app = new PIXI.Application({4 width: 750,5 height: 1440,6 backgroundColor:0xffbd3e7});8$('#app').append(app.view);9//资源加载10app.loader11.add([12 {name:'zkkl',url:'./fonts/zkkl.ttf'},13 {name:'p1_01',url:'./images/p1_01.png'},14 {name:'p1_02',url:'./images/p1_02.png'},15 {name:'p1_03',url:'./images/p1_03.png'},16 {name:'p1_04',url:'./images/p1_04.png'},17 {name:'p2_01',url:'./images/p2_01.png'},18 {name:'p2_02',url:'./images/p2_02.png'},19 {name:'p2_03',url:'./images/p2_03.png'},20 {name:'p3_01',url:'./images/p3_01.png'},21 {name:'p3_02',url:'./images/p3_02.png'},22 {name:'p3_03',url:'./images/p3_03.png'},23 {name:'p3_04',url:'./images/p3_04.png'},24 {name:'p3_black_car',url:'./images/p3_black_car.png'},25 {name:'p3_red_car',url:'./images/p3_red_car.png'},26 {name:'p3_white_car',url:'./images/p3_white_car.png'},27 {name:'p3_yellow_car',url:'./images/p3_yellow_car.png'},28 {name:'p4_01',url:'./images/p4_01.png'},29 {name:'p4_02',url:'./images/p4_02.png'},30 {name:'p4_03',url:'./images/p4_03.png'},31 {name:'p4_barrier_1',url:'./images/p4_barrier_1.png'},32 {name:'p4_barrier_2',url:'./images/p4_barrier_2.png'},33 {name:'p4_barrier_3',url:'./images/p4_barrier_3.png'},34 {name:'p4_barrier_4',url:'./images/p4_barrier_4.png'},35 {name:'p4_black_car',url:'./images/p4_black_car.png'},36 {name:'p4_red_car',url:'./images/p4_red_car.png'},37 {name:'p4_white_car',url:'./images/p4_white_car.png'},38 {name:'p4_yellow_car',url:'./images/p4_yellow_car.png'},39 {name:'p4_lane',url:'./images/p4_lane.png'},40 {name:'p4_left_btn',url:'./images/p4_left_btn.png'},41 {name:'p4_right_btn',url:'./images/p4_right_btn.png'},42])43.load(setup)44.on('progress',(loader, res)=>{45 var progress = parseInt(loader.progress);46 console.log(progress);47});48function setup(loader, res){49 console.log('加载完成');...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const { p4 } = require('fast-check-monorepo')2p4()3const { p5 } = require('fast-check-monorepo')4p5()5const { p6 } = require('fast-check-monorepo')6p6()7const { p7 } = require('fast-check-monorepo')8p7()9const { p8 } = require('fast-check-monorepo')10p8()11const { p9 } = require('fast-check-monorepo')12p9()13const { p10 } = require('fast-check-monorepo')14p10()15const { p11 } = require('fast-check-monorepo')16p11()17const { p12 } = require('fast-check-monorepo')18p12()19const { p13 } = require('fast-check-monorepo')20p13()21const { p14 } = require('fast-check-monorepo')22p14()23const { p15 } = require('fast-check-monorepo')24p15()25const { p16 } = require('fast-check-monorepo')26p16()27const { p17 } = require('fast-check-monorepo')28p17()29const { p18 } = require('fast-check-monorepo')30p18()31const { p19 } = require('fast-check-monorepo')32p19()33const {

Full Screen

Using AI Code Generation

copy

Full Screen

1import * as fc from 'fast-check';2const p4 = require('p4');3fc.assert(4 fc.property(fc.integer(), fc.integer(), (a, b) => {5 const sum = p4.add(a, b);6 return sum === a + b;7 })8);9{10 "scripts": {11 },12 "dependencies": {13 }14}15{16 "scripts": {17 },18 "dependencies": {19 }20}21{22 "scripts": {23 },24 "dependencies": {25 }26}

Full Screen

Using AI Code Generation

copy

Full Screen

1const {p4} = require('fast-check-monorepo');2describe('p4', () => {3 it('should always pass', () => {4 fc.assert(5 fc.property(p4(), (v) => {6 return true;7 })8 );9 });10});11{12 "scripts": {13 },14 "dependencies": {15 }16}

Full Screen

Using AI Code Generation

copy

Full Screen

1const p4 = require('fast-check-monorepo/src/p4.js');2const fc = require('fast-check');3const { p4: p4Arb } = require('fast-check-monorepo/src/arbitrary/p4.js');4const p4Arb = p4Arb();5fc.assert(6 fc.property(p4Arb, (p4) => {7 return p4.length === 4;8 })9);10{11 "dependencies": {12 }13}14const p4 = require('fast-check-monorepo/src/p4.js');15const fc = require('fast-check');16const { p4: p4Arb } = require('fast-check-monorepo/src/arbitrary/p4.js');17const p4Arb = p4Arb();18fc.assert(19 fc.property(p4Arb, (p4) => {20 return p4.length === 4;21 })22);23I am trying to import the fast-check-monorepo package in my test.js file. I have tried 3 different approaches and none of them work:

Full Screen

Using AI Code Generation

copy

Full Screen

1const p4 = require('fast-check-monorepo').p42const fc = require('fast-check')3fc.assert(fc.property(fc.integer(), (i) => i === i))4p4()5const fc = require('fast-check')6const p4 = require('fast-check').p47fc.assert(fc.property(fc.integer(), (i) => i === i))8p4()

Full Screen

Using AI Code Generation

copy

Full Screen

1const { p4 } = require('fast-check');2const { run } = require('p4js');3const { pipe } = require('fp-ts/lib/function');4const p4Arbitrary = p4(arbitrary => {5 return pipe(6 arbitrary.string(),7 arbitrary.map(s => s.length)8 );9});10describe('p4', () => {11 it('should work', () => {12 expect(run(p4Arbitrary)).toEqual(2);13 });14});

Full Screen

Using AI Code Generation

copy

Full Screen

1const fc = require('fast-check');2const p4 = require('fast-check-monorepo').p4;3const randomArray = fc.array(fc.integer());4const sort = (a, b) => a - b;5const sortedArray = fc.array(fc.integer()).map(a => a.sort(sort));6fc.assert(7 fc.property(randomArray, a => {8 const b = p4(a);9 b.sort(sort);10 return sortedArray.is(b);11 })12);13const fc = require('fast-check');14const p4 = require('fast-check-monorepo').p4;15const randomArray = fc.array(fc.integer());16const sort = (a, b) => a - b;17const sortedArray = fc.array(fc.integer()).map(a => a.sort(sort));18fc.assert(19 fc.property(randomArray, a => {20 const b = p4(a);21 b.sort(sort);22 return sortedArray.is(b);23 })24);25const fc = require('fast-check');26const p4 = require('fast-check-monorepo').p4;27const randomArray = fc.array(fc.integer());28const sort = (a, b) => a - b;29const sortedArray = fc.array(fc.integer()).map(a => a.sort(sort));30fc.assert(31 fc.property(randomArray, a => {32 const b = p4(a);33 b.sort(sort);34 return sortedArray.is(b);35 })36);37const fc = require('fast-check');38const p4 = require('fast-check-monorepo').p4;39const randomArray = fc.array(fc.integer());40const sort = (a, b) => a - b;41const sortedArray = fc.array(fc.integer()).map(a => a.sort(sort));42fc.assert(43 fc.property(randomArray, a => {44 const b = p4(a);45 b.sort(sort);46 return sortedArray.is(b);

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run fast-check-monorepo automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful