Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ''' Simple "Blank" PlanetWars controller bot.
- The Bot does nothing, but shows the minimum a bot needs to have.
- See the `update` method which is where your code goes.
- The `PlanetWars` `Player` object (see players.py), will contain your bot
- controller instance. The Player will provide a current `GameInfo` instance
- to your bot `update` method each time it is called.
- The `gameinfo` instance is a facade of the state of the game for the `Player`,
- and includes all planets and fleets that currently exist. Note that the
- details are limited by "fog of war" visions and only match what you can see.
- A gameinfo instance has various (possibly useful) dict's for you to use:
- # all planet and fleets (that you own or can see)
- planets
- fleets
- # dict's of just your planets/fleets
- my_planets
- my_fleets
- # dict's of both neutral and enemy planets/fleets
- not_my_planets
- not_my_fleets
- # dict's of just the enemy planet/fleets (fog limited)
- enemy_planets
- enemy_fleets
- You issue orders from your bot using the methods of the gameinfo instance.
- gameinfo.planet_order(src, dest, ships)
- gameinfo.fleet_order(src, dest, ships)
- For example, to send 10 ships from planet src to planet dest, you would
- say `gameinfo.planet_order(src, dest, 10)`.
- There is also a player specific log if you want to leave a message
- gameinfo.log("Here's a message from the bot")
- '''
- from random import choice
- SPY_TIME = 10
- class Tactics():
- #dest = None
- #src = None
- #numShips = 0
- #gameinfo.planetOrder(src, dest, numShips)
- #gameinfo.fleetOrder(src, dest, numShips)
- def Fortify(self, details, gameinfo, estimate):
- pass
- def Attack(self, details, gameinfo, estimate):
- pass
- def Scout(self, details, gameinfo, estimate):
- gameinfo.planet_order(choice(gameinfo.my_planets), details, 1)
- TACTICS = {"Fortify" : Fortify, "Attack" : Attack, "Scout": Scout}
- class ArtOfWar(object):
- def __init__(self):
- self._last_gameinfo = None
- self._estimate = Estimator()
- self._calculator = Calculator()
- self._currentTactics = [] #Tuple of Sets e.g. [("Fortify": PlanetX), ("Colonize": PlanetY)])
- def update(self, gameinfo):
- """Plan:
- 1. Measurement of visible data (automatic)
- 2. Estimation of data outside the scope (using class Estimate update method)
- 3. Calculation of possible tactics (using AoW Heuristics)
- 4. Comparison of possible tactics
- 5. Utilization of tactics for victory """
- self._last_gameinfo = gameinfo
- self._estimation()
- new_tactics = self._calculation()
- self._compare(new_tactics)
- for tactic in self._currentTactics:
- self._act(tactic)
- self._currentTactics.remove(tactic)
- self._cleanup()
- def _estimation(self):
- """Plan:
- Estimate opponents current forces
- Estimate what the opponent currently knows"""
- self._estimate.update(self._last_gameinfo)
- def _calculation(self):
- """Plan:
- Calculate what tactics are viable from the current information known"""
- return self._calculator.update(self._estimate, self._last_gameinfo)
- def _compare(self, new_tactics):
- """Plan:
- Compare a variety of tactics to determine the most necessary or likely to work
- Check if any _currentTactics are "holding tactics" that require a change into their active state
- adds the chosen tactics to _currentTactics"""
- #Remove this from Compare, add to Estimate.Initialize
- temp_scouting = [] #starts as tuple for adding data
- for tactic in new_tactics:
- if tactic[0] == "Scout":
- for old_tactic in self._currentTactics:
- #If not already being scouted
- if (old_tactic[0] == "Scouting") and (old_tactic[1] == tactic[1]):
- pass
- else:
- temp_scouting.append(tactic[1])
- scouting = set(temp_scouting) #convert to set for no duplicate elements for later testing
- scout_data = {} #dict of {Planet to be scouted: (Set of planets it can see)}
- for i in scouting:
- scout_data[i] = [] #default can't see any other planets
- for j in scouting:
- if j in self._estimate.planets_see[i]:
- scout_data[i].append(j)
- #Formula that determines the minimum number of planets to be scouted to see all of them
- removal = []
- for p in scouting:
- temp_scouting.remove(p)
- temp_scout_can_see = []
- for i in temp_scouting:
- for j in temp_scouting:
- if j in self._estimate.planets_see[i]:
- temp_scout_can_see.append(j)
- for ptest in scouting:
- if ptest not in temp_scout_can_see:
- temp_scouting.append(p)
- if p not in temp_scouting:
- removal.append(p)
- for p in removal:
- for tactic in new_tactics:
- if (tactic[0] == "Scout") and (tactic[1] == p):
- new_tactics.remove(p)
- self._currentTactics.append(new_tactics)
- def _act(self, tactic):
- """Plan:
- Act out the given tactic
- If necessary adds a "holding tactic" pending a future condition
- May also use gameinfo.log to post messages to the screen"""
- if tactic[0] in Tactics.TACTICS.keys():
- func = Tactics.TACTICS[tactic]
- func(tactic[1], self._last_gameinfo, self._estimate)
- if tactic[0] == "Scout":
- self._currentTactics.append(("Scouting", tactic[1]))
- def _cleanup(self):
- for tactic in self._currentTactics:
- if tactic[0] == "Scouting":
- if self._estimate.planet_info[tactic[1]]["Data Age"] < SPY_TIME:
- self._currentTactics.remove(tactic)
- class Calculator():
- def __init__(self):
- self.must_hasten = () #planets, enemy must hasten, rescue, etc. >Appear here
- self.undefended = () #planets, >Attack here
- def update(self, estimate, gameinfo):
- """update information first
- then make broad assumptions
- return a dict of possible tactics"""
- new_tactics = [("Blank", "Filler")]
- #for fleet in self.fleets:
- #if there is no gain RTB
- for p in estimate.planet_info:
- if estimate.planet_info[p]["Data Age"] > SPY_TIME:
- new_tactics.append(("Scout", p))
- return new_tactics
- class Estimator():
- def __init__(self):
- self.planet_info = {} #{planet: (time since last info, last info)}
- self.hidden_planets = {} #{planet: (time since enemy last saw, what enemy last saw)}
- #not sure if possible
- self.planet_distances = {} #{planet: {planet: distance}}
- self.planets_see = {}
- self.terrain = {} #{planet: Terrain}
- #Accessible, Entangling, Deadlock, Enclosed, Precipitous, Distant
- self.ground = {} #{planet: Ground}
- #Scattering, Light, Strategic, Open, Crossroad, Heavy, Intractable, Enclosed, Death
- self.initialized = False
- def update(self, gameinfo):
- if self.initialized == False:
- self._initialize(gameinfo)
- for p in gameinfo.not_my_planets:
- if p not in gameinfo.enemy_planets:
- if p in self.planet_info:
- self.planet_info[p]["Data Age"] += 1
- else:
- self.planet_info[p]["Ships"] = gameinfo.enemy_planets[p].num_ships
- self.planet_info[p]["Data Age"] = 0
- def _initialize(self, gameinfo):
- self.initialized = True
- for p in gameinfo.not_my_planets:
- self.planet_info[p] = {"Ships" : gameinfo.not_my_planets[p].num_ships, "Data Age" : 0}
- for p in gameinfo.planets:
- planet = gameinfo.planets[p]
- self.planet_distances[planet] = {}
- self.planets_see[planet] = []
- for q in gameinfo.planets:
- qlanet = gameinfo.planets[q]
- self.planet_distances[planet][qlanet] = planet.distance_to(qlanet)
- if self.planet_distances[planet][qlanet] < planet.vision_range():
- self.planets_see[planet].append(qlanet)
- #YELL AT CLINTON FOR PASSING GAMEINFO.PLANETS AS A FUCKING GODDAWFUL DICTIONARY
- #I MEAN, SERIOUSLY, IS THIS FUCKING 1989 USING C
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement