def create_character_char_creator(cls, **kwargs):
     """Создание персонажа с использованием редактора"""
     world = get_active_world()
     race = kwargs['race']
     pops = Pop.objects.select_related('location').filter(
         location__world_id=world.id, race=race)
     cell = choice(pops).location
     player = kwargs['player']
     char = create_character_outta_nowhere(cell, 16, None, kwargs['gender'])
     control_tag = CharTag(character=char,
                           name=CHAR_TAG_NAMES.CONTROLLED,
                           content=f'{player.id}')
     control_tag.save()
     blood_tag = CharTag(character=char,
                         name=CHAR_TAG_NAMES.BLOODLINE,
                         content=f'{player.id}')
     blood_tag.save()
     spec = Trait.objects.get(name=f'exp.{kwargs["exp"]}1')
     spec.character.add(char)
     if kwargs["name"]:
         rr = RenameRequest(player=player,
                            character=char,
                            new_name=kwargs["name"])
         rr.save()
     return char
    def get_cell_projects(cls, char, x, y):
        if char is None:
            return []
        if not char.is_alive:
            return []
        try:
            cell = get_active_world()[x][y]
            loc = char.location
            dist = max(abs(loc['x'] - cell.x), abs(loc['y'] - cell.y))
            char_can = get_available_projects(char)
            result = []
            if RelocateHelpers.can_relocate(char, cell):
                result.append(PROJECTS.TYPES.RELOCATE)
            if dist <= BALANCE.BASE_COMMUNICATION_RANGE:
                population = cell.pop_set.count()
                if population == 0 and cell.main_biome != MAIN_BIOME.WATER:
                    result += [
                        PROJECTS.TYPES.FORTIFY_CITY, PROJECTS.TYPES.BUILD_TILE
                    ]
                elif population > 0:
                    result += [
                        PROJECTS.TYPES.MAKE_FACTION,
                        PROJECTS.TYPES.RENAME_TILE,
                        PROJECTS.TYPES.IMPROVE_MANA,
                        PROJECTS.TYPES.IMPROVE_FOOD,
                        PROJECTS.TYPES.GATHER_SUPPORT
                    ]

            return list(set(result) & set(char_can))
        except Cell.DoesNotExist:
            return []
def roll_for_death():
    world_age = get_active_world().ticks_age
    old_chars = Character.objects.filter(birth_date__lt=world_age -
                                         HEALTH.OLD_AGE)
    old_chars = old_chars.exclude(
        tags__name=CHAR_TAG_NAMES.DEATH)  # No need to kill already dead

    for old_timer in old_chars:
        if randint(HEALTH.OLD_AGE, HEALTH.HARD_AGE_CAP) < old_timer.age:
            old_timer.die()
def process_pregancies():
    world_age = get_active_world().ticks_age
    mothers = Character.objects.filter(tags__name=CHAR_TAG_NAMES.PREGNANCY)
    for mother in mothers:
        p = mother.pregnancy
        father = Character.objects.get(id=p['father'])
        if p['date'] <= world_age - CHILDREN.PREGNANCY_TICKS:
            if randint(1, 100) <= calc_stillborn_chance(mother):
                mother.pregnancy = None
            elif randint(1, 100) <= CHILDREN.TWINS_CHANCE:
                character_birth(mother, father)
                character_birth(mother, father)
            else:
                character_birth(mother, father)
 def get_available_chars(cls, player):
     current = cls.get_current_char(player)
     world_age = get_active_world().ticks_age
     young_blood = Character.objects.filter(
         tags__name=CHAR_TAG_NAMES.BLOODLINE, tags__content=f'{player.id}'
     ).exclude(tags__name=CHAR_TAG_NAMES.CONTROLLED).exclude(
         primary_race=POP_RACE.FEY
     ).exclude(
         birth_date__gt=world_age - EXP.
         UNDERSTANDING_START  #отсекаем персонажей до 4, т.к. у них нет проектов
     )
     if current is not None:
         young_blood = young_blood.filter(birth_date__gt=current.birth_date)
     return young_blood
 def target(self):
     kwargs = json.loads(self.arguments)
     target = kwargs.get('target', None)
     if target is None:
         return None
     if self.type in PROJECTS.TARGETS_CELL:
         return get_active_world()[int(target['x'])][int(target['y'])]
     if self.type in PROJECTS.TARGETS_CHARACTER:
         try:
             target = int(target)
             target = Character.objects.get(pk=target)
             return target
         except ValueError:
             return None
         except Character.DoesNotExist:
             return None
Exemple #7
0
def calc_exp(char, subject, teacher_id = None , on_purpose = False):
    lvl = char.level(subject) # Дабы не лезть в БД лишние разы
    teacher_buff = 0
    teacher_lvl_diff = 0
    if teacher_id is not None:
        try:
            teacher = Character.objects.get(pk=int(teacher_id))
            if teacher.current_project is not None:
                if teacher.current_project.name == p.TYPES.TEACH: #учитель должен учить
                    kwargs = teacher.current_project.arguments_dict
                    pupils = []
                    if len(kwargs['pupils'])>0:
                        pupils = [int(i) for i in kwargs['pupils'].split(',')]
                    if char.id in pupils and subject == kwargs['subject']:
                        teacher_lvl_diff = max( teacher.level(subject) - lvl, 0)
        except Character.DoesNotExist:
            pass

    teacher_buff = EXP.TEACHER_LVL_BUFF * (teacher_lvl_diff -1)

    bloodline_buff = 0
    bloodline_level = char.bloodline_level(subject)

    if bloodline_level > 0:
        bloodline_buff += EXP.BLOODLINE_PERK_BUFF
    if bloodline_level > lvl and char.controller is not None:
        bloodline_buff += EXP.BLOODLINE_MEMORY_BUFF

    age_buff = 0
    world_age = get_active_world().ticks_age
    age = world_age - char.birth_date
    if age < EXP.UNDERSTANDING_START:
        return 0
    elif age < EXP.EDUCATION_START:
        age_buff = EXP.TOO_YOUNG_EXP_MOD
    elif age < EXP.YOUNG_BUFF_CUTOFF:
        age_buff = EXP.YOUNG_EXP_MOD
    elif age>=EXP.OLD_DEBUFF_START:
        age_buff = EXP.TOO_OLD_EXP_MOD

    total_exp = EXP.NORMAL_EXP_GAIN + teacher_buff + bloodline_buff + age_buff

    if not on_purpose:
        total_exp = int(total_exp / 2)

    return max(total_exp, EXP.MINIMUM_EXP_GAINED)
def character_birth(mother, father):
    world_age = get_active_world().ticks_age
    gender = choice([GENDER.MALE, GENDER.FEMALE])

    # Start name picking
    first_name_mother, last_name_mother = mother.name.split(None, maxsplit=1)
    first_name_father, last_name_father = father.name.split(None, maxsplit=1)

    #default to random first name
    first_name = hungarian.get_name_simple(gender).split()[0]

    #get grandparents of appropriate gender
    grandparents = mother.parents.filter(
        gender=gender) | father.parents.filter(gender=gender)
    grandparents = grandparents.distinct()

    if randint(1, 100) <= 25 and grandparents.count(
    ) > 0:  # 25% chance to pick grandparent's first name
        first_name = choice([p.name.split()[0] for p in grandparents])
    elif randint(1,
                 100) <= 10:  # another roll, 10% to pick parent's first name
        first_name = first_name_father if gender == GENDER.MALE else first_name_mother

    mother_bc = mother.bloodlines.count()
    father_bc = father.bloodlines.count()
    weights = [mother_bc, father_bc]
    if mother_bc == 0 and father_bc == 0:
        weights = None

    last_name = choices([last_name_mother, last_name_father],
                        weights=weights)[0]

    final_name = f'{first_name} {last_name}'

    child = Character(name=final_name,
                      gender=gender,
                      birth_date=world_age,
                      primary_race=mother.primary_race,
                      secondary_race=father.primary_race)
    child.save()
    child.location = mother.location
    child.add_parents(mother, father)
    add_racial_traits(child, mother, father)
    add_bloodlines(child, mother, father)
    def handle(self, *args, **options):

        npcs = Character.objects.exclude(tags__name='controlled_by') #All Non-players
        npcs = npcs.exclude(traits__name__startswith='exp.') #who do not already have exp trait

        world_date = get_active_world().ticks_age

        templates = ['exp.science{lvl}','exp.economics{lvl}','exp.military{lvl}','exp.politics{lvl}']
        for npc in npcs:
            age = world_date - npc.birth_date

            lvl = normal_npc_trait_gain(age)
            if options['verbosity']>2:
                    print(npc.name,"age:",age,"lvl:",lvl)
            if lvl>0:
                tname = choice(templates).format(lvl=lvl)
                trait = Trait.objects.get(name=tname)
                if options['verbosity']>2:
                    print("Added",trait.name,"to",npc.name)
                trait.character.add(npc)
Exemple #10
0
def roll_for_pregnancies():
    world_age = get_active_world().ticks_age
    min_age = world_age - CHILDREN.MIN_AGE
    males = Character.objects.filter(gender=GENDER.MALE).exclude(
        birth_date__gt=min_age)
    for m in males:
        weights = []
        fs = list(get_available_females(m))
        for f in fs:
            if f.is_enemy_of(m):
                weights.append(CHILDREN.ENEMY_ROLL_WEIGHT)
            elif f.is_friend_of(m):
                weights.append(CHILDREN.FRIEND_ROLL_WEIGHT)
            elif f.is_lover_of(m):
                weights.append(CHILDREN.LOVER_ROLL_WEIGHT)
            elif f.is_spouse_of(m):
                weights.append(CHILDREN.SPOUSE_ROLL_WEIGHT)
            else:
                weights.append(CHILDREN.NORMAL_ROLL_WEIGHT)

        rollnum = randint(0, CHILDREN.MAX_ROLLS_PER_MALE)
        partners = choices(fs, weights=weights, k=rollnum)

        for f in partners:
            roll = randint(1, 100)
            pregnancy = {'father': m.id, 'date': world_age}
            if f.is_enemy_of(m) and roll <= CHILDREN.ENEMY_PREGNANCY_CHANCE:
                f.pregnancy = pregnancy
            elif f.is_friend_of(
                    m) and roll <= CHILDREN.FRIEND_PREGNANCY_CHANCE:
                f.pregnancy = pregnancy
            elif f.is_lover_of(m) and roll <= CHILDREN.LOVER_PREGNANCY_CHANCE:
                f.pregnancy = pregnancy
            elif f.is_spouse_of(
                    m) and roll <= CHILDREN.SPOUSE_PREGNANCY_CHANCE:
                f.pregnancy = pregnancy
            elif roll <= CHILDREN.NORMAL_PREGNANCY_CHANCE:
                f.pregnancy = pregnancy
Exemple #11
0
    def start_cell_project(cls, char, x, y, project_type, data):
        allowed_projects = PCUtils.get_cell_projects(char, x, y)

        if project_type not in allowed_projects:
            raise cls.InvalidParameters(
                f"Your character ({char}) cannot start {project_type} project to target ({x}x{y})."
            )

        cell = get_active_world()[x][y]
        proj_args = {'target': {'x': x, 'y': y}}
        if project_type == PROJECTS.TYPES.RELOCATE:
            if not RelocateHelpers.can_relocate_to_coords(char, x, y):
                raise cls.InvalidParameters(
                    f"Your character ({char}) cannot relocate to target ({x}x{y})."
                )
            project, created = char.projects.get_or_create( #get_or_create  чтобы обновлять существующий проект, вместо пложения нового
                type = PROJECTS.TYPES.RELOCATE,
                defaults = {
                    'work_done':0,
                    'work_required':-1,
                    'is_current':False,
                    'arguments':json.dumps(proj_args)
                }
            )
            project.is_current = True
            project.save()
            return project.id

        elif project_type == PROJECTS.TYPES.FORTIFY_CITY:
            missing = []
            pop_str = data.get('with_pop', None)
            if pop_str is None:
                missing.append('with_pop')
            if len(missing) > 0:
                raise cls.MissingData(
                    f"Request is missng POST parameters: {missing}.")

            pop_id = int(pop_str)
            player_cell = get_active_world()[char.location['x']][
                char.location['y']]
            if not player_cell.pop_set.filter(pk=pop_id).exists():
                raise cls.InvalidParameters(
                    f"Your character ({char}) must be on the same cell with selected pop."
                )
            project = char.projects.create(
                type=PROJECTS.TYPES.FORTIFY_CITY,
                work_done=0,
                work_required=PROJECTS.WORK.BASE_NEED,
                is_current=False)
            proj_args['with_pop'] = pop_id
            proj_args['target'] = {'x': x, 'y': y}
            project.arguments_dict = proj_args
            project.is_current = True
            project.save()
            return project.id

        elif project_type == PROJECTS.TYPES.BUILD_TILE:
            missing = []
            pop_str = data.get('with_pop', None)
            city_type = data.get('city_type', None)
            if pop_str is None:
                missing.append('with_pop')
            if city_type is None:
                missing.append('city_type')
            if len(missing) > 0:
                raise cls.MissingData(
                    f"Request is missng POST parameters: {missing}.")

            if city_type not in CIVILIAN_CITIES:
                raise cls.InvalidParameters(
                    f"City type '{city_type}' cannot be built with this type of project"
                )
            pop_id = int(pop_str)
            player_cell = get_active_world()[char.location['x']][
                char.location['y']]
            if not player_cell.pop_set.filter(pk=pop_id).exists():
                raise cls.InvalidParameters(
                    f"Your character ({char}) must be on the same cell with selected pop."
                )
            project = char.projects.create(
                type=PROJECTS.TYPES.BUILD_TILE,
                work_done=0,
                work_required=PROJECTS.WORK.BASE_NEED,
                is_current=False)
            proj_args['with_pop'] = pop_id
            proj_args['target'] = {'x': x, 'y': y}
            project.arguments_dict = proj_args
            project.is_current = True
            project.save()
            return project.id
        elif project_type == PROJECTS.TYPES.MAKE_FACTION:
            missing = []
            pop_str = data.get('with_pop', None)
            name = data.get('name', None)
            if name is None:
                missing.append('name')
            if pop_str is None:
                missing.append('with_pop')
            if len(missing) > 0:
                raise cls.MissingData(
                    f"Request is missng POST parameters: {missing}.")
            pop_id = int(pop_str)
            project = char.projects.create(
                type=PROJECTS.TYPES.MAKE_FACTION,
                work_done=0,
                work_required=PROJECTS.WORK.BASE_NEED,
                is_current=False)
            proj_args['with_pop'] = pop_id
            proj_args['author'] = char.controller.id
            proj_args['name'] = name
            project.arguments_dict = proj_args
            project.is_current = True
            project.save()
            return project.id
        elif project_type == PROJECTS.TYPES.RENAME_TILE:
            missing = []
            name = data.get('name', None)
            if name is None:
                missing.append('name')
            if len(missing) > 0:
                raise cls.MissingData(
                    f"Request is missng POST parameters: {missing}.")
            project = char.projects.create(
                type=PROJECTS.TYPES.RENAME_TILE,
                work_done=0,
                work_required=PROJECTS.WORK.BASE_NEED,
                is_current=False)
            proj_args['name'] = name
            proj_args['author'] = char.controller.id
            project.arguments_dict = proj_args
            project.is_current = True
            project.save()
            return project.id
        elif project_type == PROJECTS.TYPES.IMPROVE_MANA:
            project = char.projects.create(
                type=PROJECTS.TYPES.IMPROVE_MANA,
                work_done=0,
                work_required=PROJECTS.WORK.BASE_NEED,
                is_current=False)

            project.is_current = True
            project.save()
            return project.id
        elif project_type == PROJECTS.TYPES.IMPROVE_FOOD:
            project = char.projects.create(
                type=PROJECTS.TYPES.IMPROVE_FOOD,
                work_done=0,
                work_required=PROJECTS.WORK.BASE_NEED,
                is_current=False)

            project.is_current = True
            project.save()
            return project.id
        elif project_type == PROJECTS.TYPES.GATHER_SUPPORT:
            missing = []
            pop_str = data.get('with_pop', None)
            if pop_str is None:
                missing.append('with_pop')
            if len(missing) > 0:
                raise cls.MissingData(
                    f"Request is missng POST parameters: {missing}.")

            pop_id = int(pop_str)
            if not cell.pop_set.filter(pk=pop_id).exists():
                raise cls.InvalidParameters(
                    f"Selected pop must be on specified cell.")
            project = char.projects.create(
                type=PROJECTS.TYPES.GATHER_SUPPORT,
                work_done=0,
                work_required=PROJECTS.WORK.BASE_NEED,
                is_current=False)
            proj_args['with_pop'] = pop_id
            project.arguments_dict = proj_args
            project.is_current = True
            project.save()
            return project.id
 def die(self):
     world_age = get_active_world().ticks_age
     t = CharTag(character=self,
                 name=CHAR_TAG_NAMES.DEATH,
                 content=f'{world_age}')
     t.save()
 def age(self):
     world_age = get_active_world().ticks_age
     return world_age - self.birth_date
Exemple #14
0
 def can_relocate_to_coords(cls, char , x, y):
     try:
         target = get_active_world().cell_set.get(x = x, y= y)
         return cls.can_relocate(char, target)
     except Cell.DoesNotExist:
         return False