File: _ratings.py

package info (click to toggle)
freeorion 0.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 194,940 kB
  • sloc: cpp: 186,508; python: 40,969; ansic: 1,164; xml: 719; makefile: 32; sh: 7
file content (104 lines) | stat: -rw-r--r-- 3,570 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
from collections import Counter
from typing import Optional

from CombatRatingsAI._fleet_combat_stats import get_fleet_combat_stats
from CombatRatingsAI._ship_combat_stats import AttackCount, AttackDamage, ShipCombatStats, get_ship_combat_stats
from common.fo_typing import FleetId, ShipId, SpeciesName
from EnumsAI import MissionType
from freeorion_tools import get_species_ship_shields
from freeorion_tools.caching import cache_for_current_turn


@cache_for_current_turn
def get_empire_standard_military_ship_stats() -> ShipCombatStats:
    """Get the current empire standard military ship stats, i.e. the most common ship type within the empire.

    :return: Stats of most common military ship in the empire
    """

    # avoid circular imports
    from FleetUtilsAI import get_empire_fleet_ids_by_role

    stats_dict = Counter()
    for fleet_id in get_empire_fleet_ids_by_role(MissionType.MILITARY):
        ship_stats = get_fleet_combat_stats(fleet_id, max_stats=True).get_ship_combat_stats()
        stats_dict.update(ship_stats)

    most_commons = stats_dict.most_common(1)
    if most_commons:
        return most_commons[0][0]
    else:
        return default_ship_stats()


def default_ship_stats() -> ShipCombatStats:
    """Return some ship stats to assume if no other intel is available.

    :return: Some weak standard ship
    """
    return ShipCombatStats(
        attacks={AttackDamage(6.0): AttackCount(1)},
        structure=15,
        shields=0,
        fighter_capacity=0,
        fighter_launch_rate=0,
        fighter_damage=0,
        flak_shots=0,
        has_interceptors=False,
        damage_vs_planets=0,
        has_bomber=False,
    )


def species_shield_bonus(species: Optional[SpeciesName], shield_type: Optional[str]) -> float:
    skill = get_species_ship_shields(species)
    shield_class = {
        "SH_DEFENSE_GRID": 1,
        "SH_DEFLECTOR": 2,
        "SH_PLASMA": 3,
        "SH_MULTISPEC": 4,
        "SH_BLACK": 5,
    }
    # Ships without or with robotic shield get no bonus, see shields.macro
    return skill * shield_class.get(shield_type, 0)


def rating_needed(target: float, current: float = 0) -> float:
    """Estimate the needed rating to achieve target rating.

    :param target: Target rating to be reached
    :param current: Already existing rating
    :return: Estimated missing rating to reach target
    """
    if current >= target or target <= 0:
        return 0
    else:
        return target + current - 2 * (target * current) ** 0.5


def rating_difference(first_rating: float, second_rating: float) -> float:
    """Return the absolute nonlinear difference between ratings.

    :param first_rating: rating of a first force
    :param second_rating: rating of a second force
    :return: Estimated rating by which the greater force (nonlinearly) exceeds the lesser
    """

    return rating_needed(max(first_rating, second_rating), min(first_rating, second_rating))


def get_fleet_rating(fleet_id: FleetId, enemy_stats: ShipCombatStats = None) -> float:
    """Get rating for the fleet against specified enemy.

    :param fleet_id: fleet to be rated
    :param enemy_stats: enemy to be rated against
    """
    return get_fleet_combat_stats(fleet_id, max_stats=False).get_rating(enemy_stats)


def get_fleet_rating_against_planets(fleet_id: FleetId):
    return get_fleet_combat_stats(fleet_id, max_stats=False).get_rating_vs_planets()


def get_ship_rating(ship_id: ShipId, enemy_stats=None):
    return get_ship_combat_stats(ship_id=ship_id, max_stats=False).get_rating(enemy_stats)