//-------- Begin of function SpyArray::catch_spy ------// // // <int> spyPlace - either SPY_TOWN or SPY_FIRM // <int> spyPlacePara - town_recno or firm_recno // int SpyArray::catch_spy(int spyPlace, int spyPlacePara) { int nationRecno, totalPop; if( spyPlace == SPY_TOWN ) { Town* townPtr = town_array[spyPlacePara]; nationRecno = townPtr->nation_recno; totalPop = townPtr->population; } else if( spyPlace == SPY_FIRM ) { Firm* firmPtr = firm_array[spyPlacePara]; nationRecno = firmPtr->nation_recno; if( firmPtr->cast_to_FirmCamp() ) { FirmCamp *firmCamp = firmPtr->cast_to_FirmCamp(); totalPop = firmCamp->soldier_count + (firmCamp->overseer_recno>0); } else if( firmPtr->cast_to_FirmWork() ) { FirmWork *firmWork = firmPtr->cast_to_FirmWork(); totalPop = firmWork->worker_count; } else if( firmPtr->cast_to_FirmTrain() ) { totalPop = firmPtr->cast_to_FirmTrain()->trainee_count; return 0; // don't catch spy } else if( firmPtr->cast_to_FirmInn() ) { totalPop = firmPtr->cast_to_FirmInn()->inn_unit_count; return 0; // don't catch spy } else if( firmPtr->cast_to_FirmMarket() ) { totalPop = 0; return 0; } else if( firmPtr->cast_to_FirmMonsterTrain() ) { totalPop = firmPtr->cast_to_FirmMonsterTrain()->trainee_count; return 0; // don't catch spy } else if( firmPtr->cast_to_FirmMonsterAlchemy() ) { totalPop = 0; return 0; } else if( firmPtr->cast_to_FirmLishorr() ) { totalPop = 0; return 0; } else if( firmPtr->cast_to_FirmMonsterFortress() ) { FirmMonsterFortress *firmMonsterFortress = firmPtr->cast_to_FirmMonsterFortress(); totalPop = firmMonsterFortress->archer_count + firmMonsterFortress->extra_builder_count; } else if( firmPtr->cast_to_FirmAnimal() ) { totalPop = 0; return 0; } else if( firmPtr->cast_to_FirmIncubator() ) { totalPop = 0; return 0; } else if( firmPtr->cast_to_FirmMagic() ) { totalPop = 0; return 0; } else if( firmPtr->cast_to_FirmOffensive() ) { totalPop = 0; return 0; } else if( firmPtr->cast_to_FirmOffensive2() ) { totalPop = 0; return 0; } else { err_here(); totalPop = 0; } } else err_here(); //--- calculate the total of anti-spy skill in this town ----// int enemySpyCount=0, counterSpySkill=0; Spy* spyPtr; int techLevel = 0; if( nationRecno ) techLevel = tech_res[TECH_COUNTER_SPY]->get_nation_tech_level(nationRecno); int i; for( i=size() ; i>0 ; i-- ) { if( is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->spy_place == spyPlace && spyPtr->spy_place_para == spyPlacePara ) { if( spyPtr->true_nation_recno == nationRecno ) counterSpySkill += spyPtr->spy_skill + spyPtr->spy_skill * techLevel / 2; else enemySpyCount++; } } //----- if all citizens are enemy spies ----// if( enemySpyCount == totalPop ) return 0; err_when( enemySpyCount > totalPop ); //-------- try to catch enemy spies now ------// for( i=spy_array.size() ; i>0 ; i-- ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->action_mode == SPY_IDLE ) // it is very hard to get caught in sleep mode continue; if( spyPtr->spy_place == spyPlace && spyPtr->spy_place_para == spyPlacePara && spyPtr->true_nation_recno != nationRecno ) // doesn't get caught in sleep mode { int escapeChance = 100 + spyPtr->spy_skill - counterSpySkill; escapeChance = max( spyPtr->spy_skill/10, escapeChance ); if( m.random(escapeChance) == 0 ) { spyPtr->get_killed(); // only catch one spy per calling return 1; } } } return 0; }
//--------- Begin of function Firm::spy_bribe ---------// // // The money the spy offers to bribe the unit. // // <int> bribeAmount - the amount offered // <short> birberSpyRecno - spy recno of the briber // <short> workerId - if 0, then bribe the overseer, // if >0, then bribe a worker. // // return: <int> >0 - bribing succeeded, return the spy recno of the bribed unit (as it has been turned into a spy) // 0 - bribing failed // int Firm::spy_bribe(int bribeAmount, short briberSpyRecno, short workerId) { if( !can_spy_bribe(workerId, spy_array[briberSpyRecno]->true_nation_recno) ) // this can happen in multiplayer as there is a one frame delay when the message is sent and when it is processed return 0; //---------------------------------------// int succeedChance = spy_bribe_succeed_chance(bribeAmount, briberSpyRecno, workerId); Spy* spyPtr = spy_array[briberSpyRecno]; nation_array[spyPtr->true_nation_recno]->add_expense( EXPENSE_BRIBE, (float) bribeAmount, 0 ); //------ if the bribe succeeds ------// if( succeedChance > 0 && misc.random(100) < succeedChance ) { int spyRecno = spy_array.add_spy(); // add a new Spy record Spy* newSpy = spy_array[spyRecno]; newSpy->spy_skill = 10; newSpy->action_mode = SPY_IDLE; newSpy->spy_loyalty = MIN( 100, MAX(30,succeedChance) ); // within the 30-100 range newSpy->true_nation_recno = spyPtr->true_nation_recno; newSpy->cloaked_nation_recno = spyPtr->cloaked_nation_recno; if( workerId ) { Worker* workerPtr = worker_array+workerId-1; workerPtr->spy_recno = spyRecno; newSpy->race_id = workerPtr->race_id; newSpy->name_id = workerPtr->name_id; err_when( newSpy->race_id < 1 || newSpy->race_id > MAX_RACE ); if( !newSpy->name_id ) // if this worker does not have a name, give him one now as a spy must reserve a name (see below on use_name_id() for reasons) newSpy->name_id = race_res[newSpy->race_id]->get_new_name_id(); } else if( overseer_recno ) { Unit* unitPtr = unit_array[overseer_recno]; unitPtr->spy_recno = spyRecno; newSpy->race_id = unitPtr->race_id; newSpy->name_id = unitPtr->name_id; err_when( newSpy->race_id < 1 || newSpy->race_id > MAX_RACE ); } else err_here(); newSpy->set_place( SPY_FIRM, firm_recno ); //-- Spy always registers its name twice as his name will be freed up in deinit(). Keep an additional right because when a spy is assigned to a town, the normal program will free up the name id., so we have to keep an additional copy race_res[newSpy->race_id]->use_name_id(newSpy->name_id); bribe_result = BRIBE_SUCCEED; if( firm_recno == firm_array.selected_recno ) info.disp(); return newSpy->spy_recno; } else //------- if the bribe fails --------// { spyPtr->get_killed(0); // the spy gets killed when the action failed. // 0 - don't display new message for the spy being killed, so we already display the msg on the interface bribe_result = BRIBE_FAIL; if( firm_recno == firm_array.selected_recno ) info.disp(); return 0; } }
//-------- Begin of function SpyArray::catch_spy ------// // // <int> spyPlace - either SPY_TOWN or SPY_FIRM // <int> spyPlacePara - town_recno or firm_recno // int SpyArray::catch_spy(int spyPlace, int spyPlacePara) { int nationRecno, totalPop; if( spyPlace == SPY_TOWN ) { Town* townPtr = town_array[spyPlacePara]; nationRecno = townPtr->nation_recno; totalPop = townPtr->population; } else if( spyPlace == SPY_FIRM ) { Firm* firmPtr = firm_array[spyPlacePara]; nationRecno = firmPtr->nation_recno; totalPop = firmPtr->worker_count + (firmPtr->overseer_recno>0); } else err_here(); //--- calculate the total of anti-spy skill in this town ----// int enemySpyCount=0, counterSpySkill=0; Spy* spyPtr; int i; for( i=size() ; i>0 ; i-- ) { if( is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->spy_place == spyPlace && spyPtr->spy_place_para == spyPlacePara ) { if( spyPtr->true_nation_recno == nationRecno ) counterSpySkill += spyPtr->spy_skill; else enemySpyCount++; } } //----- if all villagers are enemy spies ----// if( enemySpyCount == totalPop ) return 0; err_when( enemySpyCount > totalPop ); //-------- try to catch enemy spies now ------// for( i=spy_array.size() ; i>0 ; i-- ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->action_mode == SPY_IDLE ) // it is very hard to get caught in sleep mode continue; if( spyPtr->spy_place == spyPlace && spyPtr->spy_place_para == spyPlacePara && spyPtr->true_nation_recno != nationRecno ) // doesn't get caught in sleep mode { int escapeChance = 100 + spyPtr->spy_skill - counterSpySkill; escapeChance = MAX( spyPtr->spy_skill/10, escapeChance ); if( m.random(escapeChance) == 0 ) { spyPtr->get_killed(); // only catch one spy per calling return 1; } } } return 0; }