Skip to content

Commit 81af09d

Browse files
authored
Added IO_COMPASS and documenting some IO commands (#84)
Implemented IO_MARK and IO_MARK_READ. Added documentation for some IO commands. Added IO_COMPASS for finding local orientation. Changed IO_BATTERY to push a normalized value. Changed IO_MARK stack order offset pushed first. Added IO_LASER and IO_RECEIVE aliases.
1 parent cc4d129 commit 81af09d

3 files changed

Lines changed: 120 additions & 7 deletions

File tree

SPEC.md

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,17 +319,92 @@ The maximum CPU speed is 100, setting any number higher is the same as setting
319319
to 100. The game operates at 10 frames per second meaning a fully overclocked
320320
CPU will execute 1000 instructions per second, 100 per frame.
321321

322+
### Battery Check
323+
324+
A robot can know how much battery it has:
325+
326+
```
327+
push8 #IO_BATTERY
328+
io
329+
popf batteryLevel
330+
```
331+
332+
The float on the stack will be between `0.0` and `1.0` describing how much
333+
battery is remaining.
334+
322335
### Laser
323336

324-
*Not yet implemented*
337+
Robots get a laser beam which can damage some obstacles and other robots in
338+
combat. Currently a laser can break rocks which may be blocking doors. Having
339+
the laser on costs up to `256` battery per game frame, less if the laser is
340+
not fully powered or hits something early.
325341

326-
Will deal battery damage to other bots.
342+
```
343+
; Full power laser
344+
pushf 1.0
345+
push8 #IO_LASER
346+
io
347+
348+
; Laser off
349+
pushf 0.0
350+
push8 #IO_LASER
351+
io
352+
```
327353

328354
### Accelerometer
329355

356+
The accelerometer allows a robot to detect relative changes in it's position.
357+
Each time you use the IO_ACCELEROMETER command the last position is saved and
358+
the difference is pushed on the stack as two floats.
359+
330360
```
331361
push8 #IO_ACCELEROMETER
332362
io
333363
popf relY
334364
popf relX
335365
```
366+
367+
### Compass
368+
369+
The compass allows a robot to determine which direction they are facing.
370+
371+
```
372+
push8 #IO_COMPASS
373+
io
374+
popf facing
375+
```
376+
377+
### World Marking
378+
379+
Robots can "mark" the world which is kind of like how animals can pee and sniff
380+
the pee. A robot uses `IO_MARK` to write bytes to the current tile and can
381+
use `IO_MARK_READ` to read data of the current tile. Each tile has 8 bytes
382+
of storage.
383+
384+
```
385+
push8 #00 ; Offset
386+
push8 #42 ; Value to save
387+
push8 #IO_MARK
388+
io
389+
```
390+
391+
You can read the same data back using:
392+
393+
```
394+
push8 #00 ; Offset
395+
push8 #IO_MARK_READ
396+
io
397+
pop8 tileData
398+
```
399+
400+
Note that other robots (if in a shared world) also may read or write data to
401+
the same tile.
402+
403+
### Radio
404+
405+
*Note the radio isn't implemented entirely yet*
406+
407+
The radio allows robots to send and receive messages with one another. Robots
408+
"tune" their radio using the `IO_RADIO` command setting a frequency and
409+
transmit power. The `IO_SEND` and `IO_RECV` to send and receive messages.
410+

src/asmcup/runtime/Robot.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,26 @@ public float getY() {
4040
return y;
4141
}
4242

43+
public int getColumn() {
44+
return (int)(x / World.TILE_SIZE);
45+
}
46+
47+
public int getRow() {
48+
return (int)(y / World.TILE_SIZE);
49+
}
50+
51+
public int getCellX() {
52+
return getColumn() / World.TILES_PER_CELL;
53+
}
54+
55+
public int getCellY() {
56+
return getRow() / World.TILES_PER_CELL;
57+
}
58+
59+
public int getCellKey() {
60+
return getCellX() | (getCellY() << 16);
61+
}
62+
4363
public float getFacing() {
4464
return facing;
4565
}
@@ -303,11 +323,11 @@ protected void handleIO(World world) {
303323
lazer = popFloatSafe(0.0f, 1.0f);
304324
break;
305325
case IO_BATTERY:
306-
vm.pushFloat(battery);
326+
vm.pushFloat((float)battery / BATTERY_MAX);
307327
break;
308328
case IO_MARK:
309-
offset = vm.pop8();
310329
value = vm.pop8();
330+
offset = vm.pop8();
311331
world.mark(this, offset, value);
312332
break;
313333
case IO_MARK_READ:
@@ -330,6 +350,9 @@ protected void handleIO(World world) {
330350
case IO_RECV:
331351
vm.push8(world.recv(this, frequency));
332352
break;
353+
case IO_COMPASS:
354+
vm.pushFloat(facing);
355+
break;
333356
default:
334357
lastInvalidIO = world.getFrame();
335358
return;
@@ -414,14 +437,17 @@ protected static float clampSafe(float f, float min, float max) {
414437
public static final int IO_STEER = 2;
415438
public static final int IO_OVERCLOCK = 3;
416439
public static final int IO_LAZER = 4;
440+
public static final int IO_LASER = 4;
417441
public static final int IO_BATTERY = 5;
418442
public static final int IO_MARK = 6;
419443
public static final int IO_MARK_READ = 7;
420444
public static final int IO_ACCELEROMETER = 8;
421445
public static final int IO_RADIO = 9;
422446
public static final int IO_SEND = 10;
423447
public static final int IO_RECV = 11;
448+
public static final int IO_RECEIVE = 11;
424449
public static final int IO_SENSOR_CONFIG = 12;
450+
public static final int IO_COMPASS = 13;
425451

426452
public static final float SPEED_MAX = 8;
427453
public static final float STEER_RATE = (float)(Math.PI * 0.1);

src/asmcup/runtime/World.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
public class World {
66
protected final ArrayList<Robot> robots;
77
protected final HashMap<Integer, Cell> cells;
8+
protected final HashMap<Integer, byte[]> tileData;
89
protected final int seed;
910
protected int frame;
1011

@@ -15,6 +16,7 @@ public World() {
1516
public World(int seed) {
1617
this.robots = new ArrayList<>();
1718
this.cells = new HashMap<>();
19+
this.tileData = new HashMap<>();
1820
this.seed = seed;
1921
this.frame = 0;
2022
}
@@ -157,12 +159,21 @@ protected void tickItems(Robot robot) {
157159
}
158160

159161
public void mark(Robot robot, int offset, int value) {
160-
// TODO read data from tile
162+
int key = robot.getColumn() | (robot.getRow() << 16);
163+
byte[] data = tileData.get(key);
164+
165+
if (data == null) {
166+
data = new byte[8];
167+
tileData.put(key, data);
168+
}
169+
170+
data[offset & 0b11] = (byte)(value & 0xFF);
161171
}
162172

163173
public int markRead(Robot robot, int offset) {
164-
// TODO write data to tile
165-
return 0;
174+
int key = robot.getColumn() | (robot.getRow() << 16);
175+
byte[] data = tileData.get(key);
176+
return (data == null) ? 0 : data[offset & 0b11];
166177
}
167178

168179
public void send(Robot robot, float frequency, int data) {
@@ -180,4 +191,5 @@ public int recv(Robot robot, float frequency) {
180191
public static final int CELL_SIZE = TILES_PER_CELL * TILE_SIZE;
181192
public static final int CELL_COUNT = 0xFF;
182193
public static final int SIZE = TILE_SIZE * TILES_PER_CELL * CELL_COUNT;
194+
public static final int CENTER = SIZE / 2;
183195
}

0 commit comments

Comments
 (0)