Ключевое слово
19 | 04 | 2024
Новости Библиотеки
Шахматы Онлайн
Welcome, Guest
Username: Password: Remember me

TOPIC: Bitboard в программировании шахмат №2

Bitboard в программировании шахмат 28 Нояб 2022 08:34 #61

  • Vladimirovich
  • Vladimirovich's Avatar
  • OFFLINE
  • Инквизитор
  • Posts: 106785
  • Thank you received: 2073
  • Karma: 105
Ruslan73 wrote:
Я так понимаю автора как раз интересует как битовыми операциями найти этого ближайшего к ладье коня на линии d и отсечь оставшиеся поля.
Не вопрос. Одна битовая 64-маска - наличие фигуры вообще
Вторая цвет.
Т.е найти коня просто. Притом определить, надо ли включать d6 в маску запрещения или нет.
Отсечь сложнее

Но вроде все операции битовые тут есть
github.com/official-stockfish/Stockfish/...aster/src/bitboard.h
Никаких циклов

Надо адаптировать под свой язык разве.
Каждому - своё.

Bitboard в программировании шахмат 28 Нояб 2022 08:37 #62

  • Ruslan73
  • Ruslan73's Avatar
  • OFFLINE
  • Администратор
  • Posts: 35559
  • Thank you received: 757
  • Karma: 56
Vladimirovich wrote:
Т.е найти коня просто.
Если он 1 на линии d да, а если на d5 белый слоник, на d7 черная пешка на d8 черный ферзь, то надо как-то понять что ладья ничего не берёт.
Я про это.
alexlaw wrote:
www.pvsm.ru/game-development/17378?utm_s...=l9zgbf9nj6679415818
Если вы внимательно читали эту статью то поймете о чем я говорю.
Никак не читал ещё. За ссылку спасибо, вечерком посмотрю.
Свободу Джулиану Ассанжу!
Last Edit: 28 Нояб 2022 08:38 by Ruslan73.

Bitboard в программировании шахмат 28 Нояб 2022 10:29 #63

  • Vladimirovich
  • Vladimirovich's Avatar
  • OFFLINE
  • Инквизитор
  • Posts: 106785
  • Thank you received: 2073
  • Karma: 105
Ruslan73 wrote:
Если он 1 на линии d да, а если на d5 белый слоник, на d7 черная пешка на d8 черный ферзь, то надо как-то понять что ладья ничего не берёт.
Я про это.
Ну да, белая фигура по ходу должна резать все, что за ней. - красные клетки на картинке ранее
Точную битовую формулу сейчас крайне лень писать, должно быть построено на битовых сдвигах в направлении, но в хедере воблы все должно быть.
Каждому - своё.

Bitboard в программировании шахмат 29 Нояб 2022 16:27 #64

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Первый шаг к вращаемым bitbord - FirstRankAttacks256x8
Атаки первого ранга (атаки по одной горизонтали)
Предположим, что мы (временно) уменьшаем шахматную доску до одного разряда (биты 0-7). Занятость битовой маски составляет один байт с 256 различными состояниями бит. Атака ладьи с одного из восьми полей на этой одиночной горизонтали также составляет всего один байт. Таким образом, мы можем создать массив байтов[256][8], проиндексированный по всем 256 занятиям полей фигурами и одном из 8 положением ладьи и предварительно рассчитать атаку этой ладьи по этой горизонтали.
BYTE arrFirstRankAttacks256x8[256][8]; // 2048 Bytes = 2KByte
Теперь для нахождения атаки ладьи достаточно просто обратиться к массиву arrFirstRankAttacks256x8[256][8], где первый индекс расположение фигур на горизонтали, второй индекс положение ладьи.
firstRankAttack = arrFirstRankAttacks256x8[rankOccupancy][squareOnRank];
Вроде все понятно и реализовывается просто.
Тестовая прога
В статье сказано, что что внешние квадраты не имеют значения (крайние биты) и массива [64][8] вполне достаточно для реализации идеи предварительного расчета атак ладьи и получения этих атак простым обращением к массиву -
BYTE arrFirstRankAttacks64x8[64][8]; // 512 Bytes = 1/2KByte
К сожаление у меня не получилось использовать массив [64][8];
Как это сделать пока не соображу(
Last Edit: 29 Нояб 2022 23:01 by alexlaw.

Bitboard в программировании шахмат 30 Нояб 2022 10:51 #65

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
alexlaw wrote:
Как это сделать пока не соображу(
Получилось)
Агоритм такой:
1. Цикл1 i := 0 to 63 //всевозможные комбинации расположурия фигур (игнорируем первый и последний бит горизонтали
2. Цикл2 j := 0 to 7 //поз белой ладьи, 0 и 7 ладья расположена на краях горизонтали
3. AllPiece(все фигуры на горизонтали) << 1(сдвигаем на 1 бит в сторону LSB (Наименьший значащий бит))
4. Находим линию атаки от позиции ладьи до ближайших фигур для (AllPiece<<1) и объеденяем их операцией OR
5. Для позиций ладьи 0 и 7 атаки находим для AllPiece без исключения позиции ладьи (ладья атакует сама себя)
При других индексах позиции ладьи исключаем ее (ладья НЕ атакует сама себя)
6. заполняем массив arrFirstRankAttacks64x8[64][8]
Массив arrFirstRankAttacks64x8[64][8] заполняется один раз при запуске программы

Получение значений массива в зависимости от положения фигур и ладьи
1.n=arrFirstRankAttacks64x8[(AllPiece >> 1) & 63][squareOnRank]
где squareOnRank - позиция ладьи
AllPiece - битовая маска всех фигур на горизонтали

Тестовая прога

Вывод массива arrFirstRankAttacks64x8 в файл:
1: i=0, j=0: 254
2: i=0, j=1: 2
3: i=0, j=2: 4
4: i=0, j=3: 8
5: i=0, j=4: 16
6: i=0, j=5: 32
7: i=0, j=6: 64
8: i=0, j=7: 127
9: i=1, j=0: 2
10: i=1, j=1: 253
11: i=1, j=2: 4
12: i=1, j=3: 8
13: i=1, j=4: 16
14: i=1, j=5: 32
15: i=1, j=6: 64
16: i=1, j=7: 126
17: i=2, j=0: 6
18: i=2, j=1: 2
19: i=2, j=2: 251
20: i=2, j=3: 8
21: i=2, j=4: 16
22: i=2, j=5: 32
23: i=2, j=6: 64
24: i=2, j=7: 124
25: i=3, j=0: 2
26: i=3, j=1: 5
27: i=3, j=2: 250
28: i=3, j=3: 8
29: i=3, j=4: 16
30: i=3, j=5: 32
31: i=3, j=6: 64
32: i=3, j=7: 124
33: i=4, j=0: 14
34: i=4, j=1: 2
35: i=4, j=2: 4
36: i=4, j=3: 247
37: i=4, j=4: 16
38: i=4, j=5: 32
39: i=4, j=6: 64
40: i=4, j=7: 120
41: i=5, j=0: 2
42: i=5, j=1: 13
43: i=5, j=2: 4
44: i=5, j=3: 246
45: i=5, j=4: 16
46: i=5, j=5: 32
47: i=5, j=6: 64
48: i=5, j=7: 120
49: i=6, j=0: 6
50: i=6, j=1: 2
51: i=6, j=2: 11
52: i=6, j=3: 244
53: i=6, j=4: 16
54: i=6, j=5: 32
55: i=6, j=6: 64
56: i=6, j=7: 120
57: i=7, j=0: 2
58: i=7, j=1: 5
59: i=7, j=2: 10
60: i=7, j=3: 244
61: i=7, j=4: 16
62: i=7, j=5: 32
63: i=7, j=6: 64
64: i=7, j=7: 120
65: i=8, j=0: 30
66: i=8, j=1: 2
67: i=8, j=2: 4
68: i=8, j=3: 8
69: i=8, j=4: 239
70: i=8, j=5: 32
71: i=8, j=6: 64
72: i=8, j=7: 112
73: i=9, j=0: 2
74: i=9, j=1: 29
75: i=9, j=2: 4
76: i=9, j=3: 8
77: i=9, j=4: 238
78: i=9, j=5: 32
79: i=9, j=6: 64
80: i=9, j=7: 112
81: i=10, j=0: 6
82: i=10, j=1: 2
83: i=10, j=2: 27
84: i=10, j=3: 8
85: i=10, j=4: 236
86: i=10, j=5: 32
87: i=10, j=6: 64
88: i=10, j=7: 112
89: i=11, j=0: 2
90: i=11, j=1: 5
91: i=11, j=2: 26
92: i=11, j=3: 8
93: i=11, j=4: 236
94: i=11, j=5: 32
95: i=11, j=6: 64
96: i=11, j=7: 112
97: i=12, j=0: 14
98: i=12, j=1: 2
99: i=12, j=2: 4
100: i=12, j=3: 23
101: i=12, j=4: 232
102: i=12, j=5: 32
103: i=12, j=6: 64
104: i=12, j=7: 112
105: i=13, j=0: 2
106: i=13, j=1: 13
107: i=13, j=2: 4
108: i=13, j=3: 22
109: i=13, j=4: 232
110: i=13, j=5: 32
111: i=13, j=6: 64
112: i=13, j=7: 112
113: i=14, j=0: 6
114: i=14, j=1: 2
115: i=14, j=2: 11
116: i=14, j=3: 20
117: i=14, j=4: 232
118: i=14, j=5: 32
119: i=14, j=6: 64
120: i=14, j=7: 112
121: i=15, j=0: 2
122: i=15, j=1: 5
123: i=15, j=2: 10
124: i=15, j=3: 20
125: i=15, j=4: 232
126: i=15, j=5: 32
127: i=15, j=6: 64
128: i=15, j=7: 112
129: i=16, j=0: 62
130: i=16, j=1: 2
131: i=16, j=2: 4
132: i=16, j=3: 8
133: i=16, j=4: 16
134: i=16, j=5: 223
135: i=16, j=6: 64
136: i=16, j=7: 96
137: i=17, j=0: 2
138: i=17, j=1: 61
139: i=17, j=2: 4
140: i=17, j=3: 8
141: i=17, j=4: 16
142: i=17, j=5: 222
143: i=17, j=6: 64
144: i=17, j=7: 96
145: i=18, j=0: 6
146: i=18, j=1: 2
147: i=18, j=2: 59
148: i=18, j=3: 8
149: i=18, j=4: 16
150: i=18, j=5: 220
151: i=18, j=6: 64
152: i=18, j=7: 96
153: i=19, j=0: 2
154: i=19, j=1: 5
155: i=19, j=2: 58
156: i=19, j=3: 8
157: i=19, j=4: 16
158: i=19, j=5: 220
159: i=19, j=6: 64
160: i=19, j=7: 96
161: i=20, j=0: 14
162: i=20, j=1: 2
163: i=20, j=2: 4
164: i=20, j=3: 55
165: i=20, j=4: 16
166: i=20, j=5: 216
167: i=20, j=6: 64
168: i=20, j=7: 96
169: i=21, j=0: 2
170: i=21, j=1: 13
171: i=21, j=2: 4
172: i=21, j=3: 54
173: i=21, j=4: 16
174: i=21, j=5: 216
175: i=21, j=6: 64
176: i=21, j=7: 96
177: i=22, j=0: 6
178: i=22, j=1: 2
179: i=22, j=2: 11
180: i=22, j=3: 52
181: i=22, j=4: 16
182: i=22, j=5: 216
183: i=22, j=6: 64
184: i=22, j=7: 96
185: i=23, j=0: 2
186: i=23, j=1: 5
187: i=23, j=2: 10
188: i=23, j=3: 52
189: i=23, j=4: 16
190: i=23, j=5: 216
191: i=23, j=6: 64
192: i=23, j=7: 96
193: i=24, j=0: 30
194: i=24, j=1: 2
195: i=24, j=2: 4
196: i=24, j=3: 8
197: i=24, j=4: 47
198: i=24, j=5: 208
199: i=24, j=6: 64
200: i=24, j=7: 96
201: i=25, j=0: 2
202: i=25, j=1: 29
203: i=25, j=2: 4
204: i=25, j=3: 8
205: i=25, j=4: 46
206: i=25, j=5: 208
207: i=25, j=6: 64
208: i=25, j=7: 96
209: i=26, j=0: 6
210: i=26, j=1: 2
211: i=26, j=2: 27
212: i=26, j=3: 8
213: i=26, j=4: 44
214: i=26, j=5: 208
215: i=26, j=6: 64
216: i=26, j=7: 96
217: i=27, j=0: 2
218: i=27, j=1: 5
219: i=27, j=2: 26
220: i=27, j=3: 8
221: i=27, j=4: 44
222: i=27, j=5: 208
223: i=27, j=6: 64
224: i=27, j=7: 96
225: i=28, j=0: 14
226: i=28, j=1: 2
227: i=28, j=2: 4
228: i=28, j=3: 23
229: i=28, j=4: 40
230: i=28, j=5: 208
231: i=28, j=6: 64
232: i=28, j=7: 96
233: i=29, j=0: 2
234: i=29, j=1: 13
235: i=29, j=2: 4
236: i=29, j=3: 22
237: i=29, j=4: 40
238: i=29, j=5: 208
239: i=29, j=6: 64
240: i=29, j=7: 96
241: i=30, j=0: 6
242: i=30, j=1: 2
243: i=30, j=2: 11
244: i=30, j=3: 20
245: i=30, j=4: 40
246: i=30, j=5: 208
247: i=30, j=6: 64
248: i=30, j=7: 96
249: i=31, j=0: 2
250: i=31, j=1: 5
251: i=31, j=2: 10
252: i=31, j=3: 20
253: i=31, j=4: 40
254: i=31, j=5: 208
255: i=31, j=6: 64
256: i=31, j=7: 96
257: i=32, j=0: 126
258: i=32, j=1: 2
259: i=32, j=2: 4
260: i=32, j=3: 8
261: i=32, j=4: 16
262: i=32, j=5: 32
263: i=32, j=6: 191
264: i=32, j=7: 64
265: i=33, j=0: 2
266: i=33, j=1: 125
267: i=33, j=2: 4
268: i=33, j=3: 8
269: i=33, j=4: 16
270: i=33, j=5: 32
271: i=33, j=6: 190
272: i=33, j=7: 64
273: i=34, j=0: 6
274: i=34, j=1: 2
275: i=34, j=2: 123
276: i=34, j=3: 8
277: i=34, j=4: 16
278: i=34, j=5: 32
279: i=34, j=6: 188
280: i=34, j=7: 64
281: i=35, j=0: 2
282: i=35, j=1: 5
283: i=35, j=2: 122
284: i=35, j=3: 8
285: i=35, j=4: 16
286: i=35, j=5: 32
287: i=35, j=6: 188
288: i=35, j=7: 64
289: i=36, j=0: 14
290: i=36, j=1: 2
291: i=36, j=2: 4
292: i=36, j=3: 119
293: i=36, j=4: 16
294: i=36, j=5: 32
295: i=36, j=6: 184
296: i=36, j=7: 64
297: i=37, j=0: 2
298: i=37, j=1: 13
299: i=37, j=2: 4
300: i=37, j=3: 118
301: i=37, j=4: 16
302: i=37, j=5: 32
303: i=37, j=6: 184
304: i=37, j=7: 64
305: i=38, j=0: 6
306: i=38, j=1: 2
307: i=38, j=2: 11
308: i=38, j=3: 116
309: i=38, j=4: 16
310: i=38, j=5: 32
311: i=38, j=6: 184
312: i=38, j=7: 64
313: i=39, j=0: 2
314: i=39, j=1: 5
315: i=39, j=2: 10
316: i=39, j=3: 116
317: i=39, j=4: 16
318: i=39, j=5: 32
319: i=39, j=6: 184
320: i=39, j=7: 64
321: i=40, j=0: 30
322: i=40, j=1: 2
323: i=40, j=2: 4
324: i=40, j=3: 8
325: i=40, j=4: 111
326: i=40, j=5: 32
327: i=40, j=6: 176
328: i=40, j=7: 64
329: i=41, j=0: 2
330: i=41, j=1: 29
331: i=41, j=2: 4
332: i=41, j=3: 8
333: i=41, j=4: 110
334: i=41, j=5: 32
335: i=41, j=6: 176
336: i=41, j=7: 64
337: i=42, j=0: 6
338: i=42, j=1: 2
339: i=42, j=2: 27
340: i=42, j=3: 8
341: i=42, j=4: 108
342: i=42, j=5: 32
343: i=42, j=6: 176
344: i=42, j=7: 64
345: i=43, j=0: 2
346: i=43, j=1: 5
347: i=43, j=2: 26
348: i=43, j=3: 8
349: i=43, j=4: 108
350: i=43, j=5: 32
351: i=43, j=6: 176
352: i=43, j=7: 64
353: i=44, j=0: 14
354: i=44, j=1: 2
355: i=44, j=2: 4
356: i=44, j=3: 23
357: i=44, j=4: 104
358: i=44, j=5: 32
359: i=44, j=6: 176
360: i=44, j=7: 64
361: i=45, j=0: 2
362: i=45, j=1: 13
363: i=45, j=2: 4
364: i=45, j=3: 22
365: i=45, j=4: 104
366: i=45, j=5: 32
367: i=45, j=6: 176
368: i=45, j=7: 64
369: i=46, j=0: 6
370: i=46, j=1: 2
371: i=46, j=2: 11
372: i=46, j=3: 20
373: i=46, j=4: 104
374: i=46, j=5: 32
375: i=46, j=6: 176
376: i=46, j=7: 64
377: i=47, j=0: 2
378: i=47, j=1: 5
379: i=47, j=2: 10
380: i=47, j=3: 20
381: i=47, j=4: 104
382: i=47, j=5: 32
383: i=47, j=6: 176
384: i=47, j=7: 64
385: i=48, j=0: 62
386: i=48, j=1: 2
387: i=48, j=2: 4
388: i=48, j=3: 8
389: i=48, j=4: 16
390: i=48, j=5: 95
391: i=48, j=6: 160
392: i=48, j=7: 64
393: i=49, j=0: 2
394: i=49, j=1: 61
395: i=49, j=2: 4
396: i=49, j=3: 8
397: i=49, j=4: 16
398: i=49, j=5: 94
399: i=49, j=6: 160
400: i=49, j=7: 64
401: i=50, j=0: 6
402: i=50, j=1: 2
403: i=50, j=2: 59
404: i=50, j=3: 8
405: i=50, j=4: 16
406: i=50, j=5: 92
407: i=50, j=6: 160
408: i=50, j=7: 64
409: i=51, j=0: 2
410: i=51, j=1: 5
411: i=51, j=2: 58
412: i=51, j=3: 8
413: i=51, j=4: 16
414: i=51, j=5: 92
415: i=51, j=6: 160
416: i=51, j=7: 64
417: i=52, j=0: 14
418: i=52, j=1: 2
419: i=52, j=2: 4
420: i=52, j=3: 55
421: i=52, j=4: 16
422: i=52, j=5: 88
423: i=52, j=6: 160
424: i=52, j=7: 64
425: i=53, j=0: 2
426: i=53, j=1: 13
427: i=53, j=2: 4
428: i=53, j=3: 54
429: i=53, j=4: 16
430: i=53, j=5: 88
431: i=53, j=6: 160
432: i=53, j=7: 64
433: i=54, j=0: 6
434: i=54, j=1: 2
435: i=54, j=2: 11
436: i=54, j=3: 52
437: i=54, j=4: 16
438: i=54, j=5: 88
439: i=54, j=6: 160
440: i=54, j=7: 64
441: i=55, j=0: 2
442: i=55, j=1: 5
443: i=55, j=2: 10
444: i=55, j=3: 52
445: i=55, j=4: 16
446: i=55, j=5: 88
447: i=55, j=6: 160
448: i=55, j=7: 64
449: i=56, j=0: 30
450: i=56, j=1: 2
451: i=56, j=2: 4
452: i=56, j=3: 8
453: i=56, j=4: 47
454: i=56, j=5: 80
455: i=56, j=6: 160
456: i=56, j=7: 64
457: i=57, j=0: 2
458: i=57, j=1: 29
459: i=57, j=2: 4
460: i=57, j=3: 8
461: i=57, j=4: 46
462: i=57, j=5: 80
463: i=57, j=6: 160
464: i=57, j=7: 64
465: i=58, j=0: 6
466: i=58, j=1: 2
467: i=58, j=2: 27
468: i=58, j=3: 8
469: i=58, j=4: 44
470: i=58, j=5: 80
471: i=58, j=6: 160
472: i=58, j=7: 64
473: i=59, j=0: 2
474: i=59, j=1: 5
475: i=59, j=2: 26
476: i=59, j=3: 8
477: i=59, j=4: 44
478: i=59, j=5: 80
479: i=59, j=6: 160
480: i=59, j=7: 64
481: i=60, j=0: 14
482: i=60, j=1: 2
483: i=60, j=2: 4
484: i=60, j=3: 23
485: i=60, j=4: 40
486: i=60, j=5: 80
487: i=60, j=6: 160
488: i=60, j=7: 64
489: i=61, j=0: 2
490: i=61, j=1: 13
491: i=61, j=2: 4
492: i=61, j=3: 22
493: i=61, j=4: 40
494: i=61, j=5: 80
495: i=61, j=6: 160
496: i=61, j=7: 64
497: i=62, j=0: 6
498: i=62, j=1: 2
499: i=62, j=2: 11
500: i=62, j=3: 20
501: i=62, j=4: 40
502: i=62, j=5: 80
503: i=62, j=6: 160
504: i=62, j=7: 64
505: i=63, j=0: 2
506: i=63, j=1: 5
507: i=63, j=2: 10
508: i=63, j=3: 20
509: i=63, j=4: 40
510: i=63, j=5: 80
511: i=63, j=6: 160
512: i=63, j=7: 64
Last Edit: 30 Нояб 2022 11:43 by alexlaw.

Bitboard в программировании шахмат №2 03 Дек 2022 07:18 #66

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
alexlaw wrote:
Получилось)
Для горизонтали мы научились и это просто, т.к. соседние биты идут подряд.

8.jpg


7.jpg


Расположение всех фигур на горизонтале A8-H8 будет соответствовать число 255.
Младший бит у нас A8 -LSB, старший H1 - MSB.

Сегодня наконец то мне пришла идея, как реализовать концепцию предварительно рассчитанных атак ладьи по вертикали.
Как пишут умные люди для этого нужно иметь еще один битбоард повернутый на 90 градусов и обновлять его одновременно с основным.
Мне такая идея не по душе.
Итак имеем допустим такую позицию

10.jpg


9.jpg

Позиция черных фигур соответствует числу U64 - 72340172838076673

11.jpg


А нам нужно, чтобы позици укладывалась в число 255

Идея такая

12.jpg


Перенести биты с вертикали А1-А8 на горизонталь А8-H8, повернуть на 90 градусов относительно A8.
function rotate90degree(U64: UInt64):UInt64;
var
i:Integer;
Temp64,result64: UInt64;
begin
result:=0;
Temp64:=U64 and 72340172838076673;
 for i := 0 to 7 do  begin
  if (Temp64 and LineA1H8[i*8])>0 then result:=result or (LineA1H8[i*8] and 255);
 end;
end;
Last Edit: 03 Дек 2022 07:55 by alexlaw.

Bitboard в программировании шахмат №2 03 Дек 2022 07:22 #67

  • Vladimirovich
  • Vladimirovich's Avatar
  • OFFLINE
  • Инквизитор
  • Posts: 106785
  • Thank you received: 2073
  • Karma: 105
alexlaw wrote:
А нам нужно, чтобы позици укладывалась в число 255
А зачем?
Позиция это массив 64-масок будет
Каждому - своё.

Bitboard в программировании шахмат №2 03 Дек 2022 07:31 #68

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Vladimirovich wrote:
А зачем?
Будьте внимательны.alexlaw wrote:
Атаки первого ранга (атаки по одной горизонтали)
Нам же нужно заполнить массив предварительных атак ладьи по вертикале - Атаки первого ранга по вертикале
Размерность - первый индекс 255
Last Edit: 03 Дек 2022 07:37 by alexlaw.

Bitboard в программировании шахмат №2 03 Дек 2022 07:46 #69

  • Vladimirovich
  • Vladimirovich's Avatar
  • OFFLINE
  • Инквизитор
  • Posts: 106785
  • Thank you received: 2073
  • Karma: 105
alexlaw wrote:
Будьте внимательны.alexlaw wrote:
Атаки первого ранга (атаки по одной горизонтали)
Нам же нужно заполнить массив предварительных атак ладьи по вертикале - Атаки первого ранга по вертикале
Размерность - первый индекс 255

Да не нужно никаких атак первого и пр. ранга.

Все атаки ладьи это 64-число
На него накладываются другие маски - свои и чужие фигуры и т.д и получается итоговое 64-число
Я же привел типовые картинки

А 255 это уже совсем ни к чему в данной концепции

Впрочем, как хотите
Я не тактик, я стратег :)

Любимый анекдот в тему
Жили-были мыши и все их обижали. Как-то пошли они к мудрому филину
и говорят:
— Мудрый филин, помоги советом. Все нас обижают, коты разные, совы.
Что нам делать?
Филин подумал и говорит:
— А вы станьте ёжиками. У ёжиков иголки, их никто не обижает.
Мыши обрадовались и побежали домой. Но по дороге одна мышка сказала:
— Как же мы станем ёжиками? — и все побежали обратно, чтобы задать
этот вопрос мудрому филину.
Прибежав, они спросили:
— Мудрый филин, а как же мы станем ёжиками?
И ответил филин:
— Я не тактик, я страгег.
Каждому - своё.

Bitboard в программировании шахмат №2 03 Дек 2022 08:01 #70

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Пришел мужик в гости к соседу, смотрит, а тот шахматную позицию анализирует.
- А жена твоя где?
- В сарае - дрова колет.
- Ну-у, сосед, и не стыдно тебе? Ты тут сидишь в тепле, позицию анализируешь, а она там на холоде дрова колет.
- А что я могу сделать, если она в шахматы играть не умеет?

Bitboard в программировании шахмат №2 03 Дек 2022 08:14 #71

  • Vladimirovich
  • Vladimirovich's Avatar
  • OFFLINE
  • Инквизитор
  • Posts: 106785
  • Thank you received: 2073
  • Karma: 105
Жена - мужу:
- Ну и где ты был???!!!
- С Серегой в шахматы играли...
- А почему-же от тебя водкой пахнет?!
- А что, от меня должно шахматами пахнуть???
Каждому - своё.

Bitboard в программировании шахмат №2 03 Дек 2022 08:28 #72

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
alexlaw wrote:
Сегодня наконец то мне пришла идея
Терзают меня смутные сомнения, что это метод не даст преимущество в скорости.
Надо прогнать через профайлер и будет видно. что быстрее.
Потом навпишу результат
Last Edit: 04 Дек 2022 03:26 by alexlaw.

Bitboard в программировании шахмат №2 03 Дек 2022 11:50 #73

  • Ruslan73
  • Ruslan73's Avatar
  • OFFLINE
  • Администратор
  • Posts: 35559
  • Thank you received: 757
  • Karma: 56
Версия delphi у Вас какая кстати?
Свободу Джулиану Ассанжу!

Bitboard в программировании шахмат №2 03 Дек 2022 14:07 #74

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Ruslan73 wrote:
Версия delphi у Вас какая кстати?
Borland Delphi 10 Lite v3.0

Delphi 10 Lite - модификация Delphi 2006, не требующая наличия .NET. Размер архива - 63.7 MB, что тем не менее позволяет создавать полноценные программы. Особенности:
- Очень маленький размер дистрибутива. Включены только Standard Components и Database Components.
- Выключены все установочные опции, КРОМЕ "Source code".
- Добавлен программный шрифт Monospac821 BT. Рекомендуемые установки: размер 8 с включенным ClearType.
- Утилита Delphi Tweaks, расположенная в программной группе "Delphi 10 Lite", позволяет настраивать Delphi IDE. Оптимальные настройки уже применены, так что на самом деле нет необходимости запускать Delphi Tweaks кроме тех случаев, когда вы захотите вернуть стандартные настройки.
- BORLNDMM.DLL обновлена до FastMM v4.62.
- Refactoring, ErrorInsite и поддержка ActiveX отключены, т.к. требуют наличия .NET Framework.
- Welcome Page удалена.
- Добавлена утилита OpenHelp из Delphi 7.
- Опциональные компоненты вынесены в отдельные установщики.
- Справочная система заменена справкой из Delphi 7, которая намного лучше и также не требует .NET Framework SDK.
- Update 1 уже применен (версия IDE = 10.0.2166.28377)

Bitboards' Little Helper хороший помошник для битбоард
Last Edit: 03 Дек 2022 14:24 by alexlaw.

Bitboard в программировании шахмат №2 03 Дек 2022 15:02 #75

  • Ruslan73
  • Ruslan73's Avatar
  • OFFLINE
  • Администратор
  • Posts: 35559
  • Thank you received: 757
  • Karma: 56
alexlaw wrote:
модификация Delphi 2006
Т.е. это версия до XE2 у неё нет нативной поддержки 64битных приложений?
Свободу Джулиану Ассанжу!

Bitboard в программировании шахмат №2 03 Дек 2022 16:21 #76

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Базовая заготовка UI - пользовательский интерфейс
UI от 04.12.2022

Стараюсь комментировать код, надеюсь не очень запутанно

Исправил ошибку
unit VisualBoard;//UI-визуализаци польз. итерфейса alexlaw@list.ru

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, Menus;

type
  TFormBoard = class(TForm)
    ChessBoard: TImage;//изображение шахматной доски
    Desk: TImage;//изображение клеток шахматного поля
    Piece: TImage;//изображение всех фигур
    SelectBox: TImage;//изображение рамки выбора
    MainMenu1: TMainMenu;
    Menu1: TMenuItem;
    PosTest: TMenuItem;
    Position1: TMenuItem;
    Position2: TMenuItem;
    Position3: TMenuItem;
    Position4: TMenuItem;
    Position5: TMenuItem;
    Position6: TMenuItem;
    InputFEN: TMenuItem;
//https://mf.grsu.by/UchProc/livak/arxiv_22102010/kursi/programming/lections/delphi/focus.htm?ysclid=lb931bk0vc792245318
//OnMouseDown-Нажатие клавиши мыши над компонентом.
//Возмож­но распознавание нажатой кнопки и координат кур­сора мыши.
    procedure ChessBoardMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure InputFENClick(Sender: TObject);
    procedure PositionClick(Sender: TObject);
//OnClick
//Щелчок мыши на компоненте и некоторые другие действия пользователя
    procedure ChessBoardClick(Sender: TObject);
//OnMouseMove
//Перемещении курсора мыши над компонентом.
//Воз­можно распознавание нажатой кнопки и координат курсора мыши.
    procedure ChessBoardMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Board: TFormBoard;
  //дата
  ProgrammDate:String = '04.12.2022';
  Xmouse,Ymouse,NumPos:Integer;
  //0-KING, 1-QUEEN, 2-ROOK, 3-BISHOP, 4-KNIGHT, 5-PAWN
  WPieceArray: array [0..5]  of  UInt64 = (0,0,0,0,0,0);
  BPieceArray: array [0..5]  of  UInt64 = (0,0,0,0,0,0);
CONST
  //размеры игрового поля доски
  DescHeight:Integer=480;
  DescWidth:Integer=480;
  //смещение игрового поля доски от начала координат
  dX:Integer=24;
  dY:Integer=20;
  //размер клетки игрового поля
  cell:Integer=60;
   //установлен ровно один бит
  MaskOneBit: array [0..63]  of  UInt64 = (
  1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,
  524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,
  268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,
  34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,
  2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,
  70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,
  2251799813685248,4503599627370496,9007199254740992,18014398509481984,36028797018963968,
  72057594037927936,144115188075855872,288230376151711744,576460752303423488,
  1152921504606846976,2305843009213693952,4611686018427387904,9223372036854775808);
implementation

{$R *.dfm}
//----------------------------------------------------------------------
//ниже инфа пока не используется
{P=1, N=2, K=3, B=5, R=6 и Q=7.
   При анализе этих чисел проверяется результат piece_type&4,
   и если результат ненулевой, это дальнобойная фигура.
   Далее, если результат piece_type&1 отличен от нуля, эта фигура ходит по диагонали,
    а если результат piece_type&2 ненулевой, то фигура может двигаться вдоль горизонталей/вертикалей.
https://www.pvsm.ru/game-development/17378?ysclid=l9zgbf9nj6679415818 }
//----------------------------------------------------------------------
//функция парсинга fen строки в массивы фигур WPiece, BPiece
//0-KING, 1-QUEEN, 2-ROOK, 3-BISHOP, 4-KNIGHT, 5-PAWN
function FenToU64(sfen:String):boolean;
var
// i - индекс массива
// k - длина строки fen
// n - счетчик шахматных клеток (64 клетки)
// num - позиция символа в strN или strF
i,k,n,num:integer;
//строки для цифр из fen строки -  strN, фигур - strF, единичного символа - s01
strN,strF,s01:string;
//массивы фигур
 WPieceNew: array [0..5]  of  UInt64;
 BPieceNew: array [0..5]  of  UInt64;
begin
//если fen строка пустая, то ошибка fen строки
result:=false;
 if sfen='' then exit;
// инициализация строк для парсинга fen строки
 strN:='12345678';
 strF:='KQRBNPkqrbnp';
//инициализация локальных массивов фигур
   for i := 0 to 5 do  begin
    WPieceNew[i]:=0;
    BPieceNew[i]:=0;
   end;
//определяем длину fen строки
   k:=length(sfen);
//сбрасываем счетчик
   n:=-1;
//перебираем символы fen строки
      for i := 1 to k do begin
      //берем один символ  fen строки на позиции i
      //возвращает подстроку строки sfen начинающуюся с индекса i длиной 1 символ
         s01:=copy(sfen,i,1);
      //возвр. позицию символа s01 в строке strN, если нет символа, то 0
      //сначала проверяем s01 - это цифра?
         num:=pos(s01,strN);
      //continue прерывает только выполнение текущей итерации,
      //текущего выполнения тела цикла
      //и передает управление на следующую итерацию.
         if s01='/' then continue;
      //если пробел заканчиваем парсинг   
         if s01=' ' then break;
      //увеличиваем счетчик шахматных клеток n
      // если num=0, значит символ s01 фигура
         if num=0 then begin
              n:=n+1;
      // иначе цифра
         end else begin
              n:=n+num;
         end;
      //если клеток больше 64(0..63), то ошибка fen строки
         if n>63 then exit;
      //проверяем s01 - это символ фигуры?
          num:=pos(s01,strF);
      //если num - это не допустимый символ,  то ошибка fen строки
          if ((num=0) and (pos(s01,strN)=0))then exit;
      //заносим фигуры в массивы    
          if num>0 then begin
            if num<7 then begin
               WPieceNew[num-1]:=WPieceNew[num-1] or MaskOneBit[n];
            end else begin
               BPieceNew[num-7]:=BPieceNew[num-7] or MaskOneBit[n];
            end;
          end;
      end;//for
//если клеток не равно 64(0..63), то ошибка fen строки
  if n<>63 then exit;
//если королей не равно 1, то ошибка fen строки
//  if CountBitsInt64(WPieceNew[0])<>1 then exit;
//  if CountBitsInt64(BPieceNew[0])<>1 then exit;
// заполняем глобальные массивы фигур WPiece,BPiece
   for i := 0 to 5 do  begin
    WPieceArray[i]:=WPieceNew[i];
    BPieceArray[i]:=BPieceNew[i];
   end;
//ShowMessage('парсинг завершен успешно');
//парсинг завершен успешно
  result:=true;
end;

//процедура очистки изображения шахматной доски
 procedure ClearDesk ();
var
bmp: tbitmap;
begin
try
//создаем временный bmp
 bmp := tbitmap.Create;
//размером с Desk-изображение клеток шахматного поля
 bmp.Height:=DescHeight;
 bmp.Width:=DescWidth;
 //CopyRect (Dest: TRect; Canvas: TCanvas; Source: TRect) ;
 //копируем область рисунка Source(Desk) с координатами rect(0,0,DescWidth,DescHeight)
 //на наш bmp в область с коорд. rect(0,0,bmp.Width,bmp.Height)
 bmp.Canvas.CopyRect(rect(0,0,bmp.Width,bmp.Height),Board.Desk.Canvas,rect(0,0,DescWidth,DescHeight));
 //cmSrcCopy 	Копирует изображение источника на канву
 // http://it.kgsu.ru/Delphi_6/dlph0039.html
 Board.ChessBoard.Canvas.CopyMode:=cmSrcCopy;
 //рисуем bmp на ChessBoard(изображение шахматной доски)
 //по сути стираем все, что было на ней в виде фигур
 Board.ChessBoard.Canvas.Draw(dX, dY, bmp);
finally
 bmp.free;
end;
end;

//процедура рисования фигуры типа - NumP в клетке - Pos, цветом ColorP
procedure DrawPiece(Pos,NumP,ColorP: Integer);
var
bmp: tbitmap;
a,b: Integer;
begin
try
 //создаем временный bmp
 bmp := tbitmap.Create;
 //размер клетки игрового поля
 bmp.Height:=cell;
 bmp.Width:=cell;
//Пример с2 - Pos:=50;
// 00110010 and 00000111 = 00000010; 50 and 7 = 2
// 00110010  shr 3 = 00000110; 50 shr 3 = 6
//A8 - a=0,b=0 H1 - a=7,b=7 
a:=Pos and 7;//0..7 горизонталь (буквы)
b:=Pos shr 3;//0..7 вертикаль (цифры)
//выбераем фигуру из рисунка Piece (изображение всех фигур)
//CopyRect (Dest: TRect; Canvas: TCanvas; Source: TRect) ;
//копируем область рисунка Source(Piece) с координатами rect
//на наш bmp в область с коорд. rect(0,0,cell,cell) 60x60
//по сути рисуем выбранную фигуру NumP цвета ColorP на bmp
bmp.Canvas.CopyRect(rect(0,0,bmp.Width,bmp.Height),Board.Piece.Canvas,rect(cell*NumP,cell*ColorP,cell*NumP+cell,cell*ColorP+cell));
//устанавливае прозрачным фон (желтый)
bmp.TransparentColor:=clYellow;
bmp.Transparent:=true;
//рисуем фигуру на ChessBoard-изображении шахматной доски
Board.ChessBoard.Canvas.Draw(dX+cell*a, dY+cell*b, bmp);
finally
 bmp.free;
end;
end;

//рисуем позицию на доске
procedure DrawPieceBoard(APiece:array of  UInt64;ColorPiece: Integer);
var
//тип фигуры
NumPiece: Integer;
i,j: Integer;
begin
NumPiece:=0;
                          //перебираем все массивы типа фигур
                          while NumPiece<6 do begin
                          //находим установлененый бит  в  APiece[NumPiece]
                                  for i:=63 downto 0 do  begin
                                  j := (APiece[NumPiece] shr i) and 1;
                                       case j  of
                                                 1:begin
                                  //если бит установлен рисуем фигуру в позиции i
                                                   DrawPiece(i,NumPiece,ColorPiece);
                                                  end;
                                       end;
                                   end;
                            NumPiece:=NumPiece+1;
                            end;

end;

//кликнули по изображению шахматной доски
procedure TFormBoard.ChessBoardClick(Sender: TObject);
begin
if NumPos>63 then exit;
if NumPos<0 then exit;
 //ShowMessage('Кликнули по полю - '+IntToStr(NumPos));
//тест
 //рисуем белую ладью в клетке NumPos
 ClearDesk ();
 DrawPiece(NumPos,2,0);
//тест
end;

//Нажатие клавиши мыши над компонентом ChessBoard - изображение шахматной доски
procedure TFormBoard.ChessBoardMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
if NumPos>63 then exit;
if NumPos<0 then exit;
if Button=mbLeft then  DrawPiece(NumPos,2,0);
if Button=mbRight then DrawPiece(NumPos,2,1);
end;

//отслеживаем координаты мыши на изображении шахматной доски
procedure TFormBoard.ChessBoardMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
Xmouse:=X+Board.Left;Ymouse:=Y+Board.Top;
//div целочисленное деление
//вычисляем номер поля A8 - 0, H1 - 63
NumPos:= ((X-dX) div cell)+8*((Y-dY) div cell);
end;


procedure TFormBoard.InputFENClick(Sender: TObject);
var
fenpos:String;
begin
 fenpos:= InputBox('Установить позицию', 'Введите FEN строку', 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR');
if not FenToU64(fenpos) then ShowMessage('Ошибка FEN строки') else begin
ClearDesk ();
DrawPieceBoard(WPieceArray,0);
DrawPieceBoard(BPieceArray,1);
end;
end;

//клик по меню выбора стандартной тестовой позиции
procedure TFormBoard.PositionClick(Sender: TObject);
var
fenpos:String;
begin
 ShowMessage('Кликнули по '+IntToStr((Sender as TMenuItem).Tag));
 fenpos:='';
 case (Sender as TMenuItem).Tag of
	1 : fenpos:='rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR';//нач. позиция
	2 : fenpos:='r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R';
	3 : fenpos:='8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8';
	4 : fenpos:='r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1';
  5 : fenpos:='rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R';
	6 : fenpos:='r4rk1/1pp1qppp/p1np1n2/2b1p1B1/2B1P1b1/P1NP1N2/1PP1QPPP/R4RK1';
 end;
if not FenToU64(fenpos) then ShowMessage('Ошибка FEN строки') else begin
ClearDesk ();
DrawPieceBoard(WPieceArray,0);
DrawPieceBoard(BPieceArray,1);
end;
end;

end.

В шахматных боях без правил разрешается использовать не только фигуры, но так же доску, часы, стул и стол.
Last Edit: 04 Дек 2022 13:08 by alexlaw.

Bitboard в программировании шахмат №2 04 Дек 2022 08:36 #77

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Добавил нажатие правой кнопки мыши для постановки черных ладей

13.jpg

//https://mf.grsu.by/UchProc/livak/arxiv_22102010/kursi/programming/lections/delphi/focus.htm?ysclid=lb931bk0vc792245318
//OnMouseDown-Нажатие клавиши мыши над компонентом.
//Возмож­но распознавание нажатой кнопки и координат кур­сора мыши.
    procedure ChessBoardMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
//Нажатие клавиши мыши над компонентом ChessBoard - изображение шахматной доски
procedure TFormBoard.ChessBoardMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
if NumPos>63 then exit;
if NumPos<0 then exit;
if Button=mbLeft then  DrawPiece(NumPos,2,0);
if Button=mbRight then DrawPiece(NumPos,2,1);
end;

Гроссмейстер от нечего делать начинает играть в шахматы с соседом по купе... и проигрывает партию. Поражённый гроссмейстер восклицает:
- И подумать только: вы могли бы поставить мне мат ещё на три хода раньше, если бы пошли ладьёй!
- Как? Ладью тоже можно передвигать? - спрашивает попутчик.
Last Edit: 04 Дек 2022 08:38 by alexlaw.

Bitboard в программировании шахмат №2 07 Дек 2022 08:21 #78

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Добавил в отдельный файл fun.pas некоторые процедуры, которые понадобятся в дальнейшем, и это файл буду дополнять другими нужными процедурами.
unit fun;

interface
function CountBitsInt64(const integer64:UInt64):integer;
function SeniorBit(const Lo, Hi: LongWord): Integer;
function JuniorBit(const Lo, Hi: LongWord): Integer;
procedure init ();
procedure maskLine ();
var
//битовые маски из поля 0..63 до края доски  в направлении из литера 1 в литера2
//бит поля также включен в маске
  LineA1A8: array [0..63]  of  UInt64;
  LineA8A1: array [0..63]  of  UInt64;
  LineA1H1: array [0..63]  of  UInt64;
  LineH1A1: array [0..63]  of  UInt64;
  LineA1H8: array [0..63]  of  UInt64;
  LineH8A1: array [0..63]  of  UInt64;
  LineA8H1: array [0..63]  of  UInt64;
  LineH1A8: array [0..63]  of  UInt64;
implementation

uses VisualBoard;
//Использование ассемблера в Дельфи 
//http://biguniverse.narod.ru/gybels.pdf
//Подсчет количества установленных бит в integer (32 бита)
function CountBits(const Value: integer): integer;
asm
mov ECX,EAX
xor EAX,EAX
test ECX,ECX
jz @@ending
@@counting:
shr ECX,1
adc EAX,0
test ECX,ECX
jnz @@counting
@@ending:
end;
//Подсчет количества установленных бит в Int64 (64 бита)
function CountBitsInt64(const integer64:UInt64):integer;
begin
result:=CountBits(integer64)+CountBits(integer64 shr 32);
end;
//Команда BSR просматривает биты второго операнда от младшего к старшему
// и помещает индекс последнего единичного бита в регистр (для 32 бит)
function LastOne(const Value: integer): integer;
asm
bsr ECX,EAX
mov EAX,ECX
end;
function FirstOne(const Value: integer): integer;
asm    
bsf ECX,EAX
mov EAX,ECX
end;
//Входное значение передается в двух частях (длинные слова Lo и Hi). 
//Результат равен 0, если вход равен 0, в противном случае результат будет в [1..64].
// Lo - младшие 32 бита Hi - старшие 32 бита  сдвигаем на место младших(U64 <<
//SeniorBit(U64,U64 shr 32)-1; - возвращае позицию бита 0...63
function SeniorBit(const Lo, Hi: LongWord): Integer;
asm
        OR    EDX,EDX
        JZ    @@Lo
        MOV   EAX,EDX
        MOV   EDX,32
@@Lo:
        OR    EAX,EAX
        JZ    @@Done
        BSR   EAX,EAX
        ADD   EAX,EDX
        INC   EAX
@@Done:
end;
//JuniorBit(Temp64,Temp64 shr 32); - возвращае позицию бита 1...64
function JuniorBit(const Lo, Hi: LongWord): Integer;
begin
if Lo=0 then  begin
   result:=FirstOne(Hi) + 32;
   end else result:=FirstOne(Lo);
end;
procedure init ();
  var
i: Integer;
begin
for i := 0 to 63 do  begin
  LineA1A8[i]:=0;
  LineA8A1[i]:=0;
  LineA1H1[i]:=0;
  LineH1A1[i]:=0;
  LineA1H8[i]:=0;
  LineH8A1[i]:=0;
  LineA8H1[i]:=0;
  LineH1A8[i]:=0;
end;
end;
//расчет битовой маски из поля 0..63 до края доски (во всех 8 напралениях)
//направление ясно определяют поля в названии LineXX
procedure maskLine ();
 var
i,j,z,k: Integer;
begin
  for i := 0 to 63 do  begin
  z:=i div 8;
       for j := 0 to z do  begin
           k:=i-j*8;
             LineA1A8[i]:= LineA1A8[i] or MaskOneBit[k];
           if j<=(7 - k mod 8) then  begin
             LineA1H8[i]:=LineA1H8[i] or (MaskOneBit[k] shl j);
           end;
           if j<=(k mod 8) then begin
             LineH1A8[i]:=LineH1A8[i] or (MaskOneBit[k] shr j);
           end;
       end;
   z:=7 - i div 8;
       for j := 0 to z do  begin
           k:=i+j*8;
             LineA8A1[i]:= LineA8A1[i] or MaskOneBit[k];
           if j<=(7 - k mod 8) then  begin
             LineA8H1[i]:=LineA8H1[i] or (MaskOneBit[k] shl j);
           end;
           if j<=(k mod 8) then begin
             LineH8A1[i]:=LineH8A1[i] or (MaskOneBit[k] shr j);
           end;
       end;
    z:=7 - i mod 8;
        for j := 0 to z do  begin
            LineA1H1[i]:=LineA1H1[i] or (MaskOneBit[i+j]);
        end;
    z:=i mod 8;
        for j := 0 to z do  begin
            LineH1A1[i]:=LineH1A1[i] or (MaskOneBit[i-j]);
        end;
  end;
end;
end.

Основной файл
unit VisualBoard;//UI-визуализаци польз. итерфейса alexlaw@list.ru

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, Menus;

type
  TFormBoard = class(TForm)
    ChessBoard: TImage;//изображение шахматной доски
    Desk: TImage;//изображение клеток шахматного поля
    Piece: TImage;//изображение всех фигур
    SelectBox: TImage;//изображение рамки выбора
    MainMenu1: TMainMenu;
    Menu1: TMenuItem;
    PosTest: TMenuItem;
    Position1: TMenuItem;
    Position2: TMenuItem;
    Position3: TMenuItem;
    Position4: TMenuItem;
    Position5: TMenuItem;
    Position6: TMenuItem;
    InputFEN: TMenuItem;
    procedure FormCreate(Sender: TObject);
//https://mf.grsu.by/UchProc/livak/arxiv_22102010/kursi/programming/lections/delphi/focus.htm?ysclid=lb931bk0vc792245318
//OnMouseDown-Нажатие клавиши мыши над компонентом.
//Возмож­но распознавание нажатой кнопки и координат кур­сора мыши.
    procedure ChessBoardMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure InputFENClick(Sender: TObject);
    procedure PositionClick(Sender: TObject);
//OnClick
//Щелчок мыши на компоненте и некоторые другие действия пользователя
    procedure ChessBoardClick(Sender: TObject);
//OnMouseMove
//Перемещении курсора мыши над компонентом.
//Воз­можно распознавание нажатой кнопки и координат курсора мыши.
    procedure ChessBoardMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Board: TFormBoard;
  //дата
  ProgrammDate:String = '07.12.2022';
  Xmouse,Ymouse,NumPos:Integer;
  //0-KING, 1-QUEEN, 2-ROOK, 3-BISHOP, 4-KNIGHT, 5-PAWN
  //массивы фигур
  WPieceArray: array [0..5]  of  UInt64 = (0,0,0,0,0,0);
  BPieceArray: array [0..5]  of  UInt64 = (0,0,0,0,0,0);
  //Белые и черные фигуры в одном 64 битном числе
  WhitePieceU64:UInt64 = 0;
  BlackPieceU64:UInt64 = 0;
  //все фигуры в одном 64 битном числе
  AllPieceU64:UInt64 = 0;
CONST
  //размеры игрового поля доски
  DescHeight:Integer=480;
  DescWidth:Integer=480;
  //смещение игрового поля доски от начала координат
  dX:Integer=24;
  dY:Integer=20;
  //размер клетки игрового поля
  cell:Integer=60;
   //установлен ровно один бит
  MaskOneBit: array [0..63]  of  UInt64 = (
  1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,
  524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,
  268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,
  34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,
  2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,
  70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,
  2251799813685248,4503599627370496,9007199254740992,18014398509481984,36028797018963968,
  72057594037927936,144115188075855872,288230376151711744,576460752303423488,
  1152921504606846976,2305843009213693952,4611686018427387904,9223372036854775808);
implementation

uses fun;

{$R *.dfm}
//----------------------------------------------------------------------
//ниже инфа пока не используется
{P=1, N=2, K=3, B=5, R=6 и Q=7.
   При анализе этих чисел проверяется результат piece_type&4,
   и если результат ненулевой, это дальнобойная фигура.
   Далее, если результат piece_type&1 отличен от нуля, эта фигура ходит по диагонали,
    а если результат piece_type&2 ненулевой, то фигура может двигаться вдоль горизонталей/вертикалей.
https://www.pvsm.ru/game-development/17378?ysclid=l9zgbf9nj6679415818 }
//----------------------------------------------------------------------
//функция парсинга fen строки в массивы фигур WPiece, BPiece
//0-KING, 1-QUEEN, 2-ROOK, 3-BISHOP, 4-KNIGHT, 5-PAWN
function FenToU64(sfen:String):boolean;
var
// i - индекс массива
// k - длина строки fen
// n - счетчик шахматных клеток (64 клетки)
// num - позиция символа в strN или strF
i,k,n,num:integer;
//строки для цифр из fen строки -  strN, фигур - strF, единичного символа - s01
strN,strF,s01:string;
//массивы фигур
 WPieceNew: array [0..5]  of  UInt64;
 BPieceNew: array [0..5]  of  UInt64;
begin
//если fen строка пустая, то ошибка fen строки
result:=false;
 if sfen='' then exit;
// инициализация строк для парсинга fen строки
 strN:='12345678';
 strF:='KQRBNPkqrbnp';
//инициализация локальных массивов фигур
   for i := 0 to 5 do  begin
    WPieceNew[i]:=0;
    BPieceNew[i]:=0;
   end;
  WhitePieceU64:=0;
  BlackPieceU64:=0;
//определяем длину fen строки
   k:=length(sfen);
//сбрасываем счетчик
   n:=-1;
//перебираем символы fen строки
      for i := 1 to k do begin
      //берем один символ  fen строки на позиции i
      //возвращает подстроку строки sfen начинающуюся с индекса i длиной 1 символ
         s01:=copy(sfen,i,1);
      //возвр. позицию символа s01 в строке strN, если нет символа, то 0
      //сначала проверяем s01 - это цифра?
         num:=pos(s01,strN);
      //continue прерывает только выполнение текущей итерации,
      //текущего выполнения тела цикла
      //и передает управление на следующую итерацию.
         if s01='/' then continue;
      //если пробел заканчиваем парсинг   
         if s01=' ' then break;
      //увеличиваем счетчик шахматных клеток n
      // если num=0, значит символ s01 фигура
         if num=0 then begin
              n:=n+1;
      // иначе цифра
         end else begin
              n:=n+num;
         end;
      //если клеток больше 64(0..63), то ошибка fen строки
         if n>63 then exit;
      //проверяем s01 - это символ фигуры?
          num:=pos(s01,strF);
      //если num - это не допустимый символ,  то ошибка fen строки
          if ((num=0) and (pos(s01,strN)=0))then exit;
      //заносим фигуры в массивы    
          if num>0 then begin
            if num<7 then begin
               WPieceNew[num-1]:=WPieceNew[num-1] or MaskOneBit[n];
               //белые фигуры в одно 64 битное число
               WhitePieceU64:=WhitePieceU64 or WPieceNew[num-1];
            end else begin
               BPieceNew[num-7]:=BPieceNew[num-7] or MaskOneBit[n];
               //черные фигуры в одно 64 битное число
               BlackPieceU64:=BlackPieceU64 or BPieceNew[num-7];
            end;
          end;
      end;//for
//если клеток не равно 64(0..63), то ошибка fen строки
  if n<>63 then exit;
//если королей не равно 1, то ошибка fen строки
  if CountBitsInt64(WPieceNew[0])<>1 then exit;
  {
ShowMessage('Белый король на поле - ' +
IntToStr(SeniorBit(WPieceNew[0],WPieceNew[0] shr 32)-1) +' '+ IntToStr(JuniorBit(WPieceNew[0],WPieceNew[0] shr 32)));
  }
  if CountBitsInt64(BPieceNew[0])<>1 then exit;
// заполняем глобальные массивы фигур WPiece,BPiece
   for i := 0 to 5 do  begin
    WPieceArray[i]:=WPieceNew[i];
    BPieceArray[i]:=BPieceNew[i];
   end;
   //все фигуры в одно 64 битное число
   AllPieceU64:=WhitePieceU64 or BlackPieceU64;
//ShowMessage('парсинг завершен успешно');
//парсинг завершен успешно
  result:=true;
end;

//процедура очистки изображения шахматной доски
 procedure ClearDesk ();
var
bmp: tbitmap;
begin
try
//создаем временный bmp
 bmp := tbitmap.Create;
//размером с Desk-изображение клеток шахматного поля
 bmp.Height:=DescHeight;
 bmp.Width:=DescWidth;
 //CopyRect (Dest: TRect; Canvas: TCanvas; Source: TRect) ;
 //копируем область рисунка Source(Desk) с координатами rect(0,0,DescWidth,DescHeight)
 //на наш bmp в область с коорд. rect(0,0,bmp.Width,bmp.Height)
 bmp.Canvas.CopyRect(rect(0,0,bmp.Width,bmp.Height),Board.Desk.Canvas,rect(0,0,DescWidth,DescHeight));
 //cmSrcCopy 	Копирует изображение источника на канву
 // http://it.kgsu.ru/Delphi_6/dlph0039.html
 Board.ChessBoard.Canvas.CopyMode:=cmSrcCopy;
 //рисуем bmp на ChessBoard(изображение шахматной доски)
 //по сути стираем все, что было на ней в виде фигур
 Board.ChessBoard.Canvas.Draw(dX, dY, bmp);
finally
 bmp.free;
end;
end;

//процедура рисования фигуры типа - NumP в клетке - Pos, цветом ColorP
procedure DrawPiece(Pos,NumP,ColorP: Integer);
var
bmp: tbitmap;
a,b: Integer;
begin
try
 //создаем временный bmp
 bmp := tbitmap.Create;
 //размер клетки игрового поля
 bmp.Height:=cell;
 bmp.Width:=cell;
//Пример с2 - Pos:=50;
// 00110010 and 00000111 = 00000010; 50 and 7 = 2
// 00110010  shr 3 = 00000110; 50 shr 3 = 6
//A8 - a=0,b=0 H1 - a=7,b=7 
a:=Pos and 7;//0..7 горизонталь (буквы)
b:=Pos shr 3;//0..7 вертикаль (цифры)
//выбераем фигуру из рисунка Piece (изображение всех фигур)
//CopyRect (Dest: TRect; Canvas: TCanvas; Source: TRect) ;
//копируем область рисунка Source(Piece) с координатами rect
//на наш bmp в область с коорд. rect(0,0,cell,cell) 60x60
//по сути рисуем выбранную фигуру NumP цвета ColorP на bmp
bmp.Canvas.CopyRect(rect(0,0,bmp.Width,bmp.Height),Board.Piece.Canvas,rect(cell*NumP,cell*ColorP,cell*NumP+cell,cell*ColorP+cell));
//устанавливае прозрачным фон (желтый)
bmp.TransparentColor:=clYellow;
bmp.Transparent:=true;
//рисуем фигуру на ChessBoard-изображении шахматной доски
Board.ChessBoard.Canvas.Draw(dX+cell*a, dY+cell*b, bmp);
finally
 bmp.free;
end;
end;

//рисуем позицию на доске
procedure DrawPieceBoard(APiece:array of  UInt64;ColorPiece: Integer);
var
//тип фигуры
NumPiece: Integer;
i,j: Integer;
begin
NumPiece:=0;
                          //перебираем все массивы типа фигур
                          while NumPiece<6 do begin
                          //находим установлененый бит  в  APiece[NumPiece]
                                  for i:=63 downto 0 do  begin
                                  j := (APiece[NumPiece] shr i) and 1;
                                       case j  of
                                                 1:begin
                                  //если бит установлен рисуем фигуру в позиции i
                                                   DrawPiece(i,NumPiece,ColorPiece);
                                                  end;
                                       end;
                                   end;
                            NumPiece:=NumPiece+1;
                            end;

end;
//рисуем рамку выбора в полях соотвтствующим уст. битам в  u:UInt64
procedure DrawMoveBox(u:UInt64);
var
bmp: tbitmap;
a,b,i: Integer;
begin
if u=0 then exit;
try
 bmp := tbitmap.Create;
 bmp.Height:=cell;
 bmp.Width:=cell;
bmp.TransparentColor:=clWhite;
bmp.Transparent:=true;
//рамка выбора cell*6,0,cell*7 в рисунке Piece-изображение всех фигур
bmp.Canvas.CopyRect(rect(0,0,bmp.Width,bmp.Height),Board.Piece.Canvas,rect(cell*6,0,cell*7,cell));
                                  //пробегаем по числу u:UInt64
                                  for i:=63 downto 0 do  begin
                                       //если включен бит
                                       case (u shr i) and 1  of
                                                 1:begin
                                                 //вычисляем позицию бита на доске
                                                  a:=i and 7;
                                                  b:=i shr 3;
                                                 //рисуем рамку на доске для поля с координатами a,b
                                                  Board.ChessBoard.Canvas.Draw(dX+cell*a, dY+cell*b, bmp);
                                                  end;
                                       end;
                                   end;
finally
  bmp.free;
end;
end;
//кликнули по изображению шахматной доски
procedure TFormBoard.ChessBoardClick(Sender: TObject);
begin
if NumPos>63 then exit;
if NumPos<0 then exit;
 //ShowMessage('Кликнули по полю - '+IntToStr(NumPos));
//тест
 ClearDesk ();
 //рисуем белую фигуру в клетке NumPos
 //DrawPiece(NumPos,2,0);
 //DrawMoveBox(LineA1A8[NumPos] or LineA8A1[NumPos] or LineA1H1[NumPos] or LineH1A1[NumPos]);
 DrawPiece(NumPos,3,0);
 DrawMoveBox(LineA1H8[NumPos] or LineH8A1[NumPos] or LineA8H1[NumPos] or LineH1A8[NumPos]);

 //тест
end;

//Нажатие клавиши мыши над компонентом ChessBoard - изображение шахматной доски
procedure TFormBoard.ChessBoardMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
if NumPos>63 then exit;
if NumPos<0 then exit;
if Button=mbLeft then  begin
ClearDesk ();
DrawPiece(NumPos,3,0);
end;
if Button=mbRight then DrawPiece(NumPos,2,1);
end;

//отслеживаем координаты мыши на изображении шахматной доски
procedure TFormBoard.ChessBoardMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
Xmouse:=X+Board.Left;Ymouse:=Y+Board.Top;
//div целочисленное деление
//вычисляем номер поля A8 - 0, H1 - 63
NumPos:= ((X-dX) div cell)+8*((Y-dY) div cell);
end;


procedure TFormBoard.FormCreate(Sender: TObject);
begin
Board.Caption := ProgrammDate;
init ();
maskLine ();
end;

procedure TFormBoard.InputFENClick(Sender: TObject);
var
fenpos:String;
begin
 fenpos:= InputBox('Установить позицию', 'Введите FEN строку', 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR');
if not FenToU64(fenpos) then ShowMessage('Ошибка FEN строки') else begin
ClearDesk ();
DrawPieceBoard(WPieceArray,0);
DrawPieceBoard(BPieceArray,1);
end;
end;

//клик по меню выбора стандартной тестовой позиции
procedure TFormBoard.PositionClick(Sender: TObject);
var
fenpos:String;
begin
 //ShowMessage('Кликнули по '+IntToStr((Sender as TMenuItem).Tag));
 fenpos:='';
 case (Sender as TMenuItem).Tag of
	1 : fenpos:='rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR';//нач. позиция
	2 : fenpos:='r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R';
	3 : fenpos:='8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8';
	4 : fenpos:='r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1';
  5 : fenpos:='rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R';
	6 : fenpos:='r4rk1/1pp1qppp/p1np1n2/2b1p1B1/2B1P1b1/P1NP1N2/1PP1QPPP/R4RK1';
 end;
if not FenToU64(fenpos) then ShowMessage('Ошибка FEN строки') else begin
//очищаем доску
ClearDesk ();
//рисуем фигуры
DrawPieceBoard(WPieceArray,0);
DrawPieceBoard(BPieceArray,1);
//выделяем все фигуры на доске
DrawMoveBox(AllPieceU64);
end;
end;

end.

14.jpg


– Слушай, ты же программист? Какой язык чаще всего используется программистами?
– Матерный.
Last Edit: 07 Дек 2022 08:25 by alexlaw.

Bitboard в программировании шахмат №2 07 Дек 2022 18:56 #79

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Условие задачи
Среди математических развлечений давно известна задача обхода шахматной фигурой коня всех клеток шахматной доски.
Она заключается в нахождении маршрута коня на шахматной доске.
В 1823 году Варнсдорф в брошюре “Простейшее и наиболее общее решение задачи о ходе коня” предложил следующее правило обхода доски размером 8x8.
На каждом ходу ставь коня на такое поле, из которого можно совершить наименьшее число ходов на еще не пройденные поля. Если таких полей несколько, разрешается выбирать любое из них.
На практике это правило легко позволяет строить обходы доски, хотя долгое время не было известно, справедливо ли оно. Опровержение правила Варнсдорфа было найденос помощью ЭВМ “Проминь- 2” , где для любого исходного поля доски указаны контрпримеры. Иными словами, с какого бы поля конь ни начал движение, следуя правилу Варнсдорфа, его можно завести в тупик до полного обхода доски.
Но для нас это не важно и мы пойдем по пути Варнсдорфа.

15.jpg


Добавить код в опубликованный выше
   //битовая маска атак коня
  KnightAttak: array [0..63]  of  UInt64 =(132096,329728,659712,1319424,2638848,5277696,10489856,4202496,
  33816580,84410376,168886289,337772578,675545156,1351090312,2685403152,1075839008,
  8657044482,21609056261,43234889994,86469779988,172939559976,345879119952,687463207072,275414786112,
  2216203387392,5531918402816,11068131838464,22136263676928,44272527353856,88545054707712,175990581010432,70506185244672,
  567348067172352,1416171111120896,2833441750646784,5666883501293568,
  11333767002587136,22667534005174272,45053588738670592,18049583422636032,
  145241105196122112,362539804446949376,725361088165576704,1450722176331153408,
  2901444352662306816,5802888705324613632,11533718717099671552,4620693356194824192,
  288234782788157440,576469569871282176,1224997833292120064,2449995666584240128,
  4899991333168480256,9799982666336960512,1152939783987658752,2305878468463689728,
  1128098930098176,2257297371824128,4796069720358912,9592139440717824,
  19184278881435648,38368557762871296,4679521487814656,9077567998918656);
implementation

uses fun;
//рисуем линию из центра клетки a в центр клетки b цветом c
procedure DrawLine(a,b,c:Integer);
var
bmp: tbitmap;
begin
try
 bmp := tbitmap.Create;
 bmp.Height:=DescHeight;
 bmp.Width:=DescWidth;
 //копируем доску на bmp
 bmp.Canvas.CopyRect(rect(0,0,bmp.Width,bmp.Height),Board.ChessBoard.Canvas,rect(0,0,DescHeight,DescWidth));
 Board.Desk.Canvas.CopyMode:=cmSrcCopy;
 //выбираем цвет линии
 if c=0 then bmp.Canvas.Pen.Color:=clRed else bmp.Canvas.Pen.Color:=clYellow;
 //толщина линии
 bmp.Canvas.Pen.Width:=5;
 bmp.Canvas.Pen.Mode:=pmNop;
 //переносим pen в центр клетки a
 bmp.Canvas.LineTo(dX+cell*(a and 7) + (cell div 2),dY+cell*(a shr 3) + (cell div 2));
 bmp.Canvas.Pen.Mode:=pmCopy;
 //рисуем линию
 bmp.Canvas.LineTo(dX+5*c+cell*(b and 7) + (cell div 2),dY+5*c+cell*(b shr 3) + (cell div 2));
 //отображаем все на доске
 Board.ChessBoard.Canvas.Draw(0, 0, bmp);
finally
 bmp.free;
end;
end;
//процедура обхода конем шахматной доски
//Pos - позиция коня (0..63) A8-0; H1-63
//integer64 - 64 бит (конь посетил - 0; не посетил - 1)
// все биты вкл -   FullU64:UInt64 = 18446744073709551615;
procedure KnightGO(Pos:Integer;integer64:UInt64;flag:boolean);
var
To_:UInt64;
i,best,min,n,j:Integer;
begin
//если все поля посетили то выход
if integer64=0 then exit;
j:=Pos;
min:=8;
//при первом обращении к процедуре искл позицию коня из не посещеных
if (CountBitsInt64(integer64)=64) then
To_:=KnightAttak[Pos] and (integer64 xor MaskOneBit[Pos])
else
//разрешенные ходы коня - маска ходов коня и не посещеные клетки
To_:=KnightAttak[Pos] and integer64;
//если нет доступных ходов то выходим
if To_=0 then exit;
//перебираем разрешенные ходы
      for i := 0 to CountBitsInt64(To_)-1 do  begin
//находим младший вкл бит (делаем ход из Pos на поле n)
      n:=JuniorBit(To_,To_ shr 32);
//считаем кол ходов из поля n
      best:= CountBitsInt64(KnightAttak[n] and integer64);
//если кол ходов мин, то запоминаем этот ход и номер поля
if flag then begin
        if best<min then begin  //не выполняется для 24 27 49
        min:=best;
        j:=n;
        end;
end else begin
        if best<=min then begin  //не выполняется для 14 36 39
        min:=best;
        j:=n;
        end;
end; 
//исключаем ход для следующей итерации цикла
      To_:=To_ xor MaskOneBit[n];
      end;//for
//заставляет выполнить все задачи которые накопились в данный момент
Application.ProcessMessages;
//рисуем коня
DrawPiece(j,4,0);
//рисуем линию из Pos в j
DrawLine(Pos,j,0);
//рекурсивно двигаемся дальше (пока есть разр. ходы)
KnightGO(j,integer64 xor MaskOneBit[Pos],flag);
end; 
//кликнули по изображению шахматной доски
procedure TFormBoard.ChessBoardClick(Sender: TObject);
var
flag:boolean;
begin
if NumPos>63 then exit;
if NumPos<0 then exit;
// ShowMessage('Кликнули по полю - '+IntToStr(NumPos));
//тест
 ClearDesk ();
 //рисуем белую фигуру в клетке NumPos
 //DrawPiece(NumPos,2,0);
 //DrawMoveBox(LineA1A8[NumPos] or LineA8A1[NumPos] or LineA1H1[NumPos] or LineH1A1[NumPos]);
 //DrawPiece(NumPos,3,0);
 //DrawMoveBox(LineA1H8[NumPos] or LineH8A1[NumPos] or LineA8H1[NumPos] or LineH1A8[NumPos]);
 //рисуем черного коня из позиции - Кликнули по полю 
 DrawPiece(NumPos,4,1);
// 18446744073709551615 - все биты вкл
if (NumPos=14) or (NumPos=36) or (NumPos=39) then flag:=true
else flag:=false;
//начинаем обход доски конем
 KnightGO(NumPos,18446744073709551615,flag);
   //DrawPiece(NumPos,4,0);
  // DrawMoveBox(KnightAttak[NumPos]);
 //тест
end;
Last Edit: 07 Дек 2022 23:50 by alexlaw.

Bitboard в программировании шахмат №2 07 Дек 2022 19:02 #80

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Для условияalexlaw wrote:
if best<min then begin
не выполняется в 3 случаях

15-1.jpg


15-2.jpg


15-3.jpg


Для этого меняем
if best<=min then

тогда для других 3 полей не будет выполняться

Т.е. если внести небольшую правку на эти три поля, то задача решена
Last Edit: 07 Дек 2022 19:08 by alexlaw.

Bitboard в программировании шахмат №2 08 Дек 2022 08:01 #81

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Еще одна задача.

Задача о неприкосновенном короле
У белых — король на с6 (с3, f6 или f3) и ферзь, у чёрных — король. Всегда ли белые могут, не двигая своего короля, дать мат?
Решение удалось получить при помощи ЭВМ (А. Л. Брудно и И. Я. Ландау, 1969). Мат даётся не позднее 23-го хода при любом положении ферзя и чёрного короля.
При других положениях белого короля и свободном чёрном короле мат поставить нельзя.

16.jpg


Какой алгоритм можете предложить, для решения этой задачи?
Я имею ввиду математическую модель.

Bitboard в программировании шахмат №2 08 Дек 2022 09:47 #82

  • Andralex
  • Andralex's Avatar
  • OFFLINE
  • Боярин
  • на уровне 2 разряда
  • Posts: 2533
  • Thank you received: 67
  • Karma: 17
Какой алгоритм можете предложить, для решения этой задачи?

Стратегический план. Просчитать, на каком поле при неподвижности белого короля его чёрный коллега получает мат. Например, при белом короле на c6 это гибельные для чёрного поля a5, a6, a7, a8, b8, c8 и d8при условии размещения ферзя на b5, b6, b7, c7 и d7 соответственно.

Реализация плана. Манёвры ферзя.
очевидно, первым делом отсекаются ходы ферзя, ведущие к пату. Например, Qh2+ или Qg3.
...не мы первые, не мы последние...

Bitboard в программировании шахмат №2 08 Дек 2022 09:59 #83

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Andralex wrote:
Реализация плана. Манёвры ферзя.
Интуитивно чувствую, что Ферзь должен гнать черного короля к белому, держась от него на расстоянии хода коня, т.е. буквой Г
конечно избегать пата.


Animation2_2022-12-08.gif
Last Edit: 08 Дек 2022 19:36 by alexlaw.

Bitboard в программировании шахмат №2 08 Дек 2022 10:45 #84

  • Andralex
  • Andralex's Avatar
  • OFFLINE
  • Боярин
  • на уровне 2 разряда
  • Posts: 2533
  • Thank you received: 67
  • Karma: 17
Если белый король стоит на одной из центральных клеток d4-d5-e4-e5, то неясно, на каком поле ферзь заматует. Очень далеко до края доски, чёрный запросто убежит от шахов. :unsure:
...не мы первые, не мы последние...

Bitboard в программировании шахмат №2 08 Дек 2022 11:14 #85

  • Vladimirovich
  • Vladimirovich's Avatar
  • OFFLINE
  • Инквизитор
  • Posts: 106785
  • Thank you received: 2073
  • Karma: 105
Надо с хвоста решение смотреть

Например







8/8/2K5/8/1k6/8/2Q5/8 b - - 1 5

5. ... Ka3 6. Qb1 Ka4 7. Qb2 Ka5 8. Qa3# 1-0

И строить такие позиции в обратную сторону
Каждому - своё.

Bitboard в программировании шахмат №2 08 Дек 2022 11:20 #86

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Vladimirovich wrote:
Например
Ну да. Так и есть.
Осталось логику сформулировать.
Для белых одна логика, для черного падишаха другая.
Например стараться держаться в углу.
Как насчет логического описания?
Сможем совместно?

Bitboard в программировании шахмат №2 08 Дек 2022 11:36 #87

  • Vladimirovich
  • Vladimirovich's Avatar
  • OFFLINE
  • Инквизитор
  • Posts: 106785
  • Thank you received: 2073
  • Karma: 105
Не. Я шахматист и головоломки с шахматными фигурками фигурками меня не интересуют, особенно практически бесполезные.
Логики там нет. Есть цепь позиций которую надо построить.
Так, надо придумать маневр для начала выковыривания черного короля с а1
Каждому - своё.

Bitboard в программировании шахмат №2 08 Дек 2022 11:51 #88

  • Andralex
  • Andralex's Avatar
  • OFFLINE
  • Боярин
  • на уровне 2 разряда
  • Posts: 2533
  • Thank you received: 67
  • Karma: 17
Как насчет логического описания?

Тут надо создать переменную Radius которая при рассмотрении программой каждого из 8 ходов во вложенных циклах определяет расстояние между королями по
формуле
Radius := (КЧ2-КБ2),
где КЧ и КБ - координаты королей.

Чем длиннее, тем дальше чёрный король от белого.
Как в боксе, близко к канатам.


PS. Ещё лучше, для упорства чёрных, ввести массив повторённых ходов.
...не мы первые, не мы последние...

Bitboard в программировании шахмат №2 08 Дек 2022 12:11 #89

  • Vladimirovich
  • Vladimirovich's Avatar
  • OFFLINE
  • Инквизитор
  • Posts: 106785
  • Thank you received: 2073
  • Karma: 105
Как-то так








8/8/2K5/8/8/8/3Q4/k7 w - - 1 1

1. Qb4 Ka2 2. Qd4!

И тут три варианта

Самое упорное 2...Kb1
Остальное уже даже можно посчитать
Например

1. Qb4 Ka2 2. Qd4 Kb3 3. Qd2 Kc4 4. Qe3 Kb4 5. Qd3 Ka4 6. Qb5+ Ka3 7. Qb1








8/8/2K5/8/8/k7/8/1Q6 b - - 14 7

Т.е загнать в угол, а дальше задача сводится к предыдущей.
Но все эти ферзевые маневры в начальной позиции считать человечески увольте.
Каждому - своё.

Bitboard в программировании шахмат №2 11 Дек 2022 04:29 #90

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Дьяк
  • Posts: 183
  • Thank you received: 8
  • Karma: 1
Andralex wrote:
Radius := √(КЧ2-КБ2),
Это конечно не реалистичный метод.Andralex wrote:
Чем длиннее, тем дальше чёрный король от белого.
Расстояние определяется проще
Пример h1 - Pos:=63;-черный король
00111111 and 00000111 = 111; 50 and 7 = 7
00111111 shr 3 = 111; 50 shr 3 = 7
с6 - Pos:=18;
18 and 7 = 2
18 shr 3 = 2
A8 - a=0,b=0 H1 - a=7,b=7
a:=Pos and 7;//0..7 горизонталь (буквы)
b:=Pos shr 3;//0..7 вертикаль (цифры)
Расстояние между h1 и c6
(7-2)+(7-2)=10!

По поводу алгоритма - неприкосновенный король.
Можно заметить, что где бы белый король не находился (на с6 (с3, f6 или f3) ) - можно виртуально повернуть доску и сразу отсечь множество вариантов.
Поэтому снова вернулся к вращаемым битбоардам.
Немного по разбирался

Animation3.gif

//функция позвращает номер поля в повернутом битбоарде
function RotatePos(const Value,mode: integer): integer;
var
a,b,c: Integer;
begin
a:=Value and 7;//0..7 горизонталь (буквы)
b:=Value shr 3;//0..7 вертикаль (цифры)
//0 - нормальное расположение a и b не меняем
result:=a+8*b;
c:=0;
case mode  of
//180 - поворот на 180
   180:begin
   a:=7-a;
   b:=7-b;
   result:=a+8*b;
   end;
//поворот по часовой (вправо) на 90
   90:begin
   c:=a;
   a:=7-b;
   b:=c;
   result:=63-(a+8*b);
   end;
//поворот против часовой (влево) на 90 или по часовой (вправо) на 270
   270:begin
   c:=b;
   b:=7-a;
   a:=c;
   result:=63-(a+8*b);
   end;
end;
end;

В принципе биты повернуть в 64 битном числе оказалось не сложно.
Last Edit: 11 Дек 2022 04:33 by alexlaw.
Moderators: Grigoriy
Рейтинг@Mail.ru

Научно-шахматный клуб КвантоФорум