00001
00002
00003
00004 #include <OSYS.H>
00005 #include <OMATH.H>
00006 #include <ODEPT.H>
00007 #include <OINFO.H>
00008 #include <OCHANCE.H>
00009 #include <ONAMERES.H>
00010 #include <OFPHOTO.H>
00011 #include <OPSCHOOL.H>
00012 #include <OFACULTY.H>
00013 #include <OFINANCE.H>
00014 #include <OFACILIT.H>
00015 #include <OPSCHOOL.H>
00016 #include <OLIBTECH.H>
00017 #include <ODEPTRES.H>
00018 #include <OPEERSCH.H>
00019 #include <OSCHLRES.H>
00020
00021
00022
00023 static int get_discretionary_time_pref(char* discretionaryTimePref, int index);
00024
00025
00027
00028 int facultySalary, int talentTeaching, int talentScholarship, int talentResearch) {
00029 memset( this, 0, sizeof(Faculty) );
00030
00031 err_when( genderEthnicGroup < 0 || genderEthnicGroup >= GENDER_ETHNIC_TYPE_COUNT );
00032
00033
00034
00035 department_recno = departmentRecno;
00036 rank_level = rankLevel;
00037 gender_ethnic_group = genderEthnicGroup;
00038
00039 #ifdef DEBUG
00040 rank_age_group(rank_level, facultyAge);
00041 #endif
00042
00043 birthday = info.game_date - int((float)(facultyAge)*365.25) - m.random(300);
00044 salary = facultySalary;
00045 teaching_contact_hour = CONTACT_HOUR_PER_COURSE;
00046 start_teaching_date = startTeachingDate;
00047
00048 if ( age() != facultyAge && facultyAge == 41 )
00049 birthday -= 365;
00050
00051
00052
00053 int loopCount=0;
00054 int curGender;
00055
00056 if( gender_ethnic_group == NONMINORITY_MALE ||
00057 gender_ethnic_group == MINORITY_MALE ) {
00058 curGender = 'M';
00059 }
00060
00061 else if ( gender_ethnic_group == NONMINORITY_FEMALE ||
00062 gender_ethnic_group == MINORITY_FEMALE )
00063 curGender = 'F';
00064 else
00065 err_here();
00066
00067
00068 #if(GAME_VERSION>=200)
00069 do {
00070 #endif
00071 while(1) {
00072 first_name_id = m.random(name_res.first_name_count)+1;
00073
00074 if( name_res.first_name_array[first_name_id-1].gender == curGender )
00075 break;
00076 ++loopCount;
00077 err_when( loopCount > 1000 );
00078 }
00079
00080 middle_name_id = m.random(name_res.middle_name_count)+1;
00081 last_name_id = m.random(name_res.last_name_count)+1;
00082
00083 #if(GAME_VERSION>=200)
00084
00085 } while( strcmp( name_res.first_name_array[first_name_id-1].name, "Dick")==0
00086 && strcmp( name_res.last_name_array[last_name_id-1].name, "Head")==0 );
00087 #endif
00088
00089
00090
00091 research_proposal_count = 0;
00092 research_month_expense = 0;
00093 research_month_expense_direct = 0;
00094
00095 #if(GAME_VERSION>=200)
00096 employ_status = 4;
00097 #endif
00098
00099
00100
00101 off_duty_trimester = SUMMER;
00102 is_third_trimester_teaching = 0;
00103
00104
00105 reaction_summer_teaching = 0;
00106
00107
00108 talent_teaching = (float) min(100, talentTeaching);
00109 talent_scholarship = (float) min(100, talentScholarship);
00110 talent_research = (float) min(100, talentResearch);
00111
00112 err_when(talent_teaching<0 || talent_scholarship<0 || talent_research<0);
00113
00114
00115
00116 init_photo();
00117 this->name();
00118
00119
00120
00121
00122 int checkSum = 0;
00123 int checkSum2 = 0;
00124 char tmplCode = 'A';
00125
00126 FacultyTemplate *facultyTemplate = faculty_res.get_faculty_template( &tmplCode , rank_age_group(rank_level, age()));
00127
00128 for( int j=0 ; j<DISCRETIONARY_TYPE_COUNT ; j++ ) {
00129 this->discretionary_hour_array[j] = NORMAL_DISCRETIONARY_HOUR * get_discretionary_time_pref( facultyTemplate->discretionary_time_pref, j ) / 100;
00130 checkSum += discretionary_hour_array[j];
00131
00132 checkSum2 += get_discretionary_time_pref( facultyTemplate->discretionary_time_pref, j );
00133 }
00134
00135 err_when(checkSum <= 0 || checkSum2 < 90 || checkSum2 > 105);
00136
00137
00138
00139 Faculty* facultyPtr = this;
00140 float qualityDriver = facultyPtr->get_quality_driver();
00141 float oRate = finance.get_research_overhead_rate() / 100.0f;
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 facultyPtr->proj_count_mult = (0.8f + 0.4f * this->talent_research/100);
00163 facultyPtr->proj_size_mult = (0.7f + 0.6f * this->talent_research/100);
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 #if(GAME_VERSION>=200)
00175
00176
00177 float awardProb = 2.0f * (qualityDriver * 0.01f) / math.safe_pow( (1.0f + oRate), 3.0f );
00178 this->award_prob = m.fmin( 0.85f, m.fmax(0.10f, awardProb) );
00179 #else
00180 this->award_prob = (float)(0.01f + 0.9 * this->talent_research/100);
00181 #endif
00182
00183 Department* deptPtr = department_array[department_recno];
00184 char rankAgeGroup = rank_age_group(rank_level, age());
00185 deptPtr->init_proj_vars(this);
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 }
00196
00197
00198
00199
00203
00204 if( player_school.scenario_id == SCN_TEACHING_QUALITY || player_school.scenario_id == SCN_RESEARCH_QUALITY ) {
00205
00206
00207 float tempPref[DISCRETIONARY_TYPE_COUNT];
00208
00209 for( int i=0 ; i<DISCRETIONARY_TYPE_COUNT ; i++ ) {
00210 tempPref[i] = (float) discretionaryTimePref[i];
00211 }
00212
00213
00214
00215 if ( player_school.scenario_id == SCN_TEACHING_QUALITY ) {
00216 tempPref[DT_OUT_OF_CLASS_STUDENT_CONTACT] *= 0.333f;
00217 tempPref[DT_EDUCATIONAL_DEVELOPMENT] *= 0.333f;
00218 }
00219 else if( player_school.scenario_id == SCN_RESEARCH_QUALITY ) {
00220 tempPref[DT_RESEARCH] *= 0.333f;
00221 tempPref[DT_SCHOLARSHIP] *= 0.333f;
00222 }
00223
00224
00225
00226 float totalPref=0;
00227
00228 for( i=0 ; i<DISCRETIONARY_TYPE_COUNT ; i++ ) {
00229 totalPref += tempPref[i];
00230 }
00231
00232 for( i=0 ; i<DISCRETIONARY_TYPE_COUNT ; i++ ) {
00233 tempPref[i] = tempPref[i] * 100 / totalPref;
00234 }
00235
00236 int ret = (int) tempPref[index];
00237
00238 if( tempPref[index] - (int) tempPref[index] > 0.5f )
00239 ret++;
00240
00241 return ret;
00242 }
00243 else {
00244 return discretionaryTimePref[index];
00245 }
00246 }
00247
00248
00249
00250
00252
00253
00254
00255 Department* deptPtr = department_array[department_recno];
00256
00257
00258
00259 int photoId = m.random(faculty_photo_res.photo_count)+1;
00260 int tryCount=0;
00261
00262 while(1) {
00263 if( ++photoId > faculty_photo_res.photo_count )
00264 photoId = 1;
00265
00266 if( faculty_photo_res[photoId]->gender_ethnic_group != this->gender_ethnic_group )
00267 continue;
00268
00269
00270
00271 int duplicatedFlag = 0;
00272
00273 for( int i=deptPtr->faculty_array.size() ; i>0 ; i--) {
00274 if( deptPtr->faculty_array.is_deleted(i) )
00275 continue;
00276
00277 if( deptPtr->faculty_array[i]->photo_id == photoId ) {
00278 duplicatedFlag = 1;
00279 break;
00280 }
00281 }
00282
00283
00284
00285
00286 if( !duplicatedFlag || tryCount > faculty_photo_res.photo_count ) {
00287 photo_id = photoId;
00288 return;
00289 }
00290
00291 ++tryCount;
00292
00293 err_when( tryCount > 1000 );
00294 }
00295 }
00296
00297
00298
00299
00301
00302
00303
00304
00305 if ( info.game_day == player_school.trimester_array[player_school.cur_trimester].start_day
00306 && info.game_month == player_school.trimester_array[player_school.cur_trimester].start_month ) {
00307 update_history(UPDATE_TRIMESTER);
00308 #if(GAME_VERSION>=200)
00309 if ( think_dismiss() )
00310 return;
00311 #endif
00312 }
00313
00314
00315 if ( info.game_day == 1 ) {
00316 update_history(UPDATE_MONTH);
00317
00318 sys.yield();
00319
00320 if ( info.game_month == finance.fiscal_year_start_month )
00321 update_history(UPDATE_YEAR);
00322 }
00323 }
00324
00325
00326
00327
00329
00330
00331
00332 teaching_contact_hour = 0;
00333
00334
00335
00336 if ( think_departure() )
00337 return;
00338
00339 think_discretionary_time();
00340
00341 if ( think_promotion() )
00342 return;
00343 }
00344
00345
00346
00347
00351
00352 #if(GAME_VERSION>=200)
00353
00354 if ( age() >= 72 ) {
00355 department_array[department_recno]->faculty_array.del(this->faculty_recno);
00356 return 1;
00357 }
00358 #endif
00359
00360 float multiplier = 1-(satisfaction_index-50)/100.0f;
00361 float multiplierLast = 1-(satisfaction_index_last-50)/100.0f;
00362
00363
00364 multiplier = player_school.latency_func(0.25f, multiplierLast, multiplier);
00365
00366
00367 int departmentId = department_array[department_recno]->department_id;
00368 float departProb = department_res[departmentId]->faculty_departure_probability[rank_level][department_res.get_prob_school_type()];
00369
00370 #if(GAME_VERSION>=200)
00371
00372 if ( math.get_random_float() > multiplier * departProb *1.25 * 0.1)
00373 return 0;
00374 #else
00375
00376 if ( math.get_random_float() > multiplier * departProb * 0.1)
00377 return 0;
00378 #endif
00379
00380
00381
00382
00383 department_array[department_recno]->faculty_array.del(this->faculty_recno);
00384
00385 return 1;
00386 }
00387
00388
00389
00390 #if(GAME_VERSION>=200)
00391
00395
00396 if ( is_dismissed ) {
00397 if ( dismiss_trimester == 1 ) {
00398 department_array[department_recno]->faculty_array.del(this->faculty_recno);
00399
00400 return 1;
00401 }
00402 else
00403 dismiss_trimester--;
00404 }
00405
00406 return 0;
00407 }
00408
00409
00410 #endif
00411
00412
00414
00415
00416
00417
00418 float prob;
00419 DepartmentInfo *deptInfo = department_res[department_array[department_recno]->department_id];
00420
00421 if ( rank_level == ASSOC_PROF && age() >= 41 )
00422 prob = deptInfo->associate_professor_promotion_probability[department_res.get_prob_school_type()];
00423 else if ( rank_level == ASST_PROF )
00424 prob = deptInfo->assistant_professor_promotion_probability[department_res.get_prob_school_type()];
00425 else
00426 return 0;
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 Department* deptPtr = department_array[department_recno];
00441
00442 float multiplier = 1, sum = 0;
00443 float weight[3];
00444 float myTalent[3] = { talent_teaching, talent_scholarship, talent_research };
00445
00446 weight[0] = (deptPtr->priority_discretionary_hour_array[0]+deptPtr->priority_discretionary_hour_array[1]+deptPtr->priority_discretionary_hour_array[2]) / 3.0f;
00447 weight[1] = deptPtr->priority_discretionary_hour_array[DT_SCHOLARSHIP];
00448 weight[2] = deptPtr->priority_discretionary_hour_array[DT_RESEARCH];
00449
00450 for (int i=0; i<3; i++)
00451 sum += weight[i];
00452
00453 for (i=0; i<3; i++)
00454 weight[i] = math.safe_divide( weight[i], sum );
00455
00456
00457 for (i=0, sum=0; i<3; i++)
00458 sum += weight[i] * myTalent[i];
00459
00460 multiplier = 1+(sum-50.0f)/100;
00461
00462
00463
00464 if ( rank_level == ASST_PROF ) {
00465 const int remap[INPUT_OPTION_COUNT] = { 25, 50, 74 };
00466
00467 multiplier *= 1-(remap[player_school.faculty_promotion_difficulity]-50)/100.0f;
00468
00469
00470
00471 multiplier = math.single_response_func(0.1f, 1.9f, 100.0f, 50.0f, multiplier);
00472 }
00473
00474 if ( math.get_random_float() > multiplier * prob )
00475 return 0;
00476
00477 rank_level++;
00478
00479 #if(GAME_VERSION>=200)
00480
00481
00482 Faculty* orgPtr = this;
00483
00484 deptPtr->cur_faculty_array.linkin(orgPtr);
00485
00486 int arraySize = deptPtr->cur_faculty_array.size();
00487
00488 Faculty* facPtr = (Faculty*) deptPtr->cur_faculty_array.get(arraySize);
00489
00490 facPtr->employ_status = 2;
00491 #endif
00492
00493 return 1;
00494 }
00495
00496
00497
00498
00502
00503 const int VAR_COUNT = 2;
00504 float input[VAR_COUNT];
00505
00506 err_when(retireOffer<0);
00507
00508 #if(GAME_VERSION>=200)
00509 if ( rank_level == LONG_TERM_ADJUNCT )
00510 input[0] = float(retireOffer) / salary;
00511 else
00512 input[0] = float(retireOffer) / salary * 0.5;
00513 #else
00514 input[0] = float(retireOffer) / salary;
00515 #endif
00516
00517 input[1] = float(100 - satisfaction_index) / 100;
00518
00519
00520 input[0] = math.dual_response_func(0, 0.340f, 1.000f, 0.668f, 3.015f, 0.505f, 2.476f, input[0]);
00521
00522 float prob = 0;
00523 float weight[VAR_COUNT] = { 0.5f, 0.5f };
00524
00525 for (int i=0; i<VAR_COUNT; i++)
00526 prob += weight[i] * input[i];
00527
00528
00529
00530 if ( math.get_random_float() > prob )
00531 return 0;
00532
00533 department_array[department_recno]->faculty_array.del(faculty_recno);
00534
00535 return 1;
00536 }
00537
00538
00539
00540
00542
00543 int i;
00544
00545 float researchdisTimeOffset;
00546
00547
00548
00549 Department* deptPtr = department_array[department_recno];
00550 DepartmentInfo* deptInfo = department_res[deptPtr->department_id];
00551 FacultyTemplate* templ = faculty_res.get_faculty_template(deptInfo->template_discretionary_time, rank_age_group() );
00552
00553 researchdisTimeOffset = math.safe_divide(research_month_expense_direct, deptPtr->research_dollar_norm);
00554 researchdisTimeOffset = math.dual_response_func(0,10.09f, 20, 0.802f, 0.690f, 0.403f, 2.189f, researchdisTimeOffset);
00555
00556 err_when(researchdisTimeOffset < 0);
00557
00558
00559 float adjustedBaseDisTime[DISCRETIONARY_TYPE_COUNT];
00560
00561 for ( i=0; i < DISCRETIONARY_TYPE_COUNT; i++ )
00562 adjustedBaseDisTime[i] = (float) get_discretionary_time_pref( templ->discretionary_time_pref, i);
00563
00564 float base = 1 + (researchdisTimeOffset/100.0f) * (1.0f-adjustedBaseDisTime[DT_RESEARCH]/100);
00565
00566 err_when(base == 0);
00567
00568 for ( i=0; i < DISCRETIONARY_TYPE_COUNT; i++ )
00569 adjustedBaseDisTime[i] /= base;
00570
00571 adjustedBaseDisTime[DT_RESEARCH] += (researchdisTimeOffset/100.0f) * (1.0f-adjustedBaseDisTime[DT_RESEARCH]/100) * 100.0f / base;
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 float normalizedRawTimePercent[DISCRETIONARY_TYPE_COUNT];
00591
00592 const int remap[INPUT_OPTION_COUNT] = {25,50,75};
00593 int ratio = remap[player_school.faculty_degree_to_which_priorities_reflected_in_promotion];
00594
00595 i = DT_COURSE_PREPARATION;
00596 normalizedRawTimePercent[i] = (ratio*deptPtr->relative_priority_discretionary_hour_array[i] / 100.0f
00597 + talent_teaching * get_discretionary_time_pref( templ->discretionary_time_pref, i) / 100.0f) ;
00598
00599 i = DT_OUT_OF_CLASS_STUDENT_CONTACT;
00600 normalizedRawTimePercent[i] = (ratio*deptPtr->relative_priority_discretionary_hour_array[i] / 100.0f
00601 + talent_teaching * get_discretionary_time_pref( templ->discretionary_time_pref,i) / 100.0f) ;
00602
00603 i = DT_EDUCATIONAL_DEVELOPMENT;
00604 normalizedRawTimePercent[i] = (ratio*deptPtr->relative_priority_discretionary_hour_array[i] / 100.0f
00605 + (talent_teaching + talent_scholarship) * get_discretionary_time_pref( templ->discretionary_time_pref,i) / 200.0f) ;
00606
00607 i = DT_RESEARCH;
00608 normalizedRawTimePercent[i] = (ratio*deptPtr->relative_priority_discretionary_hour_array[i] / 100.0f
00609 + talent_research * adjustedBaseDisTime[i] / 100.0f) ;
00610
00611 i = DT_SCHOLARSHIP;
00612 normalizedRawTimePercent[i] = (ratio*deptPtr->relative_priority_discretionary_hour_array[i] / 100.0f
00613 + talent_scholarship * get_discretionary_time_pref( templ->discretionary_time_pref,i) / 100.0f);
00614
00615 i = DT_INSTITUTIONAL_AND_PUBLIC_SERVICE;
00616 normalizedRawTimePercent[i] = (ratio*deptPtr->relative_priority_discretionary_hour_array[i] / 100.0f
00617 + 50 * get_discretionary_time_pref( templ->discretionary_time_pref, i) / 100.0f) ;
00618
00619 float total;
00620
00621 for ( total=0, i=0; i < DISCRETIONARY_TYPE_COUNT; i++ )
00622 total += normalizedRawTimePercent[i];
00623
00624 err_when(total < 0);
00625
00626 for ( i=0; i < DISCRETIONARY_TYPE_COUNT; i++ )
00627 normalizedRawTimePercent[i] *= 100.0f / total;
00628
00629
00630
00631 float priorPercent[DISCRETIONARY_TYPE_COUNT];
00632
00633 for ( total=0, i=0; i < DISCRETIONARY_TYPE_COUNT; i++ ) {
00634 priorPercent[i] = this->discretionary_hour_array[i];
00635 total += priorPercent[i];
00636 }
00637
00638 err_when(total < 0);
00639
00640 if ( total > 0 )
00641 for ( i=0; i < DISCRETIONARY_TYPE_COUNT; i++ )
00642 priorPercent[i] *= 100.0f / total;
00643
00644
00645
00646 float checkSum = 0, checkSum2;
00647
00648 for ( i=0; i < DISCRETIONARY_TYPE_COUNT; i++ ) {
00649 priorPercent[i] = player_school.latency_func(0.67f, normalizedRawTimePercent[i], priorPercent[i]);
00650
00651 #if(GAME_VERSION>=200)
00652
00653 if( (rank_level == LONG_TERM_ADJUNCT || rank_level == SHORT_TERM_ADJUNCT)
00654 && (i == DT_RESEARCH || i == DT_SCHOLARSHIP) )
00655 priorPercent[i] = 0.0f;
00656 #endif
00657
00658 checkSum += priorPercent[i];
00659 }
00660
00661 err_when( checkSum <=0);
00662
00663 for ( i=0; i < DISCRETIONARY_TYPE_COUNT; i++ ) {
00664 priorPercent[i] *= 100 / checkSum;
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 checkSum = 0; checkSum2 = 0;
00681
00682 int check_rank_level=0;
00683
00684 check_rank_level = this->rank_level;
00685
00686 for ( i=0; i < DISCRETIONARY_TYPE_COUNT; i++ ) {
00687 #if(GAME_VERSION>=200)
00688
00689 this->discretionary_hour_array[i] = (float)(total * priorPercent[i] / 100);
00690 #else
00691
00692 if(check_rank_level ==3 || check_rank_level ==4)
00693
00694 this->discretionary_hour_array[check_rank_level] = 0;
00695 else
00696
00697 this->discretionary_hour_array[i] = char(total * priorPercent[i] / 100 + 0.5);
00698 #endif
00699
00700 checkSum += priorPercent[i];
00701 checkSum2 += discretionary_hour_array[i];
00702 }
00703
00704 err_when(total<=0 || checkSum < 90 || checkSum > 105);
00705 err_when(checkSum2 <=0);
00706
00707
00708
00709 float strainPriority=0;
00710
00711 base = 3*talent_teaching+talent_research+talent_scholarship+50;
00712
00713 for ( total=0, i=0; i < DISCRETIONARY_TYPE_COUNT; i++ ) {
00714 total += 100 * talent_teaching * math.safe_pow((priorPercent[i] - adjustedBaseDisTime[i])/100.0f, 2) / base;
00715
00716
00717 strainPriority += math.safe_pow((deptPtr->priority_discretionary_hour_array[i] - deptPtr->last_priority_discretionary_hour_array[i]) * 10.0f, 2) / 100.0f;
00718 }
00719
00720
00721
00722
00723 float strainValue = 5 - deptPtr->pressure_to_change_teaching_load / 10.0f;
00724
00725 strain_priority = player_school.latency_func(0.5f, strain_priority, strainPriority);
00726
00727 const float weight[2] = {0.4f, 0.35f};
00728
00729 strain_on_discretionary_time = weight[0]* total + weight[1] * strainValue + (1-weight[0]-weight[1]) * strain_priority;
00730
00731
00732
00733 for ( total=0, i=0; i < DISCRETIONARY_TYPE_COUNT; i++ ) {
00734
00735 deptPtr->last_priority_discretionary_hour_array[i] = deptPtr->priority_discretionary_hour_array[i];
00736 }
00737
00738 memcpy(last_discretionary_hour_array, discretionary_hour_array, sizeof(last_discretionary_hour_array));
00739 }
00740
00741
00742
00743
00747
00748
00749
00750 if ( player_school.sponsored_research_intensity <= 0 ) {
00751
00752 err_when(research_proposal_count>0);
00753 return;
00754 }
00755
00756 int i;
00757
00758
00759 if ( rank_level == LONG_TERM_ADJUNCT || rank_level == SHORT_TERM_ADJUNCT || ave_proj_size <=0 )
00760 return;
00761
00762
00763
00764
00765
00766 float oRate = finance.get_research_overhead_rate() / 100.0f;
00767 float qualityDriver = this->get_quality_driver();
00768
00769
00770
00771
00772
00773
00774
00775 this->proj_count_mult = (0.8f + 0.4f * this->talent_research/100);
00776 this->proj_size_mult = (0.7f + 0.6f * this->talent_research/100);
00777 #if(GAME_VERSION>=200)
00778
00779
00780 float awardProb = 2.0f * (qualityDriver * 0.01f) / math.safe_pow( (1.0f + oRate), 3.0f );
00781 this->award_prob = m.fmin( 0.85f, m.fmax(0.10f, awardProb) );
00782 #else
00783 this->award_prob = (float)(0.01f + 0.9 * this->talent_research/100);
00784 #endif
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 Department* deptPtr = department_array[department_recno];
00800 DepartmentInfo* deptInfo = department_res[deptPtr->department_id];
00801 FacultyTemplate* templ = faculty_res.get_faculty_template(deptInfo->template_discretionary_time, rank_age_group() );
00802 PeerSchool *playerSchool = school_res.player_peer_school;
00803
00804
00805
00806 for (i=0; i<research_proposal_count; i++) {
00807 ResearchProposal* researchProposal = research_proposal_array+i;
00808
00809 if ( researchProposal->status == RESEARCH_PROPOSED ) {
00810
00811 if ( math.get_random_float() < award_prob ) {
00812
00813 researchProposal->status = RESEARCH_ACTIVE;
00814
00815
00816
00817
00818
00819
00820
00821 researchProposal->date_to_next_status = info.game_date + (1+m.random(12)) * 30;
00822
00823
00824
00825
00826 research_month_expense += researchProposal->total_dollars / MAX_ACTIVE_RESEARCH_MONTH;
00827 research_month_expense_direct += int((researchProposal->total_dollars / MAX_ACTIVE_RESEARCH_MONTH ) / ( 1+researchProposal->overhead_rate));
00828 #if(GAME_VERSION>=200)
00829 deptPtr->research_m_history[R_ACCEPT][THIS_MONTH] += (float)researchProposal->total_dollars / (MAX_ACTIVE_RESEARCH_MONTH * 1000);
00830 #else
00831
00832
00833
00834
00835
00836
00837 deptPtr->research_m_history[R_ACCEPT][THIS_MONTH] += (researchProposal->total_dollars / MAX_ACTIVE_RESEARCH_MONTH / 1000);
00838
00839 #endif
00840 }
00841 }
00842 else if ( researchProposal->status == RESEARCH_ACTIVE ) {
00843 }
00844 else
00845 err_here();
00846
00847
00848
00849 if ( info.game_date >= researchProposal->date_to_next_status) {
00850
00851 if ( researchProposal->status == RESEARCH_PROPOSED ) {
00852 #if(GAME_VERSION>=200)
00853 deptPtr->research_m_history[R_REJECT][THIS_MONTH] += (float)researchProposal->total_dollars / (MAX_ACTIVE_RESEARCH_MONTH * 1000);
00854 #else
00855
00856
00857
00858
00859
00860
00861 deptPtr->research_m_history[R_REJECT][THIS_MONTH] += (researchProposal->total_dollars / MAX_ACTIVE_RESEARCH_MONTH / 1000);
00862
00863 #endif
00864 }
00865
00866
00867 else if ( researchProposal->status == RESEARCH_ACTIVE ) {
00868
00869 research_month_expense -= researchProposal->total_dollars / MAX_ACTIVE_RESEARCH_MONTH;
00870 research_month_expense_direct -= int((researchProposal->total_dollars / MAX_ACTIVE_RESEARCH_MONTH ) / ( 1+researchProposal->overhead_rate));
00871
00872 }
00873
00874 for (int j=i+1; j<research_proposal_count; j++) {
00875 memcpy(research_proposal_array+j-1, research_proposal_array+j, sizeof(ResearchProposal));
00876 }
00877 research_proposal_count--;
00878 i--;
00879
00880 }
00881
00882 }
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917 Faculty* facultyPtr = this;
00918 int projectCount = 0;
00919 float prob=0;
00920
00921
00922
00923
00924
00925
00926 #if(GAME_VERSION>=200)
00927 float normalSpaceArea = facility_office.normal_area[HISTORY_MONTH_COUNT-1];
00928 float actualSpaceArea = facility_office.actual_area[HISTORY_MONTH_COUNT-1];
00929 float shortFallRatio = max(0, math.safe_divide((normalSpaceArea-actualSpaceArea),normalSpaceArea));
00930
00931 float forCalcProb = (facultyPtr->award_prob);
00932
00933 forCalcProb *= (1-shortFallRatio/0.15);
00934 #else
00935
00936 const float forCalcProb = (facultyPtr->award_prob);
00937 #endif
00938
00939 float randNum = math.get_random_float();
00940
00941 for ( i=0, prob=0; i<=MAX_RESEARCH_PROPOSAL; i++) {
00942 prob += math.double_poisson(i, forCalcProb);
00943
00944 if ( randNum < prob ) {
00945 projectCount = i;
00946 break;
00947 }
00948 }
00949
00950
00951
00952 for( ; projectCount > 0 && facultyPtr->research_proposal_count < MAX_RESEARCH_PROPOSAL;
00953 projectCount--, facultyPtr->research_proposal_count++ ) {
00954 ResearchProposal* researchProposal = facultyPtr->research_proposal_array + facultyPtr->research_proposal_count;
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 int tmp = (int) m.fmax(0.0f, facultyPtr->proj_size_mult * facultyPtr->ave_proj_size * 1000 * math.get_random_snd(1.0f, 0.10f));
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974 researchProposal->total_dollars = tmp ;
00975
00976 researchProposal->overhead_rate = oRate;
00977
00978 researchProposal->status = RESEARCH_PROPOSED;
00979
00980
00981
00982
00983
00984
00985 researchProposal->date_to_next_status = info.game_date + (1 + m.random(3) ) * 30;
00986
00987 #if(GAME_VERSION>=200)
00988 deptPtr->research_m_history[R_PROPOSAL][THIS_MONTH] += (float)researchProposal->total_dollars / (MAX_ACTIVE_RESEARCH_MONTH * 1000);
00989 #else
00990
00991
00992
00993
00994
00995
00996 deptPtr->research_m_history[R_PROPOSAL][THIS_MONTH] += (researchProposal->total_dollars / MAX_ACTIVE_RESEARCH_MONTH /1000);
00997
00998 #endif
00999
01000 }
01001
01002 }
01003
01004
01005
01006
01008
01009 static String str;
01010
01011 int yearCount = (info.game_date-start_teaching_date) / 365;
01012 int monthCount = ((info.game_date-start_teaching_date) % 365) / 30;
01013
01014
01015
01016 if( yearCount > 0 ) {
01017 str = yearCount;
01018
01019 if( yearCount > 1 )
01020 str += " years";
01021 else
01022 str += " year";
01023 }
01024 else
01025 str = "";
01026
01027 str += " ";
01028
01029
01030
01031 if( monthCount > 0 ) {
01032 str += monthCount;
01033
01034 if( monthCount > 1 )
01035 str += " months";
01036 else
01037 str += " month";
01038 }
01039
01040 return str;
01041 }
01042
01043
01044
01045
01047
01048 float totalHour=teaching_contact_hour;
01049
01050 for( int i=0 ; i<DISCRETIONARY_TYPE_COUNT ; i++ )
01051 totalHour += discretionary_hour_array[i];
01052
01053 return totalHour;
01054 }
01055
01056
01057
01058
01060
01061 static String str;
01062
01063 str = hourCount;
01064
01065 if( hourCount > 1 )
01066 str += " hours";
01067 else
01068 str += " hour";
01069
01070 return str;
01071 }
01072
01073
01074
01075
01077
01078
01079
01080 if ( ! name_res.is_male(first_name_id) ) {
01081 String str = name_res.first_name_array[first_name_id-1].name;
01082
01083 if ( str == "Catherine" &&
01084
01085 ( gender_ethnic_group == NONMINORITY_MALE || gender_ethnic_group == MINORITY_MALE ) ) {
01086 err_now("ofaculty.cpp: line 864: Faculty::name():");
01087
01088 }
01089 }
01090
01091 err_if( faculty_photo_res[photo_id]->gender_ethnic_group != this->gender_ethnic_group )
01092 err_here();
01093
01094 return name_res.get_name_str( first_name_id, middle_name_id, last_name_id );
01095 }
01096
01097
01098
01099 #if(GAME_VERSION>=200)
01100
01102
01103 return name_res.get_name_str( firstNameId, middleNameId, lastNameId );
01104 }
01105
01106
01107 #endif
01108
01109
01111
01112
01113
01114 int i;
01115 const int VAR_COUNT = 4;
01116 float input[VAR_COUNT];
01117
01118 float qualityDriver=0;
01119 Department* deptPtr = department_array[department_recno];
01120
01121 input[0] = talent_research;
01122 input[1] = performance_research;
01123 input[2] = deptPtr->p_academic_standing;
01124 input[3] = school_res.player_peer_school->prestige;
01125
01126 input[0] = math.dual_response_func(0, 48.9f, 100, 65.52f, 32.19f, 29.67f, 79.24f, input[0]);
01127 input[1] = math.dual_response_func(0, 49.3f, 100, 71.18f, 23.22f, 30.35f, 62.56f, input[1]);
01128 input[2] = math.dual_response_func(0, 49.72f, 100, 72.29f, 30.76f, 39.41f, 83.34f, input[2]);
01129 input[3] = math.dual_response_func(0, 49.8f, 100, 58.89f, 18.19f, 29.91f, 89.79f, input[3]);
01130
01131 const float weight[VAR_COUNT] = { 0.3f, 0.3f, 0.25f, 0.15f };
01132
01133 for (i=0; i<VAR_COUNT; i++)
01134 qualityDriver += weight[i] * input[i];
01135
01136 return chance_event.research_adjust_multiplier * qualityDriver;
01137 }
01138
01139