Compare commits

..

31 Commits
v18 ... v38

Author SHA1 Message Date
Hatvani Tamás
eaf3bfa192 Merge pull request #5 from htamas1210/Engine/movegen-lut
Engine/movegen lut
2025-11-11 12:17:48 +01:00
Hatvani Tamás
9c73ca6838 Fix formatting of conditional checks in dispatcher.yml 2025-11-11 11:34:05 +01:00
Hatvani Tamás
0f50f31b13 Update branch checks to be case-sensitive
Refactor branch checks to be case-sensitive for Engine, Server, and UI.
2025-11-11 11:27:42 +01:00
Hatvani Tamás
b6f0b6ee5e Fix conditional syntax in dispatcher.yml 2025-11-11 11:22:21 +01:00
4ae9eea7e2 removed pull_request dispatcher from release workflow 2025-11-11 11:13:45 +01:00
1f368551c1 removed pull_request dispatch from the test files 2025-11-11 11:12:39 +01:00
Hatvani Tamás
4e9f222ddc Allow case-insensitive branch checks in dispatcher.yml 2025-11-11 11:01:38 +01:00
Varga Dávid Lajos
061795a039 implemented the generation of LUT: RAY_TABLE 2025-11-11 10:39:51 +01:00
Varga Dávid Lajos
1af497f063 implemented the generation of LUT: KNIGHT_ATTACK_MAP 2025-11-11 10:33:51 +01:00
Varga Dávid Lajos
b6cdf5b778 implemented the generation of LUT: PAWN_ATTACK_MAP 2025-11-11 10:32:41 +01:00
Varga Dávid Lajos
4eb4bc1348 implemented the generation of LUT: KING_ATTACK_MAPS 2025-11-11 10:25:23 +01:00
Varga Dávid Lajos
c2fe2e968a added masks for use against wrap-around 2025-11-11 10:22:05 +01:00
Varga Dávid Lajos
21f2890b92 added frame and tests for table: RAY_TABLE 2025-11-10 17:17:30 +01:00
Varga Dávid Lajos
5d748b07d2 added frame and tests for table: KNIGHT_ATTACK_MAP 2025-11-10 16:54:14 +01:00
Varga Dávid Lajos
b252f16b2d added frame and tests for table: PAWN_ATTACK_MAP 2025-11-10 15:50:58 +01:00
Varga Dávid Lajos
18f4060df0 added frame and tests for table: KING_ATTACK_MAP 2025-11-10 15:28:15 +01:00
Varga Dávid Lajos
033440fbac added dependency to Cargo.toml: once_cell 2025-11-10 13:18:48 +01:00
Varga Dávid Lajos
bfb2a6db23 added file and module structure for attackmaps.rs 2025-11-10 13:13:03 +01:00
Bence
70d10719e6 Dokumentumok feltöltése a master branch-re 2025-11-10 12:21:27 +01:00
Hatvani Tamás
85f7c6e690 Remove checkout step from upload_data workflow
Removed checkout step from upload job in workflow.
2025-11-09 15:05:10 +01:00
Hatvani Tamás
2ac2f17d1a Fix subprocess by adding decode to file path in upload_data.yml 2025-11-09 15:01:42 +01:00
Hatvani Tamás
7cd4bb6b09 Refactor subprocess call and print statement
Updated subprocess command to use list format and modified print statement for clarity.
2025-11-09 14:55:23 +01:00
1bf4d875af Workflow: added subprocess run to have the correct path for the test log file 2025-11-09 14:48:04 +01:00
Hatvani Tamás
8a01bba644 Update pip install command to break system packages 2025-11-09 14:34:18 +01:00
Hatvani Tamás
cf2edab297 Remove Python setup from upload_data workflow
Removed Python setup step for Google Sheets API.
2025-11-09 14:31:18 +01:00
Hatvani Tamás
5443002c5f Workflow: removed runs-on: self-hosted from test upload job 2025-11-09 14:26:28 +01:00
e19a5aac9a Workflow: Re added test-upload job, added workflow_call trigger 2025-11-09 14:24:24 +01:00
Hatvani Tamás
3515703a90 Modify zip commands in release workflow to include files in the folder with the wildcard
Update zip commands to include all files in the directories.
2025-11-09 13:12:27 +01:00
Hatvani Tamás
a6966e055d Compress build folders for upload
Added compression step for build folders before release.
2025-11-09 13:05:23 +01:00
Bence
1788cce42d Kövspec áttekintés, vágyálom rendszer hozzáadása 2025-11-04 12:01:25 +01:00
Hatvani Tamás
49f4ffc380 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.
2025-11-03 18:41:29 +01:00
11 changed files with 405 additions and 28 deletions

View File

@@ -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
@@ -68,13 +68,10 @@ jobs:
test-data-upload:
needs: [engine, server, ui]
runs-on: self-hosted
if: always()
#uses: ./.github/workflows/upload_data.yml
steps:
- name: Temp turn off
run: |
echo "Uploading data to table"
uses: ./.github/workflows/upload_data.yml
secrets: inherit
release:
needs: test-data-upload

View File

@@ -1,7 +1,6 @@
name: Engine Tests
on:
pull_request:
workflow_dispatch:
workflow_call:

View File

@@ -1,7 +1,6 @@
name: Release build
on:
pull_request:
workflow_dispatch:
workflow_call:
@@ -82,16 +81,24 @@ jobs:
cargo build --release --target x86_64-pc-windows-gnu
pwd
cp target/x86_64-pc-windows-gnu/release/ui.exe $(git rev-parse --show-toplevel)/release/windows/ui.exe
- name: Compress build folders for upload
run: |
cd $(git rev-parse --show-toplevel)
pwd
cd release/
zip linux.zip linux/*
zip windows.zip windows/*
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: "v${{ github.run_number }}"
name: "Release v${{ github.run_number }}"
generate_release_notes: true
files: |
release/linux/
release/windows/
release/linux.zip
release/windows.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,7 +1,6 @@
name: Server Tests
on:
pull_request:
workflow_dispatch:
workflow_call:

View File

@@ -1,7 +1,6 @@
name: UI Tests
on:
pull_request:
workflow_dispatch:
workflow_call:

View File

@@ -2,22 +2,15 @@ name: Upload Test Results to Google Sheets
on:
workflow_dispatch:
workflow_call:
jobs:
upload:
runs-on: self-hosted
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Setup Python (for Google Sheets API)
uses: actions/setup-python@v5
with:
python-version: '3.x'
steps:
- name: Install dependencies
run: |
pip install gspread google-auth
pip install gspread google-auth --break-system-packages
- name: Upload test_data.log to Google Sheets
env:
@@ -27,14 +20,16 @@ jobs:
echo "$GOOGLE_SERVICE_ACCOUNT_JSON" > service_account.json
python <<'PYCODE'
import gspread, json, time
import gspread, json, time, 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")
with open("test_data.log", "r") as f:
with open(f"{v}/test_data.log", "r") as f:
lines = [line.strip() for line in f if line.strip()]
project = lines[0].lower()

125
Docs/kovspec.md Normal file
View File

@@ -0,0 +1,125 @@
# 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 kliensszerver 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) |

View File

@@ -4,3 +4,4 @@ version = "0.1.0"
edition = "2024"
[dependencies]
once_cell = "1.19"

1
engine/src/bitboard.rs Normal file
View File

@@ -0,0 +1 @@
mod attackmaps;

View File

@@ -0,0 +1,252 @@
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)
> side: white = 0, black = 1
> direction_index: 0..8 = [E, NE, N, NW, W, SW, S, SE]
*/
// KING_ATTACK_MAP[<square_index>]
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;
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;
});
// PAWN_ATTACK_MAP[<square_index>][<side>]
pub static PAWN_ATTACK_MAP: Lazy<[[u64; 2]; 64]> = Lazy::new(|| {
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;
});
// KNIGHT_ATTACK_MAP[<square_index>]
pub static KNIGHT_ATTACK_MAP: Lazy<[u64; 64]> = Lazy::new(|| {
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;
});
// RAY_TABLE[<square_index>][<direction_index>]
pub static RAY_TABLE: Lazy<[[u64; 8]; 64]> = Lazy::new(|| {
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;
});
// <----- 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);
}
#[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 << 18) | (1 << 20),
(1 << 19) | (1 << 21)
];
// 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])
}
}
#[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);
}
#[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]);
}
}
}

View File

@@ -1,3 +1,5 @@
mod bitboard;
fn main() {
println!("Hello, world!");
}