def unit_movement(battle: Battle): # first pass: desire positions / optimistic move for battle_unit_in_turn in BattleUnitInTurn.objects.filter( battle_turn=battle.get_latest_turn()): for battle_contubernium_in_turn in battle_unit_in_turn.battlecontuberniuminturn_set.all( ): target_distance_function = get_target_distance_function( battle_contubernium_in_turn) if target_distance_function: optimistic_move_desire_formulation(battle_contubernium_in_turn, target_distance_function) optimistic_move_desire_resolving(battle) # second pass: if could not move, do "safe" move for battle_unit_in_turn in BattleUnitInTurn.objects.filter( battle_turn=battle.get_latest_turn()): for battle_contubernium_in_turn in battle_unit_in_turn.battlecontuberniuminturn_set.filter( moved_this_turn=False): target_distance_function = get_target_distance_function( battle_contubernium_in_turn) if target_distance_function: safe_move(battle_contubernium_in_turn, target_distance_function) # finalize for battle_unit_in_turn in BattleUnitInTurn.objects.filter( battle_turn=battle.get_latest_turn()): battle_unit_in_turn.update_pos() check_if_order_done(battle_unit_in_turn)
def battle_tick(battle: Battle): create_next_turn(battle) unit_movement(battle) unit_attack(battle) if check_end(battle): battle.current = False battle.save()
def optimistic_move_desire_resolving(battle: Battle): while BattleContuberniumInTurn.objects.filter( desires_pos=True, battle_turn=battle.get_latest_turn()).exists(): bcuit = BattleContuberniumInTurn.objects.filter( desires_pos=True, battle_turn=battle.get_latest_turn())[0] contubernia_desiring_position = battle.get_latest_turn( ).get_contubernia_desiring_position(bcuit.desired_coordinates()) desired_position_occupier = battle.get_latest_turn( ).get_contubernium_in_position(bcuit.desired_coordinates()) if desired_position_occupier: # test if mutually desiring positions if desired_position_occupier.desires_pos: for desirer in contubernia_desiring_position: if desirer.coordinates( ) == desired_position_occupier.desired_coordinates(): grant_position_swap(desirer, desired_position_occupier) continue # TODO: try to move blocking contubernium before giving up contubernia_desiring_position.update(desires_pos=False) else: contubernia_desiring_position.update(desires_pos=False) else: desire_getter = get_highest_priority_desire( contubernia_desiring_position) grant_position_desire(desire_getter) contubernia_desiring_position.update(desires_pos=False)
def battle_result_log(self, battle_id, battle_result): start_date = datetime.date.today() home = self.home_squad.squad_name away = self.away_squad.squad_name winner = battle_result.get("winner") home_casualties = json.dumps(battle_result.get("home_casualties")) away_casualties = json.dumps(battle_result.get("away_casualties")) Battle.add_data(battle_id, start_date, home, away, winner, home_casualties, away_casualties)
def battle_turn(battle: Battle): for i in range(BATTlE_TICKS_PER_TURN): battle.refresh_from_db() if battle.current: battle_tick(battle) battle.tile.world.broadcast('messaging/messages/battle_progress.html', 'Battle in {}'.format(battle.tile.name), {'battle': battle}, battle.get_absolute_url())
def battle_tick(battle: Battle): with perf_timer("Tick {} for {}".format(battle.get_latest_turn().num, battle)): create_next_turn(battle) unit_movement(battle) unit_attack(battle) if check_end(battle): battle.current = False battle.save()
def battle_turn(battle: Battle): for i in range(15): battle.refresh_from_db() if battle.current: battle_tick(battle) battle.tile.world.broadcast( ("The battle in {} continues".format(battle.tile) if battle.current else "The battle in {} has ended".format(battle.tile)), 'battle', battle.get_absolute_url())
def start_battle(battle: Battle): if battle.started: raise BattleAlreadyStartedException( "Battle {} already started!".format(battle.id)) for unit in battle.get_units_in_battle().all(): create_contubernia(unit) initialize_battle_positioning(battle) generate_in_turn_objects(battle) battle.started = True battle.save()
def test_save(self): # SETUP attacker = Player.objects.get(id = 1) defender = Player.objects.get(id = 2) battle = Battle( attacker = attacker, defender = defender, winner = defender, start = timezone.now(), end = timezone.now() ) # CALL battle.save() # ASSERT self.assertEqual(5, battle.id)
def unit_attack(battle: Battle): contubernia = list( BattleContuberniumInTurn.objects.filter( battle_turn=battle.get_latest_turn())) random.shuffle(contubernia) for contubernium in contubernia: world_unit = contubernium.battle_unit_in_turn.battle_unit.world_unit enemy_contubernia = BattleContuberniumInTurn.objects.filter( battle_turn=contubernium.battle_turn).exclude( battle_contubernium__battle_unit__battle_side=contubernium. battle_contubernium.battle_unit.battle_side) target_contubernium, distance = \ closest_in_set(contubernium.coordinates(), enemy_contubernia) if target_contubernium is None: continue if distance < 2: unit_attack_melee(contubernium, target_contubernium) contubernium.attack_type_this_turn = \ BattleContuberniumInTurn.MELEE_ATTACK contubernium.contubernium_attacked_this_turn = \ target_contubernium contubernium.save() elif (world_unit.is_ranged() and distance <= world_unit.shot_range() and contubernium.ammo_remaining > 0 and not contubernium.moved_this_turn): unit_attack_ranged(contubernium, target_contubernium) contubernium.attack_type_this_turn = \ BattleContuberniumInTurn.RANGED_ATTACK contubernium.contubernium_attacked_this_turn = \ target_contubernium contubernium.save()
def create_battles_for_judge(judge): from itertools import combinations existing_battles_matrix = {} existing_battles = Battle.objects.filter(judge=judge, pick_date__isnull=True) for battle in existing_battles: if battle.left.user_id > battle.right.user_id: existing_battles_matrix[battle.right.user_id] = battle.left.user_id else: existing_battles_matrix[battle.left.user_id] = battle.right.user_id preference_matches = PreferenceMatch.active.filter(profile=judge) target_profiles = [match.target for match in preference_matches] possible_battle_pairs = combinations(target_profiles, 2) new_battles = [] for pair in possible_battle_pairs: if pair[0].user_id > pair[1].user_id: has_existing_battle = existing_battles_matrix.get( pair[1].user_id, None) else: has_existing_battle = existing_battles_matrix.get( pair[0].user_id, None) if not has_existing_battle: new_battles.append(Battle(judge=judge, left=pair[1], right=pair[0])) created_battles = Battle.objects.bulk_create(new_battles) print "created %d battles" % len(created_battles) return created_battles
def check_end(battle: Battle): for side in battle.battleside_set.all(): if not BattleSoldierInTurn.objects.filter( battle_turn=battle.get_latest_turn(), battle_contubernium_in_turn__battle_contubernium__battle_unit__battle_side =side, wound_status__lt=BattleSoldierInTurn.DEAD).exists(): return True side_0_contubs = BattleContuberniumInTurn.objects.filter( battle_turn=battle.get_latest_turn(), battle_contubernium__battle_unit__battle_side__z=False) side_1_contubs = BattleContuberniumInTurn.objects.filter( battle_turn=battle.get_latest_turn(), battle_contubernium__battle_unit__battle_side__z=False) for contub in side_0_contubs: closest, distance = closest_in_set(contub.coordinates(), side_1_contubs) if distance is not None and distance < 40: return False return True
def start_or_resume(self, opp, rounds=settings.BATTLE_ROUNDS): self.battle = BattleModel.objects.get_by_user(user=self.engine.user.user, rounds=rounds) if self.battle is not None: return self.battle self.cards_per_battle = int(rounds) if self.engine.user.profile.energy < settings.ENERGY["new_battle"]: return ( "Not enough energy. Wait until you have at least %d energy points or <span style='font-size: 13px'><a href='%s'>fill it</a> right away</span>" % (settings.ENERGY["new_battle"], reverse("store")) ) battle = BattleModel() battle.rounds = self.cards_per_battle if int(rounds) == 1: battle.new_session( self.engine.user.user, opp, [random.choice(self.get_player()["drawed"])], [random.choice(self.get_player(opp)["drawed"])], ) elif int(rounds) == 3: battle.new_session(self.engine.user.user, opp, self.get_player()["drawed"], self.get_player(opp)["drawed"]) else: logging.critical("Unknown rounds no. %d" % int(rounds)) self.engine.user.profile.energy -= settings.ENERGY["new_battle"] self.engine.user.profile.save() self.battle = battle return battle
def start_or_resume(self, opp, rounds=settings.BATTLE_ROUNDS): self.battle = BattleModel.objects.get_by_user( user=self.engine.user.user, rounds=rounds) if self.battle is not None: return self.battle self.cards_per_battle = int(rounds) if self.engine.user.profile.energy < settings.ENERGY['new_battle']: return "Not enough energy. Wait until you have at least %d energy points or <span style='font-size: 13px'><a href='%s'>fill it</a> right away</span>" % ( settings.ENERGY['new_battle'], reverse('store')) battle = BattleModel() battle.rounds = self.cards_per_battle if int(rounds) == 1: battle.new_session(self.engine.user.user, opp, [random.choice(self.get_player()['drawed'])], [random.choice(self.get_player(opp)['drawed'])]) elif int(rounds) == 3: battle.new_session(self.engine.user.user, opp, self.get_player()['drawed'], self.get_player(opp)['drawed']) else: logging.critical("Unknown rounds no. %d" % int(rounds)) self.engine.user.profile.energy -= settings.ENERGY['new_battle'] self.engine.user.profile.save() self.battle = battle return battle
def unit_attack(battle: Battle): contubernia = list( BattleContuberniumInTurn.objects.filter( battle_turn=battle.get_latest_turn())) random.shuffle(contubernia) for contubernium in contubernia: enemy_contubernia = BattleContuberniumInTurn.objects.filter( battle_turn=contubernium.battle_turn).exclude( battle_contubernium__battle_unit__battle_side=contubernium. battle_contubernium.battle_unit.battle_side) target_contubernium, distance = \ closest_in_set(contubernium.coordinates(), enemy_contubernia) if target_contubernium is not None and distance < 2: for soldier in contubernium.battlesoldierinturn_set.all(): target_soldier = random.choice( target_contubernium.battlesoldierinturn_set.all()[:]) while (random.random() < 0.5 * soldier.attack_chance_multiplier()): if target_soldier.wound_status < BattleSoldierInTurn.DEAD: target_soldier.take_hit() target_soldier.save()
def war_request(request): if request.method == 'POST': up = UserProfile.objects.get(user=request.user) try: battle = Battle.objects.get(Q(attacker=up) | Q(defender=up), active=True) return HttpResponse( simplejson.dumps({'error': 'You are in battle'})) except Exception: try: territory = Territory.objects.get(pk=request.POST.get('id')) defender = UserProfile.objects.get( user__username=request.POST.get('username')) Battle(attacker=up, defender=defender, territory=territory).save() return HttpResponse(simplejson.dumps({'nice': 'Nice'})) except Territory.DoesNotExist: return HttpResponse( simplejson.dumps({'error': "Territory doesn't exists!"})) else: return HttpResponse('Not here')
def create_next_turn(battle: Battle): new_turn = battle.get_latest_turn() new_turn.id = None new_turn.num += 1 new_turn.save() prev_turn = battle.battleturn_set.get(num=new_turn.num - 1) for side in battle.battleside_set.all(): for organization in side.battleorganization_set.all(): for character in organization.battlecharacter_set.all(): bcit = BattleCharacterInTurn.objects.get( battle_character=character, battle_turn=prev_turn) bcit.id = None bcit.battle_turn = new_turn bcit.save() for unit in organization.battleunit_set.all(): try: buit = BattleUnitInTurn.objects.get(battle_unit=unit, battle_turn=prev_turn) if not buit.battlecontuberniuminturn_set.filter( x_pos__gte=-50, x_pos__lte=50, z_pos__gte=-50, z_pos__lte=50, ).exists(): buit.battle_unit.in_battle = False buit.battle_unit.save() buit.battle_unit.world_unit.status = \ WorldUnit.REGROUPING buit.battle_unit.world_unit.save() continue if not BattleSoldierInTurn.objects.filter( battle_contubernium_in_turn__battle_unit_in_turn= buit, wound_status__lt=BattleSoldierInTurn.DEAD).exists( ): buit.battle_unit.in_battle = False buit.battle_unit.save() buit.battle_unit.world_unit.status = \ WorldUnit.REGROUPING buit.battle_unit.world_unit.save() continue buit.id = None buit.battle_turn = new_turn buit.battle_character_in_turn = BattleCharacterInTurn.objects.get( battle_turn=new_turn, battle_character=buit.battle_character_in_turn. battle_character ) if buit.battle_character_in_turn is not None else None buit.order = buit.battle_unit.get_order() buit.save() except BattleUnitInTurn.DoesNotExist: continue for contubernium in unit.battlecontubernium_set.all(): try: bcontubit = BattleContuberniumInTurn.objects.get( battle_contubernium=contubernium, battle_turn=prev_turn) if not bcontubit.battlesoldierinturn_set.filter( wound_status__lt=BattleSoldierInTurn.DEAD ).exists(): continue if (not -50 <= bcontubit.x_pos <= 50 or not -50 <= bcontubit.z_pos <= 50): continue bcontubit.id = None bcontubit.moved_this_turn = False bcontubit.desires_pos = False bcontubit.battle_turn = new_turn bcontubit.battle_unit_in_turn = buit bcontubit.save() except BattleContuberniumInTurn.DoesNotExist: pass for soldier in contubernium.battlesoldier_set.all(): try: bsit = BattleSoldierInTurn.objects.get( battle_turn=prev_turn, battle_soldier=soldier) if bsit.wound_status == BattleSoldierInTurn.DEAD: continue bsit.id = None bsit.battle_turn = new_turn bsit.battle_contubernium_in_turn = bcontubit bsit.save() except BattleSoldierInTurn.DoesNotExist: pass
class TestRound(TestCase): def test_fight(self): self.do_setup(red_attack=3, red_speed=10, blue_attack=3, blue_speed=7) round1 = Round(battle=self.battle, red=self.red, blue=self.blue) round1.save() red_team = PlayerPokemon.objects.filter(player=round1.red) blue_team = PlayerPokemon.objects.filter(player=round1.blue) current_red_pokemon = None current_blue_pokemon = None for red_pokemon, blue_pokemon in izip(red_team, blue_team): if red_pokemon.lead: current_red_pokemon = red_pokemon if blue_pokemon.lead: current_blue_pokemon = blue_pokemon if current_red_pokemon and current_blue_pokemon: break self.assertEqual(self.battle.winner, None) self.assertEqual(current_red_pokemon.hp, 18) self.assertEqual(current_blue_pokemon.hp, 19) round1.red_selected_move = current_red_pokemon.move1 round1.blue_selected_move = current_blue_pokemon.move1 round1.save() round2 = round1.advance_round() round2.save() """ red_team = PlayerPokemon.objects.filter(player=round1.red) blue_team = PlayerPokemon.objects.filter(player=round1.blue) for red_pokemon, blue_pokemon in izip(red_team, blue_team): if red_pokemon.lead: current_red_pokemon = red_pokemon if blue_pokemon.lead: current_blue_pokemon = blue_pokemon self.assertEqual(self.battle.winner, None) self.assertLess(current_red_pokemon.hp, 18) self.assertLess(current_blue_pokemon.hp, 18) round3 = round2.advance_round() round3.save() red_team = PlayerPokemon.objects.filter(player=round1.red) blue_team = PlayerPokemon.objects.filter(player=round1.blue) for red_pokemon, blue_pokemon in izip(red_team, blue_team): if red_pokemon.lead: current_red_pokemon = red_pokemon if blue_pokemon.lead: current_blue_pokemon = blue_pokemon self.assertEqual(self.battle.winner, None) self.assertEqual(current_red_pokemon.hp, 4) self.assertEqual(current_blue_pokemon.hp, 4) round4 = round3.advance_round() round4.save() red_team = PlayerPokemon.objects.filter(player=round4.red) blue_team = PlayerPokemon.objects.filter(player=round4.blue) for red_pokemon, blue_pokemon in izip(red_team, blue_team): if red_pokemon.lead: current_red_pokemon = red_pokemon if blue_pokemon.lead: current_blue_pokemon = blue_pokemon self.assertEqual(self.battle.winner, None) self.assertEqual(current_red_pokemon.hp, 1) self.assertEqual(current_blue_pokemon.hp, 1) round5 = round4.advance_round() red_team = PlayerPokemon.objects.filter(player=round4.red) blue_team = PlayerPokemon.objects.filter(player=round4.blue) for red_pokemon, blue_pokemon in izip(red_team, blue_team): if red_pokemon.lead: current_red_pokemon = red_pokemon if blue_pokemon.lead: current_blue_pokemon = blue_pokemon self.assertEqual(self.battle.winner, self.red) self.assertEqual(current_red_pokemon.hp, 1) self.assertEqual(current_blue_pokemon.hp, 0) """ def do_setup(self, red_attack, red_speed, blue_attack, blue_speed): self.create_players() self.create_pokemon(blue_attack, blue_speed, red_attack, red_speed) self.battle = Battle(red=self.red, blue=self.blue) self.battle.save() def create_players(self): self.red = Player(username='******') self.red.save() self.blue = Player(username='******') self.blue.save() def create_pokemon(self, blue_attack, blue_speed, red_attack, red_speed): self.move_type = Type(name=Type.NORMAL) self.move_type.save() self.red_type = Type(name=Type.FIRE) self.red_type.save() self.blue_type = Type(name=Type.WATER) self.blue_type.save() self.move = Move(name='Tackle', type=self.move_type, base_power=50) self.move.save() self.red_pokemon = Pokemon(type1=self.red_type) self.red_pokemon.save() self.blue_pokemon = Pokemon(name='Squirtle', type1=self.blue_type, base_hp=44, base_attack=48, base_defence=65, base_special=50, base_speed=43) self.blue_pokemon.save() self.red_playerpokemon = PlayerPokemon(pokemon=self.red_pokemon, player=self.red, lead=True, move1=self.move) self.red_playerpokemon.save() self.blue_playerpokemon = PlayerPokemon(pokemon=self.blue_pokemon, player=self.blue, lead=True, move1=self.move) self.blue_playerpokemon.save()
def init_battle_log(self, start_date, home, away): return Battle.init(start_date, home, away)
def do_setup(self, red_attack, red_speed, blue_attack, blue_speed): self.create_players() self.create_pokemon(blue_attack, blue_speed, red_attack, red_speed) self.battle = Battle(red=self.red, blue=self.blue) self.battle.save()
def get(self, request): battle = Battle.battle() return render(request, 'home.html', battle)