Skip to content

Commit

Permalink
BlackDragon + NeutralFigureReturned/UndeployNeutralFigure
Browse files Browse the repository at this point in the history
  • Loading branch information
stanolacko committed Sep 16, 2022
1 parent d433b2c commit 5296f41
Show file tree
Hide file tree
Showing 23 changed files with 480 additions and 29 deletions.
19 changes: 19 additions & 0 deletions src/main/java/com/jcloisterzone/action/MoveBlackDragonAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.jcloisterzone.action;

import com.jcloisterzone.board.Position;
import io.vavr.collection.Set;

//TODO generic NeutralMeepleAction ?
public class MoveBlackDragonAction extends SelectTileAction {

private final String figureId;

public MoveBlackDragonAction(String figureId, Set<Position> options) {
super(options);
this.figureId = figureId;
}

public String getFigureId() {
return figureId;
}
}
1 change: 1 addition & 0 deletions src/main/java/com/jcloisterzone/engine/Engine.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ private GameSetup createSetupFromMessage(GameSetupMessage setupMsg) {
capabilities = addCapabilities(capabilities, setupMsg,"watchtower", WatchtowerCapability.class);

capabilities = addCapabilities(capabilities, setupMsg,"robbers-son", RobbersSonCapability.class);
capabilities = addCapabilities(capabilities, setupMsg,"black-dragon", BlackDragonCapability.class);

Map<Rule, Object> rules = HashMap.empty();
if (setupMsg.getElements().containsKey("farmers")) {
Expand Down
63 changes: 63 additions & 0 deletions src/main/java/com/jcloisterzone/engine/StateGsonBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,21 @@
import com.jcloisterzone.feature.Tower;
import com.jcloisterzone.figure.Follower;
import com.jcloisterzone.figure.Meeple;
import com.jcloisterzone.figure.neutral.BlackDragon;
import com.jcloisterzone.figure.neutral.Dragon;
import com.jcloisterzone.game.capability.*;
import com.jcloisterzone.game.capability.FerriesCapability.FerryToken;
import com.jcloisterzone.game.capability.GoldminesCapability.GoldToken;
import com.jcloisterzone.game.capability.LittleBuildingsCapability.LittleBuilding;
import com.jcloisterzone.game.capability.SheepToken;
import com.jcloisterzone.game.phase.BlackDragonMovePhase;
import com.jcloisterzone.game.phase.DragonMovePhase;
import com.jcloisterzone.game.phase.Phase;
import com.jcloisterzone.game.phase.RussianPromosTrapPhase;
import com.jcloisterzone.game.state.*;
import com.jcloisterzone.io.MessageParser;
import io.vavr.Tuple2;
import io.vavr.Tuple3;
import io.vavr.collection.*;

import java.lang.reflect.Type;
Expand Down Expand Up @@ -70,6 +73,7 @@ public Gson create() {
builder.registerTypeAdapter(RemoveMageOrWitchAction.class, new ActionSerializer("RemoveMageOrWitch"));
builder.registerTypeAdapter(LittleBuildingAction.class, new LittleBuildingActionSerializer());
builder.registerTypeAdapter(ScoreAcrobatsAction.class, new SelectFeatureActionSerializer());
builder.registerTypeAdapter(MoveBlackDragonAction.class, new MoveBlackDragonActionSerializer());
return builder.create();
}

Expand Down Expand Up @@ -288,6 +292,19 @@ public JsonElement serializeNeutralFigures(GameState root, JsonSerializationCont
data.add("placement", context.serialize(pos));
neutral.add("bigtop", data);
}
pos = state.getBlackDragonDeployment();
if (pos != null) {
Tuple3<Vector<Position>,Integer,Array<Integer>> blackdragonmoves = root.getCapabilityModel(BlackDragonCapability.class);
JsonObject data = new JsonObject();
data.add("position", context.serialize(pos));
if (root.getPhase() instanceof BlackDragonMovePhase) {
JsonArray visitedData = new JsonArray();
blackdragonmoves._1.forEach(p -> visitedData.add(context.serialize(p)));
data.add("visited", visitedData);
data.addProperty("remaining", blackdragonmoves._2 - blackdragonmoves._1.length());
}
neutral.add("blackdragon", data);
}
return neutral;
}

Expand Down Expand Up @@ -374,6 +391,7 @@ public JsonArray serializePlayEvents(GameState root, JsonSerializationContext co
JsonObject item = null;
JsonArray turnEvents = null;
JsonArray dragonPath = null;
JsonArray blackdragonPath = null;
for (PlayEvent ev : root.getEvents()) {
if (ev instanceof PlayerTurnEvent) {
player = ((PlayerTurnEvent) ev).getPlayer();
Expand All @@ -387,6 +405,7 @@ public JsonArray serializePlayEvents(GameState root, JsonSerializationContext co
events.add(item);
// clean-up
dragonPath = null;
blackdragonPath = null;
continue;
}
if (item == null) {
Expand Down Expand Up @@ -529,6 +548,19 @@ public JsonArray serializePlayEvents(GameState root, JsonSerializationContext co
} else {
dragonPath.add(context.serialize(nev.getTo()));
}
} else if (nev.getNeutralFigure() instanceof BlackDragon) {
if (blackdragonPath == null) {
JsonObject data = new JsonObject();
blackdragonPath = new JsonArray();
blackdragonPath.add(context.serialize(nev.getFrom()));
blackdragonPath.add(context.serialize(nev.getTo()));
data.addProperty("type", "blackdragon-moved");
data.addProperty("figure", nev.getNeutralFigure().getId());
data.add("path", blackdragonPath);
turnEvents.add(data);
} else {
blackdragonPath.add(context.serialize(nev.getTo()));
}
} else {
JsonObject data = new JsonObject();
data.addProperty("type", "neutral-moved");
Expand All @@ -539,6 +571,21 @@ public JsonArray serializePlayEvents(GameState root, JsonSerializationContext co
}
continue;
}
if (ev instanceof NeutralFigureReturned) {
NeutralFigureReturned nfr = (NeutralFigureReturned) ev;
if (nfr.isForced()) {
JsonObject data = new JsonObject();
data.addProperty("type", "neutralfigure-returned");
data.addProperty("neutralfigure", nfr.getNeutralFigure().getClass().getSimpleName().toLowerCase());
Player nfrp = nfr.getPlayer();
if (nfrp != null) {
data.addProperty("player", nfr.getPlayer().getIndex());
}
data.add("from", context.serialize(nfr.getFrom()));
turnEvents.add(data);
}
continue;
}
if (ev instanceof RansomPaidEvent) {
RansomPaidEvent rev = (RansomPaidEvent) ev;
JsonObject data = new JsonObject();
Expand Down Expand Up @@ -897,4 +944,20 @@ public JsonElement serialize(LittleBuildingAction action, Type type, JsonSeriali
return json;
}
}

private class MoveBlackDragonActionSerializer implements JsonSerializer<MoveBlackDragonAction> {
@Override
public JsonElement serialize(MoveBlackDragonAction action, Type type, JsonSerializationContext context) {
JsonObject json = new JsonObject();
json.addProperty("type", "MoveDragon");
json.addProperty("figureId", action.getFigureId());
JsonArray options = new JsonArray();
action.getOptions().forEach(pos -> {
options.add(context.serialize(pos));
});
json.add("options", options);
return json;
}
}

}
16 changes: 15 additions & 1 deletion src/main/java/com/jcloisterzone/event/NeutralFigureReturned.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@

import com.jcloisterzone.board.pointer.BoardPointer;
import com.jcloisterzone.figure.neutral.NeutralFigure;
import com.jcloisterzone.Player;

public class NeutralFigureReturned extends PlayEvent {

private final BoardPointer from;
private final NeutralFigure<?> neutralFigure;
private final boolean forced;
/** true if meeple is returned different way than scoring feature */
private final Player player;

public NeutralFigureReturned(PlayEventMeta metadata, NeutralFigure<?> neutralFigure, BoardPointer from) {
public NeutralFigureReturned(PlayEventMeta metadata, NeutralFigure<?> neutralFigure, BoardPointer from, Boolean forced, Player player) {
super(metadata);
this.neutralFigure = neutralFigure;
this.from = from;
this.forced = forced;
this.player = player;
}

public BoardPointer getFrom() {
Expand All @@ -21,4 +27,12 @@ public BoardPointer getFrom() {
public NeutralFigure<?> getNeutralFigure() {
return neutralFigure;
}

public boolean isForced() {
return forced;
}

public Player getPlayer() {
return player;
}
}
5 changes: 5 additions & 0 deletions src/main/java/com/jcloisterzone/figure/Barn.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public boolean canBeEatenByDragon(GameState state) {
return false;
}

@Override
public boolean canBeEatenByBlackDragon(GameState state) {
return false;
}

@Override
public DeploymentCheckResult isDeploymentAllowed(GameState state, FeaturePointer fp, Structure feature) {
if (!(feature instanceof Field)) {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/jcloisterzone/figure/Figure.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ public boolean isInSupply(GameState state) {
return !isDeployed(state);
}

public boolean canBeEatenByBlackDragon(GameState state) {
return true;
}

@Override
public int hashCode() {
return id.hashCode();
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/jcloisterzone/figure/Follower.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public boolean canBeEatenByDragon(GameState state) {
return !(getFeature(state) instanceof Castle);
}

@Override
public boolean canBeEatenByBlackDragon(GameState state) {
return !(getFeature(state) instanceof Castle);
}
public boolean isCaptured(GameState state) {
Array<List<Follower>> model = state.getCapabilityModel(TowerCapability.class);
return model != null && Stream.concat(model).find(f -> f == this).isDefined();
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/jcloisterzone/figure/neutral/BigTop.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.jcloisterzone.Immutable;
import com.jcloisterzone.board.Position;
import com.jcloisterzone.game.state.GameState;

@Immutable
public class BigTop extends NeutralFigure<Position> {
Expand All @@ -11,4 +12,9 @@ public class BigTop extends NeutralFigure<Position> {
public BigTop(String id) {
super(id);
}

@Override
public boolean canBeEatenByBlackDragon(GameState state) {
return false;
}
}
15 changes: 15 additions & 0 deletions src/main/java/com/jcloisterzone/figure/neutral/BlackDragon.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.jcloisterzone.figure.neutral;

import com.jcloisterzone.Immutable;
import com.jcloisterzone.board.Position;

@Immutable
public class BlackDragon extends NeutralFigure<Position> {

private static final long serialVersionUID = 1L;

public BlackDragon(String id) {
super(id);
}

}
6 changes: 6 additions & 0 deletions src/main/java/com/jcloisterzone/figure/neutral/Count.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.jcloisterzone.Immutable;
import com.jcloisterzone.board.pointer.FeaturePointer;
import com.jcloisterzone.game.state.GameState;

@Immutable
public class Count extends NeutralFigure<FeaturePointer> {
Expand All @@ -11,4 +12,9 @@ public class Count extends NeutralFigure<FeaturePointer> {
public Count(String id) {
super(id);
}

@Override
public boolean canBeEatenByBlackDragon(GameState state) {
return false;
}
}
12 changes: 0 additions & 12 deletions src/main/java/com/jcloisterzone/figure/neutral/NeutralFigure.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,4 @@ public boolean at(GameState state, Structure feature) {
FeaturePointer fp = ptr.asFeaturePointer();
return feature.getPlaces().contains(fp);
}


// @Override
// public void deploy(T at) {
// T origin = getDeployment();
// game.replaceState(state -> {
// LinkedHashMap<NeutralFigure<?>, BoardPointer> deployedNeutralFigures = state.getDeployedNeutralFigures();
// return state.setDeployedNeutralFigures(deployedNeutralFigures.put(this, at));
// });
// game.post(new NeutralFigureMoveEvent(game.getActivePlayer(), this, origin, at));
// }

}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public GameStatePhaseReducer(GameSetup setup, double initialRandom) {
next = cleanUpTurnPartPhase = new CleanUpTurnPartPhase(randomGenerator, next);
if (setup.contains(CornCircleCapability.class)) next = new CornCirclePhase(randomGenerator, next);

if (setup.contains(BlackDragonCapability.class)) next = new BlackDragonPlacePhase(randomGenerator, next);

if (setup.contains(DragonCapability.class) && "after-scoring".equals(setup.getStringRule(Rule.DRAGON_MOVEMENT))) {
next = new DragonPhase(randomGenerator, next);
}
Expand Down
Loading

0 comments on commit 5296f41

Please sign in to comment.