This repository has been archived by the owner on Aug 7, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'code_editor_frontend' of https://github.com/ocadotechno…
…logy/aimmo into code_editor_frontend
- Loading branch information
Showing
9 changed files
with
203 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
from simulation.action import MoveAction | ||
|
||
|
||
class Cell(object): | ||
""" | ||
Any position on the world grid. | ||
""" | ||
|
||
def __init__(self, location, habitable=True, generates_score=False, | ||
partially_fogged=False): | ||
self.location = location | ||
self.habitable = habitable | ||
self.generates_score = generates_score | ||
self.avatar = None | ||
self.pickup = None | ||
self.partially_fogged = partially_fogged | ||
self.actions = [] | ||
|
||
def __repr__(self): | ||
return 'Cell({} h={} s={} a={} p={} f{})'.format( | ||
self.location, self.habitable, self.generates_score, self.avatar, self.pickup, | ||
self.partially_fogged) | ||
|
||
def __eq__(self, other): | ||
return self.location == other.location | ||
|
||
def __ne__(self, other): | ||
return not self == other | ||
|
||
def __hash__(self): | ||
return hash(self.location) | ||
|
||
@property | ||
def moves(self): | ||
return [move for move in self.actions if isinstance(move, MoveAction)] | ||
|
||
@property | ||
def is_occupied(self): | ||
return self.avatar is not None | ||
|
||
def serialise(self): | ||
if self.partially_fogged: | ||
return { | ||
'generates_score': self.generates_score, | ||
'location': self.location.serialise(), | ||
'partially_fogged': self.partially_fogged | ||
} | ||
else: | ||
return { | ||
'avatar': self.avatar.serialise() if self.avatar else None, | ||
'generates_score': self.generates_score, | ||
'habitable': self.habitable, | ||
'location': self.location.serialise(), | ||
'pickup': self.pickup.serialise() if self.pickup else None, | ||
'partially_fogged': self.partially_fogged | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from .spawn_location_finder import SpawnLocationFinder | ||
from map_updaters import ScoreLocationUpdater, MapContext, PickupUpdater, MapExpander | ||
|
||
__all__ = [ | ||
'SpawnLocationFinder', | ||
'ScoreLocationUpdater', | ||
'MapContext', | ||
'PickupUpdater', | ||
'MapExpander' | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
from abc import ABCMeta, abstractmethod | ||
from collections import namedtuple | ||
import random | ||
import math | ||
from logging import getLogger | ||
from simulation.pickups import ALL_PICKUPS | ||
from simulation.cell import Cell | ||
from simulation.location import Location | ||
|
||
LOGGER = getLogger(__name__) | ||
|
||
MapContext = namedtuple('MapContext', 'num_avatars') | ||
|
||
|
||
class _MapUpdater: | ||
__metaclass__ = ABCMeta | ||
|
||
@abstractmethod | ||
def update(self, world_map, context): | ||
raise NotImplementedError | ||
|
||
|
||
class ScoreLocationUpdater(_MapUpdater): | ||
def update(self, world_map, context): | ||
for cell in world_map.score_cells(): | ||
if random.random() < world_map.settings['SCORE_DESPAWN_CHANCE']: | ||
cell.generates_score = False | ||
|
||
new_num_score_locations = len(list(world_map.score_cells())) | ||
target_num_score_locations = int(math.ceil( | ||
context.num_avatars * world_map.settings['TARGET_NUM_SCORE_LOCATIONS_PER_AVATAR'] | ||
)) | ||
num_score_locations_to_add = target_num_score_locations - new_num_score_locations | ||
locations = world_map._spawn_location_finder.get_random_spawn_locations(num_score_locations_to_add) | ||
for cell in locations: | ||
cell.generates_score = True | ||
|
||
|
||
class PickupUpdater(_MapUpdater): | ||
def update(self, world_map, context): | ||
target_num_pickups = int(math.ceil( | ||
context.num_avatars * world_map.settings['TARGET_NUM_PICKUPS_PER_AVATAR'] | ||
)) | ||
LOGGER.debug('Aiming for %s new pickups', target_num_pickups) | ||
max_num_pickups_to_add = target_num_pickups - len(list(world_map.pickup_cells())) | ||
locations = world_map._spawn_location_finder.get_random_spawn_locations(max_num_pickups_to_add) | ||
for cell in locations: | ||
if random.random() < world_map.settings['PICKUP_SPAWN_CHANCE']: | ||
LOGGER.info('Adding new pickup at %s', cell) | ||
cell.pickup = random.choice(ALL_PICKUPS)(cell) | ||
|
||
|
||
class MapExpander(_MapUpdater): | ||
def update(self, world_map, context): | ||
LOGGER.info('Expanding map') | ||
start_size = world_map.num_cells | ||
target_num_cells = int(math.ceil( | ||
context.num_avatars * world_map.settings['TARGET_NUM_CELLS_PER_AVATAR'] | ||
)) | ||
num_cells_to_add = target_num_cells - world_map.num_cells | ||
if num_cells_to_add > 0: | ||
self._add_outer_layer(world_map) | ||
assert world_map.num_cells > start_size | ||
|
||
def _add_outer_layer(self, world_map): | ||
self._add_vertical_layer(world_map, world_map.min_x() - 1) | ||
self._add_vertical_layer(world_map, world_map.max_x() + 1) | ||
self._add_horizontal_layer(world_map, world_map.min_y() - 1) | ||
self._add_horizontal_layer(world_map, world_map.max_y() + 1) | ||
|
||
def _add_vertical_layer(self, world_map, x): | ||
for y in range(world_map.min_y(), world_map.max_y() + 1): | ||
world_map.grid[Location(x, y)] = Cell(Location(x, y)) | ||
|
||
def _add_horizontal_layer(self, world_map, y): | ||
for x in range(world_map.min_x(), world_map.max_x() + 1): | ||
world_map.grid[Location(x, y)] = Cell(Location(x, y)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import random | ||
from logging import getLogger | ||
|
||
LOGGER = getLogger(__name__) | ||
|
||
|
||
class SpawnLocationFinder: | ||
|
||
def __init__(self, world_map): | ||
self._world_map = world_map | ||
|
||
def potential_spawn_locations(self): | ||
""" | ||
Used to make sure that the cell is free before spawning. | ||
""" | ||
return (c for c in self._world_map.all_cells() | ||
if c.habitable | ||
and not c.generates_score | ||
and not c.avatar | ||
and not c.pickup) | ||
|
||
def get_random_spawn_locations(self, max_locations): | ||
if max_locations <= 0: | ||
return [] | ||
potential_locations = list(self.potential_spawn_locations()) | ||
try: | ||
return random.sample(potential_locations, max_locations) | ||
except ValueError: | ||
LOGGER.debug('Not enough potential locations') | ||
return potential_locations | ||
|
||
def get_random_spawn_location(self): | ||
"""Return a single random spawn location. | ||
Throws: | ||
IndexError: if there are no possible locations. | ||
""" | ||
return self.get_random_spawn_locations(1)[0].location |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.