1
0

Compare commits

..

13 Commits

Author SHA256 Message Date
Crystal
b12db42c0b more players 2025-07-24 23:07:33 +02:00
5986e0f880 initial event picker idea 2025-07-24 23:00:34 +02:00
Crystal
0bb2c840f9 lgbtq+ texts 2025-07-24 22:58:46 +02:00
526668ed5d initial event picker idea 2025-07-24 22:57:28 +02:00
Crystal
1c284bad97 basic player entity and debug module to quickly test player attack 2025-07-24 22:36:36 +02:00
Crystal
761cf794b4 fix requirements for job-queue 2025-07-24 21:36:34 +02:00
andrea
f193464006 bot reframe, based on local_settings TOKEN, and periodic run 2025-07-24 21:28:42 +02:00
andrea
c5a6f4ea36 syntax bugfix 2025-07-24 21:27:36 +02:00
andrea
5a672b336f requirements 2025-07-24 19:18:43 +02:00
andrea
05d1718775 is_alive() is now based on player's health instead of a dedicated state 2025-07-24 19:16:30 +02:00
e66a6fbd9c Merge pull request 'master' (#3) from frostbite/battle_royale_sim:master into master
Reviewed-on: Cryz/battle_royale_sim#3
2025-07-24 19:11:17 +02:00
0098861e54 Merge pull request 'arena as class' (#2) from green/battle_royale_sim:master into master
Reviewed-on: Cryz/battle_royale_sim#2
2025-07-24 16:38:56 +02:00
db86f3dd06 arena as class 2025-07-24 16:08:06 +02:00
9 changed files with 278 additions and 122 deletions

14
assets/events.py Normal file
View File

@@ -0,0 +1,14 @@
EVENTS = [
{
'id' : 'ATTACK',
'text' : '{Player1} ha attacato {player2}',
'resolve_text' : '{Player1} ha causato {effetto_collaterale}',
'fail_text' : '{Player1} ha fallito, {player2} è indenne',
'success_percentage' : 80,
'fail_percentage' : 19,
'extreme_fail_percentage' : 1,
'required_items' : [],
'weight' : 1,
'number_of_players' : 2,
},
]

21
bot.py
View File

@@ -1,19 +1,20 @@
import asyncio
import datetime
from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes
import pytz
from telegram.ext import Application, CommandHandler, MessageHandler, filters
import bot_syms as _botsyms
import main as _brsim
async def loop_game(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
chat_id = update.effective_chat.id
async def loop_game(context):
chat_id = context.job.chat_id
if 'arena' in context.application.bot_data:
print(f'{chat_id}: Guarino ha trovato l\'arena')
pass
else:
print('Arena non trovata')
await update.message.reply_text('Che e\' successo? un Guarino ha rubato l\'arena, avvia una nuova partita con /start')
async def bot_start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
async def bot_start(update, context):
await update.message.reply_text(_botsyms.START_MSG)
chat_id = update.effective_chat.id
@@ -28,20 +29,22 @@ async def bot_start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text(f'Ecco la lista degli sfortunati avventurieri:\n{players}')
await update.message.reply_text(f'Queste le armi che avranno a disposizione nell\'arena:\n{weapons}')
context.application.bot_data['arena'] = Arena
#context.job_queue.run_repeating(loop_game, interval=10, first=0, chat_id= chat_id)
timezone = pytz.timezone('Europe/Rome')
context.job_queue.run_daily(
loop_game,
time=datetime.time(hour=0, minute=0, second=5, tzinfo=datetime.timezone.utc),
time=datetime.time(hour=13, minute=0, second=0, tzinfo= timezone),
chat_id=chat_id,
name=str(chat_id)
)
print(f'Job giornaliero creato per la chat {chat_id}')
async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
async def echo(update, context):
testo_ricevuto = update.message.text
await update.message.reply_text(_botsyms.WIP_MSG)
async def add_player(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
async def add_player(update, context):
name= " ".join(context.args)
print(f'sto aggiungendo il giocatore {name} all\'arena')
_brsim.BrSimArena

View File

@@ -1,4 +1,6 @@
TOKEN = "7670066927:AAG8jI5n9NcyxPksYky7LPYqA08BThs07c4"
from local_settings import TOKEN as _token
TOKEN= _token
START_MSG= """Benvenuto nel crudele mondo di Battle Royal Simulator,
La tua avventura e quella dei tuoi compagni inizia qui.

51
debug.py Normal file
View File

@@ -0,0 +1,51 @@
import time as _time
import random as _rand
import main as _main
from entities import weapon_syms as _wsyms
def init_debug():
players= [
{
'name': 'Elara',
},
{
'name': 'Kaelen',
},
{
'name': 'Zephyr',
},
{
'name': 'Lyra',
},
{
'name': 'Orion',
},
{
'name': 'Seraphina',
},
]
#w= _wsyms.KNIFE
##weapons= [{_wsyms.WEAPONS[w]['name' ]: 1}]
#weapons= [{w: 1}]
weapons= []
Arena= _main.init_arena(players, weapons)
print(f'Players: {Arena.get_players()}')
print(f'Weapons: {Arena.get_weapons()}')
while (len(Arena.get_alive_players()) > 1):
alive_players= Arena.get_alive_players()
p_one, p_two= _rand.sample(alive_players, 2)
p_one.attack(p_two)
#Start a day
#At 23:59:
Arena.next_day()
_time.sleep(0.3)
#End of day
last_player= Arena.get_alive_players()[0]
print(f'{last_player.get_name()} sopravvive e vince dopo {Arena.day} lunghi Giorni, conquistando l\'amore eterno di Guarino')
if __name__ == '__main__':
init_debug()

68
entities/arena.py Normal file
View File

@@ -0,0 +1,68 @@
from entities import player as _player
from entities import weapons as _weapons
from entities import weapon_syms as _wsyms
from entities import event_picker as _events
class BrSimArena():
# 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
def __init__(self, players, weapons):
self.day= 1
self.players= [_player.BrSimPlayer(p['name'], p.get('inventory')) for p in players]
self.weapons= []
self.eventClass = _events.ArenaEventPicker(self.players)
for weapon in weapons:
for wtype, quantity in weapon.items():
for i in range(quantity): self.weapons.append(_weapons.BrSimWeapon(wtype))
def next_day(self):
self.day+= 1
print(f'Giorno: {self.day}')
alive_players_str= ', '.join([p.get_name() for p in self.get_alive_players()])
print(f'Giocatori vivi: {alive_players_str}')
death_players= self.get_death_players()
if (death_players):
death_players_str= ', '.join([p.get_name() for p in death_players])
print(f'Giocatori morti: {death_players_str}')
def get_alive_players(self):
res= []
for p in self.players:
if not p.is_alive(): continue
res.append(p)
return res
def get_death_players(self):
res= []
for p in self.players:
if p.is_alive(): continue
res.append(p)
return res
def do_random_event(self):
#XXX random player does random action according to his inventory health, wounds, available weapons on the world, etc...
pass
def supporter_donation(self):
#XXX supporter donate a random item or weapon to a random player
#TODO maybe in future a player can have charism stats that can influence the chance to get a donation
pass
def add_player(self, name, inventory= None):
player= _player.BrSimPlayer(name, inventory)
self.players.append(player)
def get_players(self):
res= []
for p in self.players:
res.append(p.get_data())
return res
def get_weapons(self):
res= []
for w in self.weapons:
#XXX implement me
res.append(w)
return res

13
entities/event_picker.py Normal file
View File

@@ -0,0 +1,13 @@
from assets.events import EVENTS
import random
class ArenaEventPicker():
def __init__(self, players):
self.players = players
self.event_list = EVENTS
self.already_picked_players = []
def pick_event():
pass

View File

@@ -1,75 +1,133 @@
import random as _random
import uuid as _uuid
class BrSimPlayer():
def __init__(self, name, inventory= None):
self.id= str(_uuid.uuid4())
self.name= name
self.health= 1
self.inventory= inventory or []
self.damage= 1 # this is the punch damage amount
self.max_weight= 5 # this is the max inventory weight
self.is_alive= True
self.agility= 10 # chance to avoid an hit
self.kills= 0 # track the number of kills
self.survived_days= 0 # track the number of the survived days
self.equipped_weapon= None
self.gender= _random.sample(['m', 'f', '-'], 1)[0] # for now get a random gender
def is_alive(self):
return self.is_alive
### control methods
def attack(self, target):
if not self.is_alive(): return
if not target.is_alive(): return
if target.try_to_avoid_hit(): return # print something like 'enemy doges the attacl'
target.accuses_damage(self.damage)
def get_id(self):
return self.id
def accuses_damage(self, damage):
self.health -= damage
if self.health <= 0:
self.health = 0
self.is_alive = False
# show something like 'player is dead'
else:
# show something like 'get hit'
pass
def get_name(self):
return self.name
def try_to_avoid_hit(self):
# maybe depend on the attack, if it is a gun shot it's quite impossible to dodge
rnd= _random.randint(0, 100)
# if rnd > self.agility: return True ## XXX this is strange, if the agility is high the chances to dodge are lower
if rnd < self.agility: return True
return False
def steal(self):
#XXX can steal from death players or from sleeping players
pass
def escape(self):
#XXX It can run away from the fighting
pass
def heal(self):
#XXX if you have a wound and you have a medikit item, you can heal your wound or sickness
pass
def get_gender(self):
return self.gender
def get_inventory(self):
return self.inventory
def get_name(self):
return self.name
def get_inventory_weight(self):
weight= 0
for inv in self.get_inventory():
weight+= inv.get_weight()
return weight
def get_max_weight(self):
return self.max_weight
def get_health(self):
return self.health
def get_damage(self):
return self.damage
if not self.equipped_weapon: return self.damage
return self.equipped_weapon.damage
def get_agility(self):
return self.agility
def get_data(self):
return {
'id': self.get_id(),
'name': self.get_name(),
'gender': self.get_gender(),
'inventory': self.get_inventory(),
'inventory_weight': self.get_inventory_weight(),
'health': self.get_health(),
'damage': self.get_damage(),
'agility': self.get_agility(),
}
def is_alive(self):
return self.health > 0
### player actions
def _equip_weapon(self):
if not self.inventory: return
available_weapons= []
for inv in self.get_inventory():
# XXX
# i don't know yet if this is ok,
# we'll see it when weapon and items are defined
if not inv.damage: continue
available_weapons.append(inv)
self.equipped_weapon= random.sample(available_weapons, 1)[0]
def dodge(self):
# maybe depend on the attack, if it is a gun shot it's quite impossible to dodge
rnd= _random.randint(0, 100)
if rnd < self.agility: return True
return False
def accuses_damage(self, damage):
self.health -= damage
if self.health > 0: return self.get_health()
self.health = 0
if self.get_gender() == 'm':
print(f'[{self.get_name()}]: Guarino, perdonami se sono morto x.x')
elif self.get_gender() == 'f':
print(f'[{self.get_name()}]: Guarino, perdonami se sono morta x.x')
else:
print(f'[{self.get_name()}]: Guarino, perdonami se sono mort* x.x')
return damage
def attack(self, target):
self._equip_weapon()
if target.dodge():
if target.get_gender() == 'm':
print(f'Ehhhh voleviiii!!! sei lentoo! {target.get_name()} schiva il colpo di {self.get_name()}')
elif target.get_gender() == 'f':
print(f'Ehhhh voleviiii!!! sei lentaa! {target.get_name()} schiva il colpo di {self.get_name()}')
else:
print(f'Ehhhh voleviiii!!! sei lent##! {target.get_name()} schiva il colpo di {self.get_name()}')
return 0
target.accuses_damage(self.damage)
print(f'{self.get_name()} Colpisce {target.get_name()} in nome di Guarino')
return self.damage
def get_item(self, item):
if self.get_inventory_weight() + item.get_weight() >= self.get_max_weight():
if self.get_gender() == 'm':
print(f'Sono sovraccarico, {self.get_name} non puo\' prendere questo oggetto')
elif self.get_gender() == 'f':
print(f'Sono sovraccarica, {self.get_name} non puo\' prendere questo oggetto')
else:
print(f'Sono sovraccaric#, {self.get_name} non puo\' prendere questo oggetto')
return False
self.inventory.append(item)
def escape(self):
# TODO It can run away from the fighting
return
def heal(self):
# TODO heal system
# if you have a wound and you have a medikit item,
# you can heal your wound or sickness
return

91
main.py
View File

@@ -1,82 +1,27 @@
from entities import player as _player
from entities import weapons as _weapons
import random as _random
from entities import weapon_syms as _wsyms
from entities import arena as _arena
class BrSimArena():
def init_arena(players, weapons):
return _arena.BrSimArena(players, weapons)
# 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
def __init__(self, players, weapons):
self.day= 1
self.players= [_player.BrSimPlayer(p['name'], p.get('inventory')) for p in players]
self.weapons= []
for weapon in weapons:
for wtype, quantity in weapon.items():
for i in range(quantity): self.weapons.append(_weapons.BrSimWeapon(wtype))
def next_day(self):
self.day+= 1
print(f'Giorno: {self.day}')
print(f'Giocatori vivi: {self.get_alive_players()}')
death_players= self.get_death_players()
if (death_players):
print(f'Giocatori morti: {death_players}')
def get_alive_players(self):
res= []
for p in self.players:
if not p.is_alive(): continue
res.append(p)
return res
def get_death_players(self):
res= []
for p in self.players:
if p.is_alive(): continue
res.append(p)
return res
def do_random_event(self):
#XXX random player does random action according to his inventory health, wounds, available weapons on the world, etc...
pass
def supporter_donation(self):
#XXX supporter donate a random item or weapon to a random player
#TODO maybe in future a player can have charism stats that can influence the chance to get a donation
pass
def add_player(self, name, inventory= None):
player= _player.BrSimPlayer(name, inventory)
self.players.append(player)
def get_players(self):
res= []
for p in self.players:
res.append(p.get_data())
return res
def get_weapons(self):
res= []
for w in self.weapons:
#XXX implement me
res.append(w)
return res
def init_arena():
players= [{'name': 'Crystal'}, {'name': 'Andrea'}]
w= _wsyms.KNIFE
#weapons= [{_wsyms.WEAPONS[w]['name' ]: 1}]
weapons= [{w: 1}]
return BrSimArena(players, weapons)
def run_event(Arena):
def run_events(Arena):
#A event for each player:
pass
def local_debug():
Arena= init_arena()
players= [{'name': 'Crystal'}, {'name': 'Andrea'}, {'name' : 'giampi'}]
w= _wsyms.KNIFE
#weapons= [{_wsyms.WEAPONS[w]['name' ]: 1}]
weapons= [{w: 1}]
Arena= init_arena(players, weapons)
print(f'Players: {Arena.get_players()}')
print(f'Weapons: {Arena.get_weapons()}')
run_event(Arena)
while (len(Arena.get_alive_players()) > 1):
#Start a day
run_events(Arena)
#At 23:59:
Arena.next_day()
#End of day

View File

@@ -0,0 +1,2 @@
python-telegram-bot[job-queue]==22.3
pytz==2025.2