foul-magics/Mage/src/main/java/mage/game/command/DungeonRoom.java
Evan Kranzler bb591dd038
[AFR] Implementing dungeon mechanic (ready for review) (#7937)
* added dungeon and dungeon room class

* [AFR] Implemented Tomb of Annihilation

* [AFR] Implemented Shortcut Seeker

* [AFR] Implemented Gloom Stalker

* [AFR] Implemented Nadaar, Selfless Paladin

* added room triggers

* added more venturing code, currently untested

* fixed error

* moved venture into dungeon from player class to game class

* removed unnecessary sourceobject from dungeon

* fixed npe error

* added dungeon completion

* fixed concurrent modification exception

* added logging

* added proper copy methods

* added views

* updated room text generation

* added some missing code

* finished implementing CompletedDungeonCondition

* [AFR] Implemented Ellywick Tumblestrum

* [AFR] Implemented Lost Mine of Phandelver

* added choice dialog for dungeons

* [AFR] Implemented Dungeon of the Mad Mage

* small text fix

* added initial dungeon test

* [AFR] Implemented Cloister Gargoyle

* [AFR] Implemented Dungeon Crawler

* small text change for dungeon rooms

* added more tests

* some simplification to dungeon props

* updated testing helper functions

* added currently failing test for venturing on separate steps and turns

* added tests for dungeon completion

* fixed missing trigger visual and dungeons not persisting through turns

* some text updates

* added rollback test

* added a test for multiple dungeons at once

* added one more condition test
2021-06-29 06:57:43 -04:00

167 lines
4.6 KiB
Java

package mage.game.command;
import mage.abilities.TriggeredAbility;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.StackAbility;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.Target;
import mage.util.CardUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* @author TheElk801
*/
public class DungeonRoom {
private final UUID id;
private final String name;
private final List<DungeonRoom> nextRooms = new ArrayList<>();
private final RoomTriggeredAbility roomTriggeredAbility;
public DungeonRoom(String name, Effect... effects) {
this.id = UUID.randomUUID();
this.name = name;
roomTriggeredAbility = new RoomTriggeredAbility(this, effects);
}
private DungeonRoom(final DungeonRoom room) {
this.id = room.id;
this.name = room.name;
this.roomTriggeredAbility = new RoomTriggeredAbility(this, room.roomTriggeredAbility);
}
public DungeonRoom copy() {
return new DungeonRoom(this);
}
public void addTarget(Target target) {
roomTriggeredAbility.addTarget(target);
}
public void addNextRoom(DungeonRoom room) {
nextRooms.add(room);
}
public RoomTriggeredAbility getRoomTriggeredAbility() {
return roomTriggeredAbility;
}
public UUID getId() {
return id;
}
@Override
public String toString() {
return roomTriggeredAbility.getText();
}
public String getName() {
return name;
}
public boolean hasNextRoom() {
return !nextRooms.isEmpty();
}
List<DungeonRoom> getNextRooms() {
return nextRooms;
}
public DungeonRoom chooseNextRoom(UUID playerId, Game game) {
switch (nextRooms.size()) {
case 0:
return null;
case 1:
return nextRooms.get(0);
case 2:
DungeonRoom room1 = nextRooms.get(0);
DungeonRoom room2 = nextRooms.get(1);
Player player = game.getPlayer(playerId);
if (player == null) {
return null;
}
return player.chooseUse(
Outcome.Neutral, "Choose which room to go to",
null, room1.name, room2.name, null, game
) ? room1 : room2;
default:
throw new UnsupportedOperationException("there shouldn't be more than two rooms to go to");
}
}
String generateDestinationText() {
if (nextRooms.isEmpty()) {
return "";
}
return " <i>(Leads to "
+ nextRooms
.stream()
.map(DungeonRoom::getName)
.reduce((a, b) -> a + " or " + b)
.orElse("")
+ ")</i>";
}
public static boolean isRoomTrigger(StackObject stackObject) {
return stackObject instanceof StackAbility
&& stackObject.getStackAbility() instanceof RoomTriggeredAbility;
}
public static boolean isRoomTrigger(TriggeredAbility ability) {
return ability instanceof RoomTriggeredAbility;
}
}
class RoomTriggeredAbility extends TriggeredAbilityImpl {
private final DungeonRoom room;
RoomTriggeredAbility(DungeonRoom room, Effect... effects) {
super(Zone.COMMAND, null, false);
this.room = room;
for (Effect effect : effects) {
this.addEffect(effect);
}
this.setRuleVisible(false);
}
RoomTriggeredAbility(DungeonRoom room, final RoomTriggeredAbility ability) {
super(ability);
this.room = room;
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ROOM_ENTERED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getTargetId().equals(room.getId());
}
@Override
public RoomTriggeredAbility copy() {
return new RoomTriggeredAbility(this.room, this);
}
public String getText() {
return room.getName() + " &mdash; "
+ CardUtil.getTextWithFirstCharUpperCase(super.getRule())
+ room.generateDestinationText();
}
@Override
public String getRule() {
return "When you enter this room, " + super.getRule() + " <i>(" + room.getName() + ")</i>";
}
}