From 49f4ffc380a7aade5c8951c94dcc296002c3d219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hatvani=20Tam=C3=A1s?= <75033623+htamas1210@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:41:29 +0100 Subject: [PATCH 01/35] Document system requirements for chess application Added system requirements and specifications for a two-player chess application, detailing functional, client-side, server-side, non-functional requirements, and components. --- Docs/kovspec.md | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 Docs/kovspec.md diff --git a/Docs/kovspec.md b/Docs/kovspec.md new file mode 100644 index 0000000..d7d7bc5 --- /dev/null +++ b/Docs/kovspec.md @@ -0,0 +1,101 @@ +## 4. Rendszer követelmények + +A rendszer célja egy kétjátékos sakkalkalmazás megvalósítása, amely alapvetően hálózati kapcsolat (LAN vagy internet) segítségével biztosítja a valós idejű játékot. A rendszer kliens–szerver architektúrán alapul, ahol az egyes komponensek jól elkülönülten, meghatározott feladatokat látnak el. + +### 4.1 Kötelező funkcionális követelmények + +A rendszernek az alábbi alapvető funkciókat mindenképpen biztosítania kell: +- Két játékos közötti sakkjátszma lebonyolítása, a hivatalos sakk szabályai alapján. +- A játékosok felváltva tehetnek lépéseket, a lépések érvényességét a kliens oldali logika ellenőrzi. +- A rendszer valós időben szinkronizálja a két kliens állapotát (mindkét fél ugyanazt a táblát látja). +- A játék vége (sakkmatt, patt, idő lejárta) automatikusan felismerésre kerül. +- A szerver egyidejűleg több játékot is képes kezelni (külön szobákban vagy sessionökben). +- A játékosok elindíthatnak új meccset, illetve befejezett játék után visszatérhetnek a főmenübe. +- A rendszer minden játékban egyedi azonosítót (Game ID) használ a játékállapot nyomon követéséhez. +- A kliens értesítéseket kap az ellenfél lépéseiről és a játék állapotváltozásairól. + +### 4.2 Kliens oldali követelmények + +A kliens felelős a játékos felhasználói élményéért, a grafikus megjelenítésért és a játéklogika helyi működéséért. + +A kliensnek tudnia kell: +- A sakk tábla és a figurák megjelenítése, lépések kezelése (egérkattintás vagy billentyűparancsok). +- Lépések érvényesítése és elküldése a szervernek. +- A szervertől érkező események (ellenfél lépése, állapotváltozás) feldolgozása és megjelenítése. +- Hibák és megszakadt kapcsolat kezelése (újracsatlakozási lehetőség). +- Saját IP vagy szerver cím megadása LAN esetén. +- Alapvető menürendszer (csatlakozás, szerverindítás, új játék, kilépés). +- A hálózati kommunikáció egységes formátumban történjen (pl. JSON alapú üzenetek). + +### 4.3 Szerver oldali követelmények + +A szerver feladata a kliensek közti kommunikáció kezelése, az állapotok szinkronizálása és a játék logikai integritásának megőrzése. + +A szervernek tudnia kell: +- Kapcsolatok fogadása és kezelése több kliens esetén is. +- Új játék (session) létrehozása és azonosító kiosztása. +- Üzenetek továbbítása a kliensek között (pl. lépés, visszajelzés, játék vége). +- A játékállapot naprakészen tartása és küldése mindkét félnek. +- Kapcsolat megszakadása esetén az érintett játék szüneteltetése vagy lezárása. +- Üzenetformátumok ellenőrzése és hibás adatok elutasítása. +- Kliensazonosítás és egyszerű hitelesítés (pl. játékosnév alapján). +- A kommunikáció biztonságos kezelése (üzenetduplikáció, szinkronizációs hibák elkerülése). + +### 4.4 A komponensek közti kommunikáció (szerződések) + +A rendszer komponensei egy meghatározott üzenetprotokollon keresztül kommunikálnak egymással. +A kommunikáció kétirányú, valós idejű, és az alábbi szerződések szerint zajlik: + +A kliens minden lépést csak akkor hajt végre a felhasználói felületen, ha a szervertől visszaigazolást kapott az érvényességéről. +A szerver az üzeneteket sorosítva, FIFO-elv szerint dolgozza fel, és broadcastolja a változásokat az adott játékhoz tartozó összes kliensnek. + +### 4.5 Nem funkcionális követelmények + +- Megbízhatóság: a rendszernek stabilan kell működnie hálózati késleltetés és csomagvesztés esetén is. +- Teljesítmény: a szerver legalább 10 párhuzamos játékot képes kezelni érezhető lassulás nélkül. +- Biztonság: a kliens csak a szerver által engedélyezett parancsokat hajthatja végre. +- Bővíthetőség: a rendszer felépítése moduláris legyen, hogy később könnyen kiterjeszthető legyen (pl. online matchmaking). +- Platformfüggetlenség: a kliens és a szerver futtatható legyen Windows, Linux és esetleg webes környezetben. +- Karbantarthatóság: kódmodulok (logika, hálózat, UI) elkülönítése, jól dokumentált interfészekkel. + +### 4.6 Minimális technikai elvárások + +- Programozási nyelv: Rust, C#, Python vagy más, hálózati alkalmazásokra alkalmas nyelv. +- Kommunikációs protokoll: TCP vagy WebSocket alapú kapcsolat. +- Adatcsere formátum: JSON. +- Grafikus felület: desktop GUI (pl. egérvezérlés, drag & drop lépés). +- Követelmény kliensoldalon: legalább 4 GB RAM, modern operációs rendszer. +- Követelmény szerveroldalon: 1 CPU mag, 512 MB RAM, állandó hálózati kapcsolat. + +## 5. Követelménylista + +### Szerver +| Név | Verzió | Leírás | +| --- | ------ | ------ | +| **WebSocket** | 1.0 | A szerver és a kliens között folyamatos kétirányú kommunikációt biztosít. A kapcsolat létrejötte után a szerver valós időben képes fogadni és továbbítani az eseményeket (pl. lépés végrehajtása, állapotfrissítés). Hiba esetén a kapcsolat automatikusan újraépül. | +| **Kapcsolatok csoportosítása** | 1.0 | A szerver figyeli az elérhető, szabad klienseket, majd két szabad kapcsolatot automatikusan összerendel egy meccsbe. A csoportosítás után a játékosok azonos „room”-ba kerülnek, és a szerver biztosítja az egymás közötti adatkommunikációt. | +| **Kommunikáció az engine-nel** | 1.0 | A szerver a játékosoktól érkező lépéseket és játékinformációkat továbbítja az engine-nek feldolgozásra. Az engine válasza után a szerver visszaküldi az eredményt a klienseknek (pl. érvényes lépés, matt, patt). A kommunikáció aszinkron módon zajlik, válaszidő-ellenőrzéssel. | +| **Kommunikáció a UI-al** | 1.0 | A szerver WebSocket-en keresztül adatokat továbbít a felhasználói felület és az engine között. A UI által kért műveletek (pl. új meccs létrehozása, állapotlekérés) feldolgozását a szerver közvetíti.| +### Engine +| Név | Verzió | Leírás | +| --- | ------ | ------ | +| **Bitboard** | 1.0 | A játék táblaállapotát bitműveletekkel reprezentálja a hatékonyság érdekében. Minden bábu típus és szín külön bitmask-on kerül tárolásra, lehetővé téve a gyors lekérdezéseket és lépésellenőrzéseket. | +| **Lépésgenerálás LUT** | 1.0 | Előre kiszámított lookup táblák segítségével gyorsítja a lépésgenerálást és szabályellenőrzést. Ez csökkenti a számítási időt, és optimalizálja az engine teljesítményét. | +| **Lépésgenerálás** | 1.0 | A különböző bábutípusok (gyalog, bástya, futó, stb.) lépési logikáját valósítja meg. A függvények ellenőrzik a lépés érvényességét, figyelembe véve az aktuális állást, sakkhelyzetet és speciális szabályokat (pl. sáncolás, en passant). | +| **Util függvények** | 1.0 | Segédfüggvények az engine belső működéséhez, például raycast műveletek, bitműveleti maszkok kezelése, valamint logikai ellenőrzések a lépések és ütések számításához. | + +### UI +| Név | Verzió | Leírás | +| --- | ------ | ------ | +| **Belépés** | 1.0 | A felhasználó a kezdőképernyőn keresztül adhatja meg a nevét lokális játékhoz, vagy hitelesítheti magát online játékmód esetén. Hibás adatok esetén a rendszer figyelmeztetést küld. | +| **Főmenü** | 1.0 | Az alkalmazás központi navigációs felülete, ahol a felhasználó meccset kereshet, új játékot indíthat lokálisan, vagy beállításokat módosíthat. A menü megjeleníti az aktuális státuszt (online/offline). | +| **Játék** | 1.0 | A játékfelület megjeleníti a táblát, bábukat, lépéseket, és az aktuális játékállást. Támogatja mind az online, mind a lokális módot. A felület kezeli az interakciókat (lépéskattintás, visszavonás, végeredmény kijelzés). | +| **Kommunikáció a szerverrel** | 1.0 | A kliens a szerveren keresztül kommunikál az engine-nel. A UI felel az üzenetek küldéséért (lépés, új játék, visszajelzés), valamint a szervertől kapott események vizuális megjelenítéséért. | + + +### GitHub Actions (CI/CD) +| Név | Leírás | +| --- | ------ | +| Folyamatos tesztelés | A projekt minden commit után automatikusan tesztelődik. A pipeline lefuttatja a teszteket, és értesítést küld hibás build esetén. | +| Folyamatos integráció | Az új funkciók beolvadásakor a rendszer automatikusan integrálja a változtatásokat, új buildet hoz létre, és frissíti a fejlesztői környezetet. | +| Tesztadatok | A tesztadatok legyenek elérhetőek egy táblázatban, dátummal ellátva. (Google Sheets) | From 1788cce42ddf75d00a0a16244d1a953a3d6d4770 Mon Sep 17 00:00:00 2001 From: Bence <76205860+kbence04@users.noreply.github.com> Date: Tue, 4 Nov 2025 12:01:25 +0100 Subject: [PATCH 02/35] =?UTF-8?q?K=C3=B6vspec=20=C3=A1ttekint=C3=A9s,=20v?= =?UTF-8?q?=C3=A1gy=C3=A1lom=20rendszer=20hozz=C3=A1ad=C3=A1sa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Docs/kovspec.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Docs/kovspec.md b/Docs/kovspec.md index d7d7bc5..a90794f 100644 --- a/Docs/kovspec.md +++ b/Docs/kovspec.md @@ -1,3 +1,27 @@ +# Követelmény-specifikáció + +## 1. Áttekintés + +A jelen dokumentum célja, hogy bemutassa a CastlingCreations megrendelésére készülő Knightly nevű alkalmazás alapvető céljait, funkcionális és nem funkcionális követelményeinek áttekintését, valamint a fejlesztés kontextusát. + +A Knightly egy modern, digitális sakkalkalmazás, amely kezdetben helyi hálózaton (LAN) keresztül teszi lehetővé két játékos számára, hogy valós időben mérkőzzenek meg egymással. A rendszer egy grafikus felhasználói felületen keresztül biztosítja a játék indítását, a szerver futtatását és a másik félhez történő csatlakozást. + +A projekt hosszú távú célja, hogy a Knightly egy online platformmá fejlődjön, amely hasonló módon működik, mint a népszerű sakkportálok (pl. chess.com): a felhasználók fiókot hozhatnak létre, bejelentkezhetnek, és egy központi szerveren keresztül kereshetnek, illetve indíthatnak mérkőzéseket. + +A fejlesztés első szakasza azonban a LAN-alapú verzió megvalósítására koncentrál, amely a sakkjátszma logikai alapjainak, a játékállapot kezelésének és a hálózati kommunikáció modelljének megvalósítását célozza. A későbbi online verzió ezekre az alapokra építkezve bővíthető tovább. + +## 2. Vágyálom rendszer +A vágyálom rendszer célja egy teljes körű, modern online sakkplatform létrehozása, amely nemcsak a klasszikus sakkjáték digitális megvalósítását kínálja, hanem egy közösségi, versenyképes és kényelmes felhasználói élményt is biztosít. A hosszú távú cél, hogy a rendszer működése és felépítése a nagyobb nemzetközi sakkoldalakhoz (például a chess.com-hoz vagy a lichess.org-hoz) hasonló legyen, de saját, könnyen kezelhető és letisztult felülettel. + +A felhasználók a rendszerben saját profilt hozhatnak létre, amellyel be tudnak jelentkezni, és részt vehetnek online mérkőzéseken más játékosok ellen. A rendszer automatikusan párosítaná őket ellenfelekkel, de lehetőséget adna arra is, hogy barátokat hívjanak meg privát meccsekre. A lejátszott mérkőzések mentésre kerülnének, így a játékosok bármikor visszanézhetnék vagy elemezhetnék azokat. + +A játék mellett a felhasználók statisztikákat is láthatnának magukról, például nyerési arányt, aktuális értékszámot (rating), leggyakoribb megnyitásokat, illetve fejlődési tendenciát az idő során. A rendszer ezen felül egy egyszerű chat funkciót is tartalmazna, hogy a játékosok kommunikálhassanak egymással a játszmák közben vagy akár azokon kívül is. + +A vágyálom rendszer alapját egy központi szerver képezné, amely kezeli a felhasználói fiókokat, a bejelentkezéseket, a matchmaking folyamatot, valamint a játékok futását és szinkronizálását. A szerver a kliensalkalmazásokkal valós idejű adatkapcsolatot tartana fenn, így a játék során minden lépés azonnal megjelenne a másik játékosnál is. + +A platform célja a megbízható és folyamatos működés, akár nagyobb terhelés mellett is. A rendszer fejlesztése során kiemelt szempont lenne a biztonság (adatvédelem, csalás elleni védelem), a stabil hálózati kommunikáció, valamint a bővíthetőség – például ranglisták, versenyek vagy mobilalkalmazás későbbi integrálásának lehetősége. + +Összességében a vágyálom rendszer egy minden szempontból teljes értékű, közösségorientált sakkalkalmazás lenne, amely a mostani, helyi hálózaton működő változatból fejlődne tovább egy interneten keresztül bárhonnan elérhető platformmá. ## 4. Rendszer követelmények A rendszer célja egy kétjátékos sakkalkalmazás megvalósítása, amely alapvetően hálózati kapcsolat (LAN vagy internet) segítségével biztosítja a valós idejű játékot. A rendszer kliens–szerver architektúrán alapul, ahol az egyes komponensek jól elkülönülten, meghatározott feladatokat látnak el. From bfb2a6db234cdbcf0534922c637061a0ce145055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Mon, 10 Nov 2025 13:13:03 +0100 Subject: [PATCH 03/35] added file and module structure for attackmaps.rs --- engine/src/bitboard.rs | 1 + engine/src/bitboard/attackmaps.rs | 0 engine/src/main.rs | 2 ++ 3 files changed, 3 insertions(+) create mode 100644 engine/src/bitboard.rs create mode 100644 engine/src/bitboard/attackmaps.rs diff --git a/engine/src/bitboard.rs b/engine/src/bitboard.rs new file mode 100644 index 0000000..e026910 --- /dev/null +++ b/engine/src/bitboard.rs @@ -0,0 +1 @@ +mod attackmaps; \ No newline at end of file diff --git a/engine/src/bitboard/attackmaps.rs b/engine/src/bitboard/attackmaps.rs new file mode 100644 index 0000000..e69de29 diff --git a/engine/src/main.rs b/engine/src/main.rs index e7a11a9..3555c81 100644 --- a/engine/src/main.rs +++ b/engine/src/main.rs @@ -1,3 +1,5 @@ +mod bitboard; + fn main() { println!("Hello, world!"); } From 033440fbac934afc9acd194e5c029eec8704d208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Mon, 10 Nov 2025 13:18:48 +0100 Subject: [PATCH 04/35] added dependency to Cargo.toml: once_cell --- engine/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/Cargo.toml b/engine/Cargo.toml index 43489a8..15addf3 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" edition = "2024" [dependencies] +once_cell = "1.19" \ No newline at end of file From 18f4060df0762ef869797597e4db65ce51504424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Mon, 10 Nov 2025 15:28:15 +0100 Subject: [PATCH 05/35] added frame and tests for table: KING_ATTACK_MAP --- engine/src/bitboard/attackmaps.rs | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/engine/src/bitboard/attackmaps.rs b/engine/src/bitboard/attackmaps.rs index e69de29..65d9f00 100644 --- a/engine/src/bitboard/attackmaps.rs +++ b/engine/src/bitboard/attackmaps.rs @@ -0,0 +1,54 @@ +use once_cell::sync::Lazy; + +pub static KING_ATTACK_MAP: Lazy<[u64; 64]> = Lazy::new(|| { + let table: [u64; 64] = [0u64; 64]; + return table; +}); + +// <----- TESTS -----> + +#[cfg(test)] +mod tests { + use super::*; + + + #[test] + fn test_king_attack_map() { + + // test setup for corners [SW, SE, NW, NE] + let corner_indexes: [usize; 4] = [0, 7, 56, 63]; + let corner_attack_maps: [u64; 4] = [ + (1u64 << 1) | (1u64 << 8) | (1u64 << 9), + (1u64 << 6) | (1u64 << 14) | (1u64 << 15), + (1u64 << 48) | (1u64 << 49) | (1u64 << 57), + (1u64 << 54) | (1u64 << 55) | (1u64 << 62) + ]; + + // tests for corners + for index in 0..4 { + assert_eq!(KING_ATTACK_MAP[corner_indexes[index]], corner_attack_maps[index]); + } + + // test setup for sides [S, E, W, N] + let side_indexes: [usize; 4] = [3, 31, 32, 60]; + let side_attack_maps: [u64; 4] = [ + (1 << 2) | (1 << 4) | (1 << 10) | (1 << 11) | (1 << 12), + (1 << 22) | (1 << 23) | (1 << 30) | (1 << 38) | (1 << 39), + (1 << 24) | (1 << 25) | (1 << 33) | (1 << 40) | (1 << 41), + (1 << 51) | (1 << 52) | (1 << 53) | (1 << 59) | (1 << 61) + ]; + + // tests for sides + for index in 0..4 { + assert_eq!(KING_ATTACK_MAP[side_indexes[index]], side_attack_maps[index]); + } + + // test setup for center + let center_index: usize = 27; + let center_attack_map: u64 = (1 << 18) | (1 << 19) | (1 << 20) | (1 << 26) | (1 << 28) | (1 << 34) | (1 << 35) | (1 << 36); + + // test for center + assert_eq!(KING_ATTACK_MAP[center_index], center_attack_map); + + } +} \ No newline at end of file From b252f16b2de60391fa8633e1ccf8428a0291f523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Mon, 10 Nov 2025 15:50:58 +0100 Subject: [PATCH 06/35] added frame and tests for table: PAWN_ATTACK_MAP --- engine/src/bitboard/attackmaps.rs | 56 ++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/engine/src/bitboard/attackmaps.rs b/engine/src/bitboard/attackmaps.rs index 65d9f00..f728374 100644 --- a/engine/src/bitboard/attackmaps.rs +++ b/engine/src/bitboard/attackmaps.rs @@ -1,17 +1,23 @@ use once_cell::sync::Lazy; +// KING_ATTACK_MAP[] pub static KING_ATTACK_MAP: Lazy<[u64; 64]> = Lazy::new(|| { let table: [u64; 64] = [0u64; 64]; return table; }); +// PAWN_ATTACK_MAP +pub static PAWN_ATTACK_MAP: Lazy<[[u64; 2]; 64]> = Lazy::new(|| { + let table: [[u64; 2]; 64] = [[0u64; 2]; 64]; + return table; +}); + // <----- TESTS -----> #[cfg(test)] mod tests { use super::*; - #[test] fn test_king_attack_map() { @@ -51,4 +57,52 @@ mod tests { assert_eq!(KING_ATTACK_MAP[center_index], center_attack_map); } + + #[test] + fn test_pawn_attack_map() { + + // test setup for white sides + let white_side_indexes: [usize; 2] = [24, 31]; + let white_side_attack_maps: [u64; 2] = [ + (1 << 33), + (1 << 38) + ]; + // tests for white sides + for index in 0..2 { + assert_eq!(PAWN_ATTACK_MAP[white_side_indexes[index]][0], white_side_attack_maps[index]) + } + + // test setup for black sides + let black_side_indexes: [usize; 2] = [32, 39]; + let black_side_attack_maps: [u64; 2] = [ + (1 << 25), + (1 << 30) + ]; + // tests for black sides + for index in 0..2 { + assert_eq!(PAWN_ATTACK_MAP[black_side_indexes[index]][1], black_side_attack_maps[index]) + } + + // test setup for white center + let white_center_indexes: [usize; 2] = [11, 12]; + let white_center_attack_maps: [u64; 2] = [ + (1 << 19) | (1 << 21), + (1 << 20) | (1 << 22) + ]; + // tests for white center + for index in 0..2 { + assert_eq!(PAWN_ATTACK_MAP[white_center_indexes[index]][0], white_center_attack_maps[index]) + } + + // test setup for black center + let black_center_indexes: [usize; 2] = [51, 52]; + let black_center_attack_maps: [u64; 2] = [ + (1 << 42) | (1 << 44), + (1 << 43) | (1 << 45) + ]; + // tests for black center + for index in 0..2 { + assert_eq!(PAWN_ATTACK_MAP[black_center_indexes[index]][1], black_center_attack_maps[index]) + } + } } \ No newline at end of file From 5d748b07d20c86fa2327e06fe0e5a64a67e8fdf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Mon, 10 Nov 2025 16:54:14 +0100 Subject: [PATCH 07/35] added frame and tests for table: KNIGHT_ATTACK_MAP --- engine/src/bitboard/attackmaps.rs | 54 ++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/engine/src/bitboard/attackmaps.rs b/engine/src/bitboard/attackmaps.rs index f728374..f33cc04 100644 --- a/engine/src/bitboard/attackmaps.rs +++ b/engine/src/bitboard/attackmaps.rs @@ -1,17 +1,31 @@ use once_cell::sync::Lazy; +/* + EXPLANATIONS: + > square index: 8 * rank number + file number (a-h = 0-7) + > side: white = 0, black = 1 +*/ + // KING_ATTACK_MAP[] pub static KING_ATTACK_MAP: Lazy<[u64; 64]> = Lazy::new(|| { let table: [u64; 64] = [0u64; 64]; return table; }); -// PAWN_ATTACK_MAP +// PAWN_ATTACK_MAP[][] pub static PAWN_ATTACK_MAP: Lazy<[[u64; 2]; 64]> = Lazy::new(|| { let table: [[u64; 2]; 64] = [[0u64; 2]; 64]; return table; }); +// KINGHT_ATTACK_MAP[] +pub static KNIGHT_ATTACK_MAP: Lazy<[u64; 64]> = Lazy::new(|| { + let table: [u64; 64] = [0u64; 64]; + return table; +}); + + + // <----- TESTS -----> #[cfg(test)] @@ -105,4 +119,42 @@ mod tests { assert_eq!(PAWN_ATTACK_MAP[black_center_indexes[index]][1], black_center_attack_maps[index]) } } + + #[test] + fn test_knight_attack_map() { + // test setup for corners [SW, SE, NW, NE] + let corner_indexes: [usize; 4] = [0, 7, 56, 63]; + let corner_attack_maps: [u64; 4] = [ + (1 << 17) | (1 << 10), + (1 << 13) | (1 << 22), + (1 << 41) | (1 << 50), + (1 << 46) | (1 << 53) + ]; + + // tests for corners + for index in 0..4 { + assert_eq!(KNIGHT_ATTACK_MAP[corner_indexes[index]], corner_attack_maps[index]); + } + + // test setup for sides [S, E, W, N] + let side_indexes: [usize; 4] = [3, 31, 32, 60]; + let side_attack_maps: [u64; 4] = [ + (1 << 9) | (1 << 13) | (1 << 18) | (1 << 20), + (1 << 14) | (1 << 21) | (1 << 37) | (1 << 46), + (1 << 17) | (1 << 26) | (1 << 42) | (1 << 49), + (1 << 43) | (1 << 45) | (1 << 50) | (1 << 54) + ]; + + // tests for sides + for index in 0..4 { + assert_eq!(KNIGHT_ATTACK_MAP[side_indexes[index]], side_attack_maps[index]); + } + + // test setup for center + let center_index: usize = 27; + let center_attack_map: u64 = (1 << 10) | (1 << 12) | (1 << 17) | (1 << 21) | (1 << 33) | (1 << 37) | (1 << 42) | (1 << 44); + + // test for center + assert_eq!(KNIGHT_ATTACK_MAP[center_index], center_attack_map); + } } \ No newline at end of file From 21f2890b924e12cb7287facea273720d95b11c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Mon, 10 Nov 2025 17:17:30 +0100 Subject: [PATCH 08/35] added frame and tests for table: RAY_TABLE --- engine/src/bitboard/attackmaps.rs | 33 +++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/engine/src/bitboard/attackmaps.rs b/engine/src/bitboard/attackmaps.rs index f33cc04..47a9b9f 100644 --- a/engine/src/bitboard/attackmaps.rs +++ b/engine/src/bitboard/attackmaps.rs @@ -2,8 +2,9 @@ use once_cell::sync::Lazy; /* EXPLANATIONS: - > square index: 8 * rank number + file number (a-h = 0-7) + > square_index: 8 * rank number + file number (a-h = 0-7) > side: white = 0, black = 1 + > direction_index: 0..8 = [E, NE, N, NW, W, SW, S, SE] */ // KING_ATTACK_MAP[] @@ -18,12 +19,18 @@ pub static PAWN_ATTACK_MAP: Lazy<[[u64; 2]; 64]> = Lazy::new(|| { return table; }); -// KINGHT_ATTACK_MAP[] +// KNIGHT_ATTACK_MAP[] pub static KNIGHT_ATTACK_MAP: Lazy<[u64; 64]> = Lazy::new(|| { let table: [u64; 64] = [0u64; 64]; return table; }); +// RAY_TABLE[][] +pub static RAY_TABLE: Lazy<[[u64; 8]; 64]> = Lazy::new(|| { + let table: [[u64; 8]; 64] = [[0u64; 8]; 64]; + return table; +}); + // <----- TESTS -----> @@ -157,4 +164,26 @@ mod tests { // test for center assert_eq!(KNIGHT_ATTACK_MAP[center_index], center_attack_map); } + + #[test] + fn test_ray_table() { + + // test setup for all directions from center + let starting_square_index: usize = 27; + let ray_masks: [u64; 8] = [ + (1 << 28) | (1 << 29) | (1 << 30) | (1 << 31), + (1 << 36) | (1 << 45) | (1 << 54) | (1 << 63), + (1 << 35) | (1 << 43) | (1 << 51) | (1 << 59), + (1 << 34) | (1 << 41) | (1 << 48), + (1 << 26) | (1 << 25) | (1 << 24), + (1 << 18) | (1 << 9) | (1 << 0), + (1 << 19) | (1 << 11) | (1 << 3), + (1 << 20) | (1 << 13) | (1 << 6) + ]; + + // tests for all directions from starting_square + for direction in 0..8 { + assert_eq!(RAY_TABLE[starting_square_index][direction], ray_masks[direction]); + } + } } \ No newline at end of file From c2fe2e968a475a86fd35c856fedd3fdd1d0a0bdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 10:22:05 +0100 Subject: [PATCH 09/35] added masks for use against wrap-around --- engine/src/bitboard/attackmaps.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/engine/src/bitboard/attackmaps.rs b/engine/src/bitboard/attackmaps.rs index 47a9b9f..d5136e9 100644 --- a/engine/src/bitboard/attackmaps.rs +++ b/engine/src/bitboard/attackmaps.rs @@ -1,5 +1,10 @@ use once_cell::sync::Lazy; +const A_FILE: u64 = 0x0101_0101_0101_0101; +const H_FILE: u64 = 0x8080_8080_8080_8080; +const AB_FILE: u64 = 0x0303_0303_0303_0303; +const GH_FILE: u64 = 0xC0C0_C0C0_C0C0_C0C0; + /* EXPLANATIONS: > square_index: 8 * rank number + file number (a-h = 0-7) From 4eb4bc1348ad16627d4c60609233d53bb7fe901f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 10:25:23 +0100 Subject: [PATCH 10/35] implemented the generation of LUT: KING_ATTACK_MAPS --- engine/src/bitboard/attackmaps.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/engine/src/bitboard/attackmaps.rs b/engine/src/bitboard/attackmaps.rs index d5136e9..5852518 100644 --- a/engine/src/bitboard/attackmaps.rs +++ b/engine/src/bitboard/attackmaps.rs @@ -14,7 +14,16 @@ const GH_FILE: u64 = 0xC0C0_C0C0_C0C0_C0C0; // KING_ATTACK_MAP[] pub static KING_ATTACK_MAP: Lazy<[u64; 64]> = Lazy::new(|| { - let table: [u64; 64] = [0u64; 64]; + let mut table: [u64; 64] = [0u64; 64]; + + for sq in 0..64 { + let king: u64 = 1 << sq; + + let left_attacks: u64 = king << 7 | king >> 1 | king >> 9; + let right_attacks: u64 = king << 1 | king << 9 | king >> 7; + + table[sq] = (left_attacks & !H_FILE) | (right_attacks & !A_FILE) | king << 8 | king >> 8; + } return table; }); From b6cdf5b77843cd15a1277684e12101543ba80e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 10:32:41 +0100 Subject: [PATCH 11/35] implemented the generation of LUT: PAWN_ATTACK_MAP --- engine/src/bitboard/attackmaps.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/engine/src/bitboard/attackmaps.rs b/engine/src/bitboard/attackmaps.rs index 5852518..fa229cf 100644 --- a/engine/src/bitboard/attackmaps.rs +++ b/engine/src/bitboard/attackmaps.rs @@ -15,7 +15,7 @@ const GH_FILE: u64 = 0xC0C0_C0C0_C0C0_C0C0; // KING_ATTACK_MAP[] pub static KING_ATTACK_MAP: Lazy<[u64; 64]> = Lazy::new(|| { let mut table: [u64; 64] = [0u64; 64]; - + for sq in 0..64 { let king: u64 = 1 << sq; @@ -29,7 +29,18 @@ pub static KING_ATTACK_MAP: Lazy<[u64; 64]> = Lazy::new(|| { // PAWN_ATTACK_MAP[][] pub static PAWN_ATTACK_MAP: Lazy<[[u64; 2]; 64]> = Lazy::new(|| { - let table: [[u64; 2]; 64] = [[0u64; 2]; 64]; + let mut table: [[u64; 2]; 64] = [[0u64; 2]; 64]; + + for sq in 0..64 { + let pawn: u64 = 1 << sq; + table[sq][0] |= (pawn << 9) & !A_FILE; + table[sq][0] |= (pawn << 7) & !H_FILE; + } + for sq in 0..64 { + let pawn: u64 = 1 << sq; + table[sq][1] |= (pawn >> 9) & !H_FILE; + table[sq][1] |= (pawn >> 7) & !A_FILE; + } return table; }); @@ -121,8 +132,8 @@ mod tests { // test setup for white center let white_center_indexes: [usize; 2] = [11, 12]; let white_center_attack_maps: [u64; 2] = [ - (1 << 19) | (1 << 21), - (1 << 20) | (1 << 22) + (1 << 18) | (1 << 20), + (1 << 19) | (1 << 21) ]; // tests for white center for index in 0..2 { From 1af497f063eeaaaa8eaf33af4cc89e1de6c12234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 10:33:51 +0100 Subject: [PATCH 12/35] implemented the generation of LUT: KNIGHT_ATTACK_MAP --- engine/src/bitboard/attackmaps.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/engine/src/bitboard/attackmaps.rs b/engine/src/bitboard/attackmaps.rs index fa229cf..23c41df 100644 --- a/engine/src/bitboard/attackmaps.rs +++ b/engine/src/bitboard/attackmaps.rs @@ -46,7 +46,18 @@ pub static PAWN_ATTACK_MAP: Lazy<[[u64; 2]; 64]> = Lazy::new(|| { // KNIGHT_ATTACK_MAP[] pub static KNIGHT_ATTACK_MAP: Lazy<[u64; 64]> = Lazy::new(|| { - let table: [u64; 64] = [0u64; 64]; + let mut table: [u64; 64] = [0u64; 64]; + + for sq in 0..64 { + let knight: u64 = 1 << sq; + + let far_left_attacks: u64 = knight << 6 | knight >> 10; + let near_left_attacks: u64 = knight << 15 | knight >> 17; + let far_right_attacks: u64 = knight << 10 | knight >> 6; + let near_right_attacks: u64 = knight << 17 | knight >> 15; + + table[sq] = (far_left_attacks & !GH_FILE) | (far_right_attacks & !AB_FILE) | (near_left_attacks & !H_FILE) | (near_right_attacks & !A_FILE); + } return table; }); From 061795a039705e641d9a0d3185e4912bd0c86da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 10:39:51 +0100 Subject: [PATCH 13/35] implemented the generation of LUT: RAY_TABLE --- engine/src/bitboard/attackmaps.rs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/engine/src/bitboard/attackmaps.rs b/engine/src/bitboard/attackmaps.rs index 23c41df..f7fe35f 100644 --- a/engine/src/bitboard/attackmaps.rs +++ b/engine/src/bitboard/attackmaps.rs @@ -63,7 +63,34 @@ pub static KNIGHT_ATTACK_MAP: Lazy<[u64; 64]> = Lazy::new(|| { // RAY_TABLE[][] pub static RAY_TABLE: Lazy<[[u64; 8]; 64]> = Lazy::new(|| { - let table: [[u64; 8]; 64] = [[0u64; 8]; 64]; + let mut table: [[u64; 8]; 64] = [[0u64; 8]; 64]; + let dirs: [i8; 8] = [1, 9, 8, 7, -1, -9, -8, -7]; + for sq in 0..64 { + for d in 0..8 { + let mut ray: u64 = 0u64; + let origin: u64 = 1 << sq; + let mut new_target: u64 = if dirs[d] > 0 {origin << dirs[d]} else {origin >> -dirs[d]}; + if [0, 1, 7].contains(&d) { + new_target &= !A_FILE; + } + else if [3, 4, 5].contains(&d) { + new_target &= !H_FILE; + } + while new_target != 0 { + ray |= new_target; + + new_target = if dirs[d] > 0 {new_target << dirs[d]} else {new_target >> -dirs[d]}; + if [0, 1, 7].contains(&d) { + new_target &= !A_FILE; + } + else if [3, 4, 5].contains(&d) { + new_target &= !H_FILE; + } + } + table[sq][d] = ray; + } + } + return table; }); From 4e9f222ddc67ffbe90026e701ce8867c44e757e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hatvani=20Tam=C3=A1s?= <75033623+htamas1210@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:01:38 +0100 Subject: [PATCH 14/35] Allow case-insensitive branch checks in dispatcher.yml --- .github/workflows/dispatcher.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dispatcher.yml b/.github/workflows/dispatcher.yml index fed6504..d16fb75 100644 --- a/.github/workflows/dispatcher.yml +++ b/.github/workflows/dispatcher.yml @@ -26,13 +26,13 @@ jobs: SERVER=false UI=false - if [[ "$BRANCH" == *"Engine"* ]]; then + if [[ "$BRANCH" == *"Engine"* ] || [ "$BRANCH" == *"engine"* ]]; then ENGINE=true fi - if [[ "$BRANCH" == *"Server"* ]]; then + if [[ "$BRANCH" == *"Server"* ] || [ "$BRANCH" == *"server"* ]]; then SERVER=true fi - if [[ "$BRANCH" == *"UI"* ]]; then + if [[ "$BRANCH" == *"UI"* ] || [ "$BRANCH" == *"ui"* ]]; then UI=true fi From 1f368551c15b90e548773840a232f86810c3d41f Mon Sep 17 00:00:00 2001 From: htom Date: Tue, 11 Nov 2025 11:12:39 +0100 Subject: [PATCH 15/35] removed pull_request dispatch from the test files --- .github/workflows/dispatcher.yml | 6 +++--- .github/workflows/engine_test.yml | 1 - .github/workflows/server_test.yml | 1 - .github/workflows/ui_test.yml | 1 - 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/dispatcher.yml b/.github/workflows/dispatcher.yml index d16fb75..52556cc 100644 --- a/.github/workflows/dispatcher.yml +++ b/.github/workflows/dispatcher.yml @@ -26,13 +26,13 @@ jobs: SERVER=false UI=false - if [[ "$BRANCH" == *"Engine"* ] || [ "$BRANCH" == *"engine"* ]]; then + if "$BRANCH" == *"Engine"* || "$BRANCH" == *"engine"* ; then ENGINE=true fi - if [[ "$BRANCH" == *"Server"* ] || [ "$BRANCH" == *"server"* ]]; then + if "$BRANCH" == *"Server"* || "$BRANCH" == *"server"* ; then SERVER=true fi - if [[ "$BRANCH" == *"UI"* ] || [ "$BRANCH" == *"ui"* ]]; then + if "$BRANCH" == *"UI"* || "$BRANCH" == *"ui"* ; then UI=true fi diff --git a/.github/workflows/engine_test.yml b/.github/workflows/engine_test.yml index 4590631..3f4bfec 100644 --- a/.github/workflows/engine_test.yml +++ b/.github/workflows/engine_test.yml @@ -1,7 +1,6 @@ name: Engine Tests on: - pull_request: workflow_dispatch: workflow_call: diff --git a/.github/workflows/server_test.yml b/.github/workflows/server_test.yml index f39eae5..4a2e817 100644 --- a/.github/workflows/server_test.yml +++ b/.github/workflows/server_test.yml @@ -1,7 +1,6 @@ name: Server Tests on: - pull_request: workflow_dispatch: workflow_call: diff --git a/.github/workflows/ui_test.yml b/.github/workflows/ui_test.yml index 114283a..7f0ca2c 100644 --- a/.github/workflows/ui_test.yml +++ b/.github/workflows/ui_test.yml @@ -1,7 +1,6 @@ name: UI Tests on: - pull_request: workflow_dispatch: workflow_call: From 4ae9eea7e254842c5136270ac173bcdca74e1583 Mon Sep 17 00:00:00 2001 From: htom Date: Tue, 11 Nov 2025 11:13:45 +0100 Subject: [PATCH 16/35] removed pull_request dispatcher from release workflow --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b3044b9..76e25a0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,6 @@ name: Release build on: - pull_request: workflow_dispatch: workflow_call: From b6f0b6ee5ec612172f3f5450f4b391bfa326da65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hatvani=20Tam=C3=A1s?= <75033623+htamas1210@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:22:21 +0100 Subject: [PATCH 17/35] Fix conditional syntax in dispatcher.yml --- .github/workflows/dispatcher.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dispatcher.yml b/.github/workflows/dispatcher.yml index 52556cc..35e06e1 100644 --- a/.github/workflows/dispatcher.yml +++ b/.github/workflows/dispatcher.yml @@ -26,13 +26,13 @@ jobs: SERVER=false UI=false - if "$BRANCH" == *"Engine"* || "$BRANCH" == *"engine"* ; then + if [["$BRANCH" == *"Engine"* || "$BRANCH" == *"engine"*]] ; then ENGINE=true fi - if "$BRANCH" == *"Server"* || "$BRANCH" == *"server"* ; then + if [["$BRANCH" == *"Server"* || "$BRANCH" == *"server"*]] ; then SERVER=true fi - if "$BRANCH" == *"UI"* || "$BRANCH" == *"ui"* ; then + if [["$BRANCH" == *"UI"* || "$BRANCH" == *"ui"*]] ; then UI=true fi From 0f50f31b13e1d3fca5217322826d692440113a5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hatvani=20Tam=C3=A1s?= <75033623+htamas1210@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:27:42 +0100 Subject: [PATCH 18/35] Update branch checks to be case-sensitive Refactor branch checks to be case-sensitive for Engine, Server, and UI. --- .github/workflows/dispatcher.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dispatcher.yml b/.github/workflows/dispatcher.yml index 35e06e1..b462a84 100644 --- a/.github/workflows/dispatcher.yml +++ b/.github/workflows/dispatcher.yml @@ -26,13 +26,13 @@ jobs: SERVER=false UI=false - if [["$BRANCH" == *"Engine"* || "$BRANCH" == *"engine"*]] ; then + if [["$BRANCH" == *"Engine"*]] ; then ENGINE=true fi - if [["$BRANCH" == *"Server"* || "$BRANCH" == *"server"*]] ; then + if [["$BRANCH" == *"Server"*]] ; then SERVER=true fi - if [["$BRANCH" == *"UI"* || "$BRANCH" == *"ui"*]] ; then + if [["$BRANCH" == *"UI"*]] ; then UI=true fi From 9c73ca6838d32633052e28c5fb457d632175dde7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hatvani=20Tam=C3=A1s?= <75033623+htamas1210@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:34:05 +0100 Subject: [PATCH 19/35] Fix formatting of conditional checks in dispatcher.yml --- .github/workflows/dispatcher.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dispatcher.yml b/.github/workflows/dispatcher.yml index b462a84..0524127 100644 --- a/.github/workflows/dispatcher.yml +++ b/.github/workflows/dispatcher.yml @@ -26,13 +26,13 @@ jobs: SERVER=false UI=false - if [["$BRANCH" == *"Engine"*]] ; then + if [[ "$BRANCH" == *"Engine"* ]] ; then ENGINE=true fi - if [["$BRANCH" == *"Server"*]] ; then + if [[ "$BRANCH" == *"Server"* ]] ; then SERVER=true fi - if [["$BRANCH" == *"UI"*]] ; then + if [[ "$BRANCH" == *"UI"* ]] ; then UI=true fi From 5ee797e1f8e1a51e8c66ea60f5a709d99d0750ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hatvani=20Tam=C3=A1s?= <75033623+htamas1210@users.noreply.github.com> Date: Tue, 11 Nov 2025 12:32:03 +0100 Subject: [PATCH 20/35] Add conditional logging for master branch --- .github/workflows/test.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.sh b/.github/workflows/test.sh index 1191005..f948267 100755 --- a/.github/workflows/test.sh +++ b/.github/workflows/test.sh @@ -30,6 +30,9 @@ echo "$PROJECT_NAME" > "$LOG_FILE" awk '/^running [0-9]+ test[s]?$/,/^$/' full_test_output.log >> "$LOG_FILE" # --- APPEND TO GLOBAL LOG (in repo root) --- +if [[ $(git rev-parse --abbrev-ref HEAD) == "master" ]]; then + echo "master" >> $FINAL_LOG +fi cat "$LOG_FILE" >> "$FINAL_LOG" # --- SUMMARY --- From dca6eac3babc57a222598988ee817f5f09babe00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 12:50:53 +0100 Subject: [PATCH 21/35] added file bitboard/utils.rs --- engine/src/bitboard.rs | 3 ++- engine/src/bitboard/utils.rs | 0 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 engine/src/bitboard/utils.rs diff --git a/engine/src/bitboard.rs b/engine/src/bitboard.rs index e026910..67d128d 100644 --- a/engine/src/bitboard.rs +++ b/engine/src/bitboard.rs @@ -1 +1,2 @@ -mod attackmaps; \ No newline at end of file +mod attackmaps; +mod utils; \ No newline at end of file diff --git a/engine/src/bitboard/utils.rs b/engine/src/bitboard/utils.rs new file mode 100644 index 0000000..e69de29 From 258a8a0da998a6b9c1d45301b947973f9a7c88e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 13:39:26 +0100 Subject: [PATCH 22/35] added frame and tests for function: bitboard::util::pop_lsb --- engine/src/bitboard/utils.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/engine/src/bitboard/utils.rs b/engine/src/bitboard/utils.rs index e69de29..d863a15 100644 --- a/engine/src/bitboard/utils.rs +++ b/engine/src/bitboard/utils.rs @@ -0,0 +1,35 @@ + +pub fn pop_lsb(value: &mut u64) -> usize { + return 0; +} + + + +// <----- TESTS -----> + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn pop_lsb_test() { + + // test setup + let test_values: [u64; 6] = [ + 0x0000_0000_0000_0000, + 0x4E91_CF05_713E_451B, + 0xD588_2D58_6962_34B0, + 0x9581_3335_DCAB_1DD4, + 0xBEAC_DBE0_903A_AC00, + 0x01E8_C895_A6F0_0000 + ]; + let expected_values: [usize; 6] = [64, 0, 4, 2, 10, 20]; + + // tests + for index in 0..6 { + let mut test_value = test_values[index]; + assert_eq!(pop_lsb(&mut test_value), expected_values[index]) + } + } + +} \ No newline at end of file From f8894bbdfff73d970bafedb0028145865e7775d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 13:51:14 +0100 Subject: [PATCH 23/35] added frame and tests for function: bitboard::util::pop_msb --- engine/src/bitboard/utils.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/engine/src/bitboard/utils.rs b/engine/src/bitboard/utils.rs index d863a15..8cc2dd9 100644 --- a/engine/src/bitboard/utils.rs +++ b/engine/src/bitboard/utils.rs @@ -3,6 +3,9 @@ pub fn pop_lsb(value: &mut u64) -> usize { return 0; } +pub fn pop_msb(value: &mut u64) -> usize { + return 0; +} // <----- TESTS -----> @@ -32,4 +35,23 @@ mod tests { } } + #[test] + fn pop_msb_test() { + // test setup + let test_values: [u64; 6] = [ + 0x86D6_8EB0_96A8_8D1C, + 0x0000_0000_0000_0001, + 0x3809_24AF_A7AE_8129, + 0x0277_DA36_3B31_86D9, + 0x0000_C1C3_201C_0DB1, + 0x0000_0203_0DE4_E944 + ]; + let expected_values: [usize; 6] = [63, 0, 61, 57, 47, 41]; + + // tests + for index in 0..6 { + let mut test_value = test_values[index]; + assert_eq!(pop_lsb(&mut test_value), expected_values[index]) + } + } } \ No newline at end of file From 092ed19104b1df4d29a0507d6a0c7c8ddd918b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 13:59:53 +0100 Subject: [PATCH 24/35] added frame and tests for function: bitboard::util::notation_from_square_number --- engine/src/bitboard/utils.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/engine/src/bitboard/utils.rs b/engine/src/bitboard/utils.rs index 8cc2dd9..b287c06 100644 --- a/engine/src/bitboard/utils.rs +++ b/engine/src/bitboard/utils.rs @@ -7,6 +7,10 @@ pub fn pop_msb(value: &mut u64) -> usize { return 0; } +pub fn notation_from_square_number(sq: u8) -> String { + return String::new(); +} + // <----- TESTS -----> @@ -54,4 +58,26 @@ mod tests { assert_eq!(pop_lsb(&mut test_value), expected_values[index]) } } + + #[test] + fn notation_from_square_number_test() { + // test setup + let square_indices: [u8; 8] = [1, 12, 22, 27, 32, 47, 53, 58]; + let notations: [String; 8] = [ + String::from("b1"), + String::from("e2"), + String::from("g3"), + String::from("d4"), + String::from("a5"), + String::from("h6"), + String::from("f7"), + String::from("c8") + ]; + + // tests + for index in 0..8 { + let notation = notation_from_square_number(square_indices[index].clone()); + assert_eq!(notation, notations[index]); + } + } } \ No newline at end of file From f3dea86ded8f30c08d229341f700a8e46c3633f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 14:05:31 +0100 Subject: [PATCH 25/35] fixed typo in test utils::tests::pop_msb_test --- engine/src/bitboard/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/bitboard/utils.rs b/engine/src/bitboard/utils.rs index b287c06..84b02db 100644 --- a/engine/src/bitboard/utils.rs +++ b/engine/src/bitboard/utils.rs @@ -55,7 +55,7 @@ mod tests { // tests for index in 0..6 { let mut test_value = test_values[index]; - assert_eq!(pop_lsb(&mut test_value), expected_values[index]) + assert_eq!(pop_msb(&mut test_value), expected_values[index]) } } From d0e6ce81ce3a2534d468ece0d892870934b43cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 14:06:43 +0100 Subject: [PATCH 26/35] fixed bad test values in test utils::tests::pop_lsb_test --- engine/src/bitboard/utils.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/src/bitboard/utils.rs b/engine/src/bitboard/utils.rs index 84b02db..ff98b73 100644 --- a/engine/src/bitboard/utils.rs +++ b/engine/src/bitboard/utils.rs @@ -23,14 +23,14 @@ mod tests { // test setup let test_values: [u64; 6] = [ - 0x0000_0000_0000_0000, + 0x8000_0000_0000_0000, 0x4E91_CF05_713E_451B, 0xD588_2D58_6962_34B0, 0x9581_3335_DCAB_1DD4, 0xBEAC_DBE0_903A_AC00, 0x01E8_C895_A6F0_0000 ]; - let expected_values: [usize; 6] = [64, 0, 4, 2, 10, 20]; + let expected_values: [usize; 6] = [63, 0, 4, 2, 10, 20]; // tests for index in 0..6 { From 8d1300d7e25b3570d68a9cb7661673c788ddfa43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 14:14:39 +0100 Subject: [PATCH 27/35] implemented utility function: bitboard::utils::pop_lsb --- engine/src/bitboard/utils.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/engine/src/bitboard/utils.rs b/engine/src/bitboard/utils.rs index ff98b73..4ec5a58 100644 --- a/engine/src/bitboard/utils.rs +++ b/engine/src/bitboard/utils.rs @@ -1,6 +1,8 @@ pub fn pop_lsb(value: &mut u64) -> usize { - return 0; + let idx = value.trailing_zeros() as usize; + *value &= !(1 << idx); + return idx; } pub fn pop_msb(value: &mut u64) -> usize { From a6aba8801e1bfb9bcf7e179bef47c73b960a857d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 14:16:33 +0100 Subject: [PATCH 28/35] implemented utility function: bitboard::utils::pop_msb --- engine/src/bitboard/utils.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/engine/src/bitboard/utils.rs b/engine/src/bitboard/utils.rs index 4ec5a58..2a56eb5 100644 --- a/engine/src/bitboard/utils.rs +++ b/engine/src/bitboard/utils.rs @@ -6,7 +6,9 @@ pub fn pop_lsb(value: &mut u64) -> usize { } pub fn pop_msb(value: &mut u64) -> usize { - return 0; + let idx = 63 - value.leading_zeros() as usize; + *value &= !(1 << idx); + return idx; } pub fn notation_from_square_number(sq: u8) -> String { From eebdfdbee23d0665d9fea58c025aae446bd69c42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 14:21:11 +0100 Subject: [PATCH 29/35] implemented utility function: bitboard::utils::notation_from_square_number --- engine/src/bitboard/utils.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/engine/src/bitboard/utils.rs b/engine/src/bitboard/utils.rs index 2a56eb5..32d650a 100644 --- a/engine/src/bitboard/utils.rs +++ b/engine/src/bitboard/utils.rs @@ -11,8 +11,19 @@ pub fn pop_msb(value: &mut u64) -> usize { return idx; } +const RANK_NUMBERS: [char; 8] = ['1', '2', '3', '4', '5', '6', '7', '8']; +const FILE_LETTERS: [char; 8] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; pub fn notation_from_square_number(sq: u8) -> String { - return String::new(); + let row = sq / 8; + let col = sq % 8; + let mut notation = String::new(); + + let row_not = RANK_NUMBERS[row as usize]; + let col_not = FILE_LETTERS[col as usize]; + + notation.push(col_not); + notation.push(row_not); + return notation; } From 6006442f901840a629e0206a6a2c2142894a5e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Tue, 11 Nov 2025 14:23:30 +0100 Subject: [PATCH 30/35] added '#[inline(always)]' annotation to hot functions: utils::pop_lsb, utils::pop_msb --- engine/src/bitboard/utils.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engine/src/bitboard/utils.rs b/engine/src/bitboard/utils.rs index 32d650a..a30e503 100644 --- a/engine/src/bitboard/utils.rs +++ b/engine/src/bitboard/utils.rs @@ -1,10 +1,11 @@ - +#[inline(always)] pub fn pop_lsb(value: &mut u64) -> usize { let idx = value.trailing_zeros() as usize; *value &= !(1 << idx); return idx; } +#[inline(always)] pub fn pop_msb(value: &mut u64) -> usize { let idx = 63 - value.leading_zeros() as usize; *value &= !(1 << idx); From 352b4e57d7de27f94a4784eceff351e25b2f02c2 Mon Sep 17 00:00:00 2001 From: htom Date: Wed, 12 Nov 2025 18:42:17 +0100 Subject: [PATCH 31/35] rewrote the python script the script now checks for project name on every line read from the log file and appends it to a list named by the project, if the branch is master then it appends all lines into one list, then it checks if there is any data in the list and uploads them to the correct tab that matches the project name or master --- .github/workflows/upload_data.yml | 64 ++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/.github/workflows/upload_data.yml b/.github/workflows/upload_data.yml index 6cfe426..c814a4e 100644 --- a/.github/workflows/upload_data.yml +++ b/.github/workflows/upload_data.yml @@ -20,33 +20,71 @@ jobs: echo "$GOOGLE_SERVICE_ACCOUNT_JSON" > service_account.json python <<'PYCODE' - import gspread, json, time, subprocess + import gspread, json, subprocess - # credentials creds = json.load(open("service_account.json")) gc = gspread.service_account_from_dict(creds) sh = gc.open_by_key("${{ secrets.SPREADSHEET_ID }}") v = subprocess.run(['git','rev-parse','--show-toplevel'], capture_output=True).stdout.decode().strip() print(f"{v}/test_data.log") + + def writeRowsToSpreadsheet(data_list, worksheet): + existing_rows = len(worksheet.get_all_values()) + start_row = existing_rows + 3 + rows_to_append = [row.split() for row in data_list] + print(f"{rows_to_append}") + + for i, row in enumerate(rows_to_append): + worksheet.insert_row(row, start_row + i) + + with open(f"{v}/test_data.log", "r") as f: lines = [line.strip() for line in f if line.strip()] + isMaster = False project = lines[0].lower() - worksheet = sh.worksheet(project) + if project == "master": + isMaster = True + + engine_data = [] + server_data = [] + ui_data = [] + master_data = [] - # project name - data = lines[1:] + for entry in lines: + if not isMaster and entry == "engine": + project = "engine" + elif not isMaster and entry == "server": + project = "server" + elif not isMaster and entry == "ui": + project = "ui" - #blank rows - existing_rows = len(worksheet.get_all_values()) - start_row = existing_rows + 3 + if project == "engine" and entry != "engine": + engine_data.append(entry) + elif project == "server" and entry != "server": + server_data.append(entry) + elif project == "ui" and entry != "ui": + ui_data.append(entry) + elif project == "master" and entry != "master": + master_data.append(entry) - # Split data into columns (by spaces) - rows_to_append = [row.split() for row in data] + print("PRINTING FILTERED DATA\n\n") + print(f"engine\n{engine_data}") + print(f"server\n{server_data}") + print(f"ui\n{ui_data}") + print("\n\n\n") - for i, row in enumerate(rows_to_append): - worksheet.insert_row(row, start_row + i) + if isMaster and len(master_data) != 0: + worksheet = sh.worksheet("master") + writeRowsToSpreadsheet(master_data, worksheet) + exit(0) + + if len(engine_data) != 0: + writeRowsToSpreadsheet(engine_data, sh.worksheet("engine")) + if len(server_data) != 0: + writeRowsToSpreadsheet(server_data, sh.worksheet("server")) + if len(ui_data) != 0: + writeRowsToSpreadsheet(ui_data, sh.worksheet("ui")) - print(f"Uploaded {len(rows_to_append)} rows to '{project}' tab.") PYCODE From ad26d22281d2ffb9c1461077c1a020f5dca0494e Mon Sep 17 00:00:00 2001 From: htom Date: Wed, 12 Nov 2025 18:44:00 +0100 Subject: [PATCH 32/35] indentation error in python script --- .github/workflows/upload_data.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/upload_data.yml b/.github/workflows/upload_data.yml index c814a4e..fb24802 100644 --- a/.github/workflows/upload_data.yml +++ b/.github/workflows/upload_data.yml @@ -35,8 +35,8 @@ jobs: rows_to_append = [row.split() for row in data_list] print(f"{rows_to_append}") - for i, row in enumerate(rows_to_append): - worksheet.insert_row(row, start_row + i) + for i, row in enumerate(rows_to_append): + worksheet.insert_row(row, start_row + i) with open(f"{v}/test_data.log", "r") as f: From f8c14cc268e55ef1cddf58addc4a423516f8bc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hatvani=20Tam=C3=A1s?= <75033623+htamas1210@users.noreply.github.com> Date: Wed, 12 Nov 2025 18:50:01 +0100 Subject: [PATCH 33/35] Enhance logging for data upload process Added print statements to log data being uploaded to each tab. --- .github/workflows/upload_data.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/upload_data.yml b/.github/workflows/upload_data.yml index fb24802..c0ab435 100644 --- a/.github/workflows/upload_data.yml +++ b/.github/workflows/upload_data.yml @@ -33,6 +33,7 @@ jobs: existing_rows = len(worksheet.get_all_values()) start_row = existing_rows + 3 rows_to_append = [row.split() for row in data_list] + print("rows to append") print(f"{rows_to_append}") for i, row in enumerate(rows_to_append): @@ -73,18 +74,23 @@ jobs: print(f"engine\n{engine_data}") print(f"server\n{server_data}") print(f"ui\n{ui_data}") + print(f"master\n{master_data}") print("\n\n\n") if isMaster and len(master_data) != 0: + print("uploading to master tab") worksheet = sh.worksheet("master") writeRowsToSpreadsheet(master_data, worksheet) exit(0) if len(engine_data) != 0: + print("uploading to engine tab") writeRowsToSpreadsheet(engine_data, sh.worksheet("engine")) if len(server_data) != 0: + print("uploading to server tab") writeRowsToSpreadsheet(server_data, sh.worksheet("server")) if len(ui_data) != 0: + print("uploading to ui tab") writeRowsToSpreadsheet(ui_data, sh.worksheet("ui")) PYCODE From 7be3c928b741c07d4c5150bbc74ede88f917ebb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hatvani=20Tam=C3=A1s?= <75033623+htamas1210@users.noreply.github.com> Date: Wed, 12 Nov 2025 18:54:06 +0100 Subject: [PATCH 34/35] Display test_data.log in workflow script Added command to display contents of test_data.log --- .github/workflows/test.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.sh b/.github/workflows/test.sh index f948267..856d6c5 100755 --- a/.github/workflows/test.sh +++ b/.github/workflows/test.sh @@ -38,3 +38,5 @@ cat "$LOG_FILE" >> "$FINAL_LOG" # --- SUMMARY --- echo ">>> Test output extracted to $PROJECT_PATH/$LOG_FILE" echo ">>> Appended to $FINAL_LOG" + +cat $(git rev-parse --show-toplevel)/test_data.log From 39273908ac23c0565f82dcbce0b88e3d7b3d38dd Mon Sep 17 00:00:00 2001 From: htom Date: Wed, 12 Nov 2025 18:58:36 +0100 Subject: [PATCH 35/35] removed checkout to potentially fix an error with test_data.log --- .github/workflows/engine_test.yml | 2 -- .github/workflows/server_test.yml | 2 -- .github/workflows/ui_test.yml | 2 -- 3 files changed, 6 deletions(-) diff --git a/.github/workflows/engine_test.yml b/.github/workflows/engine_test.yml index 3f4bfec..78683a4 100644 --- a/.github/workflows/engine_test.yml +++ b/.github/workflows/engine_test.yml @@ -9,8 +9,6 @@ jobs: runs-on: self-hosted steps: - - uses: actions/checkout@v4 - - name: Run Engine tests run: | bash .github/workflows/test.sh engine/ diff --git a/.github/workflows/server_test.yml b/.github/workflows/server_test.yml index 4a2e817..7583a32 100644 --- a/.github/workflows/server_test.yml +++ b/.github/workflows/server_test.yml @@ -9,8 +9,6 @@ jobs: runs-on: self-hosted steps: - - uses: actions/checkout@v4 - - name: Run Server tests run: | bash .github/workflows/test.sh server/ diff --git a/.github/workflows/ui_test.yml b/.github/workflows/ui_test.yml index 7f0ca2c..c20ad98 100644 --- a/.github/workflows/ui_test.yml +++ b/.github/workflows/ui_test.yml @@ -9,8 +9,6 @@ jobs: runs-on: self-hosted steps: - - uses: actions/checkout@v4 - - name: Run UI tests run: | bash .github/workflows/test.sh ui/