-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
480 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
src/main/java/com/github/vitalibo/brickgame/game/tanks/Battlefield.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package com.github.vitalibo.brickgame.game.tanks; | ||
|
||
import com.github.vitalibo.brickgame.game.Point; | ||
import com.github.vitalibo.brickgame.game.Shape; | ||
import com.github.vitalibo.brickgame.util.Random; | ||
import lombok.Getter; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.function.Consumer; | ||
import java.util.stream.Collectors; | ||
|
||
class Battlefield { | ||
|
||
private static final Shape TANK_SHADOW = Shape.of(3, 0x7, 0x7, 0x7); | ||
|
||
@Getter | ||
private final List<Tank> tanks = new ArrayList<>(); | ||
|
||
public int canDoUp(Tank tank) { | ||
return testDoStep(tank, Tank::doUp, Direction.DOWN); | ||
} | ||
|
||
public int canDoRight(Tank tank) { | ||
return testDoStep(tank, Tank::doRight, Direction.LEFT); | ||
} | ||
|
||
public int canDoDown(Tank tank) { | ||
return testDoStep(tank, Tank::doDown, Direction.UP); | ||
} | ||
|
||
public int canDoLeft(Tank tank) { | ||
return testDoStep(tank, Tank::doLeft, Direction.RIGHT); | ||
} | ||
|
||
private int testDoStep(Tank tank, Consumer<Tank> step, Direction direction) { | ||
Tank clone = new Tank(tank); | ||
step.accept(clone); | ||
|
||
if (clone.verify()) { | ||
return 0; | ||
} | ||
|
||
if (!hasOverlap(clone)) { | ||
return 1; | ||
} | ||
|
||
if (tank.getDirection() != direction) { | ||
return 0; | ||
} | ||
|
||
step.accept(clone); | ||
if (clone.verify() || hasOverlap(clone)) { | ||
return 0; | ||
} | ||
|
||
return 2; | ||
} | ||
|
||
|
||
private boolean hasOverlap(Tank tank) { | ||
return tanks.stream() | ||
.filter(o -> !o.equals(tank)) | ||
.flatMap(Tank::stream) | ||
.anyMatch(tank::contains); | ||
} | ||
|
||
public void spawn() { | ||
spawn(4); | ||
} | ||
|
||
private void spawn(int attempt) { | ||
if (attempt == 0) { | ||
return; | ||
} | ||
|
||
Tank tank = Spawn.randomEnemyTanks(); | ||
boolean hasOverlap = tanks.stream() | ||
.filter(o -> !o.equals(tank)) | ||
.flatMap(o -> TANK_SHADOW.apply(o.getPoint())) | ||
.anyMatch(tank::contains); | ||
|
||
if (hasOverlap) { | ||
spawn(attempt - 1); | ||
return; | ||
} | ||
|
||
tanks.add(tank); | ||
} | ||
|
||
static class Spawn { | ||
|
||
private static final List<Point> SPAWN_POINTS = | ||
Arrays.asList( | ||
Point.of(0, 0), Point.of(0, 7), | ||
Point.of(17, 0), Point.of(17, 7)); | ||
|
||
public static Tank myTank() { | ||
return point(Point.of(9, 4)); | ||
} | ||
|
||
public static List<Tank> enemyTanks() { | ||
return SPAWN_POINTS.stream().map(Battlefield.Spawn::point) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private static Tank randomEnemyTanks() { | ||
return point(SPAWN_POINTS.get( | ||
Random.nextInt(SPAWN_POINTS.size()))); | ||
} | ||
|
||
private static Tank point(Point point) { | ||
return new Tank(Point.of(point), Direction.random()); | ||
} | ||
|
||
} | ||
|
||
} |
23 changes: 23 additions & 0 deletions
23
src/main/java/com/github/vitalibo/brickgame/game/tanks/Direction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.github.vitalibo.brickgame.game.tanks; | ||
|
||
import com.github.vitalibo.brickgame.game.Point; | ||
import com.github.vitalibo.brickgame.util.Random; | ||
import lombok.AllArgsConstructor; | ||
import lombok.experimental.Delegate; | ||
|
||
import java.util.function.Consumer; | ||
|
||
@AllArgsConstructor | ||
enum Direction implements Consumer<Point> { | ||
|
||
UP(Point::doUp), RIGHT(Point::doRight), | ||
DOWN(Point::doDown), LEFT(Point::doLeft); | ||
|
||
@Delegate | ||
private final Consumer<Point> consumer; | ||
|
||
public static Direction random() { | ||
return values()[Random.nextInt(4)]; | ||
} | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/com/github/vitalibo/brickgame/game/tanks/Shot.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.github.vitalibo.brickgame.game.tanks; | ||
|
||
import com.github.vitalibo.brickgame.game.Point; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
@AllArgsConstructor | ||
class Shot implements Runnable { | ||
|
||
@Getter | ||
private final Point point; | ||
@Getter | ||
private final Direction direction; | ||
|
||
@Override | ||
public void run() { | ||
direction.accept(point); | ||
} | ||
|
||
public boolean verify() { | ||
return (point.getX() < 0 || point.getX() > 9) | ||
|| (point.getY() < 0 || point.getY() > 19); | ||
} | ||
|
||
} |
101 changes: 101 additions & 0 deletions
101
src/main/java/com/github/vitalibo/brickgame/game/tanks/Tank.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package com.github.vitalibo.brickgame.game.tanks; | ||
|
||
import com.github.vitalibo.brickgame.game.Point; | ||
import com.github.vitalibo.brickgame.game.Shape; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.Getter; | ||
import lombok.experimental.Delegate; | ||
|
||
import java.util.List; | ||
import java.util.UUID; | ||
import java.util.stream.Collectors; | ||
|
||
@EqualsAndHashCode(of = "uuid") | ||
class Tank implements List<Point> { | ||
|
||
private static final Shape[] STATES = new Shape[] | ||
{ | ||
Shape.of(3, 0x2, 0x7, 0x5), | ||
Shape.of(3, 0x6, 0x3, 0x6), | ||
Shape.of(3, 0x5, 0x7, 0x2), | ||
Shape.of(3, 0x3, 0x6, 0x3) | ||
}; | ||
|
||
private final UUID uuid; | ||
|
||
@Getter | ||
private Point point; | ||
@Getter | ||
private Direction direction; | ||
@Delegate | ||
private List<Point> points; | ||
|
||
Tank(Tank o) { | ||
this(o.uuid, Point.of(o.point), o.direction); | ||
} | ||
|
||
Tank(Point point, Direction direction) { | ||
this(UUID.randomUUID(), point, direction); | ||
} | ||
|
||
Tank(UUID uuid, Point point, Direction direction) { | ||
this.uuid = uuid; | ||
this.point = point; | ||
this.direction = direction; | ||
this.points = state(point, direction.ordinal()); | ||
} | ||
|
||
public void doDown() { | ||
doStep(Direction.DOWN); | ||
} | ||
|
||
public void doLeft() { | ||
doStep(Direction.LEFT); | ||
} | ||
|
||
public void doRight() { | ||
doStep(Direction.RIGHT); | ||
} | ||
|
||
public void doUp() { | ||
doStep(Direction.UP); | ||
} | ||
|
||
private void doStep(Direction dr) { | ||
if (dr == this.direction) { | ||
points.forEach(dr); | ||
dr.accept(point); | ||
return; | ||
} | ||
|
||
points = state(point, dr.ordinal()); | ||
this.direction = dr; | ||
} | ||
|
||
public boolean verify() { | ||
return (point.getX() < 0 || point.getX() > 7) | ||
|| (point.getY() < 0 || point.getY() > 17); | ||
} | ||
|
||
public Shot doShot() { | ||
return new Shot( | ||
Point.of( | ||
point.getY() + 1 + shifting(direction, Direction.UP, Direction.DOWN), | ||
point.getX() + 1 + shifting(direction, Direction.LEFT, Direction.RIGHT)), | ||
direction); | ||
} | ||
|
||
public boolean hasKilled(Shot shot) { | ||
return points.contains(shot.getPoint()); | ||
} | ||
|
||
private static List<Point> state(Point point, int state) { | ||
return STATES[state].apply(point) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private static int shifting(Direction dr, Direction lower, Direction upper) { | ||
return dr == lower ? -1 : dr == upper ? 1 : 0; | ||
} | ||
|
||
} |
Oops, something went wrong.