Esempio n. 1
0
/* Turn a number of serfs into knight for the given player. */
int
player_promote_serfs_to_knights(player_t *player, int number)
{
    int promoted = 0;

    for (int i = 1; i < game.max_serf_index && number > 0; i++) {
        if (SERF_ALLOCATED(i)) {
            serf_t *serf = game_get_serf(i);
            if (serf->state == SERF_STATE_IDLE_IN_STOCK &&
                    SERF_PLAYER(serf) == player->player_num &&
                    SERF_TYPE(serf) == SERF_GENERIC) {
                inventory_t *inv = game_get_inventory(serf->s.idle_in_stock.inv_index);
                if (inv->resources[RESOURCE_SWORD] > 0 &&
                        inv->resources[RESOURCE_SHIELD] > 0) {
                    inv->resources[RESOURCE_SWORD] -= 1;
                    inv->resources[RESOURCE_SHIELD] -= 1;
                    inv->spawn_priority -= 1;
                    inv->serfs[SERF_GENERIC] = 0;

                    serf->type = (SERF_KNIGHT_0 << 2) | (serf->type & 3);

                    player->serf_count[SERF_GENERIC] -= 1;
                    player->serf_count[SERF_KNIGHT_0] += 1;
                    player->total_military_score += 1;

                    promoted += 1;
                    number -= 1;
                }
            }
        }
    }

    return promoted;
}
Esempio n. 2
0
/* Turn a number of serfs into knight for the given player. */
int
player_promote_serfs_to_knights(player_t *player, int number)
{
	int promoted = 0;

	for (uint i = 1; i < game.max_serf_index && number > 0; i++) {
		if (SERF_ALLOCATED(i)) {
			serf_t *serf = game_get_serf(i);
			if (serf->state == SERF_STATE_IDLE_IN_STOCK &&
			    SERF_PLAYER(serf) == player->player_num &&
			    SERF_TYPE(serf) == SERF_GENERIC) {
				inventory_t *inv = game_get_inventory(serf->s.idle_in_stock.inv_index);
				if (inv->resources[RESOURCE_SWORD] > 0 &&
				    inv->resources[RESOURCE_SHIELD] > 0) {
					inv->resources[RESOURCE_SWORD] -= 1;
					inv->resources[RESOURCE_SHIELD] -= 1;
					inv->generic_count -= 1;
					inv->serfs[SERF_GENERIC] = 0;

					serf_set_type(serf, SERF_KNIGHT_0);

					promoted += 1;
					number -= 1;
				}
			}
		}
	}

	return promoted;
}
Esempio n. 3
0
void
player_start_attack(player_t *player)
{
    const int min_level_hut[] = { 1, 1, 2, 2, 3 };
    const int min_level_tower[] = { 1, 2, 3, 4, 6 };
    const int min_level_fortress[] = { 1, 3, 6, 9, 12 };

    building_t *target = game_get_building(player->building_attacked);
    if (!BUILDING_IS_DONE(target) ||
            (BUILDING_TYPE(target) != BUILDING_HUT &&
             BUILDING_TYPE(target) != BUILDING_TOWER &&
             BUILDING_TYPE(target) != BUILDING_FORTRESS &&
             BUILDING_TYPE(target) != BUILDING_CASTLE) ||
            !BUILDING_IS_ACTIVE(target) ||
            BUILDING_STATE(target) != 3) {
        return;
    }

    for (int i = 0; i < player->attacking_building_count; i++) {
        /* TODO building index may not be valid any more(?). */
        building_t *b = game_get_building(player->attacking_buildings[i]);
        if (BUILDING_IS_BURNING(b) ||
                MAP_OWNER(b->pos) != player->player_num) {
            continue;
        }

        map_pos_t flag_pos = MAP_MOVE_DOWN_RIGHT(b->pos);
        if (MAP_SERF_INDEX(flag_pos) != 0) {
            /* Check if building is under siege. */
            serf_t *s = game_get_serf(MAP_SERF_INDEX(flag_pos));
            if (SERF_PLAYER(s) != player->player_num) continue;
        }

        const int *min_level = NULL;
        switch (BUILDING_TYPE(b)) {
        case BUILDING_HUT:
            min_level = min_level_hut;
            break;
        case BUILDING_TOWER:
            min_level = min_level_tower;
            break;
        case BUILDING_FORTRESS:
            min_level = min_level_fortress;
            break;
        default:
            continue;
            break;
        }

        int state = BUILDING_STATE(b);
        int knights_present = b->stock[0].available;
        int to_send = knights_present - min_level[player->knight_occupation[state] & 0xf];

        for (int j = 0; j < to_send; j++) {
            /* Find most approriate knight to send according to player settings. */
            int best_type = PLAYER_SEND_STRONGEST(player) ? SERF_KNIGHT_0 : SERF_KNIGHT_4;
            int best_index = -1;

            int knight_index = b->serf_index;
            while (knight_index != 0) {
                serf_t *knight = game_get_serf(knight_index);
                if (PLAYER_SEND_STRONGEST(player)) {
                    if (SERF_TYPE(knight) >= best_type) {
                        best_index = knight_index;
                        best_type = SERF_TYPE(knight);
                    }
                } else {
                    if (SERF_TYPE(knight) <= best_type) {
                        best_index = knight_index;
                        best_type = SERF_TYPE(knight);
                    }
                }

                knight_index = knight->s.defending.next_knight;
            }

            /* Unlink knight from list. */
            int *def_index = &b->serf_index;
            serf_t *def_serf = game_get_serf(*def_index);
            while (*def_index != best_index) {
                def_index = &def_serf->s.defending.next_knight;
                def_serf = game_get_serf(*def_index);
            }
            *def_index = def_serf->s.defending.next_knight;
            b->stock[0].available -= 1;

            target->progress |= BIT(0);

            /* Calculate distance to target. */
            int dist_col = (MAP_POS_COL(target->pos) -
                            MAP_POS_COL(def_serf->pos)) & game.map.col_mask;
            if (dist_col >= game.map.cols/2) dist_col -= game.map.cols;

            int dist_row = (MAP_POS_ROW(target->pos) -
                            MAP_POS_ROW(def_serf->pos)) & game.map.row_mask;
            if (dist_row >= game.map.rows/2) dist_row -= game.map.rows;

            /* Send this serf off to fight. */
            serf_log_state_change(def_serf, SERF_STATE_KNIGHT_LEAVE_FOR_WALK_TO_FIGHT);
            def_serf->state = SERF_STATE_KNIGHT_LEAVE_FOR_WALK_TO_FIGHT;
            def_serf->s.leave_for_walk_to_fight.dist_col = dist_col;
            def_serf->s.leave_for_walk_to_fight.dist_row = dist_row;
            def_serf->s.leave_for_walk_to_fight.field_D = 0;
            def_serf->s.leave_for_walk_to_fight.field_E = 0;
            def_serf->s.leave_for_walk_to_fight.next_state = SERF_STATE_KNIGHT_FREE_WALKING;

            player->knights_attacking -= 1;
            if (player->knights_attacking == 0) return;
        }
    }
}