Compare commits

..

10 Commits

Author SHA256 Message Date
Andrea De Angelis
445c51eec7 Merge branch 'master_items' into 'master'
spawn random items, and try to put on map, but i still need to investigate why...

See merge request cryz/battle_royale_simulator!1
2025-11-15 17:15:04 +00:00
andrea
676a38b904 items are now correcly shown on the map 2025-11-15 18:14:05 +01:00
andrea
054522eaf3 spawn random items, and try to put on map, but i still need to investigate why items are not correctly rendered on map 2025-11-14 23:15:14 +01:00
andrea
f408aee8f8 items syms 2025-11-14 22:00:35 +01:00
andrea
9c2b6b026b arena replace weapons with more generic items 2025-11-14 21:49:49 +01:00
andrea
f80edfff83 failback random weapon 2025-09-04 21:32:57 +02:00
andrea
4c2864634b additional debug functions 2025-09-04 21:12:12 +02:00
andrea
b4c8d94c8c initialize random_event action on Arena 2025-09-04 21:11:24 +02:00
andrea
a56d931304 fix event_picker errors that cause bot crash 2025-09-04 21:10:32 +02:00
andrea
b001c9312a fix event_pickers errors that make the bot crash 2025-09-04 21:09:15 +02:00
9 changed files with 130 additions and 65 deletions

View File

@@ -9,7 +9,7 @@ EVENTS = [
'extreme_fail_percentage' : 1, 'extreme_fail_percentage' : 1,
'requirements' : {}, 'requirements' : {},
'weight' : 1, 'weight' : 1,
'affected_players' : 1, 'affected_players' : 1, #NOTE, what is it? to why it could be integer or list?
}, },
{ {
'id' : 'BOMB_EXPLOSION', 'id' : 'BOMB_EXPLOSION',

View File

@@ -3,14 +3,39 @@ import random as _rand
import main as _main import main as _main
from utils import logs as _logs from utils import logs as _logs
from bot_libs import syms as _syms from bot_libs import syms as _syms
from entities.items import syms as _isyms
def _extract_random_number_of_items(Arena):
players= Arena.get_players()
nplayers= len(players)
min_extraction= max(nplayers - 5, 3)
max_extraction= min(nplayers - 1, 8)
nitems= _rand.randint(min_extraction, max_extraction)
return nitems
def _get_random_items(Arena):
items= []
nitems= _extract_random_number_of_items(Arena)
for n in range(nitems):
itype= _rand.sample(_isyms.ITEMS_LIST, 1)[0]
items.append(itype)
return items
def _debug_data(): def _debug_data():
players= _syms.COLORS_NAMES players= _syms.COLORS_NAMES
weapons= [] nelected_players= _rand.randint(6, 12)
elected_players= _rand.sample(players, nelected_players)
Arena= _main.init_arena() Arena= _main.init_arena()
for player in players: for player in elected_players:
Arena.add_player(player) Arena.add_player(player)
_logs.log_debug('Players: {elected_players}')
items= _get_random_items(Arena)
for item in items:
Arena.add_item(item)
_logs.log_info('Items: {items}')
return Arena return Arena
def _end_game_debug(alive_players, day): def _end_game_debug(alive_players, day):
@@ -89,9 +114,9 @@ def init_debug_simulation():
_logs.log_debug('#################') _logs.log_debug('#################')
_logs.log_debug('#################') _logs.log_debug('#################')
_logs.log_debug('#################') _logs.log_debug('#################')
_time.sleep(0.3) _time.sleep(0.7)
def init_debug_loop(): def init_debug_attack_loop():
Arena= _debug_data() Arena= _debug_data()
while (len(Arena.get_alive_players()) > 1): while (len(Arena.get_alive_players()) > 1):
alive_players= Arena.get_alive_players() alive_players= Arena.get_alive_players()
@@ -104,6 +129,18 @@ def init_debug_loop():
Arena.next_day() Arena.next_day()
_time.sleep(0.3) _time.sleep(0.3)
#End of day #End of day
Map= Arena.get_map()
_logs.log_debug(Map.get_renderized_map())
last_player= Arena.get_alive_players()[0]
_logs.log_debug(f'{last_player.get_name()} sopravvive e vince dopo {Arena.day} lunghi Giorni, conquistando l\'amore eterno di Guarino')
def init_debug_event_loop():
Arena= _debug_data()
while (len(Arena.get_alive_players()) > 1):
Arena.do_random_event()
_time.sleep(0.3)
#End of day
last_player= Arena.get_alive_players()[0] last_player= Arena.get_alive_players()[0]
_logs.log_debug(f'{last_player.get_name()} sopravvive e vince dopo {Arena.day} lunghi Giorni, conquistando l\'amore eterno di Guarino') _logs.log_debug(f'{last_player.get_name()} sopravvive e vince dopo {Arena.day} lunghi Giorni, conquistando l\'amore eterno di Guarino')
@@ -116,4 +153,6 @@ def debug_random_map():
_logs.log_debug(res) _logs.log_debug(res)
if __name__ == '__main__': if __name__ == '__main__':
init_debug() init_debug_simulation()
#init_debug_attack_loop()
#init_debug_event_loop()

View File

@@ -1,33 +1,33 @@
from entities import player as _player from entities import player as _player
from entities import event_picker as _events from entities import event_picker as _events
from entities import gamemap as _map from entities import gamemap as _map
from entities.items import weapons as _weapons from entities.items import item as _items
from utils import logs as _logs from utils import logs as _logs
class BrSimArena(): class BrSimArena():
# players = [{'name': name, 'inventory': default_inventory, other_stats}] # players = [{'name': name, 'inventory': default_inventory, other_stats}]
# weapons = [{WEAPON.KNIFE: quantity}, etc...] # this is the whole quantity of the items available on the world # items = [{WEAPON.KNIFE: quantity}, etc...] # this is the whole quantity of the items available on the world
def __init__(self, players= None, weapons= None): def __init__(self, players= None, items= None):
self.day= 1 self.day= 1
self.players= [] self.players= []
self.weapons= [] self.items= []
self.eventClass = _events.ArenaEventPicker(self.players) self.eventClass = _events.ArenaEventPicker(self.players)
self.init_players(players) self.init_players(players)
self.init_weapons(weapons) self.init_items(items)
self.Map= _map.BrSimMap(self.players, self.weapons) self.Map= _map.BrSimMap(self.players, self.items)
def init_players(self, players): def init_players(self, players):
if not players: return if not players: return
for player in players: for player in players:
self.add_player(player['name'], player.get('inventory')) self.add_player(player['name'], player.get('inventory'))
def init_weapons(self, weapons): def init_items(self, items):
if not weapons: return if not items: return
for weapon in weapons: for item in items:
for wtype, quantity in weapon.items(): for itype, quantity in item.items():
for i in range(quantity): self.weapons.append(_weapons.BrSimWeapon(wtype)) for i in range(quantity): self.items.append(_items.BrSimItem(wrype))
def next_day(self): def next_day(self):
self.day+= 1 self.day+= 1
@@ -103,7 +103,8 @@ class BrSimArena():
def do_random_event(self): def do_random_event(self):
#XXX random player does random action according to his inventory health, wounds, available weapons on the world, etc... #XXX random player does random action according to his inventory health, wounds, available weapons on the world, etc...
pass self.eventClass.resolve_event()
self.next_day()
def supporter_donation(self): def supporter_donation(self):
#XXX supporter donate a random item or weapon to a random player #XXX supporter donate a random item or weapon to a random player
@@ -115,19 +116,19 @@ class BrSimArena():
self.players.append(player) self.players.append(player)
self.Map.add_player_to_map(player) self.Map.add_player_to_map(player)
def add_weapon(self, weapon_type): def add_item(self, item_id):
weapon= _weapons.BrSimWeapon(weapon_type) Item= _items.BrSimItem(item_id)
self.weapons.append(weapon) self.items.append(Item)
self.Map.add_item_to_map(item) self.Map.add_item_to_map(Item)
def get_players(self): def get_players(self):
return self.players return self.players
def get_weapons(self): def get_items(self):
res= [] res= []
for w in self.weapons: for i in self.items:
#XXX implement me #XXX implement me
res.append(w) res.append(i)
return res return res
def get_map(self): def get_map(self):

View File

@@ -7,21 +7,21 @@ class ArenaEventPicker():
self.event_list = EVENTS self.event_list = EVENTS
self.already_picked_players = [] self.already_picked_players = []
def pick_a_player(): def pick_a_player(self):
the_player = _random.choice(self.players) the_player = _random.choice(self.players)
the_player_id = the_player.get('id') the_player_id = the_player.get_id()
self.players = list(filter(lambda x : x.get('id') != the_player_id)) self.players = list(filter(lambda x : x.get_id() != the_player_id, self.players))
self.already_picked_players.append(the_player) self.already_picked_players.append(the_player)
return the_player return the_player
def pick_event(the_player): def pick_event(self, the_player):
player_inventory = the_player.get('inventory') or [] player_inventory = the_player.get_inventory()
status = the_player['health'] status = the_player.get_health()
reputation = the_player['reputation'] reputation = the_player.get_reputation()
elegible_events = [] elegible_events = []
for event in EVENTS: for event in EVENTS:
@@ -56,17 +56,23 @@ class ArenaEventPicker():
if check == 'affected_players': if check == 'affected_players':
needed_players = event.get('affected_players') needed_players = event.get('affected_players')
if needed_players < len(self.players): #NOTE: this is only to compensate a double type of needed_players
elegible_events.append(event) # check NOTE on assets/events.py
if isinstance(needed_players, list):
if len(needed_players) < len(self.players):
elegible_events.append(event)
else:
if needed_players < len(self.players):
elegible_events.append(event)
the_event = _random.choice(elegible_events) the_event = _random.choice(elegible_events)
return the_event return the_event
def pick_targets(number_of_targets): def pick_targets(self, number_of_targets):
random.shuffle(self.players) _random.shuffle(self.players)
return list(self.players[0:number_of_targets]) return list(self.players[0:number_of_targets])
def resolve_event(): def resolve_event(self):
playing_player = self.pick_a_player() playing_player = self.pick_a_player()
assigned_event = self.pick_event(playing_player) assigned_event = self.pick_event(playing_player)
@@ -75,7 +81,6 @@ class ArenaEventPicker():
affected_players = _random.choice(affected_players) affected_players = _random.choice(affected_players)
targeted_players = self.pick_targets(affected_players) targeted_players = self.pick_targets(affected_players)
event_instance = _event.Event(assigned_event, playing_player)
# FIXME this is not implemented
#event_instance = _event.Event(assigned_event, playing_player)

View File

@@ -6,7 +6,6 @@ from PIL import ImageDraw as _ImageDraw
from utils import logs as _logs from utils import logs as _logs
from bot_libs import syms as _bot_syms from bot_libs import syms as _bot_syms
from entities import resource as _resource from entities import resource as _resource
from utils import logs as _logs
class BrSimMap(): class BrSimMap():
@@ -52,20 +51,18 @@ class BrSimMap():
#if i == 0 or i == self.world_height - 1: self.game_map.append(mon) #if i == 0 or i == self.world_height - 1: self.game_map.append(mon)
#else: self.game_map.append(_copy.deepcopy(width)) #else: self.game_map.append(_copy.deepcopy(width))
self.game_map.append(_copy.deepcopy(width)) self.game_map.append(_copy.deepcopy(width))
_logs.log_debug(f'init_map_matrix: {self.game_map}') #_logs.log_debug(f'init_map_matrix: {self.game_map}')
_logs.log_debug(f'players: %s'% [(p.get_name(), p.get_coordinates()) for p in self.players])
print('##')
_logs.log_debug(f'items: %s' % [(p.get_name(), p.get_coordinates()) for p in self.items])
def populate_map(self): def populate_map(self):
for player in self.players: for player in self.players:
p_coord_x, p_coord_y= player.get_coordinates() p_coord_x, p_coord_y= player.get_coordinates()
self.game_map[p_coord_y][p_coord_x]= player self.game_map[p_coord_y][p_coord_x]= player
#if not player.is_alive(): self.game_map[p_coord_y][p_coord_x]= self.dead_player_sym
#elif player.player_gender_is_male(): self.game_map[p_coord_y][p_coord_x]= self.player_male_sym
#elif player.player_gender_is_female(): self.game_map[p_coord_y][p_coord_x]= self.player_female_sym
#else: self.game_map[p_coord_y][p_coord_x]= self.player_nonbinary_sym
for item in self.items: for item in self.items:
i_coord_x, i_coord_y= item.get_coordinates() i_coord_x, i_coord_y= item.get_coordinates()
self.game_map[p_coord_y][p_coord_x]= item self.game_map[i_coord_y][i_coord_x]= item
#self.game_map[i_coord_y][i_coord_x]= self.item_sym
def _put_resource_on_map(self, target): def _put_resource_on_map(self, target):
#x= _random.randint(1, self.world_width -2) # from 1 to width-2 because 1 cell is occupied by the mountain #x= _random.randint(1, self.world_width -2) # from 1 to width-2 because 1 cell is occupied by the mountain

View File

@@ -1,27 +1,35 @@
import random as _random import random as _random
from entities import resource as _resource from entities import resource as _resource
from entities.items import syms as _isyms
class BrSimItem(_resource.BrSimResource): class BrSimItem(_resource.BrSimResource):
#XXX i don't know yet if we need to call this clas
# or we need to have subclasses that inherit this one
# for example class Weapon and class Medikit (or something else)
# this decision would change everything from Arena init
# test def __init__(self, item_id):
def __init__(self): self.item= _isyms.ITEMS[item_id]
self.coord_x= 0
self.coord_y= 0
def is_item(self): def is_item(self):
return True return True
def get_name(self): def get_data(self):
return self.name return self.item
def get_item_type(self): def get_name(self):
return self.item_type idata= self.get_data()
return idata['name']
def get_weight(self): def get_weight(self):
return self.weight idata= self.get_data()
return idata['weight']
def is_weapon(self): def is_weapon(self):
return False idata= self.get_data()
return idata['is_weapon']
def is_cure(self): def is_cure(self):
return False #XXX not sure about it
# maybe we could have more item type, like foods, drink, poison...
return not self.is_weapon()

View File

@@ -1,11 +1,23 @@
KNIFE= 1 MEDIKIT= 1
ARCH= 2 #FOOD= 2 #XXX not yet implemented, how to manage it?
#DRINK= 3 #XXX not yet implemented, how to manage it?
KNIFE= 4
ARCH= 5
SHORT_RANGE= 1 SHORT_RANGE= 1
FAR_RANGE= 2 FAR_RANGE= 2
WEAPONS= { ITEMS= {
MEDIKIT: {
'is_weapon': False,
'weight': 0.5,
'name': 'medikit',
'description': 'useful tool to restore health',
'health': 1,
},
KNIFE: { KNIFE: {
'is_weapon': True,
'weight': 1, 'weight': 1,
'name': 'knife', 'name': 'knife',
'damage': 3, 'damage': 3,
@@ -14,6 +26,7 @@ WEAPONS= {
'range': SHORT_RANGE, 'range': SHORT_RANGE,
}, },
ARCH: { ARCH: {
'is_weapon': True,
'weight': 2, 'weight': 2,
'name': 'gun', 'name': 'gun',
'damage': 3, 'damage': 3,
@@ -22,3 +35,5 @@ WEAPONS= {
'range': FAR_RANGE, 'range': FAR_RANGE,
}, },
} }
ITEMS_LIST= list(ITEMS.keys())

View File

@@ -5,7 +5,7 @@ from entities.items import weapon_syms as _syms
class BrSimWeapon(_item.BrSimItem): class BrSimWeapon(_item.BrSimItem):
def __init__(self, wtype= None): def __init__(self, wtype= None):
self.weapon= _syms.WEAPONS[wtype or _random.randint(1,2)] self.weapon= _syms.WEAPONS.get(wtype) or _syms.WEAPONS.get(_random.choice(list(_syms.WEAPONS.keys())))
self.name= self.weapon['name'] self.name= self.weapon['name']
self.damage= self.weapon['damage'] self.damage= self.weapon['damage']
self.weight= self.weapon['weight'] self.weight= self.weapon['weight']

View File

@@ -1,7 +1,7 @@
from entities import arena as _arena from entities import arena as _arena
def init_arena(players= None, weapons= None): def init_arena(players= None, items= None):
return _arena.BrSimArena(players, weapons) return _arena.BrSimArena(players, items)
def run_events(Arena): def run_events(Arena):
#A event for each player: #A event for each player: