⚙ AI Algoritması

Level Difficulty Analyzer scoring breakdown

← Difficulty Analyzer Dashboard

AI Algoritması — Difficulty Analyzer

Bu döküman, scripts/difficulty_analyzer/ai_player.py içindeki AI'nın bir hamleyi nasıl seçtiğini özetler. AI, oyunun kendisini değil, oynanabilirlik analizi için kullanılan otomatik oyuncudur: her seferinde standalone engine'den bir board snapshot alır, legal_swaps listesindeki her aday hamleye bir skor atar, en yüksek skorlu hamleyi seçer.

Temel akış

engine snapshot  ──►  her aday swap için skor hesapla  ──►  en yüksek skor kazanır
   (legal_swaps)              (score function)              (AIPlayer.choose)

Önemli: AI cascade simülasyonu yapmaz. Sadece şu anki board üzerinde bir swap'in *anlık* etkisini tahmin eder. Tasarımdaki tercih: hızlı + "yeterince akıllı" sezgisel skor.

Skor formülü

Bir aday swap için skor:

score = (1) match-size bonusu
      + (2) collectable katkısı
      + (3 + 4 + 5) × urgency çarpanı
      + (7) look-ahead bonusu

Komponent (3), (4) ve (5) sadece power-up ile ilgili olanlar; urgency çarpanı yalnızca onlara uygulanır. Match ve collectable katkıları her zaman 1.0 ağırlıkta. Look-ahead bonusu ayrı bir bileşen — bir hamle sonrasını dikkate alır, kendi içinde 0.75 ile ölçeklenir, urgency çarpanı dolaylı olarak içsel skor üzerinden uygulanır.

1. Match-size bonusu

Swap sonrası oluşacak match deseni → sabit puan tablosu. Tablodaki sıralama, oluşan power-up'ın gücüyle paraleldir:

DesenSpawn olan PUBonus
3'lü satır (h-3 / v-3)yok1
4'lü satır (h-4 / v-4)knife8
L veya T şeklifalcon12
2×2 karebomb18
5+ satır (h-5 / v-5)lightning30

Lightning en yüksek puanı alır, çünkü kombo potansiyeli oyun içindeki en güçlü PU'yu üretir.

2. Collectable katkısı

Swap'in temizleyeceği her hücre için:

İki katkı bağımsız ve birikimli. Levellarımızın çoğu special-collectable kullandığı için ikincisi pratikte daha sık devreye girer.

3. Power-up aktivasyon bonusu

Swap'in iki ucundan biri veya ikisi PU ise:

power_up_score += ACTIVATION_BASE_BY_TYPE[pu]
                + 2.0 × (PU'nun blast footprint'inde kalan collectable hücre sayısı)

Tip-bazlı base değerleri (PU'ların temizleme gücüne göre):

PU tipiYaklaşık temizlemeBase
falcon5 + 1 garanti10
verticalKnife / horizontalKnifebir satır/sütun (~9)12
bomb5×5 = 25 hücre20
lightningtek tip tüm hücreler + kombo25

Blast footprint yaklaşımları:

4. Power-up kombo bonusu (her iki uç da PU ise)

KombinasyonBonus
lightning + lightning (tüm board temizlenir)+120
lightning + diğer PU (10–15 PU saçar)+70
non-lightning kombo (bomb+bomb, knife+falcon, vs.)+30

5. Falcon late-game garanti bonusu

Falcon'un ayırt edici özelliği: gittiği son hedefte garanti vuruş. Şu üç koşul birden sağlanırsa, her falcon ucu için +20 flat bonus eklenir:

6. Urgency çarpanı

Sadece power-up portion'ına (3 + 4 + 5) uygulanır. Match-size ve collectable katkıları ölçeklenmez.

f = moves_remaining / moves_total

f ≥ 0.40                ─► çarpan = 1.0      (early/mid game, biriktirme serbest)
0.20 ≤ f < 0.40         ─► 1.0 → 2.0 lineer  (urgency, PU'ları kullanmaya yönel)
0.00 ≤ f < 0.20         ─► 2.0 → 4.0 lineer  (very-urgency, bitirme zamanı)

Yani: erken ve orta oyunda AI yeni PU üretmeye serbestçe karar verebilir; hamle sayısı azaldıkça eldeki PU'ları kullanmak ve aktive etmek dramatik olarak daha cazip hale gelir.

7. Look-ahead bonusu (1-kademelik cascade)

Mevcut hamlenin direkt etkisinin yanı sıra, AI bir hamle sonrasında ortaya çıkabilecek yeni PU↔PU komşuluklarını da hesaba katar. Mantık:

1. Aday hamleyi sanal olarak uygula:

2. Sadece vertical gravity uygulanır (diagonal slide göz ardı edilir, basitleştirme). 3. Gravity-blocker hücreler (B/DB/TB/Box renkli varyantları/W/DW/BW/I/DI/TI/J/DJ) kolonu segmentlere böler; her segment kendi içinde compact edilir. 4. Mobil tile'lar (regular tile'lar ve PU'lar, special'sız) bottom-up sıralanır ve her segmentin altına yerleştirilir; segmentin üstünde kalan hücreler placeholder regular tile ile doldurulur (refill'in PU üretmediği gerçeğini yansıtır). 5. Sonrasında board'da, hamle öncesinde olmayan yeni PU↔PU 4-komşulukları taranır. 6. Her yeni komşuluk için, sanal post-board üzerinde o iki PU'nun swap olması durumunda alacağı skor hesaplanır (apply_lookahead=False ile, sonsuz özyineleme önlenir; içsel skorda match-size sıfır olur, ama aktivasyon + kombo + falcon late-game + urgency normalde uygulanır). 7. Her yeni komşuluğun katkısı 0.75 ile çarpılıp toplanır.

Bonus, aday skorun yanına eklenir. Bonus 0.0 olabilir (yeni komşuluk yoksa, look-ahead atlanırsa, ya da aday hamle inelegible ise — örneğin PU↔PU ya da falcon aktivasyonu).

Look-ahead'in yaklaşımları (heuristik)

KonuDavranışNot
Diagonal gravityYokXH gap'leri etrafında küçük hata payı
Refill cellsregular_type=-1 placeholder, no PUEngine'in random regular refill'i ile uyumlu
Stokastik PU aktivasyonları (falcon)AtlanırRandom hedefler tahmin edilemez
Stokastik PU aktivasyonları (lightning)Partner'ın regular tipindeki tüm hücrelerEngine'in lightning davranışına yaklaşım
Secondary cascade'in spawn ettiği PU'larYok"Sadece PU↔PU komşuluk" kuralının doğal sonucu
Special'ların collectable katkı progression'ıModellenmezİçsel skor azca overestimate edebilir; 0.75 ile dengeleniyor
DeterminismSağlanırSaf hesaplama, RNG yok

En yüksek skoru seçme — AIPlayer.choose

legal_swaps üzerinde tek geçişli linear tarama:

1. Her aday için score(swap, state) hesaplanır. 2. Strict maksimum kazanır. 3. Beraberlikte kural: lexicographic olarak (row, col) en küçük "alt uç"a sahip swap kazanır. Swap mantıksal olarak sırasız bir çift olduğundan, tie-break tuple içindeki sıralamadan bağımsızdır. 4. Tam beraberlikte (aynı skor + aynı alt uç) legal_swaps sırasında ilk gelen kazanır.

Engine legal_swaps'i deterministik board-scan sırasında üretir; aynı board → aynı seçim. Bu, run'ların tekrarlanabilir olmasını sağlar.

Engine ile sözleşme — legal_swaps

AI'ın asla "engine'in sessizce reddedeceği" bir swap görmemesi kritik. Bunu sağlamak için engine tarafındaki enumerateLegalSwaps doğrudan BoardLogic.isSwapValid'e (engine'in _trySwap içinde hamle harcamadan önce kullandığı predicate'in kendisi) delege eder. Bu sayede şu kurallar otomatik olarak filtrelenir:

AI'ın gördüğü legal_swaps = engine'in hamle harcayacağı legal_swaps. Bu eşitlik infinite-loop bug'ını önleyen anahtar invariant.

Tasarım dışında bıraktıklarımız

Bilinçli olarak şu an dahil edilmedi, ileride eklenebilir:

Kısa özet

AI her hamlede legal_swaps'teki tüm adayları skorlar; skor = match-size bonusu + collectable katkısı + (PU aktivasyon + kombo + falcon late-game) × urgency çarpanı + look-ahead bonusu. En yüksek skoru deterministik tie-break ile seçer. Lightning > Bomb > Knife/Falcon hiyerarşisi, special-collectable farkındalığı ve smooth iki-tier urgency eğrisi (0.4 ve 0.2 eşikleri) AI'nın hem PU üretmesini hem de zamanı geldiğinde kullanmasını dengeler. Look-ahead bonusu (1-kademelik vertical-only cascade) hamle sonrasında ortaya çıkacak yeni PU↔PU komşuluklarını tespit eder; her yeni komşuluk için sanal swap skoru × 0.75 eklenir, böylece AI gravity ile düşecek PU'ların bir araya gelme potansiyelini de değerlendirir.