[gnome-nibbles/arnaudb/fix-level-25: 4/8] Rework worms direction code.
- From: Arnaud B. <arnaudb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-nibbles/arnaudb/fix-level-25: 4/8] Rework worms direction code.
- Date: Mon, 29 Jun 2020 17:09:02 +0000 (UTC)
commit a1a3fb1f30eaf23d75baa77b6e6077c52a5d751d
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date: Tue Jun 23 17:18:35 2020 +0200
Rework worms direction code.
src/worm.vala | 227 ++++++++++++++++++++++++++++------------------------------
1 file changed, 108 insertions(+), 119 deletions(-)
---
diff --git a/src/worm.vala b/src/worm.vala
index d49d145..584e120 100644
--- a/src/worm.vala
+++ b/src/worm.vala
@@ -26,6 +26,42 @@ private enum WormDirection
DOWN,
LEFT,
UP;
+
+ internal WormDirection opposite ()
+ {
+ switch (this)
+ {
+ case RIGHT: return LEFT;
+ case LEFT: return RIGHT;
+ case DOWN: return UP;
+ case UP: return DOWN;
+ default: assert_not_reached ();
+ }
+ }
+
+ internal WormDirection turn_left ()
+ {
+ switch (this)
+ {
+ case RIGHT: return UP;
+ case UP: return LEFT;
+ case LEFT: return DOWN;
+ case DOWN: return RIGHT;
+ default: assert_not_reached ();
+ }
+ }
+
+ internal WormDirection turn_right ()
+ {
+ switch (this)
+ {
+ case RIGHT: return DOWN;
+ case DOWN: return LEFT;
+ case LEFT: return UP;
+ case UP: return RIGHT;
+ default: assert_not_reached ();
+ }
+ }
}
private struct Position
@@ -119,7 +155,7 @@ private class Worm : Object
list.add (starting_position);
starting_direction = direction;
- this.direction = starting_direction;
+ this.direction = direction;
change = 0;
key_queue.clear ();
}
@@ -137,21 +173,25 @@ private class Worm : Object
if (position.y < 0)
position.y = NibblesGame.HEIGHT - 1;
break;
+
case WormDirection.DOWN:
position.y = ++head.y;
if (position.y >= NibblesGame.HEIGHT)
position.y = 0;
break;
+
case WormDirection.LEFT:
position.x = --head.x;
if (position.x < 0)
position.x = NibblesGame.WIDTH - 1;
break;
+
case WormDirection.RIGHT:
position.x = ++head.x;
if (position.x >= NibblesGame.WIDTH)
position.x = 0;
break;
+
default:
assert_not_reached ();
}
@@ -338,21 +378,25 @@ private class Worm : Object
if (position.y < 0)
position.y = NibblesGame.HEIGHT - 1;
break;
+
case WormDirection.DOWN:
position.y = ++head.y;
if (position.y >= NibblesGame.HEIGHT)
position.y = 0;
break;
+
case WormDirection.LEFT:
position.x = --head.x;
if (position.x < 0)
position.x = NibblesGame.WIDTH - 1;
break;
+
case WormDirection.RIGHT:
position.x = ++head.x;
if (position.x >= NibblesGame.WIDTH)
position.x = 0;
break;
+
default:
assert_not_reached ();
}
@@ -361,22 +405,18 @@ private class Worm : Object
}
private void direction_set (WormDirection dir)
+ requires (dir != WormDirection.NONE)
{
if (!is_human)
return;
- if (dir > 4)
- dir = (WormDirection) 1;
- if (dir < 1)
- dir = (WormDirection) 4;
-
if (keypress)
{
queue_keypress (dir);
return;
}
- direction = (WormDirection) dir;
+ direction = dir;
keypress = true;
}
@@ -391,11 +431,6 @@ private class Worm : Object
return ((char) keyval).toupper ();
}
- private void handle_direction (WormDirection dir)
- {
- direction_set (dir);
- }
-
internal bool handle_keypress (uint keyval, Gee.HashMap<Worm, WormProperties> worm_props)
{
if (lives <= 0 || is_stopped)
@@ -413,22 +448,22 @@ private class Worm : Object
if ((keyvalUpper == propsUp) && (direction != WormDirection.DOWN))
{
- handle_direction (WormDirection.UP);
+ direction_set (WormDirection.UP);
return true;
}
if ((keyvalUpper == propsDown) && (direction != WormDirection.UP))
{
- handle_direction (WormDirection.DOWN);
+ direction_set (WormDirection.DOWN);
return true;
}
if ((keyvalUpper == propsRight) && (direction != WormDirection.LEFT))
{
- handle_direction (WormDirection.RIGHT);
+ direction_set (WormDirection.RIGHT);
return true;
}
if ((keyvalUpper == propsLeft) && (direction != WormDirection.RIGHT))
{
- handle_direction (WormDirection.LEFT);
+ direction_set (WormDirection.LEFT);
return true;
}
@@ -474,50 +509,38 @@ private class Worm : Object
private static int ai_deadend (int[,] board, int numworms, int x, int y, int length_left)
{
- int cdir, cx, cy;
-
if (x >= NibblesGame.WIDTH)
x = 0;
- if (x < 0)
+ else if (x < 0)
x = NibblesGame.WIDTH - 1;
if (y >= NibblesGame.HEIGHT)
y = 0;
- if (y < 0)
+ else if (y < 0)
y = NibblesGame.HEIGHT - 1;
if (length_left <= 0)
return 0;
- cdir = 5;
- while (--cdir > 0)
+ for (int dir = 4; dir > 0; dir--)
{
- cx = x;
- cy = y;
- switch (cdir)
+ int cx = x;
+ int cy = y;
+ switch ((WormDirection) dir)
{
- case WormDirection.UP:
- cy -= 1;
- break;
- case WormDirection.DOWN:
- cy += 1;
- break;
- case WormDirection.LEFT:
- cx -= 1;
- break;
- case WormDirection.RIGHT:
- cx += 1;
- break;
- default:
- assert_not_reached ();
+ case WormDirection.UP: cy -= 1; break;
+ case WormDirection.DOWN: cy += 1; break;
+ case WormDirection.LEFT: cx -= 1; break;
+ case WormDirection.RIGHT: cx += 1; break;
+ default: assert_not_reached ();
}
if (cx >= NibblesGame.WIDTH)
cx = 0;
- if (cx < 0)
+ else if (cx < 0)
cx = NibblesGame.WIDTH - 1;
if (cy >= NibblesGame.HEIGHT)
cy = 0;
- if (cy < 0)
+ else if (cy < 0)
cy = NibblesGame.HEIGHT - 1;
if ((board[cx, cy] <= NibblesGame.EMPTYCHAR
@@ -543,7 +566,7 @@ private class Worm : Object
* least BOARDWIDTH, so that on the levels with long thin paths a worm
* won't start down the path if it'll crash at the other end.
*/
- private static int ai_deadend_after (int[,] board, Gee.LinkedList<Worm> worms, int numworms, int x, int
y, int dir, int length)
+ private static int ai_deadend_after (int[,] board, Gee.LinkedList<Worm> worms, int numworms, int x, int
y, WormDirection direction, int length)
{
int cx, cy, cl, i;
@@ -552,11 +575,6 @@ private class Worm : Object
++deadend_runnumber;
- if (dir > 4)
- dir = 1;
- if (dir < 1)
- dir = 4;
-
i = numworms;
while (i-- > 0)
{
@@ -564,19 +582,19 @@ private class Worm : Object
cy = worms[i].head.y;
if (cx != x || cy != y) {
if (cx > 0)
- deadend_board[cx-1, cy] = deadend_runnumber;
+ deadend_board[cx - 1, cy] = deadend_runnumber;
if (cy > 0)
- deadend_board[cx, cy-1] = deadend_runnumber;
- if (cx < NibblesGame.WIDTH-1)
- deadend_board[cx+1, cy] = deadend_runnumber;
- if (cy < NibblesGame.HEIGHT-1)
- deadend_board[cx, cy+1] = deadend_runnumber;
+ deadend_board[cx, cy - 1] = deadend_runnumber;
+ if (cx < NibblesGame.WIDTH - 1)
+ deadend_board[cx + 1, cy] = deadend_runnumber;
+ if (cy < NibblesGame.HEIGHT - 1)
+ deadend_board[cx, cy + 1] = deadend_runnumber;
}
}
cx = x;
cy = y;
- switch (dir)
+ switch (direction)
{
case WormDirection.UP:
cy -= 1;
@@ -596,11 +614,11 @@ private class Worm : Object
if (cx >= NibblesGame.WIDTH)
cx = 0;
- if (cx < 0)
+ else if (cx < 0)
cx = NibblesGame.WIDTH - 1;
if (cy >= NibblesGame.HEIGHT)
cy = 0;
- if (cy < 0)
+ else if (cy < 0)
cy = NibblesGame.HEIGHT - 1;
deadend_board[x, y] = deadend_runnumber;
@@ -651,14 +669,9 @@ private class Worm : Object
return false;
}
- private static bool ai_wander (int[,] board, int numworms, int x, int y, int dir, int ox, int oy)
+ private static bool ai_wander (int[,] board, int numworms, int x, int y, WormDirection direction, int
ox, int oy)
{
- if (dir > 4)
- dir = 1;
- if (dir < 1)
- dir = 4;
-
- switch (dir)
+ switch (direction)
{
case WormDirection.UP:
y -= 1;
@@ -678,11 +691,11 @@ private class Worm : Object
if (x >= NibblesGame.WIDTH)
x = 0;
- if (x < 0)
+ else if (x < 0)
x = NibblesGame.WIDTH - 1;
if (y >= NibblesGame.HEIGHT)
y = 0;
- if (y < 0)
+ else if (y < 0)
y = NibblesGame.HEIGHT - 1;
switch (board[x, y] - 'A')
@@ -708,7 +721,7 @@ private class Worm : Object
if (ox == x && oy == y)
return false;
- return Worm.ai_wander (board, numworms, x, y, dir, ox, oy);
+ return Worm.ai_wander (board, numworms, x, y, direction, ox, oy);
}
}
}
@@ -716,50 +729,24 @@ private class Worm : Object
/* Determines the direction of the AI worm. */
internal void ai_move (int[,] board, int numworms, Gee.LinkedList<Worm> worms)
{
- var opposite = (direction + 1) % 4 + 1;
+ WormDirection opposite = direction.opposite ();
- var front = Worm.ai_wander (board, numworms, head.x, head.y, direction, head.x, head.y);
- var left = Worm.ai_wander (board, numworms, head.x, head.y, direction - 1, head.x, head.y);
- var right = Worm.ai_wander (board, numworms, head.x, head.y, direction + 1, head.x, head.y);
-
- int dir;
- if (!front)
+ /* if no bonus in front */
+ if (!Worm.ai_wander (board, numworms, head.x, head.y, direction, head.x, head.y))
{
- if (left)
- {
- /* Found a bonus to the left */
- dir = direction - 1;
- if (dir < 1)
- dir = 4;
+ /* FIXME worms will prefer to turn left than right */
- direction = (WormDirection) dir;
- }
- else if (right)
- {
- /* Found a bonus to the right */
- dir = direction + 1;
- if (dir > 4)
- dir = 1;
+ /* if bonus found to the left */
+ if (Worm.ai_wander (board, numworms, head.x, head.y, direction.turn_left (), head.x, head.y))
+ direction = direction.turn_left ();
- direction = (WormDirection) dir;
- }
- else
- {
- /* Else move in random direction at random time intervals */
- if (Random.int_range (0, 30) == 1)
- {
- dir = direction + (Random.boolean () ? 1 : -1);
- if (dir != opposite)
- {
- if (dir > 4)
- dir = 1;
- if (dir < 1)
- dir = 4;
-
- direction = (WormDirection) dir;
- }
- }
- }
+ /* if bonus found to the right */
+ else if (Worm.ai_wander (board, numworms, head.x, head.y, direction.turn_right (), head.x,
head.y))
+ direction = direction.turn_right ();
+
+ /* if no bonus found, move in random direction at random time intervals */
+ else if (Random.int_range (0, 30) == 1)
+ direction = Random.boolean () ? direction.turn_right () : direction.turn_left ();
}
/* Avoid walls, dead-ends and other worm's heads. This is done using
@@ -773,16 +760,17 @@ private class Worm : Object
* that the dead end will disappear (e.g. if it's made from the tail
* of some worm, as often happens).
*/
- var old_dir = direction;
- var best_yet = NibblesGame.CAPACITY * 2;
- var best_dir = -1;
+ WormDirection prev_dir = direction;
+ WormDirection best_dir = NONE;
+ int best_yet = NibblesGame.CAPACITY * 2;
int this_len;
- for (dir = 1; dir <= 4; dir++)
+ for (int dir = 1; dir <= 4; dir++)
{
+ /* TODO make method static, and do not make tests with the class direction variable */
direction = (WormDirection) dir;
- if (dir == opposite)
+ if (direction == opposite)
continue;
this_len = 0;
@@ -792,9 +780,9 @@ private class Worm : Object
if (ai_too_close (worms, numworms))
this_len += 4;
- this_len += ai_deadend_after (board, worms, numworms, head.x, head.y, dir, length + change);
+ this_len += ai_deadend_after (board, worms, numworms, head.x, head.y, direction, length +
change);
- if (dir == old_dir && this_len <= 0)
+ if (direction == prev_dir && this_len <= 0)
this_len -= 100;
/* If the favoured direction isn't appropriate, then choose
@@ -807,24 +795,25 @@ private class Worm : Object
if (this_len < best_yet)
{
best_yet = this_len;
- best_dir = dir;
+ best_dir = direction;
}
}
- direction = (WormDirection) best_dir;
+ if (best_dir == NONE)
+ assert_not_reached ();
+
+ direction = best_dir;
/* Make sure we are at least avoiding walls.
* Mostly other snakes should avoid our head.
*/
- for (dir = 1; dir <= 4; dir++)
+ for (int dir = 1; dir <= 4; dir++)
{
- if (dir == opposite)
+ if (opposite == (WormDirection) dir)
continue;
if (!can_move_to (board, numworms))
direction = (WormDirection) dir;
- else
- continue;
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]