aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ch/epfl/xblast/Lists.java39
-rw-r--r--src/ch/epfl/xblast/RunLengthEncoder.java192
-rw-r--r--src/ch/epfl/xblast/server/GameStateSerializer.java141
-rw-r--r--src/ch/epfl/xblast/server/Level.java134
-rw-r--r--src/ch/epfl/xblast/server/painter/ExplosionPainter.java7
5 files changed, 512 insertions, 1 deletions
<
diff --git a/src/ch/epfl/xblast/Lists.java b/src/ch/epfl/xblast/Lists.java
index ef17f05..b943162 100644
--- a/src/ch/epfl/xblast/Lists.java
+++ b/src/ch/epfl/xblast/Lists.java
@@ -93,6 +93,30 @@ public final class Lists {
93 } 93 }
94 94
95 /** 95 /**
96 * Returns a copy of the given list with element e prepended.
97 *
98 * @param l the list
99 * @param e the element to prepend
100 * @param <T> the type of the list's elements
101 * @return a copy of the list with the element prepended
102 */
103 public static <T> List<T> prepended(List<T> l, T e) {
104 return Lists.inserted(l, 0, e);
105 }
106
107 /**
108 * Returns a copy of the given list with element e appended.
109 *
110 * @param l the list
111 * @param e the element to append
112 * @param <T> the type of the list's elements
113 * @return a copy of the list with the element appended
114 */
115 public static <T> List<T> appended(List<T> l, T e) {
116 return Lists.inserted(l, l.size(), e);
117 }
118
119 /**
96 * Returns all the permutations of the elements of the given list. 120 * Returns all the permutations of the elements of the given list.
97 * 121 *
98 * @param l given list 122 * @param l given list
@@ -113,4 +137,19 @@ public final class Lists {
113 return p; 137 return p;
114 } 138 }
115 139
140 /**
141 * Returns a copy of the given list with the first n items dropped.
142 *
143 * @param l given list
144 * @param n number of items to drop
145 * @param <T> the type of the list's elements
146 * @return a copy of the list with the n first element dropped
147 */
148 public static <T> List<T> firstDropped(List<T> l, int n) {
149 if (Objects.isNull(l))
150 return Collections.emptyList();
151
152 return new ArrayList<>(l.subList(n, l.size()));
153 }
154
116} 155}
diff --git a/src/ch/epfl/xblast/RunLengthEncoder.java b/src/ch/epfl/xblast/RunLengthEncoder.java
new file mode 100644
index 0000000..d7ab106
--- /dev/null
+++ b/src/ch/epfl/xblast/RunLengthEncoder.java
@@ -0,0 +1,192 @@
1package ch.epfl.xblast;
2
3import java.util.Arrays;
4import java.util.Collections;
5import java.util.List;
6import java.util.Objects;
7import java.util.stream.Collectors;
8
9/**
10 * Run-length byte array encoder and decoder.
11 *
12 * @author Pacien TRAN-GIRARD (261948)
13 */
14public final class RunLengthEncoder {
15
16 private static final int REPLACE_THRESHOLD = 2;
17 private static final int MAX_RUN_LENGTH = -Byte.MIN_VALUE + REPLACE_THRESHOLD;
18
19 /**
20 * A run-length representing a sequence of a byte repeated n times.
21 */
22 static class RunLength {
23
24 final int len;
25 final byte val;
26
27 /**
28 * Instantiates a run-length of byte val and length len.
29 *
30 * @param len the length
31 * @param val the value
32 */
33 RunLength(int len, byte val) {
34 this.len = ArgumentChecker.requireNonNegative(len);
35 this.val = val;
36 }
37
38 /**
39 * Instantiates a unit length RunLength of the given value.
40 *
41 * @param val the value
42 */
43 RunLength(byte val) {
44 this(1, val);
45 }
46
47 /**
48 * Instantiates a run-length from its byte encoded representation.
49 *
50 * @param len the encoded byte length
51 * @param val the value
52 */
53 RunLength(byte len, byte val) {
54 this(-len + REPLACE_THRESHOLD, val);
55 }
56
57 /**
58 * Merges tho current and the given same value RunLengths.
59 *
60 * @param rl the other RunLength to combine.
61 * @return the summed-length RunLength
62 */
63 RunLength merge(RunLength rl) {
64 if (Objects.isNull(rl) || rl.val != this.val)
65 throw new IllegalArgumentException();
66
67 return new RunLength(this.len + rl.len, this.val);
68 }
69
70 /**
71 * Splits the RunLength in one or more RunLengths, ensuring they do not exceed the maximum encode-able length.
72 *
73 * @return the split RunLength list
74 */
75 List<RunLength> split() {
76 List<RunLength> fullRll = Collections.nCopies(this.len / MAX_RUN_LENGTH, new RunLength(MAX_RUN_LENGTH, this.val));
77 int remainder = this.len % MAX_RUN_LENGTH;
78
79 if (remainder == 0)
80 return fullRll;
81 else
82 return Lists.appended(fullRll, new RunLength(remainder, this.val));
83 }
84
85 /**
86 * Encodes a RunLength into its byte array representation.
87 *
88 * @return the byte array representation
89 */
90 List<Byte> encode() {
91 if (this.len <= REPLACE_THRESHOLD)
92 return this.expand();
93 else
94 return Arrays.asList((byte) (-this.len + REPLACE_THRESHOLD), this.val);
95 }
96
97 /**
98 * Returns the expanded byte array form of a RunLength.
99 *
100 * @return the expanded byte array form
101 */
102 List<Byte> expand() {
103 return Collections.nCopies(this.len, this.val);
104 }
105
106 @Override
107 public String toString() {
108 return String.format("(%d,%d)", this.len, this.val);
109 }
110
111 @Override
112 public boolean equals(Object o) {
113 if (this == o) return true;
114 if (o == null || getClass() != o.getClass()) return false;
115
116 RunLength rl = (RunLength) o;
117 return len == rl.len && val == rl.val;
118 }
119
120 }
121
122 /**
123 * Collapses contiguous same-value RunLength in the given list.
124 * Optimal collapse is not guaranteed if zero-length elements are not filtered out first.
125 *
126 * @param rll the RunLength list
127 * @return a collapsed RunLength list
128 */
129 static List<RunLength> collapseRunLengths(List<RunLength> rll) {
130 if (Objects.isNull(rll) || rll.isEmpty())
131 return Collections.emptyList();
132
133 if (rll.size() == 1)
134 return rll;
135
136 RunLength current = rll.get(0), next = rll.get(1);
137 if (current.val == next.val)
138 return collapseRunLengths(Lists.prepended(Lists.firstDropped(rll, 2), current.merge(next)));
139 else
140 return Lists.prepended(collapseRunLengths(Lists.firstDropped(rll, 1)), current);
141 }
142
143 /**
144 * Decodes a RunLengths byte array representation into a RunLength list.
145 *
146 * @param el the encoded byte array
147 * @return the decoded RunLength lest
148 */
149 static List<RunLength> decodeRunLengths(List<Byte> el) {
150 if (Objects.isNull(el) || el.isEmpty())
151 return Collections.emptyList();
152
153 if (el.get(0) < 0 && el.size() >= 2)
154 return Lists.prepended(
155 decodeRunLengths(Lists.firstDropped(el, 2)),
156 new RunLength(el.get(0), el.get(1)));
157 else if (el.get(0) >= 0)
158 return Lists.prepended(
159 decodeRunLengths(Lists.firstDropped(el, 1)),
160 new RunLength(el.get(0)));
161 else
162 throw new IllegalArgumentException();
163 }
164
165 /**
166 * Encodes the given Byte sequence using the run length encoding.
167 *
168 * @param bl the given byte sequence
169 * @return the encoded byte sequence
170 */
171 public static List<Byte> encode(List<Byte> bl) {
172 List<RunLength> rll = bl.stream().map(RunLength::new).collect(Collectors.toList());
173