finished fight logic
~2h work
This commit is contained in:
parent
4874f110c1
commit
37d9f84787
@ -2,16 +2,25 @@ package at.nanopenguin.mtcg.application;
|
||||
|
||||
import at.nanopenguin.mtcg.Pair;
|
||||
import at.nanopenguin.mtcg.application.service.schemas.Card;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.*;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class Battle {
|
||||
private record RoundResult(String winnerName, Card winnerCard, String loserName, Card loserCard, boolean draw) {};
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private enum ElementMod {
|
||||
HALF(0.5),
|
||||
NONE(1),
|
||||
DOUBLE(2);
|
||||
|
||||
public final double percentMod;
|
||||
}
|
||||
private record FightDTO(Combatant player, Card card) {};
|
||||
private record RoundResult(FightDTO winner, FightDTO loser, boolean draw, ElementMod winnerMod, ElementMod loserMod) {};
|
||||
private Pair<Combatant, Combatant> combatants;
|
||||
@Getter
|
||||
private volatile List<String> log = new ArrayList<>();
|
||||
@ -27,28 +36,151 @@ public class Battle {
|
||||
}
|
||||
|
||||
public void start() throws SQLException {
|
||||
boolean leftWins;
|
||||
|
||||
int round = 0;
|
||||
do {
|
||||
this.playRound();
|
||||
} while (combatants.left().deckSize() > 0 && combatants.right().deckSize() > 0);
|
||||
this.playRound(++round);
|
||||
if (round == 100) return; // don't update stats on draw
|
||||
|
||||
System.out.println(combatants.left().deckSize() + " - " + combatants.right().deckSize() );
|
||||
} while ((leftWins = combatants.left().deckSize() > 0) && combatants.right().deckSize() > 0);
|
||||
|
||||
// placeholder
|
||||
boolean leftWins = new Random().nextBoolean();
|
||||
this.combatants.left().updateStats(leftWins);
|
||||
this.combatants.right().updateStats(!leftWins);
|
||||
}
|
||||
|
||||
private void playRound() {
|
||||
Pair<Card, Card> cards = new Pair<>(this.combatants.left().getCard(), this.combatants.right().getCard());
|
||||
//RoundResult result = this.fight(cards.left(), cards.right());
|
||||
//this.log.add("");
|
||||
private void playRound(int round) {
|
||||
RoundResult result = this.fight(
|
||||
new FightDTO(
|
||||
this.combatants.left(),
|
||||
this.combatants.left().getAndRemoveCard()),
|
||||
new FightDTO(
|
||||
this.combatants.right(),
|
||||
this.combatants.right().getAndRemoveCard()));
|
||||
|
||||
this.log.add(this.createCombatString(round, result));
|
||||
|
||||
result.winner().player().addCard( // return card to winner deck
|
||||
result.winner().card());
|
||||
|
||||
if (result.draw()) {
|
||||
result.loser().player().addCard( // on draw both players get their card
|
||||
result.loser().card());
|
||||
return;
|
||||
}
|
||||
|
||||
result.winner.player().addCard( // on lose winner gets losers card to deck
|
||||
result.loser().card());
|
||||
}
|
||||
|
||||
private boolean fight(Card left, Card right) {
|
||||
return true;
|
||||
private boolean isImmune(Card defend, Card attack) {
|
||||
if (defend.name().equals("Dragon") && attack.name().endsWith("Goblin")) return true;
|
||||
if (defend.name().equals("Wizzard") && attack.name().equals("Ork")) return true;
|
||||
if (defend.name().equals("WaterSpell") && attack.name().equals("Knight")) return true;
|
||||
if (defend.name().equals("Kraken") && attack.name().endsWith("Spell")) return true;
|
||||
if (defend.name().equals("FireElf") && attack.name().equals("Dragon")) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private String createCombatString(RoundResult result) {
|
||||
return "";
|
||||
private enum Element {
|
||||
NORMAL,
|
||||
FIRE,
|
||||
WATER;
|
||||
private Element[] strong;
|
||||
private Element[] weak;
|
||||
|
||||
// improvement: map to get mods straight from this enum
|
||||
|
||||
static {
|
||||
NORMAL.strong = new Element[]{WATER};
|
||||
NORMAL.weak = new Element[]{FIRE};
|
||||
|
||||
FIRE.strong = new Element[]{NORMAL};
|
||||
FIRE.weak = new Element[]{WATER};
|
||||
|
||||
WATER.strong = new Element[]{FIRE};
|
||||
WATER.weak = new Element[]{NORMAL};
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<ElementMod, ElementMod> getElementMod(Card left, Card right) {
|
||||
Pair<ElementMod, ElementMod> returnMods = new Pair<>(ElementMod.NONE, ElementMod.NONE);
|
||||
|
||||
if (!left.name().endsWith("Spell") && !right.name().endsWith("Spell")) return returnMods;
|
||||
|
||||
Element leftElement = Element.NORMAL;
|
||||
Element rightElement = Element.NORMAL;
|
||||
|
||||
for (val value : Element.values()) {
|
||||
if (left.name().toLowerCase().startsWith(value.name().toLowerCase())) leftElement = value;
|
||||
if (right.name().toLowerCase().startsWith(value.name().toLowerCase())) rightElement = value;
|
||||
}
|
||||
|
||||
final Element finalLeftElement = leftElement; // lambdas
|
||||
final Element finalRightElement = rightElement;
|
||||
|
||||
if (Arrays.stream(leftElement.strong).anyMatch(value -> value == finalRightElement)) returnMods.setLeft(ElementMod.DOUBLE);
|
||||
else if (Arrays.stream(leftElement.weak).anyMatch(value -> value == finalRightElement)) returnMods.setLeft(ElementMod.HALF);
|
||||
|
||||
if (Arrays.stream(rightElement.strong).anyMatch(value -> value == finalLeftElement)) returnMods.setRight(ElementMod.DOUBLE);
|
||||
else if (Arrays.stream(rightElement.weak).anyMatch(value -> value == finalLeftElement)) returnMods.setRight(ElementMod.HALF);
|
||||
|
||||
return returnMods;
|
||||
}
|
||||
|
||||
private RoundResult fight(FightDTO left, FightDTO right) {
|
||||
if (this.isImmune(left.card(), right.card())) return new RoundResult(left, right, false, ElementMod.NONE, ElementMod.NONE);
|
||||
if (this.isImmune(right.card(), left.card())) return new RoundResult(right, left, false, ElementMod.NONE, ElementMod.NONE);
|
||||
|
||||
Pair<ElementMod, ElementMod> dmgMods = getElementMod(left.card(), right.card());
|
||||
|
||||
boolean leftWins = left.card().damage()*dmgMods.left().percentMod > right.card().damage()*dmgMods.right().percentMod;
|
||||
return new RoundResult(
|
||||
leftWins ? left : right,
|
||||
leftWins ? right : left,
|
||||
left.card().damage()*dmgMods.left().percentMod == right.card().damage()*dmgMods.right().percentMod,
|
||||
leftWins ? dmgMods.left() : dmgMods.right(),
|
||||
leftWins ? dmgMods.right() : dmgMods.left());
|
||||
}
|
||||
|
||||
private String createCombatString(int round, RoundResult result) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder
|
||||
.append(round)
|
||||
.append(": ")
|
||||
.append(String.format("%s: %s (%s damage)",
|
||||
result.winner().player().name,
|
||||
result.winner().card().name(),
|
||||
result.winner().card().damage()))
|
||||
.append(" vs. ")
|
||||
.append(String.format("%s: %s (%s damage)",
|
||||
result.loser().player().name,
|
||||
result.loser().card().name(),
|
||||
result.loser().card().damage()))
|
||||
.append(" => ");
|
||||
|
||||
if (result.winnerMod() != ElementMod.NONE || result.loserMod() != ElementMod.NONE) {
|
||||
stringBuilder
|
||||
.append(String.format("%s vs. %s",
|
||||
result.winner().card().damage(),
|
||||
result.loser().card().damage()))
|
||||
.append(" -> ")
|
||||
.append(String.format("%s vs. %s",
|
||||
result.winner().card().damage() * result.winnerMod().percentMod,
|
||||
result.loser().card().damage() * result.loserMod().percentMod))
|
||||
.append(" => ");
|
||||
}
|
||||
|
||||
if (result.draw()) {
|
||||
return stringBuilder.append("Draw").toString();
|
||||
}
|
||||
|
||||
stringBuilder
|
||||
.append(result.winner().card().name())
|
||||
.append(" wins");
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ public class Combatant {
|
||||
.executeUpdate();
|
||||
};
|
||||
|
||||
public Card getCard() {
|
||||
public Card getAndRemoveCard() {
|
||||
return this.deck.popRandom();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user