From 81af09d27016aa179bb1644ac54e2e10eb0e911d Mon Sep 17 00:00:00 2001 From: Kristopher Ives Date: Mon, 24 Oct 2016 15:37:39 -0700 Subject: [PATCH] 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. --- SPEC.md | 79 ++++++++++++++++++++++++++++++++++- src/asmcup/runtime/Robot.java | 30 ++++++++++++- src/asmcup/runtime/World.java | 18 ++++++-- 3 files changed, 120 insertions(+), 7 deletions(-) diff --git a/SPEC.md b/SPEC.md index db4847e..64a843f 100755 --- a/SPEC.md +++ b/SPEC.md @@ -319,17 +319,92 @@ The maximum CPU speed is 100, setting any number higher is the same as setting to 100. The game operates at 10 frames per second meaning a fully overclocked CPU will execute 1000 instructions per second, 100 per frame. +### Battery Check + +A robot can know how much battery it has: + +``` +push8 #IO_BATTERY +io +popf batteryLevel +``` + +The float on the stack will be between `0.0` and `1.0` describing how much +battery is remaining. + ### Laser -*Not yet implemented* +Robots get a laser beam which can damage some obstacles and other robots in +combat. Currently a laser can break rocks which may be blocking doors. Having +the laser on costs up to `256` battery per game frame, less if the laser is +not fully powered or hits something early. -Will deal battery damage to other bots. +``` +; Full power laser +pushf 1.0 +push8 #IO_LASER +io + +; Laser off +pushf 0.0 +push8 #IO_LASER +io +``` ### Accelerometer +The accelerometer allows a robot to detect relative changes in it's position. +Each time you use the IO_ACCELEROMETER command the last position is saved and +the difference is pushed on the stack as two floats. + ``` push8 #IO_ACCELEROMETER io popf relY popf relX ``` + +### Compass + +The compass allows a robot to determine which direction they are facing. + +``` +push8 #IO_COMPASS +io +popf facing +``` + +### World Marking + +Robots can "mark" the world which is kind of like how animals can pee and sniff +the pee. A robot uses `IO_MARK` to write bytes to the current tile and can +use `IO_MARK_READ` to read data of the current tile. Each tile has 8 bytes +of storage. + +``` +push8 #00 ; Offset +push8 #42 ; Value to save +push8 #IO_MARK +io +``` + +You can read the same data back using: + +``` +push8 #00 ; Offset +push8 #IO_MARK_READ +io +pop8 tileData +``` + +Note that other robots (if in a shared world) also may read or write data to +the same tile. + +### Radio + +*Note the radio isn't implemented entirely yet* + +The radio allows robots to send and receive messages with one another. Robots +"tune" their radio using the `IO_RADIO` command setting a frequency and +transmit power. The `IO_SEND` and `IO_RECV` to send and receive messages. + diff --git a/src/asmcup/runtime/Robot.java b/src/asmcup/runtime/Robot.java index 0b0ae54..7e39494 100755 --- a/src/asmcup/runtime/Robot.java +++ b/src/asmcup/runtime/Robot.java @@ -40,6 +40,26 @@ public float getY() { return y; } + public int getColumn() { + return (int)(x / World.TILE_SIZE); + } + + public int getRow() { + return (int)(y / World.TILE_SIZE); + } + + public int getCellX() { + return getColumn() / World.TILES_PER_CELL; + } + + public int getCellY() { + return getRow() / World.TILES_PER_CELL; + } + + public int getCellKey() { + return getCellX() | (getCellY() << 16); + } + public float getFacing() { return facing; } @@ -303,11 +323,11 @@ protected void handleIO(World world) { lazer = popFloatSafe(0.0f, 1.0f); break; case IO_BATTERY: - vm.pushFloat(battery); + vm.pushFloat((float)battery / BATTERY_MAX); break; case IO_MARK: - offset = vm.pop8(); value = vm.pop8(); + offset = vm.pop8(); world.mark(this, offset, value); break; case IO_MARK_READ: @@ -330,6 +350,9 @@ protected void handleIO(World world) { case IO_RECV: vm.push8(world.recv(this, frequency)); break; + case IO_COMPASS: + vm.pushFloat(facing); + break; default: lastInvalidIO = world.getFrame(); return; @@ -414,6 +437,7 @@ protected static float clampSafe(float f, float min, float max) { public static final int IO_STEER = 2; public static final int IO_OVERCLOCK = 3; public static final int IO_LAZER = 4; + public static final int IO_LASER = 4; public static final int IO_BATTERY = 5; public static final int IO_MARK = 6; public static final int IO_MARK_READ = 7; @@ -421,7 +445,9 @@ protected static float clampSafe(float f, float min, float max) { public static final int IO_RADIO = 9; public static final int IO_SEND = 10; public static final int IO_RECV = 11; + public static final int IO_RECEIVE = 11; public static final int IO_SENSOR_CONFIG = 12; + public static final int IO_COMPASS = 13; public static final float SPEED_MAX = 8; public static final float STEER_RATE = (float)(Math.PI * 0.1); diff --git a/src/asmcup/runtime/World.java b/src/asmcup/runtime/World.java index ad7309d..0ac18ed 100755 --- a/src/asmcup/runtime/World.java +++ b/src/asmcup/runtime/World.java @@ -5,6 +5,7 @@ public class World { protected final ArrayList robots; protected final HashMap cells; + protected final HashMap tileData; protected final int seed; protected int frame; @@ -15,6 +16,7 @@ public World() { public World(int seed) { this.robots = new ArrayList<>(); this.cells = new HashMap<>(); + this.tileData = new HashMap<>(); this.seed = seed; this.frame = 0; } @@ -157,12 +159,21 @@ protected void tickItems(Robot robot) { } public void mark(Robot robot, int offset, int value) { - // TODO read data from tile + int key = robot.getColumn() | (robot.getRow() << 16); + byte[] data = tileData.get(key); + + if (data == null) { + data = new byte[8]; + tileData.put(key, data); + } + + data[offset & 0b11] = (byte)(value & 0xFF); } public int markRead(Robot robot, int offset) { - // TODO write data to tile - return 0; + int key = robot.getColumn() | (robot.getRow() << 16); + byte[] data = tileData.get(key); + return (data == null) ? 0 : data[offset & 0b11]; } public void send(Robot robot, float frequency, int data) { @@ -180,4 +191,5 @@ public int recv(Robot robot, float frequency) { public static final int CELL_SIZE = TILES_PER_CELL * TILE_SIZE; public static final int CELL_COUNT = 0xFF; public static final int SIZE = TILE_SIZE * TILES_PER_CELL * CELL_COUNT; + public static final int CENTER = SIZE / 2; }