void send (PORT dest_port, void* data) { PROCESS dest; assert (dest_port->magic == MAGIC_PORT); dest = dest_port->owner; assert (dest->magic == MAGIC_PCB); if (dest_port->open && dest->state == STATE_RECEIVE_BLOCKED) { /* * Receiver is receive blocked. We can deliver our message * immediately. */ dest->param_proc = active_proc; dest->param_data = data; active_proc->state = STATE_REPLY_BLOCKED; add_ready_queue (dest); } else { /* * Receiver is busy or the port is closed. * Get on the send blocked queue of the port. */ add_to_send_blocked_list (dest_port, active_proc); active_proc->state = STATE_SEND_BLOCKED; active_proc->param_data = data; } active_proc->param_data = data; remove_ready_queue (active_proc); resign(); }
void message(PORT dest_port, void *data) { volatile unsigned int cpsr_flag; PROCESS dest; SAVE_CPSR_DIS_IRQ(cpsr_flag); assert(dest_port->magic == MAGIC_PORT); dest = dest_port->owner; assert(dest->magic == MAGIC_PCB); if (dest_port->open && dest->state == STATE_RECEIVE_BLOCKED) { dest->param_proc = active_proc; dest->param_data = data; add_ready_queue(dest); // kprintf("Wakeup %s\n", dest->name); } else { /* * Receiver is busy or the port is closed. * Get on the send blocked queue of the port. */ add_to_send_blocked_list(dest_port, active_proc); remove_ready_queue(active_proc); active_proc->state = STATE_MESSAGE_BLOCKED; active_proc->param_data = data; // kprintf("%s Message BLOCKED\n", active_proc->name); } resign(); RESUME_CPSR(cpsr_flag); }
//Sends data to specified port void send (PORT dest_port, void* data) { volatile int flag; DISABLE_INTR(flag); PROCESS dest_process = dest_port->owner; //if (reciever is recieved blocked and port is open) if (dest_port->open && dest_process->state == STATE_RECEIVE_BLOCKED) { dest_process->param_proc = active_proc; dest_process->param_data = data; //Change Reciever to STATE_READY //taken care of by dispatch add_ready_queue (dest_process); //Change to STATE_REPLY_BLOCKED active_proc->state = STATE_REPLY_BLOCKED; } //else else { active_proc->param_data = data; //Get on the send blocked list of the port if (dest_port->blocked_list_head == NULL) dest_port->blocked_list_head = active_proc; else dest_port->blocked_list_tail->next_blocked = active_proc; dest_port->blocked_list_tail = active_proc; active_proc->next_blocked = NULL; //change state to STATE_SEND_BLOCKED active_proc->state = STATE_SEND_BLOCKED; } active_proc->param_data = data; remove_ready_queue (active_proc); resign(); ENABLE_INTR(flag); }
//Sends data to specified port void message (PORT dest_port, void* data) { volatile int flag; DISABLE_INTR(flag); PROCESS dest_process = dest_port->owner; //if (receiver is receive blocked and port is open) if (dest_process->state == STATE_RECEIVE_BLOCKED && dest_port->open) { dest_process->param_proc = active_proc; dest_process->param_data = data; //Change receiver to STATE_READY add_ready_queue (dest_process); } //else else { active_proc->param_data = data; //Get on the send blocked list of the port if (dest_port->blocked_list_head == NULL) dest_port->blocked_list_head = active_proc; else dest_port->blocked_list_tail->next_blocked = active_proc; dest_port->blocked_list_tail = active_proc; active_proc->next_blocked = NULL; remove_ready_queue (active_proc); //Change to STATE_MESSAGE_BLOCKED active_proc->state = STATE_MESSAGE_BLOCKED; active_proc->param_data = data; } resign(); ENABLE_INTR(flag); }
void train_process(PROCESS self, PARAM param) { disable_keyboard(); run_train(); enable_keyboard(); remove_ready_queue(self); resign(); }
void reply (PROCESS sender) { if (sender->state != STATE_REPLY_BLOCKED) panic ("reply(): Not reply blocked"); add_ready_queue (sender); resign(); }
void send(PORT dest_port, void *data) { volatile unsigned int cpsr_flag; PROCESS dest; SAVE_CPSR_DIS_IRQ(cpsr_flag); assert(dest_port->magic == MAGIC_PORT); dest = dest_port->owner; assert(dest->magic == MAGIC_PCB); if (dest_port->open && dest->state == STATE_RECEIVE_BLOCKED) { /* * Receiver is receive blocked. We can deliver our message * immediately. */ dest->param_proc = active_proc; dest->param_data = data; active_proc->state = STATE_REPLY_BLOCKED; // kprintf("Wakeup %s, %s REPLY BLOCKED\n", dest->name, // active_proc->name); add_ready_queue(dest); } else { /* * Receiver is busy or the port is closed. * Get on the send blocked queue of the port. */ add_to_send_blocked_list(dest_port, active_proc); active_proc->state = STATE_SEND_BLOCKED; active_proc->param_data = data; // kprintf("%s Send BLOCKED\n", active_proc->name); } active_proc->param_data = data; remove_ready_queue(active_proc); resign(); RESUME_CPSR(cpsr_flag); }
void f() { PROCESS proc; proc = fork(); if (proc == NULL) { kprintf("Child process\n"); print_all_processes(kernel_window); kprintf("\n"); // Give the parent a chance to run resign(); test_failed(90); } // Give the parent a chance to run resign(); kprintf("Parent process\n"); }
void reply (PROCESS sender) { volatile int flag; DISABLE_INTR (flag); //Add the process replied to back to the ready queue add_ready_queue (sender); //resign() resign(); ENABLE_INTR (flag); }
void reply(PROCESS sender) { volatile unsigned int cpsr_flag; SAVE_CPSR_DIS_IRQ(cpsr_flag); if (sender->state != STATE_REPLY_BLOCKED) panic("reply(): Not reply blocked"); add_ready_queue(sender); // kprintf("Wake up %s\n", sender->name); resign(); RESUME_CPSR(cpsr_flag); }
void* receive (PROCESS* sender) { volatile int flag; DISABLE_INTR(flag); PROCESS receiver_process; //Scanning send blocked list PORT p = active_proc->first_port; while (p != NULL) { if (p->open && p->blocked_list_head != NULL) // Found a process on the send blocked list break; p = p->next; } //if (send blocked list is not empty) if (p != NULL) { //sender = first process on the send blocked list receiver_process = p->blocked_list_head; *sender = receiver_process; //data = receiver_process->param_data; //cleanup pointer to next process p->blocked_list_head = p->blocked_list_head->next_blocked; if (p->blocked_list_head == NULL) p->blocked_list_tail = NULL; //if (sender is STATE_MESSAGE_BLOCKED) if (receiver_process->state == STATE_MESSAGE_BLOCKED) { //Change state of sender to STATE_READY add_ready_queue (receiver_process); ENABLE_INTR (flag); return receiver_process->param_data; } //if (sender is STATE_SEND_BLOCKED) else if (receiver_process->state == STATE_SEND_BLOCKED) { //Change state of sender to STATE_REPLY_BLOCKED receiver_process->state = STATE_REPLY_BLOCKED; ENABLE_INTR (flag); return receiver_process->param_data; } } //else remove_ready_queue (active_proc); active_proc->param_data = NULL; active_proc->state = STATE_RECEIVE_BLOCKED; //Change to STATE_RECEIVED_BLOCKED resign(); *sender = active_proc->param_proc; ENABLE_INTR (flag); return active_proc->param_data; }
void test_dispatcher_7_process_f(PROCESS self, PARAM param) { kprintf("%s\n", self->name); if (check_sum != 0) test_failed(23); check_sum += 1; resign(); kprintf("Back to %s \n", self->name); if (check_sum != 7) test_failed(24); check_sum += 8; remove_ready_queue(self); check_num_proc_on_ready_queue(2); if (test_result != 0) test_failed(test_result); resign(); test_failed(26); }
void test_dispatcher_7_process_d(PROCESS self, PARAM param) { kprintf("%s\n", self->name); if (check_sum != 3) test_failed(24); check_sum += 4; resign(); kprintf("Back to process %s \n", self->name); if (check_sum != 15) test_failed(24); check_sum += 16; resign(); kprintf("Back to process %s again\n\n", self->name); if (check_sum != 31) test_failed(24); check_sum += 32; return_to_boot(); }
void test_dispatcher_5_process_d(PROCESS self, PARAM param) { kprintf("Process: %s\n\n", self->name); print_all_processes(kernel_window); kprintf("\n"); if (check_sum != 2) test_failed(23); check_sum += 1; resign(); test_failed(24); }
/* * This test creates a sender and a receiver process. The receiver process * has the higher priority and is scheduled first. * The execution sequence is as follow: * 1. The receiver executes a receive() and becomes RECEIVE_BLOCKED. * 2. The sender gets executed and does a send(). The message is immediately * delivered, unblocking the receiver and making the sender REPLY_BLOCKED. * 3. The receiver is executed. It does a receive and becomes RECEIVE_BLOCKED * again. * 4. The sender gets executed and does a message(). The message is immediately * delivered, unblocking the receiver. The sender is still STATE_READY. * 5. The receiver gets the execution again. * This test send() and message() in the case that the receiver is * ready to receive. It also test receive() in the case that there is no * messages pending. */ void test_ipc_3() { PORT new_port; test_reset(); new_port = create_process (test_ipc_3_receiver_process, 6, 0, "Receiver"); create_process(test_ipc_3_sender_process, 5, (PARAM) new_port, "Sender"); resign(); kprintf("Back to boot.\n"); if (check_sum == 1 || check_sum == 7) test_failed(52); }
void *receive(PROCESS *sender) { PROCESS deliver_proc; PORT port; void *data; volatile unsigned int cpsr_flag; SAVE_CPSR_DIS_IRQ(cpsr_flag); data = NULL; port = active_proc->first_port; if (port == NULL) panic("receive(): no port created for this process"); while (port != NULL) { assert(port->magic == MAGIC_PORT); if (port->open && port->blocked_list_head != NULL) break; port = port->next; } if (port != NULL) { deliver_proc = port->blocked_list_head; assert(deliver_proc->magic == MAGIC_PCB); *sender = deliver_proc; data = deliver_proc->param_data; port->blocked_list_head = port->blocked_list_head->next_blocked; if (port->blocked_list_head == NULL) port->blocked_list_tail = NULL; if (deliver_proc->state == STATE_MESSAGE_BLOCKED) { add_ready_queue(deliver_proc); // kprintf("Receive wakeup %s\n", deliver_proc->name); RESUME_CPSR(cpsr_flag); return data; } else if (deliver_proc->state == STATE_SEND_BLOCKED) { deliver_proc->state = STATE_REPLY_BLOCKED; // kprintf("%s reply blocked\n", deliver_proc->name); RESUME_CPSR(cpsr_flag); return data; } } /* No messages pending */ active_proc->param_data = data; active_proc->state = STATE_RECEIVE_BLOCKED; // kprintf("%s receive blocked\n", active_proc->name); remove_ready_queue(active_proc); resign(); *sender = active_proc->param_proc; data = active_proc->param_data; RESUME_CPSR(cpsr_flag); return data; }
/* This test creates a receiver process. * The execution sequences are: * 1. The receiver creates three sender processes with lower priority. * sender_2 and sender_3 has higher priority than sender_1. * 2. The receiver creates two new ports: port3 and port2 * 3. The receiver closes its port2 and port3. * 4. The receiver executes a receive() and become STATE_RECEIVE_BLOCKED * 5. Sender_process_3 gets the chance to run. It does a message() to port3 of * the receiver and become STATE_MESSAGE_BLOCKED. It is added to the blocked list of port3. * 6. Sender_process_2 gets the chance to run. It does a message() to port2 of * the receiver and become STATE_MESSAGE_BLOCKED. It is added to the blocked list of port2. * 7. Sender_process_1 gets the chance to run. It does a send() to port1 of * the receiver and become STATE_REPLY_BLOCKED. * 8. The receiver wakes up and receives the message from sender_process_1. * 9. The receiver opens port2 and port3. * 10. The receiver does a receive, and receiver the message from sender_ process_3 (or sender_process_2, depending on the implementation of create_new_port() ). * 11. The receiver executes a receive() again and receives the message from * sender_process_2 ( or sender_process_3. ) * This test case tests scanning the ports. */ void test_ipc_6() { PORT port1; test_reset(); port1 = create_process(test_ipc_6_receiver, 6, 0, "Receiver"); check_sum = 0; resign(); kprintf("Back to boot.\n"); if (check_sum != 15) test_failed(59); }
/* * Passes execution to boot process. * Precondition: * 1. pcb[0] is used for boot process. * 2. boot process must be on ready queue */ void return_to_boot() { asm("cli"); int i; for ( i = 1; i < MAX_PROCS; i ++) { if (pcb[i].used) if (is_on_ready_queue(&pcb[i])) remove_ready_queue(&pcb[i]); } resign(); }
void Role::makeConnection() { connect(logic->getClient(),SIGNAL(getMessage(QString)),this,SLOT(decipher(QString))); connect(this,SIGNAL(sendCommand(QString)),logic->getClient(),SLOT(sendMessage(QString))); connect(decisionArea,SIGNAL(okClicked()),this,SLOT(onOkClicked())); connect(decisionArea,SIGNAL(cancelClicked()),this,SLOT(onCancelClicked())); connect(decisionArea,SIGNAL(exchangeClicked()),this,SLOT(exchangeCards())); connect(decisionArea,SIGNAL(resignClicked()),this,SLOT(resign())); connect(buttonArea->getButtons().at(0),SIGNAL(buttonSelected(int)),this,SLOT(buy())); connect(buttonArea->getButtons().at(1),SIGNAL(buttonSelected(int)),this,SLOT(synthetize())); connect(buttonArea->getButtons().at(2),SIGNAL(buttonSelected(int)),this,SLOT(extract())); connect(buttonArea,SIGNAL(buttonUnselected()),this,SLOT(onCancelClicked())); connect(handArea,SIGNAL(cardReady()),this,SLOT(cardAnalyse())); connect(playerArea,SIGNAL(playerReady()),this,SLOT(playerAnalyse())); }
void test_isr_2() { test_reset(); check_sum = 0; test_isr_2_check_sum = 0; init_interrupts(); kprintf("=== test_isr_2 === \n"); kprintf("This test will take a while.\n\n\n"); kprintf("Process 1: A\n"); kprintf("Process 2: Z\n"); create_process(test_isr_2_process_1, 5, 0, "Process 1"); create_process(test_isr_2_process_2, 5, 0, "Process 2"); resign(); if (check_sum == 0 || test_isr_2_check_sum == 0) test_failed(71); }
/* * This test creates two processes with the same priority. Doing * a resign() in the main process should continue execution in * test_process_e(). When this process does a resign(), execution * should resume in test_process_d(). Then the execution should * be passed back to test_process_e(). This basically tests Round- * Robin of ready processes. */ void test_dispatcher_5() { test_reset(); create_process(test_dispatcher_5_process_e, 5, 0, "Test process E"); kprintf("Created process E\n"); create_process(test_dispatcher_5_process_d, 5, 0, "Test process D"); kprintf("Created process D\n"); check_sum = 0; resign(); if(check_sum == 0) test_failed(21); if(check_sum != 7) test_failed(25); }
/* * Creates two new processes with different priorities. When the main * thread calls resign(), execution should continue with test_process_c() * This process then removes itself from the ready queue and calls resign() * again. Execution should then continue in test_process_a() */ void test_dispatcher_4() { test_reset(); create_process(test_dispatcher_4_process_a, 5, 42, "Test process A"); kprintf("Created process A\n"); create_process(test_dispatcher_4_process_c, 7, 0, "Test process C"); kprintf("Created process C\n"); check_sum = 0; resign(); if (check_sum == 0) test_failed(21); if (check_sum != 3) test_failed(22); }
/* * This test creates a sender and a receiver process. The sender process * has the higher priority and will be scheduled first. * The execution sequence is as follow: * 1. The sender executes a send(). Since the receiver is not RECEIVE_BLOCKED, * the sender will be SEND_BLOCKED. * 2. Execution resumes with the receiver. The receiver executes a receive(), * which will return immediately, and change the sender to state * REPLY_BLOCKED. * 3. The receivers does a reply(), and put the sender back on the ready queue. * The resign() in the reply() will therefore transfer the control back to * the sender. * 4. The sender executes a message(). Since the receiver is not * RECEIVE_BLOCKED, the sender will be MESSAGE_BLOCKED. * 5. Execution resumes with the receiver. The receiver executes a receive(), * which will return immediately, and change the sender to STATE_READY. * 6. The receiver does a resign() and pass the execution back to the sender. * This test send() and message() in the case that the receiver is not * ready to receive. It also test receive() in the case that there are messages * pending. */ void test_ipc_2 () { PORT new_port; test_reset(); new_port = create_process (test_ipc_2_receiver_process, 5, 0, "Receiver"); create_process (test_ipc_2_sender_process, 6, (PARAM) new_port, "Sender"); check_num_proc_on_ready_queue(3); check_process("Sender", STATE_READY, TRUE); check_process("Receiver", STATE_READY, TRUE); if (test_result != 0) test_failed(test_result); resign(); }
void test_dispatcher_5_process_e(PROCESS self, PARAM param) { kprintf("\nProcess: %s\n\n", self->name); if (check_sum != 0) test_failed(23); check_sum += 2; resign(); kprintf("Back to %s", self->name); if (check_sum != 3) test_failed(24); check_sum += 4; return_to_boot(); }
void* receive (PROCESS* sender) { PROCESS deliver_proc; PORT port; void *data; data = NULL; port = active_proc->first_port; if (port == NULL) panic ("receive(): no port created for this process"); while (port != NULL) { assert (port->magic == MAGIC_PORT); if (port->open && port->blocked_list_head != NULL) break; port = port->next; } if (port != NULL) { deliver_proc = port->blocked_list_head; assert (deliver_proc->magic == MAGIC_PCB); *sender = deliver_proc; data = deliver_proc->param_data; port->blocked_list_head = port->blocked_list_head->next_blocked; if (port->blocked_list_head == NULL) port->blocked_list_tail = NULL; if (deliver_proc->state == STATE_MESSAGE_BLOCKED) { add_ready_queue (deliver_proc); return data; } else if (deliver_proc->state == STATE_SEND_BLOCKED) { deliver_proc->state = STATE_REPLY_BLOCKED; return data; } } /* No messages pending */ remove_ready_queue (active_proc); active_proc->param_data = data; active_proc->state = STATE_RECEIVE_BLOCKED; resign(); *sender = active_proc->param_proc; data = active_proc->param_data; return data; }
void test_dispatcher_4_process_c(PROCESS self, PARAM param) { kprintf("\nProcess: %s\n\n", self->name); print_all_processes(kernel_window); kprintf("\n"); if (check_sum != 0) test_failed(22); check_sum += 2; remove_ready_queue(active_proc); check_num_proc_on_ready_queue(2); if (test_result != 0) test_failed(test_result); resign(); test_failed(26); }
//--------- Begin of function Unit::ai_handle_seek_path_fail --------// // // This function is used for handling cases when AI units are not // able to seek a path successfully. // int Unit::ai_handle_seek_path_fail() { if( seek_path_fail_count < 5*SEEK_PATH_FAIL_INCREMENT ) // wait unit it has failed many times return 0; //----- try to move to a new location -----// if( seek_path_fail_count==5*SEEK_PATH_FAIL_INCREMENT ) { stop_order(); // stop the unit and think for new action return 0; } //--- if the seek path has failed too many times, resign the unit ---// int resignFlag = 0; if( rank_id == RANK_SOLDIER && !leader_unit_recno ) { if( seek_path_fail_count>=7*SEEK_PATH_FAIL_INCREMENT ) resignFlag = 1; } else if( rank_id == RANK_GENERAL ) { if( seek_path_fail_count >= (7+skill_level()/10)*SEEK_PATH_FAIL_INCREMENT ) resignFlag = 1; } else { if( seek_path_fail_count >= 7*SEEK_PATH_FAIL_INCREMENT ) resignFlag = 1; } if( resignFlag && is_visible() ) { resign(COMMAND_AI); return 1; } else return 0; }
/* * This test creates three processes with the same priority. * The execution sequence is as following: * 1. After the boot process resign(), process F (test_process_f)is executed. * 2. Process F resign, process E (test_process_e) is then executed. * 3. Process E remove itself from the ready queue and then resign, process D * (test_process_d) is then executed. * 4. Process D resign(), process F is then executed. * 5. Process F remove itself from ready queue and then resign. Process D is * the next to be executed since Process E is off ready queue. * 6. Process D resign, the next to be executed is still process D since both * process F and E are off ready queue. * * The execution sequence should be: boot -> F -> E -> D -> F -> D -> D */ void test_dispatcher_7() { test_reset(); create_process(test_dispatcher_7_process_f, 5, 0, "Test process F"); kprintf("Created process F\n"); create_process(test_dispatcher_7_process_e, 5, 0, "Test process E"); kprintf("Created process E\n"); create_process(test_dispatcher_7_process_d, 5, 0, "Test process D"); kprintf("Created process D\n"); kprintf("\n"); check_num_proc_on_ready_queue(4); if (test_result != 0) test_failed(test_result); check_sum = 0; resign(); if(check_sum == 0) test_failed(21); if (check_sum != 63) test_failed(25); }
void test_isr_3 () { test_reset(); check_sum = 0; int check_2 = 0; kprintf("=== test_isr_3 === \n"); kprintf("This test will take a while.\n\n"); init_interrupts(); create_process(isr_process, 5, 0, "ISR process"); resign(); int i; int j = 0; unsigned char* screen_base; screen_base = (unsigned char*) 0xb8000 + 7 * 80 * 2; kprintf("\n\nBoot process:\n"); kprintf("ABCDEF"); PROCESS isr_pro = find_process_by_name("ISR process"); for (i = 0; i < 600000; i++) { if (isr_pro->state == STATE_INTR_BLOCKED) check_2++; *(screen_base + j * 2) = *(screen_base + j * 2) + 1; j++; if (j == 6) j = 0; } if (check_2 == 0) test_failed(72); if (check_sum <= 1) test_failed(73); }
//--------- Begin of function Unit::process_ai --------// // // [int] forceExecute - whether force execute all AI functions // without checking day interavals. // (default: 0) // void Unit::process_ai() { err_when( !nation_recno ); //-*********** simulate aat ************-// #ifdef DEBUG if(debug_sim_game_type) return; #endif //-*********** simulate aat ************-// //------ the aggressive_mode of AI units is always 1 ------// aggressive_mode = 1; //------- handle Seek Path failures ------// if( ai_handle_seek_path_fail() ) return; //--- if it's a spy from other nation, don't control it ---// if( spy_recno && true_nation_recno() != nation_recno ) { //--- a random chance of the AI catching the spy and resign it ---// if( is_visible() && misc.random(365 * FRAMES_PER_DAY)==0 ) // if the unit stay outside for one year, it will get caught { stop2(); resign(COMMAND_AI); return; } if( !spy_array[spy_recno]->notify_cloaked_nation_flag ) // if notify_cloaked_nation_flag is 1, the nation will take it as its own spies return; } //----- think about rewarding this unit -----// if( race_id && rank_id != RANK_KING && info.game_date%5 == sprite_recno%5 ) { think_reward(); } //-----------------------------------------// if( !is_visible() ) return; //--- if the unit has stopped, but ai_action_id hasn't been reset ---// if( cur_action==SPRITE_IDLE && action_mode==ACTION_STOP && action_mode2==ACTION_STOP && ai_action_id ) { nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno); err_when( ai_action_id ); // it should have been reset } //---- King flees under attack or surrounded by enemy ---// if( race_id && rank_id==RANK_KING ) { if( think_king_flee() ) return; } //---- General flees under attack or surrounded by enemy ---// if( race_id && rank_id==RANK_GENERAL && info.game_date%7 == sprite_recno%7 ) { if( think_general_flee() ) return; } //-- let Unit::next_day() process it process original_action_mode --// if( original_action_mode ) return; //------ if the unit is not stop right now ------// if( !is_ai_all_stop() ) { think_stop_chase(); return; } //-----------------------------------------// if( mobile_type==UNIT_LAND ) { if( ai_escape_fire() ) return; } //---------- if this is your spy --------// if( spy_recno && true_nation_recno()==nation_recno ) think_spy_action(); //------ if this unit is from a camp --------// if( home_camp_firm_recno ) { Firm* firmCamp = firm_array[home_camp_firm_recno]; int rc; if( rank_id == RANK_SOLDIER ) rc = firmCamp->worker_count < MAX_WORKER; else rc = !firmCamp->overseer_recno; if( rc ) { if( return_camp() ) return; } home_camp_firm_recno = 0; // the camp is already occupied by somebody } //----------------------------------------// if( race_id && rank_id==RANK_KING ) { think_king_action(); } else if( race_id && rank_id==RANK_GENERAL ) { think_general_action(); } else { if( unit_res[unit_id]->unit_class == UNIT_CLASS_WEAPON ) { if( info.game_date%15 == sprite_recno%15 ) // don't call too often as the action may fail and it takes a while to call the function each time { think_weapon_action(); //-- ships AI are called in UnitMarine --// } } else if( race_id ) { //--- if previous attempts for new action failed, don't call think_normal_human_action() so frequently then ---// if( ai_no_suitable_action ) { if( info.game_date%15 != sprite_recno%15 ) // don't call too often as the action may fail and it takes a while to call the function each time return; } //---------------------------------// if( !think_normal_human_action() ) { ai_no_suitable_action = 1; // set this flag so think_normal_human_action() won't be called continously if( !leader_unit_recno ) // only when the unit is not led by a commander { resign(COMMAND_AI); } else { ai_move_to_nearby_town(); } } } } }