SteamWar/FightSystem
Archiviert
13
1

Improved Pathplanning, WIP StateMachine

Signed-off-by: Lixfel <agga-games@gmx.de>
Dieser Commit ist enthalten in:
Lixfel 2023-09-03 13:39:38 +02:00
Ursprung 71ddeb4ac8
Commit 39ccb113a8
2 geänderte Dateien mit 195 neuen und 58 gelöschten Zeilen
FightSystem_Core/src/de/steamwar/fightsystem/ai

Datei anzeigen

@ -26,17 +26,14 @@ import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.*;
import java.util.function.Function;
public class LixfelAI extends AI {
private Random random;
private LixfelPathplanner pathplanner;
private List<Cannon> cannons;
private List<Cannon> shootingList;
private Action action;
public LixfelAI(FightTeam team, String user) {
super(team, SteamwarUser.get(user));
@ -45,8 +42,6 @@ public class LixfelAI extends AI {
@Override
public SchematicNode chooseSchematic() {
random = new Random();
cannons = new ArrayList<>();
shootingList = new ArrayList<>();
List<SchematicNode> publics = SchematicNode.getAllSchematicsOfType(0, Config.SchematicType.toDB());
SchematicNode schem = publics.get(random.nextInt(publics.size()));
@ -54,47 +49,194 @@ public class LixfelAI extends AI {
pathplanner = new LixfelPathplanner(schem);
cannons.add(new Cannon(new Vector(11,25,11), 10,23,14, 12,23,14, 10,23,12, 12,23,12, 12,24,15, 10,24,14, 12,23,15, 12,24,14, 11,24,12, 10,24,15, 12,24,12, 10,23,15, 10,24,12));
cannons.add(new Cannon(new Vector(39,25,11), 38,24,15, 38,23,12, 40,23,14, 40,24,12, 40,23,15, 40,24,14, 39,24,12, 38,23,14, 40,24,15, 40,23,12, 38,23,15, 38,24,12, 38,24,14));
cannons.add(new Cannon(new Vector(12,18,11), 13,17,15, 13,17,16, 13,18,16, 13,18,14, 14,18,14, 14,17,15, 14,17,16, 14,18,16, 13,17,14, 14,17,14, 13,18,15, 14,18,15));
cannons.add(new Cannon(new Vector(38,18,11), 37,18,14, 36,18,14, 36,17,15, 37,17,15, 37,18,15, 36,18,15, 36,17,14, 37,17,14, 36,17,16, 37,17,16, 36,18,16, 37,18,16));
cannons.add(new Cannon(new Vector(8,9,16), 10,11,17, 10,8,19, 10,8,17, 11,8,19, 11,8,15, 10,8,15, 12,8,15, 10,10,15, 12,7,19, 11,10,15, 12,8,19, 12,7,15, 11,7,15, 10,9,17, 11,9,19, 12,9,19, 10,9,19, 10,7,17, 11,7,19, 10,7,15, 10,7,19, 10,10,17, 12,9,15, 10,9,15, 11,9,15, 12,10,19, 11,10,19, 12,10,15, 10,6,17, 10,10,19));
//cannons.add(new Cannon(null, 23,5,9, 23,6,9, 23,7,9, 23,8,9));
//cannons.add(new Cannon(null, 27,5,9, 27,6,9, 27,7,9, 27,8,9));
cannons.add(new Cannon(null, 23,5,9, 23,6,9, 23,7,9, 23,8,9, 27,5,9, 27,6,9, 27,7,9, 27,8,9, 23,5,9, 23,6,9, 23,7,9, 23,8,9, 27,5,9, 27,6,9, 27,7,9, 27,8,9, 23,5,9, 23,6,9, 23,7,9, 23,8,9, 27,5,9, 27,6,9, 27,7,9, 27,8,9, 23,5,9, 23,6,9, 23,7,9, 23,8,9, 27,5,9, 27,6,9, 27,7,9, 27,8,9));
Collections.shuffle(cannons);
action = new BlockAction(Collections.emptyList(), Collections.singletonList(new Vector(25, 15, 25)),
new MoveToRangeAction(new Vector(21, 15, 24),
new FunctionAction(ai -> {
setReady();
return FightState.getFightState() == FightState.PRE_RUNNING;
},
new WaitAction(420,
new BlockAction(Collections.emptyList(), Collections.singletonList(new Vector(21, 15, 24)),
new FunctionAction(ai -> FightState.getFightState() == FightState.RUNNING,
new ChooseCannonAction(
new Cannon(new Vector(11,25,11), 10,23,14, 12,23,14, 10,23,12, 12,23,12, 12,24,15, 10,24,14, 12,23,15, 12,24,14, 11,24,12, 10,24,15, 12,24,12, 10,23,15, 10,24,12),
new Cannon(new Vector(39,25,11), 38,24,15, 38,23,12, 40,23,14, 40,24,12, 40,23,15, 40,24,14, 39,24,12, 38,23,14, 40,24,15, 40,23,12, 38,23,15, 38,24,12, 38,24,14),
new Cannon(new Vector(12,18,11), 13,17,15, 13,17,16, 13,18,16, 13,18,14, 14,18,14, 14,17,15, 14,17,16, 14,18,16, 13,17,14, 14,17,14, 13,18,15, 14,18,15),
new Cannon(new Vector(38,18,11), 37,18,14, 36,18,14, 36,17,15, 37,17,15, 37,18,15, 36,18,15, 36,17,14, 37,17,14, 36,17,16, 37,17,16, 36,18,16, 37,18,16),
new Cannon(new Vector(8,9,16), 10,11,17, 10,8,19, 10,8,17, 11,8,19, 11,8,15, 10,8,15, 12,8,15, 10,10,15, 12,7,19, 11,10,15, 12,8,19, 12,7,15, 11,7,15, 10,9,17, 11,9,19, 12,9,19, 10,9,19, 10,7,17, 11,7,19, 10,7,15, 10,7,19, 10,10,17, 12,9,15, 10,9,15, 11,9,15, 12,10,19, 11,10,19, 12,10,15, 10,6,17, 10,10,19),
new Cannon(null, 23,5,9, 23,6,9, 23,7,9, 23,8,9),
new Cannon(null, 27,5,9, 27,6,9, 27,7,9, 27,8,9)
)
)
)
)
)
)
);
return schem;
}
@Override
protected void plan() {
setReady();
if(shootingList.isEmpty())
shootingList.addAll(cannons);
if(shootingList.isEmpty() || FightState.getFightState() != FightState.RUNNING) {
moveTo(pathplanner.getWalkable().get(random.nextInt(pathplanner.getWalkable().size())));
return;
}
Cannon cannon = shootingList.remove(0);
cannon.shoot();
LixfelPathplanner getPathplanner() {
return pathplanner;
}
private boolean moveTo(Vector destination) {
List<Vector> path = pathplanner.plan(getPosition(), destination);
if(path.isEmpty())
return false;
void setAction(Action action) {
this.action = action;
}
path.forEach(this::move);
return true;
@Override
protected void plan() {
action.plan(this);
}
private abstract static class Action {
private Action next;
public Action(Action next) {
this.next = next;
}
public abstract void plan(LixfelAI ai);
public void setNext(Action followup) {
this.next = followup;
}
protected void next(LixfelAI ai) {
ai.setAction(next);
next.plan(ai);
}
}
private static class FunctionAction extends Action {
private final Function<LixfelAI, Boolean> action;
public FunctionAction(Function<LixfelAI, Boolean> action, Action followup) {
super(followup);
this.action = action;
}
@Override
public void plan(LixfelAI ai) {
if(action.apply(ai))
next(ai);
}
}
private static class WaitAction extends Action {
private int remaining;
public WaitAction(int ticks, Action followup) {
super(followup);
this.remaining = ticks;
}
@Override
public void plan(LixfelAI ai) {
if(--remaining == 0)
next(ai);
}
}
private static class MoveToRangeAction extends Action {
private final Vector target;
public MoveToRangeAction(Vector target, Action next) {
super(next);
this.target = target;
}
@Override
public void plan(LixfelAI ai) {
Vector position = ai.getPosition();
Vector eyePosition = new Vector(0, ai.getEntity().getEyeHeight(), 0).add(position);
if(eyePosition.distance(target) > 5) {
List<Vector> path = new ArrayList<>(ai.getPathplanner().planToRange(position, target, 5.0));
if(path.isEmpty())
path.add(new Vector(0, 1, 0).add(position));
ai.move(path.get(0));
} else {
next(ai);
}
}
}
private static class BlockAction extends Action {
private final List<Vector> tntToPlace;
private final List<Vector> interactables;
public BlockAction(List<Vector> tntToPlace, List<Vector> interactables, Action followup) {
super(followup);
this.tntToPlace = new ArrayList<>(tntToPlace);
this.interactables = new ArrayList<>(interactables);
}
@Override
public void plan(LixfelAI ai) {
if(!tntToPlace.isEmpty()) {
if(outOfRange(ai, tntToPlace.get(0)))
return;
ai.setTNT(tntToPlace.remove(0));
return;
}
if(!interactables.isEmpty()) {
if(outOfRange(ai, interactables.get(0)))
return;
ai.interact(interactables.remove(0));
return;
}
next(ai);
}
private boolean outOfRange(LixfelAI ai, Vector location) {
Vector position = ai.getPosition();
Vector eyePosition = new Vector(0, ai.getEntity().getEyeHeight(), 0).add(position);
boolean outOfRange = eyePosition.distance(location) > 5;
if(outOfRange) {
List<Vector> path = new ArrayList<>(ai.getPathplanner().planToRange(position, location, 5.0));
if(path.isEmpty())
path.add(new Vector(0, 1, 0).add(position));
System.out.println(ai.getEntity().getName() + ": " + position + "->" + path.get(0));
ai.move(path.get(0));
}
return outOfRange;
}
}
private static class ChooseCannonAction extends Action {
private final List<Cannon> cannons;
private final List<Cannon> shootingList = new ArrayList<>();
public ChooseCannonAction(Cannon... cannons) {
super(null);
this.cannons = Arrays.asList(cannons);
Collections.shuffle(this.cannons);
}
@Override
public void plan(LixfelAI ai) {
if(shootingList.isEmpty())
shootingList.addAll(cannons);
setNext(shootingList.remove(0).toAction(this));
next(ai);
}
}
private class Cannon {
private final Vector activator;
private final List<Vector> tnt = new ArrayList<>();
private final Vector entityLocation;
public Cannon(Vector activator, int... tntpos) {
this.activator = activator;
@ -102,25 +244,10 @@ public class LixfelAI extends AI {
for(int i = 0; i < tntpos.length; i+=3) {
tnt.add(new Vector(tntpos[i], tntpos[i+1], tntpos[i+2]));
}
List<Vector> locations = new ArrayList<>(tnt);
if(activator != null)
locations.add(activator);
entityLocation = pathplanner.walkableNearby(getEntity().getEyeHeight(), 5, locations);
}
public boolean shoot() {
if(entityLocation == null)
return false;
if(!moveTo(entityLocation))
return false;
tnt.forEach(LixfelAI.this::setTNT);
if(activator != null)
interact(activator);
return true;
public BlockAction toAction(Action next) {
return new BlockAction(new ArrayList<>(tnt), activator == null ? Collections.emptyList() : Collections.singletonList(activator), next);
}
}
}

Datei anzeigen

@ -125,6 +125,7 @@ public class LixfelPathplanner {
}
}
@Deprecated
public Vector walkableNearby(double eyeHeight, double distance, List<Vector> nearby) {
List<Vector> moddedNearby = nearby.stream().map(n -> n.clone().subtract(new Vector(0, eyeHeight, 0))).collect(Collectors.toList());
return walkable.stream()
@ -145,12 +146,21 @@ public class LixfelPathplanner {
return plan;
}
public List<Vector> planToRange(Vector start, Vector destination, double range) {
return plan(start, walkable.stream().filter(vector -> vector.distance(destination) <= range).collect(Collectors.toList()));
}
public List<Vector> plan(Vector start, Vector destination) {
if(neighbouring(start, destination))
return Collections.singletonList(destination);
return plan(start, Collections.singletonList(destination));
}
public List<Vector> plan(Vector start, List<Vector> destinations) {
for(Vector destination : destinations)
if(neighbouring(start, destination))
return Collections.singletonList(destination);
Map<Vector, Vector> approach = new HashMap<>();
Set<Vector> checking = Collections.singleton(destination);
Set<Vector> checking = new HashSet<>(destinations);
while(!checking.isEmpty()) {
Set<Vector> toCheck = new HashSet<>();
@ -168,7 +178,7 @@ public class LixfelPathplanner {
List<Vector> path = new ArrayList<>();
path.add(firstStep);
while(path.get(path.size()-1) != destination) {
while(!destinations.contains(path.get(path.size()-1))) {
path.add(approach.get(path.get(path.size()-1)));
}