int console_cmd_rein(game_state *gs, int argc, char **argv) { scene *sc = game_state_get_scene(gs); if(is_arena(sc->id)) { arena_toggle_rein(sc); return 0; } return 1; }
int ai_controller_poll(controller *ctrl, ctrl_event **ev) { ai *a = ctrl->data; object *o = ctrl->har; if (!o) { return 1; } har *h = object_get_userdata(o); object *o_enemy = game_state_get_player(o->gs, h->player_id == 1 ? 0 : 1)->har; // Do not run AI while the game is paused if(game_state_is_paused(o->gs)) { return 0; } // Do not run AI while match is starting or ending // XXX this prevents the AI from doing scrap/destruction moves // XXX this could be fixed by providing a "scene changed" event if(is_arena(game_state_get_scene(o->gs)->id) && arena_get_state(game_state_get_scene(o->gs)) != ARENA_STATE_FIGHTING) { // null out selected move to fix the "AI not moving problem" a->selected_move = NULL; return 0; } // Grab all projectiles on screen vector_clear(&a->active_projectiles); game_state_get_projectiles(o->gs, &a->active_projectiles); // Try to block har if(ai_block_har(ctrl, ev)) { return 0; } // Try to block projectiles if(ai_block_projectile(ctrl, ev)) { return 0; } if(a->selected_move) { // finish doing the selected move first if(a->input_lag_timer > 0) { a->input_lag_timer--; } else { a->move_str_pos--; if(a->move_str_pos <= 0) { a->move_str_pos = 0; } a->input_lag_timer = a->input_lag; } int ch = str_at(&a->selected_move->move_string, a->move_str_pos); controller_cmd(ctrl, char_to_act(ch, o->direction), ev); } else if(rand_int(100) < a->difficulty) { af_move *selected_move = NULL; int top_value = 0; // Attack for(int i = 0; i < 70; i++) { af_move *move = NULL; if((move = af_get_move(h->af_data, i))) { move_stat *ms = &a->move_stats[i]; if(is_valid_move(move, h)) { int value = ms->value + rand_int(10); if (ms->min_hit_dist != -1){ if (ms->last_dist < ms->max_hit_dist+5 && ms->last_dist > ms->min_hit_dist+5){ value += 2; } else if (ms->last_dist > ms->max_hit_dist+10){ value -= 3; } } value -= ms->attempts/2; value -= ms->consecutive*2; if (is_special_move(move) && !maybe(a->difficulty)) { DEBUG("skipping special move %s because of difficulty", str_c(&move->move_string)); continue; } if (selected_move == NULL){ selected_move = move; top_value = value; } else if (value > top_value) { selected_move = move; top_value = value; } } } } for(int i = 0; i < 70; i++) { a->move_stats[i].consecutive /= 2; } if(selected_move) { a->move_stats[selected_move->id].attempts++; a->move_stats[selected_move->id].consecutive++; // do the move a->selected_move = selected_move; a->move_str_pos = str_size(&selected_move->move_string)-1; a->move_stats[a->selected_move->id].last_dist = fabsf(o->pos.x - o_enemy->pos.x); a->blocked = 0; DEBUG("AI selected move %s", str_c(&selected_move->move_string)); } } else { // Change action after 30 ticks if(a->act_timer <= 0 && rand_int(100) > 88){ int p = rand_int(100); if(p > 40){ // walk forward a->cur_act = (o->direction == OBJECT_FACE_RIGHT ? ACT_RIGHT : ACT_LEFT); } else if(p > 20){ // walk backward a->cur_act = (o->direction == OBJECT_FACE_RIGHT ? ACT_LEFT : ACT_RIGHT); } else if(p > 10){ // do nothing a->cur_act = ACT_STOP; } else { // crouch and block a->cur_act = (o->direction == OBJECT_FACE_RIGHT ? ACT_DOWN|ACT_LEFT : ACT_DOWN|ACT_RIGHT); } a->act_timer = 30; controller_cmd(ctrl, a->cur_act, ev); } else { a->act_timer--; } // Jump once in a while if(rand_int(100) == 88){ if(o->vel.x < 0) { controller_cmd(ctrl, ACT_UP|ACT_LEFT, ev); } else if(o->vel.x > 0) { controller_cmd(ctrl, ACT_UP|ACT_RIGHT, ev); } else { controller_cmd(ctrl, ACT_UP, ev); } } } return 0; }