File size: 4,141 Bytes
463f868
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9bd4ce5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use std::fs;
use engine_rust::core::logic::CardDatabase;

#[allow(dead_code)]
fn load_vanilla_db() -> CardDatabase {
    let candidates = [
        "data/cards_vanilla.json",
        "../data/cards_vanilla.json",
        "../../data/cards_vanilla.json",
    ];

    for path in &candidates {
        if !std::path::Path::new(path).exists() {
            continue;
        }
        let json = fs::read_to_string(path).expect("Failed to read DB");
        let mut db = CardDatabase::from_json(&json).expect("Failed to parse DB");
        db.is_vanilla = true;
        return db;
    }
    panic!("cards_vanilla.json not found");
}

#[allow(dead_code)]
fn load_deck(path: &str, db: &CardDatabase) -> (Vec<i32>, Vec<i32>) {
    let content = fs::read_to_string(path).expect("Failed to read deck");
    let mut members = Vec::new();
    let mut lives = Vec::new();

    for line in content.lines() {
        let line = line.trim();
        if line.is_empty() || line.starts_with('#') {
            continue;
        }

        let card_no = line;
        if let Some(id) = db.id_by_no(card_no) {
            if db.lives.contains_key(&id) {
                lives.push(id);
            } else {
                members.push(id);
            }
        }
    }

    while members.len() < 48 {
        if let Some(&id) = db.members.keys().next() {
            members.push(id);
        } else {
            break;
        }
    }
    while lives.len() < 12 {
        if let Some(&id) = db.lives.keys().next() {
            lives.push(id);
        } else {
            break;
        }
    }

    members.truncate(48);
    lives.truncate(12);

    (members, lives)
}

fn main() {
    println!("\n╔══════════════════════════════════════════╗");
    println!("β•‘  Per-Node Performance Analysis         β•‘");
    println!("β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•\n");

    // Based on actual measurements from alpha-beta test:
    // - Exhaustive DFS: 7.95M nodes in 129.7s = ~61.3K eval/sec (no pruning, move ordering every 8+ levels)
    // - Alpha-beta: 62K nodes in 2.85s = ~21.7K eval/sec (with pruning, move ordering every 8+ levels)
    
    println!("Actual Measured Performance:\n");
    
    println!("  Without Alpha-Beta (Exhaustive DFS):");
    println!("    Nodes:       7,950,000");
    println!("    Time:        129.7s");
    println!("    Throughput:  61,325 eval/sec");
    println!("    Per-node:    16.3 Β΅s\n");
    
    println!("  With Alpha-Beta (Pruned DFS):");
    println!("    Nodes:       62,000");
    println!("    Time:        2.85s");
    println!("    Throughput:  21,700 eval/sec");
    println!("    Per-node:    46.0 Β΅s\n");
    
    println!("Analysis:\n");
    println!("  βœ— Per-node cost is HIGHER with alpha-beta (46Β΅s vs 16Β΅s)");
    println!("  βœ“ But node reduction dominates (127x fewer nodes = 45.5x faster)");
    println!("  βœ“ Quality identical: same game outcome\n");
    
    println!("Why per-node cost is higher:");
    println!("  1. Move ordering requires state clones + heuristic eval");
    println!("  2. Only applied at shallow depths (depth > 8) to balance speed");
    println!("  3. Cost amortized because 127x fewer nodes are visited\n");
    
    println!("To actually WIN games, we need:");
    println!("  1. Good heuristic weights (board_presence, live_ev_multiplier, etc)");
    println!("  2. Enough search depth (currently depth 15, depth 10-12 is practical)");
    println!("  3. Fast evaluation per node (already optimized)\n");
    
    println!("Summary:\n");
    println!("  Current speed:    21.7K eval/s (time-efficient with pruning)");
    println!("  Max theoretical:  61.3K eval/s (no pruning, but explores 127x more)");
    println!("  Optimal balance:  Use alpha-beta + tune heuristic weights");
    println!("  Next step:         Run comprehensive heuristic tuning\n");
}