diff --git a/levels/battles/chapter001/level001/scene.txt b/levels/battles/chapter001/level001/scene.txt index 634bdbc3..f732c7d5 100644 --- a/levels/battles/chapter001/level001/scene.txt +++ b/levels/battles/chapter001/level001/scene.txt @@ -5,18 +5,19 @@ Resume.E text="Build your base and eliminate your foe!" Level type=CODE_BATTLE magnifyDamage=10 BeginObject +LevelController script="%cat%/deruiner.txt" // Team "Blue" (1) -CreateObject pos= 5;-35 dir=1.5 type=WheeledGrabber team=1 -CreateObject pos=0;-35 type=Titanium -CreateObject pos=-5;-35 dir=1.5 type=WheeledBuilder team=1 select=true -CreateObject pos=0;-58 dir=1.5 type=Derrick magnifyDamage=0 selectable=false +CreateObject pos=-5;-65 dir=1.5 type=WheeledGrabber team=1 select=1 +CreateObject pos=0;-65 type=Titanium +CreateObject pos=5;-65 dir=1.5 type=WheeledBuilder team=1 +CreateObject pos=0;-88 dir=1.5 type=Derrick team=1 magnifyDamage=0 // Team "Red" (2) -CreateObject pos=-5;35 dir=0.5 type=WheeledGrabber team=2 -CreateObject pos=0;35 type=Titanium -CreateObject pos=5;35 dir=0.5 type=WheeledBuilder team=2 -CreateObject pos=0;58 dir=0.5 type=Derrick magnifyDamage=0 selectable=false +CreateObject pos=5;65 dir=0.5 type=WheeledGrabber team=2 +CreateObject pos=0;65 type=Titanium +CreateObject pos=-5;65 dir=0.5 type=WheeledBuilder team=2 +CreateObject pos=0;88 dir=0.5 type=Derrick team=2 magnifyDamage=0 -EndMissionTake pos=0;0 dist=10000 type=Any team=-1 min=0 max=0 winTeam=1 -EndMissionTake pos=0;0 dist=10000 type=Any team=-2 min=0 max=0 winTeam=2 +EndMissionTake pos=0;0 dist=10000 type=Any team=-1 min=0 max=1 winTeam=1 +EndMissionTake pos=0;0 dist=10000 type=Any team=-2 min=0 max=1 winTeam=2 diff --git a/levels/battles/chapter002/level001/scene.txt b/levels/battles/chapter002/level001/scene.txt index 8c39405b..f7552ced 100644 --- a/levels/battles/chapter002/level001/scene.txt +++ b/levels/battles/chapter002/level001/scene.txt @@ -5,16 +5,16 @@ Resume.E text="A map for begginers! Research technologies, build your infrastruc Level type=CODE_BATTLE BeginObject +LevelController script="%cat%/deruiner.txt" // Team "Blue" (1) -CreateObject pos=5;-35 dir=1.5 type=WheeledGrabber team=1 -CreateObject pos=0;-35 type=Titanium -CreateObject pos=-5;-35 dir=1.5 type=WheeledBuilder team=1 select=true -CreateObject pos=0;-58 dir=1.5 type=Derrick magnifyDamage=0 selectable=false -CreateObject pos=0;-65 dir=1.5 type=RadarStation magnifyDamage=0 selectable=false +CreateObject pos=-5;-65 dir=1.5 type=WheeledGrabber team=1 select=1 +CreateObject pos=0;-65 type=Titanium +CreateObject pos=5;-65 dir=1.5 type=WheeledBuilder team=1 +CreateObject pos=0;-88 dir=1.5 type=Derrick team=1 magnifyDamage=0 +CreateObject pos=-46;-103 dir=1.5 type=RadarStation team=1 magnifyDamage=0 // Team "Red" (2) -// TODO: Write (or find) some better ant scripts for this purpose CreateObject pos=0;35 type=AlienNest CreateObject pos=-43;43 dir=0.3 type=AlienAnt script1="ant03.txt" run=1 CreateObject pos=33;31 dir=1.1 type=AlienAnt script1="antatt30.txt" run=1 @@ -26,5 +26,5 @@ CreateObject pos=18;70 dir=0.7 type=AlienEgg autoValue1=14.4 autoType=AlienAnt a CreateObject pos=-23;82 dir=0.1 type=AlienAnt script1="antattaw.txt" run=1 CreateObject pos=-21;101 dir=0.5 type=AlienEgg autoValue1=38.5 autoType=AlienAnt autoString="ant03.txt" run=1 +EndMissionTake pos=0;0 dist=10000 type=Any team=1 lost=2 EndMissionTake pos=0;0 dist=10000 type=AlienAnt min=0 max=0 -EndMissionTake pos=0;0 dist=10000 type=Any team=1 lost=0 diff --git a/levels/battles/chapter002/level002/program-a.txt b/levels/battles/chapter002/level002/program-a.txt new file mode 100644 index 00000000..64cb51d8 --- /dev/null +++ b/levels/battles/chapter002/level002/program-a.txt @@ -0,0 +1,1297 @@ +/*******************/ +/* 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(); +} diff --git a/levels/battles/chapter002/level002/program-b.txt b/levels/battles/chapter002/level002/program-b.txt new file mode 100644 index 00000000..e3f7f954 --- /dev/null +++ b/levels/battles/chapter002/level002/program-b.txt @@ -0,0 +1,4 @@ +extern void object::BB_Builder() +{ + BB_BuilderProgram(); +} diff --git a/levels/battles/chapter002/level002/program.txt b/levels/battles/chapter002/level002/program.txt deleted file mode 100644 index 6f5c4135..00000000 --- a/levels/battles/chapter002/level002/program.txt +++ /dev/null @@ -1,215 +0,0 @@ -object RadarFriendly(int cat) -{ - return radar(cat, 0, 360, 0, 1000, 1, FilterFriendly); -} - -object SearchObjectAt(int cat, point pos) -{ - object item = search(Titanium, pos); - if(item == null) return null; - if(distance(pos, item.position) > 0.5) return null; - return item; -} - -public void object::StandardEnemy_Recharge() -{ - object item = RadarFriendly(PowerStation); - goto(item.position); - if(this.load != null && this.load.category == PowerCell) - { - while(this.load.energyLevel < 1) wait(0.05); - } - while(this.energyLevel < 1) wait(0.05); -} - -void object::GetTitanium() -{ - object item; - do - { - item = radar(TitaniumOre, 0, 360, 0, 40); - } - while(item == null); - goto(item.position); - grab(); - item = RadarFriendly(Converter); - goto(item.position); - drop(); - move(-2.5); - point converterPos = item.position; - while((item = SearchObjectAt(Titanium, converterPos)) == null) wait(0.05); - goto(item.position); - grab(); -} - -void object::GetPowerCell() -{ - object item = radar(PowerCell, 0, 360, 0, 40); - if (item != null) - { - goto(item.position); - grab(); - if(item.energyLevel < 1) - { - StandardEnemy_Recharge(); - } - } - else - { - GetTitanium(); - item = RadarFriendly(PowerPlant); - goto(item.position); - drop(); - while(item.energyCell == null || item.energyCell.category != PowerCell) wait(0.05); - grab(); - } -} - -void object::BuildSomewhere(int cat) -{ - GetTitanium(); - goto(flatspace(this.position, 10, 10, 40, 8)); - drop(); - build(cat); -} - -void object::GoResearch(int what) -{ - GetPowerCell(); - object item = RadarFriendly(ResearchCenter); - goto(item.position); - while(item.busy()) wait(0.05); - if (item.energyCell != null) - { - drop(Behind); - grab(); - turn(90); - drop(); - turn(-90); - grab(Behind); - } - drop(); - item.research(what); -} - -void object::FactoryRobot(int cat, string program) -{ - GetTitanium(); - object item = RadarFriendly(BotFactory); - goto(item.position); - drop(); - move(-5); - item.factory(cat, program); - point pos = this.position; - GetPowerCell(); - goto(pos); - turn(direction(item.position)); - while(radar(cat, 0, 45, 0, 10) == null) wait(0.05); - goto(item.position); - drop(); - move(-5); -} - -extern void object::StandardEnemy() -{ - // TODO: Enable after done debugging - //errmode(0); - - build(Converter); - BuildSomewhere(PowerStation); - BuildSomewhere(BotFactory); - BuildSomewhere(PowerPlant); - BuildSomewhere(ResearchCenter); - GoResearch(ResearchWinged); - GoResearch(ResearchShooter); - while(true) - { - if (this.energyCell.energyLevel < 0.25) - { - StandardEnemy_Recharge(); - } - FactoryRobot(WingedShooter, "StandardEnemy_Attack"); - } -} - -public void object::StandardEnemy_Attack() -{ - while(this.energyCell == null) wait(0.05); - while(radar(Any, 180, 45, 0, 5) != null) wait(0.05); - move(-7.5); - - while(true) - { - if(this.energyCell.energyLevel < 0.3 || this.temperature > 0.5) - { - StandardEnemy_Recharge(); - while(this.temperature > 0) wait(0.05); - } - - bool isInFront = true; - object item = radar(Any, 0, 120, 0, 1000, 1, FilterEnemy); - if (item == null) - { - isInFront = false; - item = radar(Any, 0, 360, 0, 1000, 1, FilterEnemy); - if (item == null) - { - wait(0.05); - continue; - } - } - - float targetHeight = topo(this.position); - if(targetHeight < 0) targetHeight = 0; - targetHeight += 9; - - float targetSpeed = distance(this.position, item.position)/40; - if(targetSpeed > 1) targetSpeed = 1; - if(!isInFront) targetSpeed = 1; - - float targetDirection = direction(item.position); - - bool canShoot = true; - if(abs(targetDirection) > 10) canShoot = false; - if(distance(this.position, item.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 - */ - float H = item.position.z-this.position.z; - float L = distance2d(this.position, item.position); - float angle = atan(H/L); - if(aim(angle, -targetDirection) != 0) canShoot = false; // funkcja aim() zwraca != 0 jesli cel poza zasiegiem - - if(!canShoot) targetSpeed = 1; - - jet((targetHeight-this.position.z)/4); - if(targetDirection < 0) - { - motor(targetSpeed, targetSpeed+targetDirection/90); - } - else - { - motor(targetSpeed-targetDirection/90, targetSpeed); - } - - if(canShoot) - { - fire(0.1); - } - else - { - wait(0.05); - } - } -} diff --git a/levels/battles/chapter002/level002/scene.txt b/levels/battles/chapter002/level002/scene.txt index 49d5a047..f1d0b27c 100644 --- a/levels/battles/chapter002/level002/scene.txt +++ b/levels/battles/chapter002/level002/scene.txt @@ -5,19 +5,19 @@ Resume.E text="Challenge the developers! Fight against a simple enemy program." Level type=CODE_BATTLE magnifyDamage=10 BeginObject +LevelController script="%cat%/deruiner.txt" // Team "Blue" (1) -CreateObject pos=5;-35 dir=1.5 type=WheeledGrabber team=1 -CreateObject pos=0;-35 type=Titanium -CreateObject pos=-5;-35 dir=1.5 type=WheeledBuilder team=1 select=true -CreateObject pos=0;-58 dir=1.5 type=Derrick magnifyDamage=0 selectable=false +CreateObject pos=-5;-65 dir=1.5 type=WheeledGrabber team=1 select=1 +CreateObject pos=0;-65 type=Titanium +CreateObject pos=5;-65 dir=1.5 type=WheeledBuilder team=1 +CreateObject pos=0;-88 dir=1.5 type=Derrick team=1 magnifyDamage=0 selectable=0 // Team "Red" (2) -// TODO: selectable=0, but only before start? -CreateObject pos=-5;35 dir=0.5 type=WheeledGrabber team=2 script1="%lvl%/program-a.txt" scriptReadOnly1=true run=1 -CreateObject pos=0;35 type=Titanium -CreateObject pos=5;35 dir=0.5 type=WheeledBuilder team=2 script1="%lvl%/program-b.txt" scriptReadOnly1=true run=1 -CreateObject pos=0;58 dir=0.5 type=Derrick magnifyDamage=0 selectable=false +CreateObject pos=5;65 dir=0.5 type=WheeledGrabber trainer=1 team=2 script1="%lvl%/program-a.txt" run=1 selectable=0 +CreateObject pos=0;65 type=Titanium +CreateObject pos=-5;65 dir=0.5 type=WheeledBuilder trainer=1 team=2 script1="%lvl%/program-b.txt" run=1 selectable=0 +CreateObject pos=0;88 dir=0.5 type=Derrick team=2 magnifyDamage=0 selectable=0 -EndMissionTake pos=0;0 dist=10000 type=Any team=1 lost=0 -EndMissionTake pos=0;0 dist=10000 type=Any team=-1 min=0 max=0 +EndMissionTake pos=0;0 dist=10000 type=Any team=1 lost=1 +EndMissionTake pos=0;0 dist=10000 type=Any team=2 min=0 max=1 diff --git a/levels/battles/chapter002/level003/scene.txt b/levels/battles/chapter002/level003/scene.txt index 9765b82d..e3b9f0ac 100644 --- a/levels/battles/chapter002/level003/scene.txt +++ b/levels/battles/chapter002/level003/scene.txt @@ -10,8 +10,7 @@ BeginObject CreateObject pos=0;-40 dir=1.5 type=WingedShooter range=0 power=100 team=1 select=true // Team "Red" (2) -// TODO: selectable=0, but only before start? -CreateObject pos=0;40 dir=0.5 type=PracticeBot team=2 script1="flash.txt" scriptReadOnly1=true run=1 +CreateObject pos=0;40 dir=0.5 type=PracticeBot team=2 script1="flash.txt" run=1 selectable=0 DoneResearch type=WINGER DoneResearch type=SHOOTER diff --git a/levels/battles/chapter002/level004/scene.txt b/levels/battles/chapter002/level004/scene.txt index e6de198e..ba38518d 100644 --- a/levels/battles/chapter002/level004/scene.txt +++ b/levels/battles/chapter002/level004/scene.txt @@ -10,8 +10,7 @@ BeginObject CreateObject pos=0;-40 dir=1.5 type=WingedShooter range=0 power=100 team=1 select=true // Team "Red" (2) -// TODO: selectable=0, but only before start? -CreateObject pos=0;40 dir=0.5 type=WingedShooter range=0 power=100 team=2 script1="%lvl%/program.txt" scriptReadOnly1=true run=1 +CreateObject pos=0;40 dir=0.5 type=WingedShooter trainer=1 range=0 power=100 team=2 script1="%lvl%/program.txt" run=1 selectable=0 DoneResearch type=WINGER DoneResearch type=SHOOTER diff --git a/levels/battles/deruiner.txt b/levels/battles/deruiner.txt new file mode 100644 index 00000000..ca188a0e --- /dev/null +++ b/levels/battles/deruiner.txt @@ -0,0 +1,12 @@ +extern void object::Deruin() +{ + while(true) + { + while(radar(606) != null) + { + delete(radar(606).id); + wait(rand()+1); + } + wait(1); + } +} \ No newline at end of file diff --git a/levels/battles/level_common.txt b/levels/battles/level_common.txt index 17e76420..ee3e493c 100644 --- a/levels/battles/level_common.txt +++ b/levels/battles/level_common.txt @@ -7,6 +7,7 @@ FogColor air=0.816;0.784;0.875;0.000 water=0.369;0.600;0.706;0.000 // magenta VehicleColor color=0.784;0.769;0.682;0.000 // sable VehicleColor team=1 color=0;0;1 VehicleColor team=2 color=1;0;0 +SecondTexture rank=1 Background up=0.937;0.875;0.878;0.000 down=0.749;0.753;0.875;0.000 cloudUp=0.306;0.306;0.498;0.000 cloudDown=0.306;0.306;0.498; ForegroundName image="lens5.png" Planet pos=3.0;0.2 dim=0.35 speed= 0.001 dir=0.4 image="planet03.png" uv1=0.5;0.5 uv2=1.0;1.0 @@ -106,5 +107,14 @@ EnableResearch type=iGUN EnableResearch type=SUBBER EnableResearch type=SNIFFER EnableResearch type=RECYCLER +EnableResearch type=BUILDER +DoneResearch type=BUILDER + +View eye= 20;25;-100 lookat=-8;8;-10 button=136 +View eye=-20;25; 100 lookat= 8;8;10 button=159 +View eye=0;175;0 lookat=0;0;0.1 button=95 +View eye=85;35;0 lookat=0;25;0 button=79 + +EndMissionDelay win=5 lost=5 Camera eye=0.00;5.00;0.00 lookat=0.00;1.00;0.00 delay=0 diff --git a/levels/battles/res.png b/levels/battles/res.png index 930c4908..c6a75ff8 100644 Binary files a/levels/battles/res.png and b/levels/battles/res.png differ