#include "control_parser.h" #include #include #include typedef control_parser_ctx context; static void extract(context *ctx, char *fpc) { gssize curpos = (fpc - ctx->buffer->str); gssize len = curpos - ctx->mark; g_string_truncate(ctx->tmp, 0); g_string_append_len(ctx->tmp, ctx->buffer->str + ctx->mark, len); ctx->mark = -1; /* printf("Read chunk '%s'\n", ctx->tmp->str); */ } static double extract_double(context *ctx, char *fpc) { extract(ctx, fpc); return strtod(ctx->tmp->str, NULL); } static timestamp extract_ts(context *ctx, char *fpc) { extract(ctx, fpc); return atoi(ctx->tmp->str); } %%{ machine control_parser; variable cs ctx->cs; action done { t->alive = 0; /* fprintf(stderr, "Run finished\n"); */ fbreak; } action mark { ctx->mark = fpc - ctx->buffer->str; } action telemetrystart { ctx->tm = telemetry_new(); } action telemetrystop { g_queue_push_tail(&t->telemetry, ctx->tm); if (!t->alive) { t->vehicle.accel = ctx->tm->vehicle.accel; t->vehicle.turn = ctx->tm->vehicle.turn; gettimeofday(&t->started, NULL); /* fprintf(stderr, "New run\n"); */ } else { dgl(t, &t->sim.tm.vehicle, &t->sim.tm.vehicle, ctx->tm->ts - t->sim.tm.ts); ctx->tm->vehicle.w = t->sim.tm.vehicle.w; /* fprintf(stderr, "time difference [ms]: %i\n", getcurts(t) - ctx->tm->ts); */ fprintf(stderr, "Miss predict: dx=%f, dy=%f, ddir=%f, steps=%u\n", t->sim.tm.vehicle.x - t->vehicle.x, t->sim.tm.vehicle.y - t->vehicle.y, t->sim.tm.vehicle.dir - t->vehicle.dir, t->sim.steps); } /* Reset simulation */ t->sim.tm.ts = ctx->tm->ts; t->sim.tm.vehicle = ctx->tm->vehicle; g_array_set_size(t->sim.tm.objects, 0); g_array_append_vals(t->sim.tm.objects, ctx->tm->objects->data, ctx->tm->objects->len); t->sim.steps = 0; t->last_ts = ctx->tm->ts; ctx->tm = NULL; t->alive = 1; } action vehicle { ctx->tm->ts = ctx->ts; ctx->tm->vehicle.x = ctx->x; ctx->tm->vehicle.y = ctx->y; ctx->tm->vehicle.dir = ctx->dir; ctx->tm->vehicle.speed = ctx->speed; t->vehicle.x = ctx->x; t->vehicle.y = ctx->y; t->vehicle.dir = ctx->dir; t->vehicle.speed = ctx->speed; /* printf("Vehicle at %f / %f\n", ctx->x, ctx->y); */ } SP = " "; double = '-'? (digit | '.')*; dx = double >mark % { t->map.dx = extract_double(ctx, fpc); }; dy = double >mark % { t->map.dy = extract_double(ctx, fpc); }; min_sensor = double >mark % { t->map.min_sensor = extract_double(ctx, fpc); }; max_sensor = double >mark % { t->map.max_sensor = extract_double(ctx, fpc); }; max_speed = double >mark % { t->map.max_speed = extract_double(ctx, fpc); }; max_turn = double >mark % { t->map.max_turn = extract_double(ctx, fpc); }; max_hard_turn = double >mark % { t->map.max_hard_turn = extract_double(ctx, fpc); }; init = "I" SP dx SP dy SP double SP min_sensor SP max_sensor SP max_speed SP max_turn SP max_hard_turn SP ";"; x = double >mark % { ctx->x = extract_double(ctx, fpc); }; y = double >mark % { ctx->y = extract_double(ctx, fpc); }; r = double >mark % { ctx->r = extract_double(ctx, fpc); }; dir = double >mark % { ctx->dir = extract_double(ctx, fpc); }; speed = double >mark % { ctx->speed = extract_double(ctx, fpc); }; ctl = ( "a" @ { ctx->tm->vehicle.accel = ACCEL; } | "-" @ { ctx->tm->vehicle.accel = ROLL; } | "b" @ { ctx->tm->vehicle.accel = BRAKE; } ) ( "L" @ { ctx->tm->vehicle.turn = TURN_HARD_LEFT; } | "l" @ { ctx->tm->vehicle.turn = TURN_LEFT; } | "-" @ { ctx->tm->vehicle.turn = TURN_STRAIGHT; } | "r" @ { ctx->tm->vehicle.turn = TURN_RIGHT; } | "R" @ { ctx->tm->vehicle.turn = TURN_HARD_RIGHT; } ); timestamp = (digit*) >mark % { ctx->ts = extract_ts(ctx, fpc); }; score = (digit*) >mark % { printf("Score %u\n", extract_ts(ctx, fpc)); }; boulder = "b" SP x SP y SP r SP % { object *o = object_new(BOLDER, ctx->x, ctx->y, ctx->r, 0, 0); /* g_array_append_vals(ctx->tm->objects, o, 1); */ g_hash_table_replace(t->map.solid_objects, o, o); }; crater = "c" SP x SP y SP r SP % { object *o = object_new(CRATER, ctx->x, ctx->y, ctx->r, 0, 0); /* g_array_append_vals(ctx->tm->objects, o, 1); */ g_hash_table_replace(t->map.solid_objects, o, o); }; homebase = "h" SP x SP y SP r SP; # ignore it martian = "m" SP x SP y SP dir SP speed SP % { object o = { MARTIAN, ctx->x, ctx->y, MARTIAN_RADIUS, ctx->dir, ctx->speed }; g_array_append_val(ctx->tm->objects, o); }; object = boulder | crater | homebase | martian; objects = object*; telemetry = ( ("T" SP timestamp SP ctl SP x SP y SP dir SP speed SP) %vehicle objects) >telemetrystart ";" % telemetrystop; # crash Boulder = "B" SP timestamp SP ";"; # fell Crater = "C" SP timestamp SP ";"; # killed by martian Kill = "K" SP timestamp SP ";"; Success = "S" SP timestamp SP ";"; End = "E" SP timestamp SP score SP ";"; main := init? (telemetry | Boulder)* (Crater | Kill | Success)? End @ done; }%% %% write data; static int control_parser_has_error(context *ctx) { return ctx->cs == control_parser_error; } static int control_parser_is_finished(context *ctx) { return ctx->cs >= control_parser_first_final; } void control_parser_new(trial *t) { context *ctx = t->parse_ctx = g_slice_new(context); %% write init; ctx->buffer = g_string_sized_new(0); ctx->tmp = g_string_sized_new(0); ctx->mark = -1; ctx->pos = 0; } void control_parser_reset(trial *t) { context *ctx = t->parse_ctx; %% write init; g_string_truncate(ctx->tmp, 0); ctx->mark = -1; /* fprintf(stderr, "Parser reset\n"); */ } void control_parser_free(trial *t) { g_string_free(t->parse_ctx->buffer, TRUE); g_string_free(t->parse_ctx->tmp, TRUE); g_slice_free(context, t->parse_ctx); } run_t control_parse(trial *t) { context *ctx = t->parse_ctx; gsize wehave; if (0 < (wehave = ctx->buffer->len - ctx->pos)) { char *p, *pe; p = ctx->buffer->str + ctx->pos; pe = p + wehave; /* fprintf(stderr, "Parsing '%s' (len=%zu)\n", p, wehave); */ %% write exec; ctx->pos = p - ctx->buffer->str; if (ctx->mark == -1) { g_string_erase(ctx->buffer, 0, ctx->pos); ctx->pos = 0; } else if (ctx->mark) { g_string_erase(ctx->buffer, 0, ctx->mark); ctx->pos -= ctx->mark; ctx->mark = 0; } } else { fprintf(stderr, "No data to parse\n"); } if (control_parser_has_error(ctx)) { fprintf(stderr, "Parse error: '%s'\n", ctx->buffer->str + ctx->pos); shutdown(t->socket, SHUT_RDWR); close(t->socket); exit(126); return RUN_ERROR; } if (control_parser_is_finished(ctx)) return RUN_DONE; return RUN_GO_ON; }