Compare winner's share between 2-player and multi-player tournaments.
(log_dir: Path, game_pattern: str = "CoreWar.r15.s1000")
| 46 | |
| 47 | |
| 48 | def analyze_winner_share(log_dir: Path, game_pattern: str = "CoreWar.r15.s1000"): |
| 49 | """Compare winner's share between 2-player and multi-player tournaments.""" |
| 50 | |
| 51 | # Collect 2-player data |
| 52 | print("Analyzing 2-player tournaments...") |
| 53 | winner_shares_2p = [] |
| 54 | for metadata_path in log_dir.rglob(f"*{game_pattern}.p2.*/metadata.json"): |
| 55 | winner_shares_2p.extend(calculate_winner_share(metadata_path, num_players=2)) |
| 56 | |
| 57 | # Collect 6-player data |
| 58 | print("Analyzing 6-player tournaments...") |
| 59 | winner_shares_6p = [] |
| 60 | for metadata_path in log_dir.rglob(f"*{game_pattern}.p6.*/metadata.json"): |
| 61 | winner_shares_6p.extend(calculate_winner_share(metadata_path, num_players=6)) |
| 62 | |
| 63 | # Print statistics |
| 64 | print("\n" + "=" * 70) |
| 65 | print("WINNER'S SHARE COMPARISON") |
| 66 | print("=" * 70) |
| 67 | |
| 68 | print("\n2-Player Tournaments:") |
| 69 | print(f" Mean: {np.mean(winner_shares_2p):.1f}%") |
| 70 | print(f" Median: {np.median(winner_shares_2p):.1f}%") |
| 71 | print(f" Range: {np.min(winner_shares_2p):.1f}% - {np.max(winner_shares_2p):.1f}%") |
| 72 | print(f" Samples: {len(winner_shares_2p)}") |
| 73 | |
| 74 | print("\n6-Player Tournaments:") |
| 75 | print(f" Mean: {np.mean(winner_shares_6p):.1f}%") |
| 76 | print(f" Median: {np.median(winner_shares_6p):.1f}%") |
| 77 | print(f" Range: {np.min(winner_shares_6p):.1f}% - {np.max(winner_shares_6p):.1f}%") |
| 78 | print(f" Samples: {len(winner_shares_6p)}") |
| 79 | |
| 80 | print("\n" + "=" * 70) |
| 81 | print("KEY INSIGHT") |
| 82 | print("=" * 70) |
| 83 | ratio = np.mean(winner_shares_2p) / np.mean(winner_shares_6p) |
| 84 | print(f""" |
| 85 | In 6-player tournaments, the winner captures only {np.mean(winner_shares_6p):.1f}% of total points |
| 86 | on average, compared to {np.mean(winner_shares_2p):.1f}% in 2-player tournaments. |
| 87 | |
| 88 | This means 6-player games are MUCH less dominated by a single winner - victories |
| 89 | are more competitive and less clear-cut ({ratio:.2f}x less dominant). |
| 90 | |
| 91 | 👉 Bottom line: Multi-player tournaments show MORE COMPETITIVE BALANCE and LESS |
| 92 | WINNER DOMINANCE than 2-player head-to-head matches. |
| 93 | """) |
| 94 | |
| 95 | # Create visualization |
| 96 | fig, axes = plt.subplots(1, 2, figsize=(12, 5)) |
| 97 | |
| 98 | # Plot 1: Histogram comparison |
| 99 | ax1 = axes[0] |
| 100 | ax1.hist(winner_shares_6p, bins=20, alpha=0.7, label="6-Player", color="steelblue", edgecolor="black") |
| 101 | ax1.hist(winner_shares_2p, bins=20, alpha=0.7, label="2-Player", color="coral", edgecolor="black") |
| 102 | ax1.axvline( |
| 103 | np.mean(winner_shares_6p), |
| 104 | color="steelblue", |
| 105 | linestyle="--", |
no test coverage detected