Effect snake now uses a "proper", albeit simple neural network instead of simple decisions.
This commit is contained in:
@ -38,15 +38,33 @@ void SnakeEffect::_place_apple() {
|
||||
}
|
||||
|
||||
void SnakeEffect::_decide() {
|
||||
uint8_t input = 0;
|
||||
if (_is_free(_dir - 1)) input |= 1<<5;
|
||||
if (_is_free(_dir)) input |= 1<<4;
|
||||
if (_is_free(_dir + 1)) input |= 1<<3;
|
||||
if (_to_apple(_dir - 1)) input |= 1<<2;
|
||||
if (_to_apple(_dir)) input |= 1<<1;
|
||||
if (_to_apple(_dir + 1)) input |= 1;
|
||||
uint8_t f_l = _free_spaces(_dir - 1);
|
||||
uint8_t f_s = _free_spaces(_dir);
|
||||
uint8_t f_r = _free_spaces(_dir + 1);
|
||||
uint8_t a_l = _to_apple(_dir - 1);
|
||||
uint8_t a_s = _to_apple(_dir);
|
||||
uint8_t a_r = _to_apple(_dir + 1);
|
||||
|
||||
_dir += _decisions[input];
|
||||
uint8_t inputs[6] = {f_l, f_s, f_r, a_l, a_s, a_r};
|
||||
|
||||
float outputs[3] = {0.0, 0.0, 0.0};
|
||||
|
||||
for (int i=0; i<18; i++) {
|
||||
uint8_t out = i/6;
|
||||
uint8_t in = i%6;
|
||||
outputs[out] += _weights[i] * inputs[in];
|
||||
}
|
||||
|
||||
int8_t decision = 0;
|
||||
if (outputs[0]>=outputs[1] && outputs[0]>=outputs[2]) {
|
||||
decision = -1;
|
||||
} else if (outputs[1]>=outputs[2]) {
|
||||
decision = 0;
|
||||
} else {
|
||||
decision = 1;
|
||||
}
|
||||
|
||||
_dir += decision;
|
||||
if (_dir < 0) _dir += 4;
|
||||
}
|
||||
|
||||
@ -80,15 +98,40 @@ bool SnakeEffect::_is_free(uint8_t dir) {
|
||||
return np.x>=0 && np.x<window->width && np.y>=0 && np.y<window->height && _map[_xy2i(np)]==0;
|
||||
}
|
||||
|
||||
bool SnakeEffect::_to_apple(uint8_t dir) {
|
||||
uint8_t SnakeEffect::_free_spaces(uint8_t dir) {
|
||||
int8_t x=0;
|
||||
int8_t y=0;
|
||||
uint8_t d = dir % 4;
|
||||
switch(d) {
|
||||
case SNAKE_DIR_NORTH: return _apple.y<_pos.y;
|
||||
case SNAKE_DIR_EAST: return _apple.x>_pos.x;
|
||||
case SNAKE_DIR_SOUTH: return _apple.y>_pos.y;
|
||||
case SNAKE_DIR_WEST: return _apple.x<_pos.x;
|
||||
case SNAKE_DIR_NORTH: y=-1; break;
|
||||
case SNAKE_DIR_EAST: x=1; break;
|
||||
case SNAKE_DIR_SOUTH: y=1; break;
|
||||
case SNAKE_DIR_WEST: x=-1; break;
|
||||
}
|
||||
return true;
|
||||
Coords p(_pos);
|
||||
uint8_t i;
|
||||
for(i=0; i<window->width || i<window->height; i++) {
|
||||
p.x += x;
|
||||
p.y += y;
|
||||
if (p.x<0 || p.x>=window->width || p.y<0 || p.y>=window->height || _map[_xy2i(p)]!=0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
uint8_t SnakeEffect::_to_apple(uint8_t dir) {
|
||||
uint8_t d = dir % 4;
|
||||
int8_t d_x = _apple.x - _pos.x;
|
||||
int8_t d_y = _apple.y - _pos.y;
|
||||
|
||||
switch(d) {
|
||||
case SNAKE_DIR_NORTH: return d_y < 0 ? -d_y : 0;
|
||||
case SNAKE_DIR_EAST: return d_x > 0 ? d_x : 0;
|
||||
case SNAKE_DIR_SOUTH: return d_y > 0 ? d_y : 0;
|
||||
case SNAKE_DIR_WEST: return d_x < 0 ? -d_x : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Coords SnakeEffect::_new_pos(uint8_t dir) {
|
||||
|
Reference in New Issue
Block a user