[gnome-robots] add arena iterator and simplify teleportation code
- From: Andrey Kutejko <akutejko src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-robots] add arena iterator and simplify teleportation code
- Date: Tue, 6 Oct 2020 19:31:41 +0000 (UTC)
commit 69248af8fae7dec952954277deb365b50c34186c
Author: Andrey Kutejko <andy128k gmail com>
Date: Sun Sep 20 21:26:02 2020 +0200
add arena iterator and simplify teleportation code
src/arena.vala | 48 ++++++++++++++++++
src/game.vala | 156 ++++++++++++++-------------------------------------------
2 files changed, 86 insertions(+), 118 deletions(-)
---
diff --git a/src/arena.vala b/src/arena.vala
index a6c3f96..e04526a 100644
--- a/src/arena.vala
+++ b/src/arena.vala
@@ -98,5 +98,53 @@ public class Arena {
}
return result;
}
+
+ public ArenaIterable iterate_from (int x, int y) {
+ return new ArenaIterable (this, x, y);
+ }
+}
+
+public class ArenaIterable {
+ private Arena arena;
+ private int initial_x;
+ private int initial_y;
+
+ public ArenaIterable (Arena arena, int initial_x, int initial_y) {
+ this.arena = arena;
+ this.initial_x = initial_x;
+ this.initial_y = initial_y;
+ }
+
+ public Iterator iterator() {
+ return new Iterator(this);
+ }
+
+ public class Iterator {
+ private int initial_position;
+ private int width;
+ private int size;
+ private int i;
+
+ public Iterator (ArenaIterable iterable) {
+ this.initial_position =
+ iterable.initial_x + iterable.arena.width * iterable.initial_y;
+ this.width = iterable.arena.width;
+ this.size = iterable.arena.width * iterable.arena.height;
+ this.i = 0;
+ }
+
+ public Arena.Coords? next_value() {
+ if (i >= size) {
+ return null;
+ }
+ var position = (initial_position + i) % size;
+ var result = Arena.Coords () {
+ x = position % width,
+ y = position / width
+ };
+ i += 1;
+ return result;
+ }
+ }
}
diff --git a/src/game.vala b/src/game.vala
index b0c917f..e9e22cb 100644
--- a/src/game.vala
+++ b/src/game.vala
@@ -243,15 +243,22 @@ public class Game {
update_game_status (score, current_level, safe_teleports);
for (int i = 0; i < num_robots1; ++i) {
- var p = random_position ((x, y) => arena[x, y] == ObjectType.NONE);
- assert (p != null);
- arena[p.x, p.y] = ObjectType.ROBOT1;
+ place_randomly (ObjectType.ROBOT1);
}
for (int i = 0; i < num_robots2; ++i) {
- var p = random_position ((x, y) => arena[x, y] == ObjectType.NONE);
- assert (p != null);
- arena[p.x, p.y] = ObjectType.ROBOT2;
+ place_randomly (ObjectType.ROBOT2);
+ }
+ }
+
+ private void place_randomly (ObjectType obj) {
+ int rand_x = rand.int_range (0, arena.width);
+ int rand_y = rand.int_range (0, arena.height);
+ foreach (var p in arena.iterate_from (rand_x, rand_y)) {
+ if (arena[p.x, p.y] == ObjectType.NONE) {
+ arena[p.x, p.y] = obj;
+ return;
+ }
}
}
@@ -628,32 +635,7 @@ public class Game {
return false;
}
- /**
- * safe_teleport_available
- *
- * Description:
- * Check for a safe teleport.
- *
- * Returns:
- * TRUE is a safe teleport is possible, FALSE otherwise.
- *
- */
- bool safe_teleport_available () {
- for (int x = 0; x < arena.width; x++) {
- for (int y = 0; y < arena.height; y++) {
- if (arena[x, y] == ObjectType.NONE) {
- var change = teleport_to (x, y);
- if (check_safe (change)) {
- return true;
- }
- }
- }
- }
-
- return false;
- }
-
- private ArenaChange teleport_to (int x, int y) {
+ private ArenaChange teleport_to (Arena.Coords coords) {
var new_arena = arena.map ((obj) => {
if (obj != ObjectType.PLAYER) {
return obj;
@@ -661,10 +643,10 @@ public class Game {
return ObjectType.NONE;
}
});
- new_arena[x, y] = ObjectType.PLAYER;
+ new_arena[coords.x, coords.y] = ObjectType.PLAYER;
return ArenaChange () {
arena = new_arena,
- player = Arena.Coords () { x = x, y = y },
+ player = coords,
push = null
};
}
@@ -714,23 +696,14 @@ public class Game {
* TRUE if the player can be teleported, FALSE otherwise
**/
bool random_teleport () {
- var temp_arena = arena.map ((obj) => {
- if (obj != ObjectType.PLAYER) {
- return obj;
- } else {
- return ObjectType.NONE;
+ int rand_x = rand.int_range (0, arena.width);
+ int rand_y = rand.int_range (0, arena.height);
+ foreach (var p in arena.iterate_from (rand_x, rand_y)) {
+ if (arena[p.x, p.y] != ObjectType.NONE) {
+ continue;
}
- });
-
- var p = random_position ((x, y) => temp_arena[x, y] == ObjectType.NONE);
- if (p != null) {
- temp_arena[p.x, p.y] = ObjectType.PLAYER;
- var change = ArenaChange () {
- arena = temp_arena,
- player = p,
- push = null
- };
+ var change = teleport_to (p);
update_arena (change);
splat = null;
@@ -738,13 +711,12 @@ public class Game {
play_sound (Sound.TELEPORT);
return true;
- } else {
- /* This should never happen. */
- message_box (_("There are no teleport locations left!!"));
- return false;
}
- }
+ /* This should never happen. */
+ message_box (_("There are no teleport locations left!!"));
+ return false;
+ }
/**
* safe_teleport
@@ -756,88 +728,36 @@ public class Game {
* TRUE if player can be teleported, FALSE otherwise
**/
bool safe_teleport () {
- if (!safe_teleport_available ()) {
- message_box (_("There are no safe locations to teleport to!!"));
- kill_player ();
+ if (safe_teleports <= 0) {
return false;
}
- if (safe_teleports <= 0)
- return false;
-
- var temp_arena = arena.map ((obj) => {
- if (obj != ObjectType.PLAYER) {
- return obj;
- } else {
- return ObjectType.NONE;
+ int rand_x = rand.int_range (0, arena.width);
+ int rand_y = rand.int_range (0, arena.height);
+ foreach (var p in arena.iterate_from (rand_x, rand_y)) {
+ if (arena[p.x, p.y] != ObjectType.NONE) {
+ continue;
}
- });
- var p = random_position ((x, y) => {
- if (temp_arena[x, y] != ObjectType.NONE) {
- return false;
+ var change = teleport_to (p);
+ if (!check_safe (change)) {
+ continue;
}
- var try_change = ArenaChange () {
- arena = temp_arena,
- player = Arena.Coords() { x = x, y = y },
- push = null
- };
- return check_safe (try_change);
- });
- if (p != null) {
- temp_arena[p.x, p.y] = ObjectType.PLAYER;
safe_teleports -= 1;
update_game_status (score, current_level, safe_teleports);
- var change = ArenaChange () {
- arena = temp_arena,
- player = p,
- push = null
- };
-
update_arena (change);
splat = null;
game_area.queue_draw ();
play_sound (Sound.TELEPORT);
return true;
- } else {
- /* This should never happen. */
- message_box (_("There are no teleport locations left!!"));
- return false;
}
- }
-
- delegate bool PositionPredicate(int x, int y);
-
- private Arena.Coords? random_position (PositionPredicate predicate) {
- int ixp = rand.int_range (0, arena.width);
- int iyp = rand.int_range (0, arena.height);
-
- int xp = ixp;
- int yp = iyp;
- while (true) {
- if (predicate(xp, yp)) {
- return Arena.Coords() {
- x = xp,
- y = yp
- };
- }
-
- ++xp;
- if (xp >= arena.width) {
- xp = 0;
- ++yp;
- if (yp >= arena.height) {
- yp = 0;
- }
- }
- if (xp == ixp && yp == iyp) {
- return null;
- }
- }
+ message_box (_("There are no safe locations to teleport to!!"));
+ kill_player ();
+ return false;
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]