SnakeEffect now uses a hand-crafted meandering algorithm. Still not perfect, but it works as good as the old code while looking more "natural".

This commit is contained in:
Fabian Schlenz 2020-04-30 06:40:05 +02:00
parent 599bcd87bc
commit 9de77349e8

View File

@ -30,10 +30,6 @@ SnakeEffect::~SnakeEffect() {
} }
void SnakeEffect::_place_apple() { void SnakeEffect::_place_apple() {
if (SNAKE_DEBUG) {
_apple = {3, 3};
return;
}
if (_length < _pixels) { if (_length < _pixels) {
uint8_t start = random8(_pixels); uint8_t start = random8(_pixels);
for (int i=0; i<_pixels; i++) { for (int i=0; i<_pixels; i++) {
@ -60,7 +56,7 @@ void SnakeEffect::_decide() {
inputs[3] = a_l; inputs[3] = a_l;
inputs[4] = a_s; inputs[4] = a_s;
inputs[5] = a_r; inputs[5] = a_r;
if (SNAKE_DEBUG) LOGln("SnakeEffect * Position: %d, %d - Inputs: %3.1f %3.1f %3.1f %3.1f %3.1f %3.1f", _pos.x, _pos.y, inputs[0], inputs[1], inputs[2], inputs[3], inputs[4], inputs[5]); if (SNAKE_DEBUG) DBG("SnakeEffect * Position: %d, %d - Inputs: %3.1f %3.1f %3.1f %3.1f %3.1f %3.1f", _pos.x, _pos.y, inputs[0], inputs[1], inputs[2], inputs[3], inputs[4], inputs[5]);
float* outputs = NULL; float* outputs = NULL;
uint8_t i=0; uint8_t i=0;
for (uint8_t layer=1; layer<_net_layers; layer++) { for (uint8_t layer=1; layer<_net_layers; layer++) {
@ -92,7 +88,7 @@ void SnakeEffect::_decide() {
decision = decision - 1; decision = decision - 1;
delete outputs; delete outputs;
if (SNAKE_DEBUG) LOGln("SnakeEffect * Decision: %d", decision); if (SNAKE_DEBUG) DBG("SnakeEffect * Decision: %d", decision);
_dir += decision; _dir += decision;
if (_dir < 0) _dir += 4; if (_dir < 0) _dir += 4;
@ -130,6 +126,36 @@ int8_t SnakeEffect::_manual_decision() {
(2) Having a number smaller than the field the apple is on. (Watch out for "overflows".) (2) Having a number smaller than the field the apple is on. (Watch out for "overflows".)
*/ */
int8_t SnakeEffect::_manual_decision() { int8_t SnakeEffect::_manual_decision() {
uint8_t head_index = _coords_to_field_id(_pos);
uint8_t apple_index = _coords_to_field_id(_apple);
uint8_t tail_index = _coords_to_field_id(_tail);
if (SNAKE_DEBUG) DBG("SnakeEffect * Decision. head: %d, apple: %d, tail: %d", head_index, apple_index, tail_index);
uint16_t best_distance = 0xFFFF;
int8_t decision = 0;
for (int i=-1; i<=1; i++) { // Test all thre possible directions (left, ahead, right)
Coords new_pos = _new_pos(_dir + i);
uint8_t new_index = _coords_to_field_id(new_pos);
int16_t distance;
if (apple_index >= new_index) {
distance = apple_index - new_index;
} else {
distance = (window->width * window->height) - apple_index + new_index;
}
if (SNAKE_DEBUG) DBG("SnakeEffect * Decision: %d would have distance %d", i, distance);
if (distance < best_distance && _is_free(_dir + i)) {
best_distance = distance;
decision = i;
}
}
if (SNAKE_DEBUG) DBG("SnakeEffect * Decision taken: %d with distance %d", decision, best_distance);
/* apple_index > new_index && head_index > apple_index
apple_index > new_index && head_index < apple_index && new_index > head_index
uint16_t head_index = (_head_rounds<<8) | _coords_to_field_id(_pos); uint16_t head_index = (_head_rounds<<8) | _coords_to_field_id(_pos);
uint16_t apple_index = (_head_rounds<<8) | _coords_to_field_id(_apple); uint16_t apple_index = (_head_rounds<<8) | _coords_to_field_id(_apple);
uint16_t tail_index = (_tail_rounds<<8) | _coords_to_field_id(_tail); uint16_t tail_index = (_tail_rounds<<8) | _coords_to_field_id(_tail);
@ -148,7 +174,7 @@ int8_t SnakeEffect::_manual_decision() {
decision = i; decision = i;
best_dist = dist; best_dist = dist;
} }
} }*/
_dir = (_dir + decision) % 4; _dir = (_dir + decision) % 4;
return decision; return decision;
} }
@ -242,7 +268,7 @@ void SnakeEffect::_move() {
} }
unsigned long now = millis(); unsigned long now = millis();
if (_last_move_at < now && now - _last_move_at < 0) { if (_last_move_at < now && now - _last_move_at < 50) {
return; return;
} }
_round++; _round++;