AI
General AI concepts:
Priorities:
Agression:
- Defeat Player
- Take Player's Regions
- Destroy Player's Units
Expansion:
- Take Territories according to Desirability of Region
Defence:
- Do not allow player to take home base
- Do not allow player to take regions
- Do not allow player to destroy units
Overall:
1. Top Priority
- Do not allow player to take home base
- Defeat Player
2. High Priority
- Do not allow player to take regions
- Take Player's Regions
3. Medium Priority
- Do not allow player to destroy units
- Destroy Player's Units
4. Low Priority
Higher priority tasks are generally fulfilled by completing lower priority tasks first. However if a high priority task is merited it takes precedent over lower priority tasks.
Details:
Agression
- Defeating the Player is Top Priority. If the player's base can be destroyed the game is won. When the game is won all other factors are void.
- Taking the Player's Regions strengthens the AI while weakening theirs.
- Destroying Player's Units renders the player unable to capture territories and gives the AI numerical supremacy.
Expansion
Capturing neutral regions strengthens the AI.
Desirability of Region is affected by:
- Quality
- Distance & Time to Take
- Military
Defence
- Defence of home base is Top Priority. If it is lost the game is lost. When the game is lost all other factors are void.
- Losing regions to the player weakens the AI while strengthening the Player.
- Losing units renders the AI unable to capture territories and gives the player numerical supremacy.
AI Framework
Region Ranking
Quality
What does the AI obtain from the region? Does it give more than another region? Are the bonuses given more useful at this period in time?
Quality = Production * Relevance of Bonus
If Region is a base it has the highest quality level possible.
Relevance of Bonus - AI has a known enemy troop composition. Is the troop or bonus given a counter to enemy troop composition?
e.g. Player has all type A units. Assuming A > B > C > A.
B = 1.0 B troops beat A type units.
A = 0.5 A type units don't beat A type unless you have more of them.
C = 0.0 C type units are worthless against A type units.
Distance and Time to Take
How long will it take the AI to take this territory? Can the AI capture two other territories in the time taken to capture this one?
D&T = Estimate time most available unit that can be sent will require to capture region.
Military
How many troops can the AI potentially send to this territory? How long will they take to get there? How many troops can the Player potentially send to this territory? How long will they take to get there? What type of troops can be mustered to defend vs What types of troops can attack? Are there any bonuses or special things to take into account?
Military = (Available Defending Troops - Available Attacking Troops) * TroopTypeComposition
TroopTypeComposition is a ratio of Defending A,B & C vs Attacking A, B & C.
Decision Making
Once regions have been ranked the AI can make decisions based on it's priorities.
1. Top Priority
- Do not allow player to take home base
- Defeat Player
2. High Priority
- Do not allow player to take regions
- Take Player's Regions
3. Medium Priority
- Do not allow player to destroy units
- Destroy Player's Units
4. Low Priority
The AI will obey priorities in a descending order. If it cannot take any regions and is not threatened it will expand if there is an available spot.
The AI should be aware of it's own and the player's strength. This can be perfect or imperfect(estimated) knowledge. If the AI is ahead on regions and units it should attempt to "trade down". That is, the AI should be willing to accept a 1:1 or even slightly unfair ratio of unit losses. This is because while 21 units are only slightly better than 20 units, 1 unit is infinitely better than 0 units.
AI Strength
The strength of the AI will depend upon:
- Quality & Quantity of it's information. If the AI has perfect knowledge it will play better than if it has imperfect knowledge. The ability of the AI to predict future actions will also impact it's strength.
- Speed of Play. If the AI can make decisions and issue orders faster than a Player it will have a signifiant advantage. The AI will be granted the initiative in all actions.
e.g. Assume the Player and the AI are equal. The AI launches an attack on a territory of the player. The player attempts to defend by moving troops there. The AI instantly pulls back it's troops knowing that it will lose and then attacks the place the Players defenders have just vacated. The Player is forced to move the defenders back and the AI again pulls back and reattacks the original region. The Player is again forced to respond.
This can be considered manageable if annoying. However, now imagine the AI doing this across a large number of regions instantly. Pulling back and receiving no losses when it knows it will lose and attacking relentlessly wherever it will win. The human player would have absolutely no hope of keeping up and would ultimately be defeated.
Now imagine that it is two AI opponents competing. The attacking player will still always be a split second ahead of the defenders. Assuming that neither side takes any losses, the attacking player will eventually win due to denying production in territories that he is able to hold for a split second before retreating. This is assuming that the defending AI player does defend against the attack rather than taking advantage of the attackers absence from his regions to launch an attack of his own.
This indicates that the game balance is fundamentally skewed toward being the attacker and having mobility of forces. This may be offset by having a move time between regions and having production in regions. In this way by the time an attacker arrives more defenders will have been produced. This might just skew the game the other way though and force no one to ever attack. If we had a game balance page I'd say move that in there but I don't know if we have time for any of that. Instead I suggest introducing elements of randomness and crippling the AI to make slightly stupid decisions at times and perhaps react slower.
Coding
The AI will need:
- A list of all it's troops and data on troops
- A list of all it's regions and data on regions
- A list of neutral regions and neutral troops(if any) and data on them. This data can be perfect or imperfect. Imperfect data will result in the AI needing to make assumptions.
- A list of enemy troops and data on troops. This data can be perfect or imperfect. Imperfect data will result in the AI needing to make assumptions.
- A list of enemy regions and data on regions. This data can be perfect or imperfect. Imperfect data will result in the AI needing to make assumptions.
- A way to command troops
I would suggest that when the AI updates it run down it's priorities list checking in order to see if a task is required. When it decides a task is required it should select appropriate units and give them the order. It should assign these units a priority level variable indicating that they are "occupied" and it shouldn't order them to do something else unless they are required for a higher priority task.
9:00pm 17/05/06 file : AI.py
from Entity import *
from Level import *
class AI:
TroopList = []
RegionList = []
myTeam = 2
myTroops = []
enemyTroops = []
neutralRegions = []
myRegions = []
enemyRegions = []
def __init__(self,someRandomEntity, theLevel):
self.LoadLevel(theLevel)
self.Refresh(someRandomEntity)
#Refreshes Troop knowledge
def Refresh(self, ARandomEntity): #Linked Lists are goddamn stupid
temp = ARandomEntity
self.TroopList.append(temp)
ARandomEntity = ARandomEntity.nextEnt
while(temp !=ARandomEntity):
self.TroopList.append(ARandomEntity)
ARandomEntity = ARandomEntity.nextEnt
for i in range (0,len(self.TroopList)):
if (self.TroopList[i].team != self.myTeam):
self.enemyTroops.append(self.TroopList[i])
else:
self.myTroops.append(self.TroopList[i])
#Adds Regions
def LoadLevel(self, theLevel): #See how much simpler things are without linked lists? :P
self.RegionList = theLevel.regions
for i in range (0,len(self.RegionList)): #Go through Regions
if self.RegionList[i].owner == self.myTeam: #My Region
self.myRegions.append(self.RegionList[i])
elif self.RegionList[i].owner != 0: #Enemy Region
self.enemyRegions.append(self.RegionList[i])
else: #Neutral Region
self.neutralRegions.append(self.RegionList[i])
def Update(self, someRandomEntity, theLevel):
print("AI is updating")
self.LoadLevel(theLevel)
self.Refresh(someRandomEntity)
#CheckforWin
#CheckforLoss
self.CheckAttack()
self.CheckDefend()
#Kill Units
#Look After my Units
self.Expand()
## 1. Top Priority
## * Do not allow player to take home base
## * Defeat Player
##
## 2. High Priority
##
## * Do not allow player to take regions
## * Take Player's Regions
##
## 3. Medium Priority
##
## * Do not allow player to destroy units
## * Destroy Player's Units
##
## 4. Low Priority
##
## * Expand
#stuff
def CheckAttack(self):
pass
#Cycle Through Enemy Zones
#If Zone is weak to Attack
#Attack
def CheckDefend(self):
pass
#Cycle Through My Zones
#If Zone is weak to Attack
#Defend
def Expand(self):
#Search for Best Expansion
BestExpansion = self.FindBestExpansion()
#Search for Best Troop to use
TroopToMove = self.FindIdleTroop()
if TroopToMove != None:
TroopToMove.orderMove(BestExpansion.pos)
#Move it there selection[i].orderMove(m.pos)
def FindIdleTroop(self):
for i in range (0,len(self.myTroops)):
if(self.myTroops[i].Priority == 0):
return self.myTroops[i] #Needs to find Troop closest to target
def FindBestExpansion(self):
temp = self.RankNeutralRegion(self.neutralRegions[0])
for i in range (0,len(self.neutralRegions)):
if self.RankNeutralRegion(self.neutralRegions[i]) > temp:
temp = self.neutralRegions
return temp
def RankNeutralRegion(self, aneutralRegion):
return aneutralRegion.production# * aNeutralZone.unitType