internal SortedBindingList<Unit> GetTargetUnits()
        {
            UnitList units = UnitList.GetForces( TargetHouse.ID );
            SortedBindingList<Unit> list = new Csla.SortedBindingList<Unit>( units );
            list.ApplySort( "Cost", ListSortDirection.Descending );

            return list;
        }
        protected override void DataPortal_Execute()
        {
            ATConfiguration config = ATConfiguration.Instance;

            double chanceOfSuccess = Operation.Success;

            // modify chance of success based on compared intelligence scores - max influence of 50%
            chanceOfSuccess = GetAppliedIntelligenceDifference( chanceOfSuccess, 0.5 );

            // modify chance of success based on surveillance scores
            chanceOfSuccess += GetAppliedSpyDifference( OperatingSpies.Expropriation, DefendingSpies.Expropriation, 200 );

            // modify chance of success based on operating house's ambition - max influence of 25%
            chanceOfSuccess = OperatingHouse.ApplyAmbition( chanceOfSuccess, 0.25 );

            Random random = new Random();
            int num = random.Next( 1, 100 );

            PayForOperation();

            int techCount = 0;
            if ( num <= chanceOfSuccess ) // success
            {
                Description.Add( "Expropriation Operation: SUCCESS" );
                Description.Add( "" );

                TechnologyList operatingTech = TechnologyList.GetResearchedTechnologies( OperatingHouse.ID );
                TechnologyList targetTech = TechnologyList.GetResearchedTechnologies( TargetHouse.ID );

                SortedBindingList<Technology> list = new Csla.SortedBindingList<Technology>( targetTech );
                list.ApplySort( "Cost", ListSortDirection.Ascending );

                // find the first technology the target house has that the operating house doesn't,
                // starting with the cheapest technology first
                int technologyId = 0;
                string technologyName = string.Empty;
                foreach ( Technology target in list )
                {
                    bool alreadyHasTech = false;
                    foreach ( Technology tech in operatingTech )
                    {
                        if ( tech.ID == target.ID )
                        {
                            alreadyHasTech = true;
                            break;
                        }

                        if ( !alreadyHasTech )
                        {
                            technologyId = target.ID;
                            technologyName = target.Name;
                            break;
                        }
                    }
                }

                if ( technologyId == 0 )
                {
                    Description.Add( "Your efforts were squandered. House " + TargetHouse.Name + " does not possess any technology unknown to you." );
                    Description.Add( "" );
                }
                else
                {

                    using ( SqlConnection cn = new SqlConnection( Database.AphelionTriggerConnection ) )
                    {
                        cn.Open();
                        using ( SqlCommand cm = cn.CreateCommand() )
                        {
                            cm.CommandType = CommandType.Text;
                            cm.CommandText = "INSERT INTO bbgResearch (HouseId,TechnologyID,ResearchStateID,AgeID) VALUES (" + OperatingHouse.ID.ToString() + "," + technologyId.ToString() + ",4,dbo.GetAge())";
                            techCount = Convert.ToInt32( cm.ExecuteScalar() );
                        }
                    }

                    Description.Add( "You expropriated the research for " + technologyName + ", making the technology available to your house." );
                    Description.Add( "" );

                    ApplyExperience();
                }

                LogOperation( true, false );
            }
            else // failure
            {
                Description.Add( "Expropriation Operation: FAILURE" );
                Description.Add( "" );

                DetectEspionage();
            }
        }
        protected override void DataPortal_Execute()
        {
            ATConfiguration config = ATConfiguration.Instance;

            double chanceOfSuccess = Operation.Success;

            // modify chance of success based on compared intelligence scores - max influence of 50%
            chanceOfSuccess = GetAppliedIntelligenceDifference( chanceOfSuccess, 0.5 );

            // modify chance of success based on Ambush scores
            chanceOfSuccess += GetAppliedSpyDifference( OperatingSpies.Ambush, DefendingSpies.Ambush, 50 );

            // modify chance of success based on operating house's ambition - max influence of 25%
            chanceOfSuccess = (int)OperatingHouse.ApplyAmbition( chanceOfSuccess, 0.25 );

            Random random = new Random();
            int num = random.Next( 1, 100 );

            PayForOperation();

            if ( num <= chanceOfSuccess ) // success
            {
                Description.Add( "Ambush Operation: SUCCESS" );
                Description.Add( "" );

                //always apply faction bonus to ambush score
                int operatingHouseAmbush = (int)OperatingHouse.ApplyFactionLeaderBonus( OperatingSpies.Ambush );

                // calculate base units killed
                double percentKilled = ( operatingHouseAmbush / 25 ) * 0.005;

                // modify kills on the basis of ambition
                percentKilled = OperatingHouse.ApplyAmbition( percentKilled, 0.25 );

                UnitList units = UnitList.GetForces( TargetHouse.ID );
                SortedBindingList<Unit> list = new Csla.SortedBindingList<Unit>( units );
                list.ApplySort( "Cost", ListSortDirection.Descending );

                int totalUnits = 0;
                foreach ( Unit unit in units )
                    totalUnits += unit.Count;

                // calculate how many units are killed
                int murderedUnits = (int)Math.Ceiling( totalUnits * percentKilled );

                // always convert at least one spy
                if ( murderedUnits < 0 ) murderedUnits = 1;

                using ( SqlConnection cn = new SqlConnection( Database.AphelionTriggerConnection ) )
                {
                    cn.Open();

                    // randomly select a type of spy to convert until all conversions have been performed
                    int killCount = 0;
                    foreach ( Unit unit in units )
                    {
                        int killed = ( murderedUnits - killCount );
                        if ( killed > unit.Count ) killed = unit.Count;

                        if ( killed > 0 )
                        {
                            using ( SqlCommand cm = cn.CreateCommand() )
                            {
                                cm.CommandType = CommandType.StoredProcedure;
                                cm.CommandText = "AddCasualties";
                                cm.Parameters.AddWithValue( "@HouseID", TargetHouse.ID );
                                cm.Parameters.AddWithValue( "@UnitID", unit.ID );
                                cm.Parameters.AddWithValue( "@Casualties", killed );
                                cm.ExecuteNonQuery();
                            }

                            Description.Add( "You ambushed and murdered " + killed.ToString() + " " + unit.Name + "." );
                            Description.Add( "" );

                            killCount += killed;
                        }
                    }
                }

                ApplyExperience();

                LogOperation( true, false );

            }
            else // failure
            {
                Description.Add( "Ambush Operation: FAILURE" );
                Description.Add( "" );

                DetectEspionage();
            }
        }
        internal SortedBindingList<Spy> ApplySortForOperation( SpyList spies )
        {
            SortedBindingList<Spy> list = new Csla.SortedBindingList<Spy>( spies );

            switch ( Operation.ID )
            {
                case 1:
                    for ( int spy = 0; spy < list.Count; spy++ ) if ( list[spy].Larceny == 0 ) list.RemoveAt( spy );
                    list.ApplySort( "Larceny", ListSortDirection.Descending );
                    break;
                case 2:
                    for ( int spy = 0; spy < list.Count; spy++ ) if ( list[spy].Surveillance == 0 ) list.RemoveAt( spy );
                    list.ApplySort( "Surveillance", ListSortDirection.Descending );
                    break;
                case 3:
                    for ( int spy = 0; spy < list.Count; spy++ ) if ( list[spy].Reconnaissance == 0 ) list.RemoveAt( spy );
                    list.ApplySort( "Reconnaissance", ListSortDirection.Descending );
                    break;
                case 4:
                    for ( int spy = 0; spy < list.Count; spy++ ) if ( list[spy].MICE == 0 ) list.RemoveAt( spy );
                    list.ApplySort( "MICE", ListSortDirection.Descending );
                    break;
                case 5:
                    for ( int spy = 0; spy < list.Count; spy++ ) if ( list[spy].Ambush == 0 ) list.RemoveAt( spy );
                    list.ApplySort( "Ambush", ListSortDirection.Descending );
                    break;
                case 6:
                    for ( int spy = 0; spy < list.Count; spy++ ) if ( list[spy].Sabotage == 0 ) list.RemoveAt( spy );
                    list.ApplySort( "Sabotage", ListSortDirection.Descending );
                    break;
                case 7:
                    for ( int spy = 0; spy < list.Count; spy++ ) if ( list[spy].Expropriation == 0 ) list.RemoveAt( spy );
                    list.ApplySort( "Expropriation", ListSortDirection.Descending );
                    break;
                case 8:
                    for ( int spy = 0; spy < list.Count; spy++ ) if ( list[spy].Inspection == 0 ) list.RemoveAt( spy );
                    list.ApplySort( "Inspection", ListSortDirection.Descending );
                    break;
                case 9:
                    for ( int spy = 0; spy < list.Count; spy++ ) if ( list[spy].Subversion == 0 ) list.RemoveAt( spy );
                    list.ApplySort( "Subversion", ListSortDirection.Descending );
                    break;
            }

            return list;
        }