| 07-28-2009, 10:07 PM | #1 |
I have this (relatively) simple AI script. It successfully creates an assault group and just after the 5 seconds is up for FormGroup, the map crashes. It doesn't get to the next line. I notice the units don't move like they should. JASS:globals integer array attackUnitId integer array attackUnitIdCount integer attackUnitCount endglobals function Msg takes string text returns nothing call DisplayTextToPlayer(Player(0), 0, 0, text) endfunction function ModInt takes integer dividend, integer divisor returns integer local integer modulus = dividend - (dividend / divisor) * divisor // If the dividend was negative, the above modulus calculation will // be negative, but within (-divisor..0). We can add (divisor) to // shift this result into the desired range of (0..divisor). if (modulus < 0) then set modulus = modulus + divisor endif return modulus endfunction function IS takes integer i returns string local string s = "" local integer n local integer orig = i loop set n = ModInt(orig, 10) if (n == 0) then set s = "0" + s elseif (n == 1) then set s = "1" + s elseif (n == 2) then set s = "2" + s elseif (n == 3) then set s = "3" + s elseif (n == 4) then set s = "4" + s elseif (n == 5) then set s = "5" + s elseif (n == 6) then set s = "6" + s elseif (n == 7) then set s = "7" + s elseif (n == 8) then set s = "8" + s elseif (n == 9) then set s = "9" + s endif set orig = orig / 10 exitwhen orig == 0 endloop return s endfunction function GetUnitIdName takes integer uId returns string if (uId == GRUNT) then return "Grunt" elseif (uId == HEAD_HUNTER) then return "Head Hunter" elseif (uId == CATAPULT) then return "Catapult" elseif (uId == BERSERKER) then return "Berserker" elseif (uId == RAIDER) then return "Raider" elseif (uId == KODO_BEAST) then return "Kodo Beast" elseif (uId == TAUREN) then return "Tauren" elseif (uId == SHAMAN) then return "Shaman" elseif (uId == WITCH_DOCTOR) then return "Witch Doctor" elseif (uId == SPIRIT_WALKER_M) or (uId == SPIRIT_WALKER)then return "Spirit Walker" endif return "Unknown Unit Id: " + IS(uId) endfunction function AttackMoveKillB takes unit target returns nothing call Msg("before debug trace") call Sleep( 5 ) debug call Trace("AttackMoveKillB\n") if target == null then call SuicideSleep(3) return endif call Msg("In AttackMoveKillB") call Sleep( 5 ) debug call Trace("AttackMoveKillA\n") call Msg("before amk") call Sleep( 5 ) call AttackMoveKill(target) call Msg("before rutd") call Sleep( 5 ) call ReformUntilTargetDead(target) call Msg("before sic") call Sleep( 5 ) call SleepInCombat() endfunction function SetAttackUnits takes nothing returns nothing set attackUnitId[0] = GRUNT set attackUnitId[1] = HEAD_HUNTER set attackUnitId[2] = CATAPULT set attackUnitId[3] = BERSERKER set attackUnitId[4] = RAIDER set attackUnitId[5] = KODO_BEAST set attackUnitId[6] = TAUREN set attackUnitId[7] = SHAMAN set attackUnitId[8] = WITCH_DOCTOR set attackUnitId[9] = SPIRIT_WALKER_M set attackUnitCount = 10 endfunction function ResetAttackReadyUnitCount takes nothing returns nothing local integer i loop exitwhen i == attackUnitCount set attackUnitIdCount[i] = 0 set i = i + 1 endloop endfunction function ConfigureAI takes nothing returns nothing call SetCampaignAI( ) call SetDefendPlayer( true ) call SetRandomPaths( true ) call SetTargetHeroes( false ) call SetPeonsRepair( true ) call SetHeroesFlee( false ) call SetHeroesBuyItems( true ) call SetUnitsFlee( true ) call SetGroupsFlee( true ) call SetWatchMegaTargets( false ) call SetIgnoreInjured( false ) call SetHeroesTakeItems( false ) call SetSlowChopping( false ) call SetCaptainChanges( false ) call SetSmartArtillery( true ) endfunction function Buildings takes nothing returns nothing call SetBuildAll( BUILD_UNIT, 3, PEON, -1) call SetBuildAll( BUILD_UNIT, 1, BURROW, -1) call SetBuildAll( BUILD_UNIT, 6, PEON, -1) call SetBuildAll( BUILD_UNIT, 2, ORC_BARRACKS, -1) call SetBuildAll( BUILD_UNIT, 3, BURROW, -1) call SetBuildAll( BUILD_UNIT, 1, STRONGHOLD, -1) call SetBuildAll( BUILD_UNIT, 2, GRUNT, -1) call SetBuildAll( BUILD_UNIT, 3, HEAD_HUNTER, -1) call SetBuildAll( BUILD_UNIT, 1, CATAPULT, -1) call SetBuildAll( BUILD_UNIT, 3, BURROW, -1) call SetBuildAll( BUILD_UNIT, 9, PEON, -1) call SetBuildAll( BUILD_UNIT, 1, FORGE, -1) call SetBuildAll( BUILD_UNIT, 4, BURROW, -1) call SetBuildAll( BUILD_UNIT, 12, PEON, -1) call SetBuildAll( BUILD_UNIT, 1, ORC_ALTAR, -1) call SetBuildAll( BUILD_UNIT, 5, BURROW, -1) call SetBuildAll( BUILD_UNIT, 1, BESTIARY, -1) call SetBuildAll( BUILD_UNIT, 1, FORTRESS, -1) call SetBuildAll( BUILD_UNIT, 6, BURROW, -1) call SetBuildAll( BUILD_UNIT, 1, TOTEM, -1) call SetBuildAll( BUILD_UNIT, 1, LODGE, -1) call SetBuildAll( BUILD_UNIT, 10, BURROW, -1) call SetBuildAll( BUILD_UNIT, 3, GRUNT, -1) call SetBuildAll( BUILD_UNIT, 3, HEAD_HUNTER, -1) call SetBuildAll( BUILD_UNIT, 3, RAIDER, -1) call SetBuildAll( BUILD_UNIT, 2, KODO_BEAST, -1) call SetBuildAll( BUILD_UNIT, 6, TAUREN, -1) call SetBuildAll( BUILD_UNIT, 2, SHAMAN, -1) call SetBuildAll( BUILD_UNIT, 2, WITCH_DOCTOR, -1) call SetBuildAll( BUILD_UNIT, 3, SPIRIT_WALKER_M, -1) endfunction function SetHarvest takes nothing returns nothing local integer mine = TownWithMine() local integer goldWorkers = 5 local integer woodWorkers = 4 call HarvestGold( mine, goldWorkers ) call HarvestWood( 0, woodWorkers ) endfunction // get the number of each type of unit we have that can attack function GetAttackReadyUnitCount takes nothing returns integer local integer i = 0 local integer count = 0 loop exitwhen (i == attackUnitCount) set attackUnitIdCount[i] = GetUnitCountDone(attackUnitId[i]) set count = count + attackUnitIdCount[i] //call Msg("Unit id: " + GetUnitIdName(attackUnitId[i]) + ", count: " + IS(attackUnitIdCount[i])) set i = i + 1 endloop return count endfunction // return true if there are any non-zero counts // ! We should not get here if all the counts are 0, which is the only condition // that should make this return false. function RemoveOneRandomNonZeroAttackUnit takes nothing returns boolean local integer array nonZero local integer nonZeroCount = 0 local integer i = 0 call Msg("RemoveOneRandomNonZeroAttackUnit") // loop through all the indices and find the non-zero counts loop exitwhen i == attackUnitCount if ( attackUnitIdCount[i] >= 0 ) then set nonZero[nonZeroCount] = i set nonZeroCount = nonZeroCount + 1 endif set i = i + 1 endloop // if we have at least one non-zero count, reduce a random one by 1 if ( nonZeroCount > 0 ) then call Msg("Removing 1 " + GetUnitIdName(attackUnitId[i])) set i = GetRandomInt(0, nonZeroCount - 1) set attackUnitIdCount[i] = attackUnitIdCount[i] - 1 return true else // return false if they're all 0 return false endif endfunction // Return true if there are any units to attack with but ensure that no more // than count units are sent. Less is ok. function GetRandomNUnits takes integer maxCount returns boolean local integer total = 0 local integer i = 0 //call ResetAttackReadyUnitCount() set total = GetAttackReadyUnitCount() call Msg("Total: " + IS(total)) // loop through all of them loop exitwhen total <= maxCount if ( RemoveOneRandomNonZeroAttackUnit() == true ) then set total = total - 1 else call Msg("RemoveOneRandomNonZeroAttackUnit returned false. total: " + IS(total)) set total = 0 // force a quit endif endloop call Msg("GetRandom(" + IS(maxCount) + ")Units: " + IS(total)) return total > 4 endfunction function SetAttackGroup takes nothing returns nothing local integer i = 0 loop exitwhen i == attackUnitCount if ( attackUnitIdCount[i] > 0 ) then call Msg("SetAssaultGroup( " + IS(attackUnitIdCount[i]) + ", " + GetUnitIdName(attackUnitId[i]) + ")") call SetAssaultGroup(attackUnitIdCount[i], attackUnitIdCount[i], attackUnitId[i]) endif set i = i + 1 endloop endfunction function AttackTarget takes unit target, boolean addAlliance returns nothing local real x local real y if (target == null) then return endif if (addAlliance) then call SetAllianceTarget( target ) endif set x = GetUnitX(target) set y = GetUnitY(target) call PingMinimapEx(x, y, 5, 100, 100, 100, false) call Msg("Forming group...") call FormGroup( 5, true ) call Msg("Attacking?") call Sleep( 5 ) call AttackMoveKillB( target ) call Msg("Wtf alliance stuff.") if (not addAlliance) then call SetAllianceTarget( null ) endif endfunction function LaunchAttack takes nothing returns nothing local unit target = null local boolean setAlly = true // Don't launch any attack while town is threatened if (TownThreatened()) then call Sleep( 2 ) return endif // Target Priority #1 call Msg("prio 1") if (target == null) then set target = GetEnemyExpansion() endif // Target Priority #2 call Msg("prio 2") if (target == null) then set target = GetEnemyExpansion() if (target == null) then call StartGetEnemyBase( ) loop exitwhen (not WaitGetEnemyBase()) call Msg("WaitGetEnemyBase") call SuicideSleep( 1 ) endloop set target = GetEnemyBase() endif endif // Target Priority #3 call Msg("prio 3") if (target == null) then set target = GetMegaTarget() endif // Target Priority #4 call Msg("prio 4") if (target == null) then set target = GetAllianceTarget() if (target != null) then set setAlly = false endif endif // Target Priority #5 call Msg("prio 5") if (target == null) then set target = GetExpansionFoe() if (target != null) then set take_exp = false endif endif // Target Priority #6 call Msg("prio 6") if (target == null) then set target = GetCreepCamp( 0, 9, false ) endif // Target Priority #7 call Msg("prio 7") if (target == null) then set target = GetCreepCamp( 10, 100, true ) endif if (target != null) then call Msg("target? yar") call AttackTarget( target, setAlly ) else // If no target was found, sleep a bit before trying again call Msg("target? nar") call Sleep( 20 ) endif endfunction function WorkerThread takes nothing returns nothing call Msg("WorkThread starting") loop // Harvesting call ClearHarvestAI( ) call SetHarvest( ) // Building call InitBuildArray( ) call Buildings( ) call Sleep( 1 ) endloop endfunction function AttackThread takes nothing returns nothing local integer count = 5 call Msg("AttackThread starting") loop if ( TownThreatened() ) then call Msg("TownThreatened()") call Sleep( 2 ) else call Msg("Attack tick: " + IS(count)) if (GetRandomNUnits(count) == true ) then call Msg("New attack coming.") call InitAssaultGroup() call SetAttackGroup() call LaunchAttack() endif call Sleep( 10 ) endif endloop endfunction function main takes nothing returns nothing call Msg("kos2jass orc.ai") call InitAI() call Msg("InitAI") call ConfigureAI() call Msg("ConfigureAI") call SetAttackUnits() //call CreateCaptains() call Sleep ( 1.0 ) call StartThread( function WorkerThread ) call StartThread( function AttackThread ) call PlayGame() endfunction |
