Skip to content

Commit

Permalink
Merge pull request #45 from CarperAI/daveey-git-pr-13444-7615
Browse files Browse the repository at this point in the history
Remove population from realm
  • Loading branch information
daveey authored Apr 20, 2023
2 parents dbac713 + dbbcfcd commit b045ede
Show file tree
Hide file tree
Showing 18 changed files with 75 additions and 139 deletions.
7 changes: 0 additions & 7 deletions nmmo/core/agent.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@

from nmmo.lib import colors


class Agent:
policy = 'Neural'

color = colors.Neon.CYAN
pop = 0

def __init__(self, config, idx):
'''Base class for agents
Expand All @@ -17,7 +11,6 @@ def __init__(self, config, idx):
'''
self.config = config
self.iden = idx
self.pop = Agent.pop

def __call__(self, obs):
'''Used by scripted agents to compute actions. Override in subclasses.
Expand Down
7 changes: 2 additions & 5 deletions nmmo/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,6 @@ class Combat:
COMBAT_SYSTEM_ENABLED = True
'''Game system flag'''

COMBAT_FRIENDLY_FIRE = True
'''Whether agents with the same population index can hit each other'''

COMBAT_SPAWN_IMMUNITY = 20
'''Agents older than this many ticks cannot attack agents younger than this many ticks'''

Expand Down Expand Up @@ -518,8 +515,8 @@ class Item:
ITEM_INVENTORY_CAPACITY = 12
'''Number of inventory spaces'''

ITEM_GIVE_TO_FRIENDLY = True
'''Whether agents with the same population index can give gold/item to each other'''
ITEM_ALLOW_GIFT = True
'''Whether agents can give gold/item to each other'''

@property
def INVENTORY_N_OBS(self):
Expand Down
17 changes: 4 additions & 13 deletions nmmo/core/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@


class Env(ParallelEnv):
'''Environment wrapper for Neural MMO using the Parallel PettingZoo API
Neural MMO provides complex environments featuring structured observations/actions,
variably sized agent populations, and long time horizons. Usage in conjunction
with RLlib as demonstrated in the /projekt wrapper is highly recommended.'''
# Environment wrapper for Neural MMO using the Parallel PettingZoo API

def __init__(self,
config: Default = nmmo.config.Default(), seed=None):
Expand Down Expand Up @@ -390,14 +386,9 @@ def _compute_rewards(self, agents: List[AgentID], dones: Dict[AgentID, bool]):
agent = self.realm.players.get(agent_id)
assert agent is not None, f'Agent {agent_id} not found'

infos[agent_id] = {'population': agent.population}

if agent.diary is None:
rewards[agent_id] = 0
continue

rewards[agent_id] = sum(agent.diary.rewards.values())
infos[agent_id].update(agent.diary.rewards)
if agent.diary is not None:
rewards[agent_id] = sum(agent.diary.rewards.values())
infos[agent_id].update(agent.diary.rewards)

return rewards, infos

Expand Down
3 changes: 0 additions & 3 deletions nmmo/core/log_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,4 @@ def _player_stats(self, player: Agent) -> Dict[str, float]:
for achievement in player.diary.achievements:
stats["Achievement_{achievement.name}"] = float(achievement.completed)

# Used for SR
stats['PolicyID'] = player.population

return stats
19 changes: 8 additions & 11 deletions nmmo/core/observation.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,11 @@ def _make_attack_mask(self):
else:
spawn_immunity = np.ones(self.entities.len, dtype=np.int8)

if not self.config.COMBAT_FRIENDLY_FIRE:
population = self.entities.values[:,EntityState.State.attr_name_to_col["population_id"]]
no_friendly_fire = population != agent.population_id # this automatically masks self
else:
# allow friendly fire but no self shooting
no_friendly_fire = np.ones(self.entities.len, dtype=np.int8)
no_friendly_fire[self.entities.index(agent.id)] = 0 # mask self
# allow friendly fire but no self shooting
not_me = np.ones(self.entities.len, dtype=np.int8)
not_me[self.entities.index(agent.id)] = 0 # mask self

return np.concatenate([within_range & no_friendly_fire & spawn_immunity,
return np.concatenate([within_range & not_me & spawn_immunity,
np.zeros(self.config.PLAYER_N_OBS - self.entities.len, dtype=np.int8)])

def _make_use_mask(self):
Expand Down Expand Up @@ -287,10 +283,11 @@ def _make_give_target_mask(self):
entities_pos = self.entities.values[:, [EntityState.State.attr_name_to_col["row"],
EntityState.State.attr_name_to_col["col"]]]
same_tile = utils.linf(entities_pos, (agent.row, agent.col)) == 0
same_team_not_me = (self.entities.ids != agent.id) & (agent.population_id == \
self.entities.values[:, EntityState.State.attr_name_to_col["population_id"]])
not_me = self.entities.ids != self.agent_id
player = (self.entities.values[:,EntityState.State.attr_name_to_col["npc_type"]] == 0)

return np.concatenate([same_tile & same_team_not_me,
return np.concatenate([
(same_tile & player & not_me),
np.zeros(self.config.PLAYER_N_OBS - self.entities.len, dtype=np.int8)])

def _make_give_gold_mask(self):
Expand Down
2 changes: 1 addition & 1 deletion nmmo/core/realm.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def packet(self):
}

@property
def population(self):
def num_players(self):
"""Number of player agents"""
return len(self.players.entities)

Expand Down
16 changes: 3 additions & 13 deletions nmmo/entity/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
EntityState = SerializedState.subclass(
"Entity", [
"id",
"population_id",
"npc_type", # 1 - passive, 2 - neutral, 3 - aggressive
"row",
"col",

Expand Down Expand Up @@ -48,7 +48,7 @@
EntityState.Limits = lambda config: {
**{
"id": (-math.inf, math.inf),
"population_id": (-3, config.PLAYER_POLICIES-1),
"npc_type": (0, 4),
"row": (0, config.MAP_SIZE-1),
"col": (0, config.MAP_SIZE-1),
"damage": (0, math.inf),
Expand Down Expand Up @@ -211,7 +211,7 @@ def packet(self):

# pylint: disable=no-member
class Entity(EntityState):
def __init__(self, realm, pos, entity_id, name, color, population_id):
def __init__(self, realm, pos, entity_id, name):
super().__init__(realm.datastore, EntityState.Limits(realm.config))

self.realm = realm
Expand All @@ -222,11 +222,9 @@ def __init__(self, realm, pos, entity_id, name, color, population_id):
self.repr = None

self.name = name + str(entity_id)
self.color = color

self.row.update(pos[0])
self.col.update(pos[1])
self.population_id.update(population_id)
self.id.update(entity_id)

self.vision = self.config.PLAYER_VISION_RADIUS
Expand Down Expand Up @@ -259,10 +257,6 @@ def packet(self):
'name': self.name,
'level': self.attack_level,
'item_level': self.item_level.val,
'color': self.color.packet(),
'population': self.population,
# FIXME: Don't know what it does. Previous nmmo entities all returned 1
# 'self': self.self.val,
}

return data
Expand Down Expand Up @@ -338,7 +332,3 @@ def attack_level(self) -> int:
mage = self.skills.mage.level.val

return int(max(melee, ranged, mage))

@property
def population(self):
return self.population_id.val
7 changes: 3 additions & 4 deletions nmmo/entity/entity_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from nmmo.entity.entity import Entity
from nmmo.entity.npc import NPC
from nmmo.entity.player import Player
from nmmo.lib import colors, spawn
from nmmo.lib import spawn
from nmmo.systems import combat


Expand Down Expand Up @@ -126,7 +126,6 @@ def actions(self, realm):
class PlayerManager(EntityGroup):
def __init__(self, realm):
super().__init__(realm)
self.palette = colors.Palette()
self.loader = self.realm.config.PLAYER_LOADER
self.agents = None
self.spawned = None
Expand All @@ -137,9 +136,9 @@ def reset(self):
self.spawned = OrderedSet()

def spawn_individual(self, r, c, idx):
pop, agent = next(self.agents)
agent = next(self.agents)
agent = agent(self.config, idx)
player = Player(self.realm, (r, c), agent, self.palette.color(pop), pop)
player = Player(self.realm, (r, c), agent)
super().spawn(player)

def spawn(self):
Expand Down
13 changes: 7 additions & 6 deletions nmmo/entity/npc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from nmmo.entity import entity
from nmmo.io import action as Action
from nmmo.lib.colors import Neon
from nmmo.systems import combat, droptable
from nmmo.systems.ai import policy
from nmmo.systems import item as Item
Expand Down Expand Up @@ -46,15 +45,17 @@ def packet(self):
return packet


# pylint: disable=no-member
class NPC(entity.Entity):
def __init__(self, realm, pos, iden, name, color, pop):
super().__init__(realm, pos, iden, name, color, pop)
def __init__(self, realm, pos, iden, name, npc_type):
super().__init__(realm, pos, iden, name)
self.skills = skill.Combat(realm, self)
self.realm = realm
self.last_action = None
self.droptable = None
self.spawn_danger = None
self.equipment = None
self.npc_type.update(npc_type)

def update(self, realm, actions):
super().update(realm, actions)
Expand Down Expand Up @@ -161,21 +162,21 @@ def is_npc(self) -> bool:

class Passive(NPC):
def __init__(self, realm, pos, iden):
super().__init__(realm, pos, iden, 'Passive', Neon.GREEN, -1)
super().__init__(realm, pos, iden, 'Passive', 1)

def decide(self, realm):
return policy.passive(realm, self)

class PassiveAggressive(NPC):
def __init__(self, realm, pos, iden):
super().__init__(realm, pos, iden, 'Neutral', Neon.ORANGE, -2)
super().__init__(realm, pos, iden, 'Neutral', 2)

def decide(self, realm):
return policy.neutral(realm, self)

class Aggressive(NPC):
def __init__(self, realm, pos, iden):
super().__init__(realm, pos, iden, 'Hostile', Neon.RED, -3)
super().__init__(realm, pos, iden, 'Hostile', 3)

def decide(self, realm):
return policy.hostile(realm, self)
8 changes: 3 additions & 5 deletions nmmo/entity/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

# pylint: disable=no-member
class Player(entity.Entity):
def __init__(self, realm, pos, agent, color, pop):
super().__init__(realm, pos, agent.iden, agent.policy, color, pop)
def __init__(self, realm, pos, agent):
super().__init__(realm, pos, agent.iden, agent.policy)

self.agent = agent
self.pop = pop
self.immortal = realm.config.IMMORTAL

# Scripted hooks
Expand Down Expand Up @@ -37,7 +36,7 @@ def __init__(self, realm, pos, agent, color, pop):

@property
def serial(self):
return self.population_id, self.ent_id
return self.ent_id

@property
def is_player(self) -> bool:
Expand Down Expand Up @@ -92,7 +91,6 @@ def packet(self):
data = super().packet()

data['entID'] = self.ent_id
data['annID'] = self.population

data['resource'] = self.resources.packet()
data['skills'] = self.skills.packet()
Expand Down
17 changes: 6 additions & 11 deletions nmmo/io/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,6 @@ def call(realm, entity, style, target):
if entity.ent_id == target.ent_id:
return None

#ADDED: POPULATION IMMUNITY
if not config.COMBAT_FRIENDLY_FIRE and entity.is_player \
and entity.population_id.val == target.population_id.val:
return None

#Can't attack out of range
if utils.linf(entity.pos, target.pos) > style.attack_range(config):
return None
Expand Down Expand Up @@ -458,10 +453,10 @@ def call(realm, entity, item, target):
if item.equipped.val or item.listed_price.val:
return

if not (config.ITEM_GIVE_TO_FRIENDLY and
entity.population_id == target.population_id and # the same team
if not (config.ITEM_ALLOW_GIFT and
entity.ent_id != target.ent_id and # but not self
utils.linf(entity.pos, target.pos) == 0): # the same tile
target.is_player and
entity.pos == target.pos): # the same tile
return

if not target.inventory.space:
Expand Down Expand Up @@ -504,10 +499,10 @@ def call(realm, entity, amount, target):
if not (target.is_player and target.alive):
return

if not (config.ITEM_GIVE_TO_FRIENDLY and
entity.population_id == target.population_id and # the same team
if not (config.ITEM_ALLOW_GIFT and
entity.ent_id != target.ent_id and # but not self
utils.linf(entity.pos, target.pos) == 0): # the same tile
target.is_player and
entity.pos == target.pos): # the same tile
return

if not isinstance(amount, int):
Expand Down
25 changes: 1 addition & 24 deletions nmmo/lib/spawn.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ class SequentialLoader:
'''config.PLAYER_LOADER that spreads out agent populations'''
def __init__(self, config):
items = config.PLAYERS
for idx, itm in enumerate(items):
itm.policyID = idx

self.items = items
self.idx = -1
Expand All @@ -15,28 +13,7 @@ def __iter__(self):

def __next__(self):
self.idx = (self.idx + 1) % len(self.items)
return self.idx, self.items[self.idx]

class TeamLoader:
'''config.PLAYER_LOADER that loads agent populations adjacent'''
def __init__(self, config):
items = config.PLAYERS
self.team_size = config.PLAYER_N // len(items)

for idx, itm in enumerate(items):
itm.policyID = idx

self.items = items
self.idx = -1

def __iter__(self):
return self

def __next__(self):
self.idx += 1
team_idx = self.idx // self.team_size
return team_idx, self.items[team_idx]

return self.items[self.idx]

def spawn_continuous(config):
'''Generates spawn positions for new agents
Expand Down
3 changes: 1 addition & 2 deletions nmmo/overlay.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,8 @@ def update(self, obs):
'''Computes a count-based exploration map by painting
tiles as agents walk over them'''
for ent_id, agent in self.realm.realm.players.items():
pop = agent.population_id.val
r, c = agent.pos
self.values[r, c][pop] += 1
self.values[r, c][ent_id] += 1

def register(self, obs):
colors = self.realm.realm.players.palette.colors
Expand Down
Loading

0 comments on commit b045ede

Please sign in to comment.