update
This commit is contained in:
1 parent
f2c609a08b
commit
1d563b9eec
34 files changed
+5486
-643
No files matched your search
+61
-24
@@ -1,7 +1,10 @@
|
||||
class_name DeckGen
|
||||
## Stapel: die vier Startdecks, Auffüllen aus der Sammlung, zufällige Stapel für Gegner.
|
||||
## Stapel: Elementstapel nach Manakurve (Startstapel und Gegner), Auffüllen aus der Sammlung,
|
||||
## zufällige Stapel für Tests und Simulation.
|
||||
|
||||
const CHEAP_IN_RANDOM := 12 # so viele im ersten Zug bezahlbare Karten hat ein zufälliger Stapel mindestens
|
||||
## Manakurve eines Stapels mit DECK_MIN Karten: so viele Karten je Kosten 0 bis 10.
|
||||
const CURVE: Array[int] = [2, 5, 6, 6, 5, 3, 2, 1, 0, 0, 0]
|
||||
|
||||
|
||||
## Zufälliger Stapel aus DECK_MIN verschiedenen Karten bis max_cost, mit genug billigen für den Anfang.
|
||||
@@ -18,41 +21,75 @@ static func random_deck(r: RandomNumberGenerator, max_cost: int = 99) -> Array:
|
||||
return out
|
||||
|
||||
|
||||
## Stapel eines Kampagnengegners: Kapitel 1 bis Kosten 3, Kapitel 2 bis 5, Kapitel 3 alles.
|
||||
static func opponent_deck(r: RandomNumberGenerator, chapter: int) -> Array:
|
||||
return random_deck(r, [3, 5, 99][clampi(chapter - 1, 0, 2)])
|
||||
## Alle Karten eines Elements (oder die neutralen) in Datenreihenfolge: die Startsammlung.
|
||||
static func element_deck(element: String) -> Array:
|
||||
return Cards.all().filter(func(c): return c.elements[0] == element).map(func(c): return c.id)
|
||||
|
||||
|
||||
## Startdeck für ein Element: die 25 Karten des Elements bis Angriff 4, dazu je fünf billige der
|
||||
## anderen Elemente (DECK_MIN Karten).
|
||||
static func start_deck(element: String) -> Array:
|
||||
var out := []
|
||||
## Stapel eines Elements nach der Manakurve: DECK_MIN verschiedene Karten des Elements bis max_cost,
|
||||
## je Kosten so viele wie CURVE vorgibt, zufällig gewählt. Was über dem Deckel fehlt, füllen die
|
||||
## erlaubten Kosten reihum von billig nach teuer auf.
|
||||
static func curve_deck(element: String, r: RandomNumberGenerator, max_cost: int = 10) -> Array:
|
||||
var by_cost := {}
|
||||
for c in Cards.all():
|
||||
if c.elements[0] == element and c.attack <= 4:
|
||||
out.append(c.id)
|
||||
for e in Cards.ELEMENTS:
|
||||
if e == element:
|
||||
continue
|
||||
var cheap := Cards.all().filter(func(c): return c.elements[0] == e and c.cost <= Game.START_MANA)
|
||||
cheap.sort_custom(func(a, b): return a.cost < b.cost if a.cost != b.cost else a.attack > b.attack)
|
||||
for c in cheap.slice(0, 5):
|
||||
out.append(c.id)
|
||||
if c.elements[0] == element and c.cost <= max_cost:
|
||||
if not by_cost.has(c.cost):
|
||||
by_cost[c.cost] = []
|
||||
by_cost[c.cost].append(c.id)
|
||||
for cost in by_cost:
|
||||
Game.shuffle(by_cost[cost], r)
|
||||
var out := []
|
||||
for cost in CURVE.size():
|
||||
for k in CURVE[cost]:
|
||||
if by_cost.has(cost) and not by_cost[cost].is_empty():
|
||||
out.append(by_cost[cost].pop_back())
|
||||
while out.size() < Game.DECK_MIN:
|
||||
var added := false
|
||||
for cost in range(0, max_cost + 1):
|
||||
if out.size() >= Game.DECK_MIN:
|
||||
break
|
||||
if by_cost.has(cost) and not by_cost[cost].is_empty():
|
||||
out.append(by_cost[cost].pop_back())
|
||||
added = true
|
||||
if not added:
|
||||
break
|
||||
return out
|
||||
|
||||
|
||||
## Füllt deck aus pool (Karten-IDs) bis limit auf, die wertvollsten zuerst (Card.value in der
|
||||
## Stufe aus levels: ID -> Stufe), bei gleichem Wert die teuersten; nichts doppelt.
|
||||
## Füllt deck aus pool (Karten-IDs) bis limit auf, die wertvollsten zuerst (Card.value in der Stufe
|
||||
## aus levels: ID -> Stufe); bei gleichem Wert zuerst, was der Manakurve (CURVE, auf limit
|
||||
## skaliert) noch fehlt, dann die billigeren, dann nach ID; nichts doppelt.
|
||||
static func fill(deck: Array, pool: Array, limit: int, levels: Dictionary = {}) -> Array:
|
||||
var out := deck.duplicate()
|
||||
var cards := pool.filter(func(id): return not (id in out)).map(func(id): return Cards.by_id(id).leveled(int(levels.get(id, 0))))
|
||||
cards.sort_custom(func(a, b):
|
||||
if a.value() != b.value():
|
||||
return a.value() > b.value()
|
||||
return a.cost > b.cost if a.cost != b.cost else a.id < b.id)
|
||||
for c in cards:
|
||||
if out.size() >= limit:
|
||||
break
|
||||
out.append(c.id)
|
||||
return a.cost < b.cost if a.cost != b.cost else a.id < b.id)
|
||||
var have := {} # Kosten -> Karten im Stapel
|
||||
for id in out:
|
||||
var slot := clampi(Cards.by_id(id).cost, 0, CURVE.size() - 1)
|
||||
have[slot] = int(have.get(slot, 0)) + 1
|
||||
var i := 0
|
||||
while i < cards.size() and out.size() < limit:
|
||||
var j := i
|
||||
while j < cards.size() and cards[j].value() == cards[i].value():
|
||||
j += 1
|
||||
var rest := []
|
||||
for c in cards.slice(i, j):
|
||||
if out.size() >= limit:
|
||||
break
|
||||
var slot := clampi(c.cost, 0, CURVE.size() - 1)
|
||||
if int(have.get(slot, 0)) < CURVE[slot] * limit / Game.DECK_MIN:
|
||||
out.append(c.id)
|
||||
have[slot] = int(have.get(slot, 0)) + 1
|
||||
else:
|
||||
rest.append(c)
|
||||
for c in rest:
|
||||
if out.size() >= limit:
|
||||
break
|
||||
out.append(c.id)
|
||||
i = j
|
||||
return out
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user