void newsroom_set_names(newsroom_local *local, const char *pilot1, const char *pilot2, const char *har1, const char *har2, int sex1, int sex2) { str_create_from_cstr(&local->pilot1, pilot1); str_create_from_cstr(&local->pilot2, pilot2); str_create_from_cstr(&local->har1, har1); str_create_from_cstr(&local->har2, har2); local->sex1 = sex1; local->sex2 = sex2; // Remove the whitespace at the end of pilots name if(isspace(str_at(&local->pilot1, str_size(&local->pilot1)-1))) { str_remove_at(&local->pilot1, str_size(&local->pilot1)-1); } if(isspace(str_at(&local->pilot2, str_size(&local->pilot2)-1))) { str_remove_at(&local->pilot2, str_size(&local->pilot2)-1); } }
int is_valid_move(af_move *move, har *h) { // If category is any of these, and bot is not close, then // do not try to execute any of them. This attempts // to make the HARs close up instead of standing in place // wawing their hands towards each other. Not a perfect solution. switch(move->category) { case CAT_CLOSE: case CAT_LOW: case CAT_MEDIUM: case CAT_HIGH: // Only allow handwaving if close or jumping if(!h->close && h->state != STATE_JUMPING) { return 0; } } if(move->category == CAT_JUMPING && h->state != STATE_JUMPING) { // not jumping but trying to execute a jumping move return 0; } if(move->category != CAT_JUMPING && h->state == STATE_JUMPING) { // jumping but this move is not a jumping move return 0; } if(move->category == CAT_SCRAP && h->state != STATE_VICTORY) { return 0; } if(move->category == CAT_DESTRUCTION && h->state != STATE_SCRAP) { return 0; } // XXX check for chaining? int move_str_len = str_size(&move->move_string); char tmp; for(int i = 0; i < move_str_len; i++) { tmp = str_at(&move->move_string, i); if(!((tmp >= '1' && tmp <= '9') || tmp == 'K' || tmp == 'P')) { return 0; } } if((move->damage > 0 || move->category == CAT_PROJECTILE || move->category == CAT_SCRAP || move->category == CAT_DESTRUCTION) && move_str_len > 0) { return 1; } return 0; }
void newsroom_fixup_str(newsroom_local *local) { /* * Substitution table 1= Player1 - Crystal 2= Player2 - Steffan 3= HAR1 - jaguar 4= HAR2 - shadow 5= Arena - power plant 6= His/Her P1 - Her 7= Him/Her P1 - Her 8= He/She P1 - She 10= Him/Her P2 - Him 11= He/She P2 - He */ const char *text = NULL; if(local->screen == 0) { text = lang_get(NEWSROOM_TEXT+local->news_id); } else { text = lang_get(NEWSROOM_TEXT+local->news_id+1); } str textstr; size_t prevpos=0, pos = 0; str_create_from_cstr(&textstr, text); str_free(&local->news_str); while(str_next_of(&textstr, '~', &pos)) { str tmp; str_create(&tmp); str_substr(&tmp, &textstr, prevpos, pos); str_append(&local->news_str, &tmp); str_free(&tmp); // replace ~n tokens char n = str_at(&textstr, pos+1); char nn = str_at(&textstr, pos+2); switch(n) { case '1': if(nn == '0') { // ~10 str_append_c(&local->news_str, object_pronoun(local->sex2)); pos++; } else if(nn == '1') { // ~11 str_append_c(&local->news_str, subject_pronoun(local->sex2)); pos++; } else { // ~1 str_append(&local->news_str, &local->pilot1); } break; case '2': str_append(&local->news_str, &local->pilot2); break; case '3': str_append(&local->news_str, &local->har1); break; case '4': str_append(&local->news_str, &local->har2); break; case '5': str_append_c(&local->news_str, "Stadium"); break; case '6': str_append_c(&local->news_str, "The"); break; case '7': str_append_c(&local->news_str, object_pronoun(local->sex1)); break; case '8': str_append_c(&local->news_str, subject_pronoun(local->sex1)); break; case '9': str_append_c(&local->news_str, "WTF"); break; } pos+=2; prevpos = pos; } str tmp; str_create(&tmp); str_substr(&tmp, &textstr, pos, str_size(&textstr)); str_append(&local->news_str, &tmp); str_free(&tmp); str_free(&textstr); }
static char _scr_str_next(string_script * scr) { char c; return (0 != (c = str_at(scr->s, scr->pos++))) ? c : EOF; }
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; }