Repository navigation
Expand file tree
/
Copy pathtest_engine.js
More file actions
136 lines (124 loc) · 8.26 KB
/
Copy pathtest_engine.js
File metadata and controls
136 lines (124 loc) · 8.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Тесты движка русских шашек: вырезаем чистые функции из HTML
const fs = require('fs');
const html = fs.readFileSync(require('path').join(__dirname,'checkers.html'), 'utf8');
const js = html.match(/<script>([\s\S]*)<\/script>/)[1];
// Берём только движок: от маркера до объявления состояния G
const start = js.indexOf('// ── Движок шашек ──');
const end = js.indexOf('let G={');
const engine = js.slice(start, end);
const ctx = {};
new Function(`
${engine}
return {cloneBoard,getCaptures,rawCaptures,getAllMoves,applyCapture,applyNormal,removeBeaten,checkEnd,isKing};
`).call(null) && Object.assign(ctx, new Function(`
${engine}
return {cloneBoard,getCaptures,rawCaptures,getAllMoves,applyCapture,applyNormal,removeBeaten,checkEnd,isKing};
`)());
const {getCaptures, getAllMoves, applyCapture, removeBeaten} = ctx;
function emptyBoard(){ return Array.from({length:8},()=>new Array(8).fill(0)); }
let pass=0, fail=0;
function check(name, cond){
if(cond){pass++;console.log(' ✓ '+name);}
else{fail++;console.log(' ✗ FAIL: '+name);}
}
// ─────────────────────────────────────────────
console.log('ТЕСТ 1: Простая бьёт во все 4 стороны (база)');
{
const b=emptyBoard();
b[4][3]=1; // белая простая
b[3][2]=-1; // чёрная спереди-слева
b[5][4]=-1; // чёрная сзади-справа
const caps=getCaptures(b,4,3,[]);
check('два взятия (вперёд и назад)', caps.length===2);
check('есть взятие назад', caps.some(m=>m.to.r===6&&m.to.c===5));
}
// ─────────────────────────────────────────────
console.log('ТЕСТ 2: Турецкий удар — побитая шашка не снимается до конца серии и блокирует дамку');
{
// Белая дамка на (7,0). Чёрные на (5,2) и (2,5) на одной диагонали.
// Дамка бьёт (5,2), встаёт, бьёт (2,5)... потом по этой же диагонали
// вернуться через побитую (5,2) нельзя.
const b=emptyBoard();
b[7][0]=2; // белая дамка
b[5][2]=-1; // чёрная 1
b[3][4]=-1; // чёрная 2 — после взятия первой дамка с (4,3) может бить дальше
// взятие 1
const caps1=getCaptures(b,7,0,[]);
check('первое взятие найдено', caps1.length>0);
const m1=caps1.find(m=>m.cap.r===5&&m.cap.c===2);
check('бьём шашку (5,2)', !!m1);
applyCapture(b,m1);
check('побитая шашка ОСТАЛАСЬ на доске (турецкий удар)', b[5][2]===-1);
const beaten=['5,2'];
// продолжение: нельзя бить (5,2) повторно
const caps2=getCaptures(b,m1.to.r,m1.to.c,beaten);
check('повторное взятие той же шашки запрещено', !caps2.some(m=>m.cap.r===5&&m.cap.c===2));
// и дамка не может пролететь СКВОЗЬ побитую: тихих ходов мы не проверяем
// в середине боя, но взятие "через" неё невозможно — направление через (5,2) обрублено
removeBeaten(b,['5,2','3,4']);
check('removeBeaten снимает шашки', b[5][2]===0 && b[3][4]===0);
}
// ─────────────────────────────────────────────
console.log('ТЕСТ 3: Дамка не может перепрыгнуть побитую шашку, чтобы взять следующую за ней');
{
// Дамка (7,0); чёрные (5,2) и (3,4) на одной диагонали с зазором (4,3).
// Бьём (5,2), встаём на (4,3) — теперь следующая (3,4) рядом. ОК.
// Но если встать на (4,3) нельзя пропустить и сразу взять (3,4) с (7,0):
const b=emptyBoard();
b[7][0]=2; b[5][2]=-1; b[3][4]=-1;
const caps=getCaptures(b,7,0,[]);
// с (7,0) можно бить только (5,2) — первая встречная; (3,4) недостижима
check('бьётся только первая шашка на луче', caps.every(m=>m.cap.r===5&&m.cap.c===2));
}
// ─────────────────────────────────────────────
console.log('ТЕСТ 4: Дамка обязана встать на поле, с которого продолжается бой');
{
// Дамка (7,0) бьёт чёрную (5,2). Поля за ней: (4,3),(3,4),(2,5),(1,6),(0,7).
// Вторая чёрная на (3,6): бой продолжается ТОЛЬКО с поля (4,3)? Проверим:
// с (4,3) можно бить (3,6)? Нет, не на одной диагонали...
// Поставим вторую чёрную на (2,3): с (3,4)? (3,4)->(2,3) диагональ вверх-влево, за ней (1,2) пусто => бой с (3,4).
// С (4,3): (2,3) не на диагонали от (4,3)? (4,3)->(3,2)->(2,1): нет. (4,3)->(3,4)->(2,5): нет. Не бьёт.
const b=emptyBoard();
b[7][0]=2; b[5][2]=-1; b[2][3]=-1;
const caps=getCaptures(b,7,0,[]);
check('варианты взятия есть', caps.length>0);
check('все варианты ведут на поле с продолжением боя: только (3,4)',
caps.length===1 && caps[0].to.r===3 && caps[0].to.c===4);
}
// ─────────────────────────────────────────────
console.log('ТЕСТ 5: Превращение в дамку посреди боя — серия продолжается дамкой');
{
// Белая простая (2,1). Чёрная (1,2): бьём -> попадаем на (0,3) = дамочное поле.
// Ещё чёрная на (1,4): после превращения дамка с (0,3) обязана бить дальше.
const b=emptyBoard();
b[2][1]=1; b[1][2]=-1; b[1][4]=-1;
const caps=getCaptures(b,2,1,[]);
const m=caps.find(x=>x.to.r===0&&x.to.c===3);
check('взятие с выходом на дамочное поле', !!m);
applyCapture(b,m);
check('шашка превратилась в дамку', b[0][3]===2);
const further=getCaptures(b,0,3,['1,2']);
check('новая дамка видит продолжение боя', further.length>0);
check('продолжение бьёт шашку (1,4)', further.some(x=>x.cap.r===1&&x.cap.c===4));
}
// ─────────────────────────────────────────────
console.log('ТЕСТ 6: Обязательность боя сохранилась');
{
const b=emptyBoard();
b[5][2]=1; b[4][3]=-1; b[5][6]=1; // у (5,2) есть взятие, у (5,6) только тихий ход
const all=getAllMoves(b,1);
check('возвращаются только взятия', all.every(m=>m.cap!==null));
check('тихие ходы шашки (5,6) скрыты', !all.some(m=>m.from.r===5&&m.from.c===6));
}
// ─────────────────────────────────────────────
console.log('ТЕСТ 7: Простая НЕ может приземлиться на побитую шашку');
{
// Белая (4,3) бьёт чёрную (3,2) -> приземление (2,1). Если (2,1) занята побитой — нельзя.
const b=emptyBoard();
b[4][3]=1; b[3][2]=-1; b[2][1]=-1; // (2,1) занята живой чёрной — взятие (3,2) невозможно
const caps=getCaptures(b,4,3,[]);
check('взятие с занятым полем приземления невозможно', !caps.some(m=>m.cap.r===3&&m.cap.c===2));
}
console.log('\\n──────────────');
console.log('Пройдено: '+pass+', провалено: '+fail);
process.exit(fail?1:0);