Somewhat functional base building AI
This commit is contained in:
@@ -19,6 +19,8 @@ public enum Gamemode{
|
||||
}),
|
||||
attack(rules -> {
|
||||
rules.attackMode = true;
|
||||
rules.waves = true;
|
||||
rules.waveTimer = true;
|
||||
}, map -> map.teams.contains(state.rules.waveTeam.id)),
|
||||
pvp(rules -> {
|
||||
rules.pvp = true;
|
||||
|
||||
@@ -22,6 +22,8 @@ public class Rules{
|
||||
public boolean waves;
|
||||
/** Whether the enemy AI has infinite resources in most of their buildings and turrets. */
|
||||
public boolean enemyCheat;
|
||||
/** Whether the enemy AI has infinite resources in their core only. TODO remove */
|
||||
public boolean enemyInfiniteResources = true;
|
||||
/** Whether the game objective is PvP. Note that this enables automatic hosting. */
|
||||
public boolean pvp;
|
||||
/** Whether reactors can explode and damage other blocks. */
|
||||
@@ -69,6 +71,8 @@ public class Rules{
|
||||
/** Whether to draw shadows of blocks at map edges and static blocks.
|
||||
* Do not change unless you know exactly what you are doing.*/
|
||||
public boolean drawDarkness = true;
|
||||
/** EXPERIMENTAL building AI. TODO remove */
|
||||
public boolean buildAI = true;
|
||||
/** Starting items put in cores */
|
||||
public Array<ItemStack> loadout = Array.with(ItemStack.with(Items.copper, 100));
|
||||
/** Weather events that occur here. */
|
||||
|
||||
@@ -6,12 +6,14 @@ import arc.files.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.graphics.gl.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import arc.util.io.Streams.*;
|
||||
import arc.util.pooling.*;
|
||||
import arc.util.serialization.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
@@ -38,6 +40,8 @@ import static mindustry.Vars.*;
|
||||
|
||||
/** Handles schematics.*/
|
||||
public class Schematics implements Loadable{
|
||||
private static final Schematic tmpSchem = new Schematic(new Array<>(), new StringMap(), 0, 0);
|
||||
private static final Schematic tmpSchem2 = new Schematic(new Array<>(), new StringMap(), 0, 0);
|
||||
public static final String base64Header = "bXNjaAB";
|
||||
|
||||
private static final byte[] header = {'m', 's', 'c', 'h'};
|
||||
@@ -526,5 +530,69 @@ public class Schematics implements Loadable{
|
||||
return null;
|
||||
}
|
||||
|
||||
//endregion
|
||||
//region misc utility
|
||||
|
||||
/** @return a temporary schematic representing the input rotated 90 degrees counterclockwise N times. */
|
||||
public static Schematic rotate(Schematic input, int times){
|
||||
if(times == 0) return input;
|
||||
|
||||
boolean sign = times > 0;
|
||||
for(int i = 0; i < Math.abs(times); i++){
|
||||
input = rotated(input, sign);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
private static Schematic rotated(Schematic input, boolean counter){
|
||||
int direction = Mathf.sign(counter);
|
||||
Schematic schem = input == tmpSchem ? tmpSchem2 : tmpSchem2;
|
||||
schem.width = input.width;
|
||||
schem.height = input.height;
|
||||
Pools.freeAll(schem.tiles);
|
||||
schem.tiles.clear();
|
||||
for(Stile tile : input.tiles){
|
||||
schem.tiles.add(Pools.obtain(Stile.class, Stile::new).set(tile));
|
||||
}
|
||||
|
||||
int ox = schem.width/2, oy = schem.height/2;
|
||||
|
||||
schem.tiles.each(req -> {
|
||||
req.config = BuildRequest.pointConfig(req.config, p -> {
|
||||
int cx = p.x, cy = p.y;
|
||||
int lx = cx;
|
||||
|
||||
if(direction >= 0){
|
||||
cx = -cy;
|
||||
cy = lx;
|
||||
}else{
|
||||
cx = cy;
|
||||
cy = -lx;
|
||||
}
|
||||
p.set(cx, cy);
|
||||
});
|
||||
|
||||
//rotate actual request, centered on its multiblock position
|
||||
float wx = (req.x - ox) * tilesize + req.block.offset(), wy = (req.y - oy) * tilesize + req.block.offset();
|
||||
float x = wx;
|
||||
if(direction >= 0){
|
||||
wx = -wy;
|
||||
wy = x;
|
||||
}else{
|
||||
wx = wy;
|
||||
wy = -x;
|
||||
}
|
||||
req.x = (short)(world.toTile(wx - req.block.offset()) + ox);
|
||||
req.y = (short)(world.toTile(wy - req.block.offset()) + oy);
|
||||
req.rotation = (byte)Mathf.mod(req.rotation + direction, 4);
|
||||
});
|
||||
|
||||
//assign flipped values, since it's rotated
|
||||
schem.width = input.height;
|
||||
schem.height = input.width;
|
||||
|
||||
return schem;
|
||||
}
|
||||
|
||||
//endregion
|
||||
}
|
||||
|
||||
@@ -148,11 +148,12 @@ public class Teams{
|
||||
public final Array<CoreEntity> cores = new Array<>();
|
||||
public final Array<Team> enemies = new Array<>();
|
||||
public final Team team;
|
||||
public final BaseAI ai;
|
||||
public Queue<BlockPlan> blocks = new Queue<>();
|
||||
public BaseAI ai = new BaseAI();
|
||||
|
||||
public TeamData(Team team){
|
||||
this.team = team;
|
||||
this.ai = new BaseAI(this);
|
||||
}
|
||||
|
||||
public boolean active(){
|
||||
@@ -173,7 +174,7 @@ public class Teams{
|
||||
|
||||
/** @return whether this team is controlled by the AI and builds bases. */
|
||||
public boolean hasAI(){
|
||||
return state.rules.attackMode && team == state.rules.waveTeam;
|
||||
return state.rules.attackMode && team == state.rules.waveTeam && state.rules.buildAI;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -191,9 +192,9 @@ public class Teams{
|
||||
public final short x, y, rotation, block;
|
||||
public final Object config;
|
||||
|
||||
public BlockPlan(short x, short y, short rotation, short block, Object config){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
public BlockPlan(int x, int y, short rotation, short block, Object config){
|
||||
this.x = (short)x;
|
||||
this.y = (short)y;
|
||||
this.rotation = rotation;
|
||||
this.block = block;
|
||||
this.config = config;
|
||||
|
||||
Reference in New Issue
Block a user