aboutsummaryrefslogtreecommitdiff
path: root/src/ch/epfl/xblast/server/Bomb.java
blob: 57c271f8da65e5c86c69a6df01a96628c93c1718 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
package ch.epfl.xblast.server;

import ch.epfl.cs108.Sq;
import ch.epfl.xblast.ArgumentChecker;
import ch.epfl.xblast.Cell;
import ch.epfl.xblast.Direction;
import ch.epfl.xblast.PlayerID;

import java.util.List;
import java.util.Objects;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * A Bomb.
 *
 * @author Pacien TRAN-GIRARD (261948)
 * @author Timothée FLOURE (257420)
 */
public final class Bomb {

    /**
     * Function consuming a step of the Bomb's fuse.
     */
    private static final UnaryOperator<Integer> FUSE_STEP_FUNCTION = fl -> fl - 1;

    /**
     * Owner of the Bomb.
     */
    private final PlayerID ownerId;

    /**
     * Position of the Bomb.
     */
    private final Cell position;

    /**
     * Fuse of the Bomb.
     */
    private final Sq<Integer> fuseLengths;

    /**
     * Range of the Bomb.
     */
    private final int range;

    /**
     * Instantiates a new Bomb.
     *
     * @param ownerId    id of the owner of the bomb
     * @param position   position of the bomb
     * @param fuseLength length of the bomb's fuse
     * @param range      range of the bomb
     * @throws IllegalArgumentException if range or fuseLengths is negative
     * @throws NullPointerException     if ownerId, position or fuseLengths is null
     */
    public Bomb(PlayerID ownerId, Cell position, int fuseLength, int range) {
        this(ownerId, position, Bomb.buildFuseSequence(fuseLength), range);
    }

    /**
     * Instantiates a new Bomb.
     *
     * @param ownerId     id of the owner of the bomb
     * @param position    position of the bomb
     * @param fuseLengths length of the bomb's fuse
     * @param range       range of the bomb
     * @throws IllegalArgumentException if range is negative or fuseLengths is empty
     * @throws NullPointerException     if ownerId, position or fuseLengths is null
     */
    public Bomb(PlayerID ownerId, Cell position, Sq<Integer> fuseLengths, int range) {
        this.ownerId = Objects.requireNonNull(ownerId);
        this.position = Objects.requireNonNull(position);
        this.fuseLengths = ArgumentChecker.requireNonEmpty(fuseLengths);
        this.range = ArgumentChecker.requireNonNegative(range);
    }

    /**
     * Builds and returns a new fuse sequence of given length.
     *
     * @param fuseLength the fuse length
     * @return the fuse sequence
     */
    private static Sq<Integer> buildFuseSequence(int fuseLength) {
        int fl = ArgumentChecker.requireNonNegative(fuseLength);
        return Sq.iterate(fl, Bomb.FUSE_STEP_FUNCTION).limit(fl);
    }

    /**
     * Generates one arm of explosion.
     *
     * @param dir the Direction of the arm
     */
    private Sq<Sq<Cell>> explosionArmTowards(Direction dir) {
        return Sq
                .constant(Sq.iterate(position, position -> position.neighbor(dir)).limit(range))
                .limit(Ticks.EXPLOSION_TICKS);
    }

    /**
     * Returns the Bomb's owner ID.
     *
     * @return the ID of the owner of the bomb
     */
    public PlayerID ownerId() {
        return this.ownerId;
    }

    /**
     * Returns the Bomb's position Cell.
     *
     * @return the position of the bomb
     */
    public Cell position() {
        return this.position;
    }

    /**
     * Returns the Bomb's fuse length sequence.
     *
     * @return the length of the fuse
     */
    public Sq<Integer> fuseLengths() {
        return this.fuseLengths;
    }

    /**
     * Returns the Bomb's fuse length.
     *
     * @return the remaining time before the explosion
     */
    public int fuseLength() {
        return this.fuseLengths.head();
    }

    /**
     * Returns the Bomb's range.
     *
     * @return the range of the Bomb
     */
    public int range() {
        return this.range;
    }

    /**
     * Builds and returns a new explosion sequence.
     *
     * @return the explosion
     */
    public List<Sq<Sq<Cell>>> explosion() {
        return Stream.of(Direction.values())
                .map(this::explosionArmTowards)
                .collect(Collectors.toList());
    }

    /**
     * Returns a String representation of the parameters of the Bomb.
     *
     * @return a String representation of the parameters of the Bomb.
     */
    @Override
    public String toString() {
        return "Bomb{" +
                "ownerId=" + ownerId +
                ", position=" + position +
                ", fuseLengths=" + fuseLengths +
                ", range=" + range +
                '}';
    }

}