1
0

Compare commits

..

15 Commits

Author SHA256 Message Date
frostbite
82be14e603 minor 2025-07-25 09:24:31 +02:00
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
frostbite
e038f711d5 Merge remote-tracking branch 'refs/remotes/origin/master' 2025-07-24 17:41:14 +02:00
frostbite
82141d89d6 escape of the combat 2025-07-24 17:39:49 +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
9 changed files with 207 additions and 55 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 asyncio
import datetime import datetime
from telegram import Update import pytz
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes from telegram.ext import Application, CommandHandler, MessageHandler, filters
import bot_syms as _botsyms import bot_syms as _botsyms
import main as _brsim import main as _brsim
async def loop_game(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def loop_game(context):
chat_id = update.effective_chat.id chat_id = context.job.chat_id
if 'arena' in context.application.bot_data: if 'arena' in context.application.bot_data:
print(f'{chat_id}: Guarino ha trovato l\'arena')
pass pass
else: else:
print('Arena non trovata') print('Arena non trovata')
await update.message.reply_text('Che e\' successo? un Guarino ha rubato l\'arena, avvia una nuova partita con /start') 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) await update.message.reply_text(_botsyms.START_MSG)
chat_id = update.effective_chat.id 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'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}') await update.message.reply_text(f'Queste le armi che avranno a disposizione nell\'arena:\n{weapons}')
context.application.bot_data['arena'] = Arena 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( context.job_queue.run_daily(
loop_game, 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, chat_id=chat_id,
name=str(chat_id) name=str(chat_id)
) )
print(f'Job giornaliero creato per la chat {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 testo_ricevuto = update.message.text
await update.message.reply_text(_botsyms.WIP_MSG) 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) name= " ".join(context.args)
print(f'sto aggiungendo il giocatore {name} all\'arena') print(f'sto aggiungendo il giocatore {name} all\'arena')
_brsim.BrSimArena _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, START_MSG= """Benvenuto nel crudele mondo di Battle Royal Simulator,
La tua avventura e quella dei tuoi compagni inizia qui. 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()

View File

@@ -1,6 +1,7 @@
from entities import player as _player from entities import player as _player
from entities import weapons as _weapons from entities import weapons as _weapons
from entities import weapon_syms as _wsyms from entities import weapon_syms as _wsyms
from entities import event_picker as _events
class BrSimArena(): class BrSimArena():
@@ -11,6 +12,7 @@ class BrSimArena():
self.day= 1 self.day= 1
self.players= [_player.BrSimPlayer(p['name'], p.get('inventory')) for p in players] self.players= [_player.BrSimPlayer(p['name'], p.get('inventory')) for p in players]
self.weapons= [] self.weapons= []
self.eventClass = _events.ArenaEventPicker(self.players)
for weapon in weapons: for weapon in weapons:
for wtype, quantity in weapon.items(): for wtype, quantity in weapon.items():
for i in range(quantity): self.weapons.append(_weapons.BrSimWeapon(wtype)) for i in range(quantity): self.weapons.append(_weapons.BrSimWeapon(wtype))
@@ -18,10 +20,12 @@ class BrSimArena():
def next_day(self): def next_day(self):
self.day+= 1 self.day+= 1
print(f'Giorno: {self.day}') print(f'Giorno: {self.day}')
print(f'Giocatori vivi: {self.get_alive_players()}') 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() death_players= self.get_death_players()
if (death_players): if (death_players):
print(f'Giocatori morti: {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): def get_alive_players(self):
res= [] res= []

13
entities/event_picker.py Normal file
View File

@@ -0,0 +1,13 @@
from assets.events import EVENTS
import random as _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,71 +1,133 @@
import random as _random import random as _random
import uuid as _uuid
class BrSimPlayer(): class BrSimPlayer():
def __init__(self, name, inventory= None): def __init__(self, name, inventory= None):
self.id= str(_uuid.uuid4())
self.name= name self.name= name
self.health= 1 self.health= 1
self.inventory= inventory or [] self.inventory= inventory or []
self.damage= 1 # this is the punch damage amount self.damage= 1 # this is the punch damage amount
self.max_weight= 5 # this is the max inventory weight self.max_weight= 5 # this is the max inventory weight
self.is_alive= True
self.agility= 10 # chance to avoid an hit 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): ### control methods
return self.is_alive
def attack(self, target): def get_id(self):
if not self.is_alive(): return return self.id
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 accuses_damage(self, damage): def get_name(self):
self.health -= damage return self.name
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 try_to_avoid_hit(self): def get_gender(self):
# maybe depend on the attack, if it is a gun shot it's quite impossible to dodge return self.gender
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 heal(self):
#XXX if you have a wound and you have a medikit item, you can heal your wound or sickness
pass
def get_inventory(self): def get_inventory(self):
return self.inventory return self.inventory
def get_name(self): def get_inventory_weight(self):
return self.name 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): def get_health(self):
return self.health return self.health
def get_damage(self): def get_damage(self):
return self.damage if not self.equipped_weapon: return self.damage
return self.equipped_weapon.damage
def get_agility(self): def get_agility(self):
return self.agility return self.agility
def get_data(self): def get_data(self):
return { return {
'id': self.get_id(),
'name': self.get_name(), 'name': self.get_name(),
'gender': self.get_gender(),
'inventory': self.get_inventory(), 'inventory': self.get_inventory(),
'inventory_weight': self.get_inventory_weight(),
'health': self.get_health(), 'health': self.get_health(),
'damage': self.get_damage(), 'damage': self.get_damage(),
'agility': self.get_agility(), '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

17
main.py
View File

@@ -1,23 +1,24 @@
import random as _random import random as _random
from entities import weapon_syms as _wsyms
from entities import arena as _arena from entities import arena as _arena
def init_arena(): def init_arena(players, weapons):
players= [{'name': 'Crystal'}, {'name': 'Andrea'}]
w= _wsyms.KNIFE
#weapons= [{_wsyms.WEAPONS[w]['name' ]: 1}]
weapons= [{w: 1}]
return _arena.BrSimArena(players, weapons) return _arena.BrSimArena(players, weapons)
def run_events(Arena): def run_events(Arena):
#A event for each player: #A event for each player:
pass pass
def local_debug(): 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'Players: {Arena.get_players()}')
print(f'Weapons: {Arena.get_weapons()}') print(f'Weapons: {Arena.get_weapons()}')
while (len(Arena.get_alive_players()) > 1) while (len(Arena.get_alive_players()) > 1):
#Start a day #Start a day
run_events(Arena) run_events(Arena)

View File

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