1298 lines
26 KiB
Plaintext
1298 lines
26 KiB
Plaintext
/*******************/
|
|
/* Data Structures */
|
|
/*******************/
|
|
public class BB_Object
|
|
{
|
|
bool isEqual(BB_Object other)
|
|
{
|
|
//message("Generic BB_Object::isEqual used", DisplayWarning);
|
|
return this == other;
|
|
}
|
|
}
|
|
|
|
public class BB_Int extends BB_Object
|
|
{
|
|
int value;
|
|
void BB_Int(int i = 0)
|
|
{
|
|
this.value = i;
|
|
}
|
|
|
|
bool isEqual(BB_Object other)
|
|
{
|
|
if (other == null) return false;
|
|
if (this == other) return true;
|
|
BB_Int intOther = other;
|
|
return this.value == intOther.value;
|
|
}
|
|
}
|
|
|
|
public class BB_GameObject extends BB_Object
|
|
{
|
|
object value;
|
|
void BB_GameObject(object value = null)
|
|
{
|
|
this.value = value;
|
|
}
|
|
|
|
bool isEqual(BB_Object other)
|
|
{
|
|
if (other == null) return false;
|
|
if (this == other) return true;
|
|
BB_GameObject objectOther = other;
|
|
return this.value == objectOther.value;
|
|
}
|
|
}
|
|
|
|
public class BB_Array
|
|
{
|
|
// synchronized is probably not enough for thread-safeness so
|
|
// todo: use some kind of mutex
|
|
|
|
private BB_Object[] data;
|
|
private int size = 0;
|
|
|
|
synchronized void push_back(BB_Object obj)
|
|
{
|
|
data[size] = obj;
|
|
size += 1;
|
|
}
|
|
|
|
synchronized BB_Object pop_back()
|
|
{
|
|
if (size == 0) return null;
|
|
BB_Object obj = data[size-1];
|
|
data[size-1] = null;
|
|
size -= 1;
|
|
return obj;
|
|
}
|
|
|
|
synchronized BB_Object back()
|
|
{
|
|
if (size == 0) return null;
|
|
return data[size-1];
|
|
}
|
|
|
|
synchronized void push_front(BB_Object obj)
|
|
{
|
|
size += 1;
|
|
for (int i = size - 1; i > 0; --i)
|
|
data[i] = data[i-1];
|
|
data[0] = obj;
|
|
}
|
|
|
|
synchronized BB_Object pop_front()
|
|
{
|
|
if (size == 0) return null;
|
|
BB_Object obj = data[0];
|
|
for (int i = 1; i < size; ++i)
|
|
data[i-1] = data[i];
|
|
data[size-1] = null;
|
|
size -= 1;
|
|
return obj;
|
|
}
|
|
|
|
synchronized BB_Object front()
|
|
{
|
|
if (size == 0) return null;
|
|
return data[0];
|
|
}
|
|
|
|
synchronized BB_Object find(BB_Object obj)
|
|
{
|
|
for (int i = 0; i < size; ++i)
|
|
if (data[i].isEqual(obj))
|
|
return data[i];
|
|
return null;
|
|
}
|
|
|
|
synchronized void remove(BB_Object obj)
|
|
{
|
|
for (int i = 0; i < size; ++i)
|
|
{
|
|
if (data[i].isEqual(obj))
|
|
{
|
|
for (int j = i + 1; j < size; ++j)
|
|
{
|
|
data[j-1] = data[j];
|
|
}
|
|
data[size-1] = null;
|
|
size -= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
int getSize()
|
|
{
|
|
return size;
|
|
}
|
|
}
|
|
/*********/
|
|
/* Tasks */
|
|
/*********/
|
|
public class BB_Task extends BB_Object
|
|
{
|
|
BB_Task update()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Generic Task";
|
|
}
|
|
|
|
bool didComplete()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool didFail()
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public class BB_TaskCompleted extends BB_Task
|
|
{
|
|
bool didComplete()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Completed";
|
|
}
|
|
}
|
|
|
|
public class BB_TaskFailed extends BB_Task
|
|
{
|
|
private BB_Task recovery;
|
|
|
|
void BB_TaskFailed(BB_Task recovery = null)
|
|
{
|
|
this.recovery = recovery;
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Failed";
|
|
}
|
|
|
|
bool didFail()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
BB_Task getRecovery()
|
|
{
|
|
return recovery;
|
|
}
|
|
}
|
|
|
|
public class BB_TaskRecharge extends BB_Task
|
|
{
|
|
private object energyCell;
|
|
|
|
void BB_TaskRecharge(object energyCell)
|
|
{
|
|
this.energyCell = energyCell;
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Recharge";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
BB_Shared shared();
|
|
object station = BB_findFriendly(PowerStation);
|
|
if (station == null) return new BB_TaskFailed();
|
|
// todo: better way to check if powerstation is occupied
|
|
int[] bots = {WheeledGrabber,WheeledBuilder,WingedShooter};
|
|
if (BB_findAt(bots, station.position, 1.0) != null)
|
|
{
|
|
BB_trygoto(space(station.position));
|
|
wait(5);
|
|
return new BB_TaskFailed();
|
|
}
|
|
BB_trygoto(station.position);
|
|
if (!BB_isAlive(station))
|
|
{
|
|
return new BB_TaskFailed();
|
|
}
|
|
while (BB_isAlive(station) && energyCell.energyLevel < 1) wait(0.1);
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
public class BB_TaskRepair extends BB_Task
|
|
{
|
|
private object bot;
|
|
|
|
void BB_TaskRepair(object bot)
|
|
{
|
|
this.bot = bot;
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Repair";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
BB_Shared shared();
|
|
object center = BB_findFriendly(RepairCenter);
|
|
if (center == null) return new BB_TaskFailed();
|
|
// todo: better way to check if center is occupied
|
|
int[] bots = {WheeledGrabber,WheeledBuilder,WingedShooter};
|
|
if (BB_findAt(bots, center.position, 1.0) != null)
|
|
{
|
|
BB_trygoto(space(center.position));
|
|
wait(5);
|
|
return new BB_TaskFailed();
|
|
}
|
|
BB_trygoto(center.position);
|
|
if (!BB_isAlive(center))
|
|
{
|
|
return new BB_TaskFailed();
|
|
}
|
|
while (BB_isAlive(center) && bot.shieldLevel < 1) wait(0.1);
|
|
BB_trygoto(space());
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
public class BB_TaskBuild extends BB_Task
|
|
{
|
|
private int category;
|
|
private object titanium;
|
|
|
|
void BB_TaskBuild(object titanium, int category)
|
|
{
|
|
this.category = category;
|
|
this.titanium = titanium;
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Build";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
BB_Shared shared();
|
|
if (titanium == null) return new BB_TaskFailed();
|
|
BB_trygoto(titanium.position);
|
|
//errmode(0);
|
|
int err = build(category);
|
|
//errmode(1);
|
|
if (err > 0)
|
|
{
|
|
if (BB_isAlive(titanium))
|
|
{
|
|
// Try again, probably someone blocked free space
|
|
wait(2);
|
|
return new BB_TaskFailed(this);
|
|
}
|
|
else
|
|
{
|
|
shared.buildingsInProgress.remove(new BB_Int(category));
|
|
shared.objectsInUse.remove(new BB_GameObject(titanium));
|
|
return new BB_TaskFailed();
|
|
}
|
|
}
|
|
shared.buildingsInProgress.remove(new BB_Int(category));
|
|
shared.objectsInUse.remove(new BB_GameObject(titanium));
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
/***************/
|
|
/* Shared data */
|
|
/***************/
|
|
public class BB_Shared
|
|
{
|
|
static BB_Array buildRequests = null;
|
|
static BB_Array buildingsInProgress = null;
|
|
static BB_Array objectsInUse = null;
|
|
|
|
void BB_Shared()
|
|
{
|
|
if (buildRequests == null)
|
|
buildRequests = new BB_Array();
|
|
if (buildingsInProgress == null)
|
|
buildingsInProgress = new BB_Array();
|
|
if (objectsInUse == null)
|
|
objectsInUse = new BB_Array();
|
|
}
|
|
}
|
|
|
|
public class BB_BuildRequest extends BB_Object
|
|
{
|
|
int category;
|
|
object titanium;
|
|
void BB_BuildRequest(object titanium, int category)
|
|
{
|
|
this.titanium = titanium;
|
|
this.category = category;
|
|
}
|
|
}
|
|
|
|
/*****************/
|
|
/* Grabber tasks */
|
|
/*****************/
|
|
public class BB_TaskGrabberRecharge extends BB_Task
|
|
{
|
|
private object energyCell;
|
|
private object loadCell;
|
|
|
|
void BB_TaskGrabberRecharge(object energyCell, object loadCell = null)
|
|
{
|
|
this.energyCell = energyCell;
|
|
this.loadCell = loadCell;
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Grabber Recharge";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
BB_Shared shared();
|
|
object station = BB_findFriendly(PowerStation);
|
|
if (station == null) return new BB_TaskFailed(new BB_TaskEnqueueBuilding(PowerStation));
|
|
// todo: find a better way to check if occupied
|
|
int[] bots = {WheeledGrabber,WheeledBuilder,WingedShooter};
|
|
if (BB_findAt(bots, station.position, 1.0) != null)
|
|
{
|
|
BB_trygoto(space(station.position));
|
|
wait(5);
|
|
return new BB_TaskFailed(); //todo: wait task
|
|
}
|
|
BB_trygoto(station.position);
|
|
if (!BB_isAlive(station))
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(PowerStation));
|
|
}
|
|
if (loadCell != null) while (BB_isAlive(station) && loadCell.energyLevel < 1) wait(0.1);
|
|
while (BB_isAlive(station) && energyCell.energyLevel < 1) wait(0.1);
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
public class BB_TaskEnqueueBuilding extends BB_Task
|
|
{
|
|
private int category;
|
|
|
|
void BB_TaskEnqueueBuilding(int category)
|
|
{
|
|
this.category = category;
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Enqueue Building";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
//todo: check if sufficient research
|
|
|
|
BB_Shared shared();
|
|
BB_Int goCategory = new BB_Int(category);
|
|
if (BB_findFriendly(category) == null && shared.buildingsInProgress.find(goCategory) != null)
|
|
{
|
|
do
|
|
{
|
|
wait(1); //todo: make it a task
|
|
} while (shared.buildingsInProgress.find(goCategory) != null);
|
|
return new BB_TaskCompleted();
|
|
}
|
|
|
|
object titanium = null;
|
|
if (!areWeHolding(Titanium))
|
|
{
|
|
titanium = BB_findInBase(Titanium);
|
|
if (titanium == null)
|
|
return new BB_TaskFailed(new BB_TaskGetTitanium());
|
|
}
|
|
else
|
|
{
|
|
titanium = getLoad();
|
|
BB_trygoto(findFlatSpace());
|
|
trydrop();
|
|
}
|
|
|
|
BB_GameObject goTitanium(titanium);
|
|
shared.objectsInUse.push_back(goTitanium);
|
|
shared.buildingsInProgress.push_back(goCategory);
|
|
shared.buildRequests.push_back(new BB_BuildRequest(titanium, category));
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
public class BB_TaskGetTitanium extends BB_Task
|
|
{
|
|
void BB_TaskGetTitanium()
|
|
{
|
|
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Get Titanium";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
BB_Shared shared();
|
|
object titanium = getLoad();
|
|
if (areWeHolding(Titanium)) return new BB_TaskCompleted();
|
|
titanium = BB_findInBase(Titanium);
|
|
if (titanium == null) return new BB_TaskFailed(new BB_TaskProduceTitanium());
|
|
BB_GameObject goTitanium(titanium);
|
|
shared.objectsInUse.push_back(goTitanium);
|
|
BB_trygoto(titanium.position);
|
|
if (!BB_isAlive(titanium))
|
|
{
|
|
shared.objectsInUse.remove(goTitanium);
|
|
return new BB_TaskFailed(this);
|
|
}
|
|
trygrab();
|
|
shared.objectsInUse.remove(goTitanium);
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
public class BB_TaskProduceTitanium extends BB_Task
|
|
{
|
|
void BB_TaskProduceTitanium()
|
|
{
|
|
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Produce Titanium";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
BB_Shared shared();
|
|
BB_Int goConverter(Converter);
|
|
object converter = BB_findFriendly(Converter);
|
|
if (converter == null && shared.buildingsInProgress.find(goConverter) == null)
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(Converter));
|
|
}
|
|
|
|
if (!areWeHolding(TitaniumOre))
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskGetTitaniumOre());
|
|
}
|
|
|
|
if (converter == null)
|
|
{
|
|
trydrop();
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(Converter));
|
|
}
|
|
|
|
BB_trygoto(converter.position);
|
|
if (!BB_isAlive(converter))
|
|
{
|
|
trydrop();
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(Converter));
|
|
}
|
|
trydrop();
|
|
BB_trymove(-3);
|
|
object titanium = null;
|
|
while (BB_isAlive(converter) && titanium == null)
|
|
titanium = BB_findAt(Titanium, converter.position); //todo: probably a wait task here?
|
|
if (titanium == null || !BB_isAlive(converter))
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(Converter));
|
|
BB_trymove(2.5);
|
|
trygrab();
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
public class BB_TaskGetTitaniumOre extends BB_Task
|
|
{
|
|
void BB_TaskGetTitaniumOre()
|
|
{
|
|
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Get Titanium Ore";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
if (areWeHolding(TitaniumOre)) return new BB_TaskCompleted();
|
|
object ore = BB_findInBase(TitaniumOre);
|
|
if (ore == null)
|
|
{
|
|
object derrick = BB_findInBase(Derrick);
|
|
BB_trygoto(derrick.position);
|
|
while (ore == null)
|
|
ore = BB_findAt(TitaniumOre, derrick.position);
|
|
}
|
|
else
|
|
{
|
|
BB_trygoto(ore.position);
|
|
}
|
|
trygrab();
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
public class BB_TaskResearch extends BB_Task
|
|
{
|
|
int subject;
|
|
|
|
void BB_TaskResearch(int subject)
|
|
{
|
|
this.subject = subject;
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Research";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
if (researched(subject)) return new BB_TaskCompleted();
|
|
|
|
BB_Shared shared();
|
|
BB_Int goResearchCenter(ResearchCenter);
|
|
object researchCenter = BB_findFriendly(ResearchCenter);
|
|
if (researchCenter == null && shared.buildingsInProgress.find(goResearchCenter) == null)
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(ResearchCenter));
|
|
}
|
|
|
|
if (!areWeHolding(PowerCell))
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskGetPowerCell());
|
|
}
|
|
|
|
if (getLoad().energyLevel < 1)
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskGrabberRecharge(getPowerCell(), getLoad()));
|
|
}
|
|
|
|
researchCenter = BB_findFriendly(ResearchCenter);
|
|
if (researchCenter == null)
|
|
{
|
|
trydrop();
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(ResearchCenter));
|
|
}
|
|
|
|
BB_trygoto(researchCenter.position);
|
|
|
|
while (isbusy(researchCenter)) wait(0.1); // todo: wait task?
|
|
|
|
if (!BB_isAlive(researchCenter))
|
|
{
|
|
trydrop();
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(ResearchCenter));
|
|
}
|
|
|
|
if (researchCenter.energyCell != null)
|
|
{
|
|
drop(Behind);
|
|
trygrab();
|
|
turn(90);
|
|
trydrop();
|
|
turn(-90);
|
|
grab(Behind);
|
|
}
|
|
trydrop();
|
|
|
|
if (!BB_isAlive(researchCenter))
|
|
{
|
|
trydrop();
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(ResearchCenter));
|
|
}
|
|
research(subject, researchCenter);
|
|
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
public class BB_TaskGetPowerCell extends BB_Task
|
|
{
|
|
void BB_TaskGetPowerCell()
|
|
{
|
|
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Power Cell";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
BB_Shared shared();
|
|
if (areWeHolding(PowerCell)) return new BB_TaskCompleted();
|
|
object powerCell = BB_findInBase(PowerCell);
|
|
if (powerCell == null) return new BB_TaskFailed(new BB_TaskProducePowerCell());
|
|
BB_Int goPowerCell(PowerCell);
|
|
shared.objectsInUse.push_back(goPowerCell);
|
|
BB_trygoto(powerCell.position);
|
|
if (!BB_isAlive(powerCell))
|
|
{
|
|
shared.objectsInUse.remove(goPowerCell);
|
|
return new BB_TaskFailed(this);
|
|
}
|
|
trygrab();
|
|
shared.objectsInUse.remove(goPowerCell);
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
public class BB_TaskProducePowerCell extends BB_Task
|
|
{
|
|
void BB_TaskProducePowerCell()
|
|
{
|
|
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Produce PowerCell";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
BB_Shared shared();
|
|
BB_Int goPowerPlant(PowerPlant);
|
|
object powerPlant = BB_findFriendly(PowerPlant);
|
|
if (powerPlant == null && shared.buildingsInProgress.find(goPowerPlant) == null)
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(PowerPlant));
|
|
}
|
|
|
|
if (!areWeHolding(Titanium))
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskGetTitanium());
|
|
}
|
|
|
|
powerPlant = BB_findFriendly(PowerPlant);
|
|
if (powerPlant == null)
|
|
{
|
|
trydrop();
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(PowerPlant));
|
|
}
|
|
|
|
BB_trygoto(powerPlant.position);
|
|
if (!BB_isAlive(powerPlant))
|
|
{
|
|
trydrop();
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(PowerPlant));
|
|
}
|
|
trydrop();
|
|
while (BB_isAlive(powerPlant) &&
|
|
powerPlant.energyCell == null || powerPlant.energyCell.category != PowerCell)
|
|
{
|
|
wait(0.1); //todo: probably a wait task here?
|
|
}
|
|
if (!BB_isAlive(powerPlant))
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(PowerPlant));
|
|
}
|
|
trygrab();
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
public class BB_TaskFactoryBot extends BB_Task
|
|
{
|
|
int category;
|
|
string program;
|
|
|
|
void BB_TaskFactoryBot(int category, string program)
|
|
{
|
|
this.category = category;
|
|
this.program = program;
|
|
}
|
|
|
|
string getName()
|
|
{
|
|
return "Task Bot Factory";
|
|
}
|
|
|
|
BB_Task update()
|
|
{
|
|
// todo: check if sufficient research done
|
|
|
|
// We need a factory
|
|
BB_Shared shared();
|
|
BB_Int goBotFactory(BotFactory);
|
|
object botFactory = BB_findFriendly(BotFactory);
|
|
|
|
if(botFactory == null)
|
|
{
|
|
goto(space());
|
|
while(shared.buildingsInProgress.find(goBotFactory) != null)
|
|
{
|
|
wait(5);
|
|
botFactory = BB_findFriendly(BotFactory);
|
|
}
|
|
if (shared.buildingsInProgress.find(goBotFactory) == null)
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(BotFactory));
|
|
}
|
|
}
|
|
|
|
|
|
// Check if there's a robot in the factory
|
|
object robot = BB_findAt(category, botFactory.position);
|
|
if (robot == null)
|
|
{
|
|
if (botFactory == null || !isbusy(botFactory))
|
|
{
|
|
// We need to build it first
|
|
if (!areWeHolding(Titanium))
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskGetTitanium());
|
|
}
|
|
else
|
|
{
|
|
object botFactory = BB_findFriendly(BotFactory);
|
|
if (botFactory == null)
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(BotFactory));
|
|
}
|
|
|
|
BB_trygoto(botFactory.position);
|
|
|
|
if (!BB_isAlive(botFactory))
|
|
{
|
|
trydrop();
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(BotFactory));
|
|
}
|
|
|
|
trydrop();
|
|
BB_trymove(-2.5);
|
|
factory(category, program, botFactory);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!areWeHolding(PowerCell))
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskGetPowerCell());
|
|
}
|
|
|
|
if (getLoad().energyLevel < 1)
|
|
{
|
|
return new BB_TaskFailed(new BB_TaskGrabberRecharge(getPowerCell(), getLoad()));
|
|
}
|
|
|
|
botFactory = BB_findFriendly(BotFactory);
|
|
if (botFactory == null)
|
|
{
|
|
trydrop();
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(BotFactory));
|
|
}
|
|
|
|
BB_trygoto(botFactory.position);
|
|
|
|
if (!BB_isAlive(botFactory))
|
|
{
|
|
trydrop();
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(BotFactory));
|
|
}
|
|
|
|
while (isbusy(botFactory)) wait(0.1); // todo: wait task?
|
|
|
|
if (!BB_isAlive(botFactory))
|
|
{
|
|
trydrop();
|
|
return new BB_TaskFailed(new BB_TaskEnqueueBuilding(BotFactory));
|
|
}
|
|
|
|
trydrop();
|
|
//BB_trymove(-10);
|
|
|
|
return new BB_TaskCompleted();
|
|
}
|
|
}
|
|
|
|
/********************/
|
|
/* Helper functions */
|
|
/********************/
|
|
void BB_trygoto(point pos)
|
|
{
|
|
//errmode(0);
|
|
int i=0;
|
|
while (goto(pos) != 0)
|
|
{
|
|
if(i>7)
|
|
{
|
|
goto(space());
|
|
goto(pos,0,1);
|
|
return;
|
|
}
|
|
else wait(2);
|
|
i++;
|
|
}
|
|
//errmode(1);
|
|
}
|
|
|
|
object BB_find(int cat, int filter = FilterNone)
|
|
{
|
|
return radar(cat, 0, 360, 0, 1000, 1, filter);
|
|
}
|
|
|
|
object[] BB_findAll(int cat, int filter = FilterNone)
|
|
{
|
|
return radarall(cat, 0, 360, 0, 1000, 1, filter);
|
|
}
|
|
|
|
object BB_findFriendly(int cat)
|
|
{
|
|
return BB_find(cat, FilterFriendly);
|
|
}
|
|
|
|
object[] BB_findAllFriendly(int cat)
|
|
{
|
|
return BB_findAll(cat, FilterFriendly);
|
|
}
|
|
|
|
object BB_findEnemy(int cat)
|
|
{
|
|
return BB_find(cat, FilterEnemy);
|
|
}
|
|
|
|
bool object::BB_isInBase(point pos)
|
|
{
|
|
switch (this.team)
|
|
{
|
|
case 1: // Blue team
|
|
return pos.y < -30;
|
|
case 2: // Red team
|
|
return pos.y > 30;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
object BB_findInBase(int cat)
|
|
{
|
|
BB_Shared shared();
|
|
object[] items = radarall(cat);
|
|
for (int i = 0; i < sizeof(items); ++i)
|
|
{
|
|
object item = items[i];
|
|
if (BB_isInBase(item.position) &&
|
|
shared.objectsInUse.find(new BB_GameObject(item)) == null)
|
|
{
|
|
return item;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
object BB_findAt(int cat, point pos, float radius = 3.0)
|
|
{
|
|
return search(cat, pos, 0, radius);
|
|
}
|
|
|
|
object BB_findAt(int[] cat, point pos, float radius = 3.0)
|
|
{
|
|
return search(cat, pos, 0, radius);
|
|
}
|
|
|
|
|
|
bool BB_isAlive(int cat, point pos)
|
|
{
|
|
return BB_findAt(cat, pos) != null;
|
|
}
|
|
|
|
bool BB_isAlive(object obj)
|
|
{
|
|
if (obj == null) return false;
|
|
return BB_isAlive(obj.category, obj.position);
|
|
}
|
|
|
|
bool BB_isAlive(int cat)
|
|
{
|
|
return BB_findFriendly(cat) != null;
|
|
}
|
|
|
|
public void object::BB_BuilderProgram()
|
|
{
|
|
errmode(0);
|
|
BB_Shared shared();
|
|
BB_Array tasks();
|
|
|
|
float WAIT_TIME = 0.5;
|
|
|
|
while (this.energyCell == null);
|
|
|
|
if (sizeof(BB_findAllFriendly(WheeledBuilder)) >= 1)
|
|
{
|
|
// We're backup
|
|
while (radar(WheeledGrabber, 180, 60, 0, 5) != null);
|
|
move(-4.5);
|
|
BB_trygoto(space());
|
|
while (sizeof(BB_findAllFriendly(WheeledBuilder)) >= 1)
|
|
{
|
|
wait(5);
|
|
}
|
|
}
|
|
|
|
while (true)
|
|
{
|
|
if (tasks.getSize() > 0)
|
|
{
|
|
BB_Task task = tasks.back();
|
|
BB_Task nextTask = task.update();
|
|
if (nextTask.didComplete())
|
|
{
|
|
tasks.pop_back();
|
|
BB_trygoto(space());
|
|
}
|
|
if (nextTask.didFail())
|
|
{
|
|
BB_TaskFailed taskFailed = nextTask;
|
|
nextTask = taskFailed.getRecovery();
|
|
if (nextTask != null) tasks.push_back(nextTask);
|
|
else
|
|
{
|
|
//message("Failed: " + task.getName(), DisplayError);
|
|
tasks.pop_back();
|
|
}
|
|
}
|
|
}
|
|
else if (shared.buildRequests.getSize() > 0)
|
|
{
|
|
BB_BuildRequest request = shared.buildRequests.pop_front();
|
|
tasks.push_back(new BB_TaskBuild(request.titanium, request.category));
|
|
}
|
|
else
|
|
{
|
|
BB_TaskRepair taskRepair = repair();
|
|
if (taskRepair != null) tasks.push_back(taskRepair);
|
|
BB_TaskRecharge taskRecharge = recharge();
|
|
if (taskRecharge != null) tasks.push_back(taskRecharge);
|
|
}
|
|
|
|
|
|
wait(WAIT_TIME);
|
|
}
|
|
}
|
|
|
|
public void object::BB_attack()
|
|
{
|
|
errmode(0);
|
|
// Wait for our battery and driving space
|
|
while (this.energyCell == null);
|
|
while (radar(WheeledGrabber, 180, 60, 0, 5) != null);
|
|
move(-4.5);
|
|
jet(1);
|
|
wait(1);
|
|
|
|
// Attack!
|
|
float ENERGY_LEVEL_TRESHOLD = 0.3;
|
|
float SHIELD_TRESHOLD = 0.5;
|
|
float TEMPERATURE_TRESHOLD = 0.8;
|
|
BB_TaskRecharge taskRecharge = null;
|
|
BB_TaskRepair taskRepair = null;
|
|
while (true)
|
|
{
|
|
if (this.energyCell.energyLevel < ENERGY_LEVEL_TRESHOLD)
|
|
{
|
|
BB_trygoto(space());
|
|
|
|
// todo: temp solution
|
|
taskRecharge = new BB_TaskRecharge(this.energyCell);
|
|
BB_Task nextTask = taskRecharge.update();
|
|
if (nextTask.didComplete()) continue;
|
|
}
|
|
|
|
if (this.shieldLevel <= SHIELD_TRESHOLD)
|
|
{
|
|
// todo: temp solution
|
|
taskRepair = new BB_TaskRepair(this);
|
|
BB_Task nextTask = taskRepair.update();
|
|
if (nextTask.didComplete()) continue;
|
|
}
|
|
|
|
if (this.temperature > TEMPERATURE_TRESHOLD)
|
|
{
|
|
BB_trygoto(space());
|
|
while (temperature > 0);
|
|
}
|
|
|
|
bool isInFront = true;
|
|
object enemy = radar(Any, 0, 120, 0, 1000, 1, FilterEnemy);
|
|
if (enemy == null)
|
|
{
|
|
isInFront = false;
|
|
enemy = radar(Any, 0, 360, 0, 1000, 1, FilterEnemy);
|
|
if (enemy == null)
|
|
{
|
|
wait(0.05);
|
|
continue;
|
|
}
|
|
}
|
|
if (enemy.category == Derrick) enemy = search(Any, enemy.position, 2, 1000, 1, FilterEnemy);
|
|
|
|
float targetHeight = topo(this.position);
|
|
if (targetHeight < 0) targetHeight = 0;
|
|
targetHeight += 10;
|
|
|
|
float targetSpeed = distance(this.position, enemy.position) / 20;
|
|
if (targetSpeed > 1) targetSpeed = 1;
|
|
if (!isInFront) targetSpeed = 1;
|
|
|
|
float targetDirection = direction(enemy.position);
|
|
|
|
bool canShoot = isInFront;
|
|
if(abs(targetDirection) > 60) canShoot = false;
|
|
if(distance(this.position, enemy.position) > 40) canShoot = false;
|
|
|
|
/*
|
|
Here we calculate the aim angle
|
|
Take a look at this picture:
|
|
(yes, I'm terrible at ASCII-art :P)
|
|
|
|
\/ target
|
|
***
|
|
* ***
|
|
H* ***
|
|
* angle** \/ robot
|
|
*************
|
|
L
|
|
*/
|
|
|
|
|
|
if(!canShoot) targetSpeed = 1;
|
|
|
|
jet(round(targetHeight - this.position.z) / 20);
|
|
if(targetDirection < 0)
|
|
{
|
|
motor(targetSpeed, targetSpeed + targetDirection / 90);
|
|
}
|
|
else
|
|
{
|
|
motor(targetSpeed - targetDirection / 90, targetSpeed);
|
|
}
|
|
|
|
float H = enemy.position.z - this.position.z;
|
|
float L = distance2d(this.position, enemy.position);
|
|
float angle = atan(H / L);
|
|
aim(angle, -targetDirection);
|
|
if(canShoot)
|
|
{
|
|
fire(0.5);
|
|
wait(0.1);
|
|
}
|
|
|
|
wait(0.1);
|
|
}
|
|
}
|
|
|
|
BB_TaskRecharge object::recharge(bool force = false, float treshold = 0.25)
|
|
{
|
|
if (force || energyCell.energyLevel < treshold)
|
|
return new BB_TaskRecharge(this.energyCell);
|
|
return null;
|
|
}
|
|
|
|
BB_TaskGrabberRecharge object::rechargeGrabber(bool force = false, float treshold = 0.25)
|
|
{
|
|
if (force || energyCell.energyLevel < treshold)
|
|
return new BB_TaskGrabberRecharge(this.energyCell);
|
|
return null;
|
|
}
|
|
|
|
BB_TaskRepair object::repair(bool force = false, float treshold = 0.5)
|
|
{
|
|
if (force || shieldLevel < treshold)
|
|
return new BB_TaskRepair(this);
|
|
return null;
|
|
}
|
|
|
|
bool object::areWeHolding(int cat)
|
|
{
|
|
return (this.load != null && this.load.category == cat);
|
|
}
|
|
|
|
object object::getLoad()
|
|
{
|
|
return this.load;
|
|
}
|
|
|
|
point object::findFlatSpace()
|
|
{
|
|
return flatspace(this.position, 10, 10, 40, 8);
|
|
}
|
|
|
|
object object::getPowerCell()
|
|
{
|
|
return this.energyCell;
|
|
}
|
|
|
|
void object::trygrab()
|
|
{
|
|
if (this.load != null)
|
|
{
|
|
point pos = this.position;
|
|
goto(space());
|
|
trydrop();
|
|
goto(pos);
|
|
turn(direction(radar(Any).position));
|
|
}
|
|
//errmode(0);
|
|
grab();
|
|
//errmode(1);
|
|
}
|
|
|
|
void object::trydrop()
|
|
{
|
|
//errmode(0);
|
|
drop();
|
|
while (this.load != null)
|
|
{
|
|
if(this.load.category != TitaniumOre || radar(Any).category != Converter)
|
|
{
|
|
drop();
|
|
goto(space());
|
|
}
|
|
else
|
|
{
|
|
drop();
|
|
move(-0.5);
|
|
}
|
|
}
|
|
//errmode(1);
|
|
}
|
|
|
|
void object::BB_trymove(float d)
|
|
{
|
|
//errmode(0);
|
|
point init_pos = position;
|
|
int err = move(d);
|
|
int EPS = 0;
|
|
while (err > 0 && distance(init_pos, position) < abs(d))
|
|
{
|
|
if (d > 0)
|
|
{
|
|
err = move(abs(d) - distance(init_pos, position) + EPS);
|
|
}
|
|
else
|
|
{
|
|
err = move(-(abs(d) - distance(init_pos, position) + EPS));
|
|
}
|
|
}
|
|
//errmode(1);
|
|
}
|
|
|
|
public void object::BB_GrabberProgram()
|
|
{
|
|
errmode(0);
|
|
BB_Shared shared();
|
|
BB_Array tasks(); // we're treating it as a stack
|
|
|
|
float WAIT_TIME = 0.5;
|
|
|
|
while (this.energyCell == null);
|
|
|
|
if (sizeof(BB_findAllFriendly(WheeledGrabber)) >= 1)
|
|
{
|
|
// Pick up that can
|
|
while (radar(WheeledGrabber, 180, 60, 0, 5) != null);
|
|
move(-4.5);
|
|
BB_trygoto(space());
|
|
while(true)
|
|
{
|
|
// todo or not todo
|
|
wait(10);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Set up the base first
|
|
tasks.push_back(new BB_TaskEnqueueBuilding(RepairCenter));
|
|
tasks.push_back(new BB_TaskFactoryBot(WingedShooter, "BB_attack"));
|
|
tasks.push_back(new BB_TaskResearch(ResearchShooter));
|
|
tasks.push_back(new BB_TaskResearch(ResearchWinged));
|
|
tasks.push_back(new BB_TaskEnqueueBuilding(ResearchCenter));
|
|
tasks.push_back(new BB_TaskEnqueueBuilding(BotFactory));
|
|
tasks.push_back(new BB_TaskEnqueueBuilding(PowerPlant));
|
|
tasks.push_back(new BB_TaskEnqueueBuilding(PowerStation));
|
|
tasks.push_back(new BB_TaskEnqueueBuilding(Converter));
|
|
}
|
|
|
|
while (true)
|
|
{
|
|
if (tasks.getSize() > 0)
|
|
{
|
|
BB_Task task = tasks.back();
|
|
BB_Task nextTask = task.update();
|
|
if (nextTask.didComplete()) tasks.pop_back();
|
|
if (nextTask.didFail())
|
|
{
|
|
BB_TaskFailed taskFailed = nextTask;
|
|
nextTask = taskFailed.getRecovery();
|
|
if (nextTask != null) tasks.push_back(nextTask);
|
|
else
|
|
{
|
|
//message("Failed: " + task.getName(), DisplayError);
|
|
tasks.pop_back();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Build some backups
|
|
if (sizeof(BB_findAllFriendly(Converter)) == 1
|
|
&& shared.buildingsInProgress.find(new BB_Int(Converter)) == null)
|
|
{
|
|
tasks.push_back(new BB_TaskEnqueueBuilding(Converter));
|
|
}
|
|
else if (sizeof(BB_findAllFriendly(WheeledBuilder)) == 1)
|
|
{
|
|
tasks.push_back(new BB_TaskFactoryBot(WheeledBuilder, "BB_BuilderProgram"));
|
|
}
|
|
else if (sizeof(BB_findAllFriendly(PowerStation)) == 0)
|
|
{
|
|
tasks.push_back(new BB_TaskEnqueueBuilding(PowerStation));
|
|
}
|
|
else if (sizeof(BB_findAllFriendly(RepairCenter)) == 0)
|
|
{
|
|
tasks.push_back(new BB_TaskEnqueueBuilding(RepairCenter));
|
|
}
|
|
else
|
|
{
|
|
// Pump shooters otherwise
|
|
BB_TaskRepair taskRepair = repair();
|
|
if (taskRepair != null) tasks.push_back(taskRepair);
|
|
tasks.push_back(new BB_TaskFactoryBot(WingedShooter, "BB_attack"));
|
|
}
|
|
}
|
|
|
|
BB_TaskGrabberRecharge task = rechargeGrabber();
|
|
if (task != null) tasks.push_back(task);
|
|
|
|
wait(WAIT_TIME);
|
|
}
|
|
}
|
|
|
|
extern void object::BB_Grabber()
|
|
{
|
|
BB_GrabberProgram();
|
|
}
|