public static void read(RobotFile f, Stream s) { // Buffer into this memory stream System.IO.MemoryStream ms = new MemoryStream(BUFFER_SIZE); // read the stream byte[] buffer = new byte[BUFFER_SIZE]; int len; while ((len = s.Read(buffer, 0, BUFFER_SIZE)) > 0) ms.Write(buffer, 0, len); f.program = ms.GetBuffer(); // FIXME: where would one store hardware here? }
/// <summary> /// Checks if the specified line is a hardware specifier. If so, it reflects the specifier onto the /// bot. /// </summary> /// <param name="f"></param> /// <param name="line"></param> private static void setHardware(RobotFile f, string line) { if (line.Trim().ToLower().StartsWith(HARDWARE_STRING)) { string hardwareSpecifier = line.Trim().Substring(HARDWARE_STRING.Length); // split off the values and look for string[] values = hardwareSpecifier.Split(':').Select(str => str.Trim()).ToArray(); if (values.Length != 2) { throw new CompilerException(String.Format("MalFormed hardware specifier: {0}", line)); } PropertyInfo property = f.hardware.GetType().GetProperty(values[0]); // basic checks and errors if (property == null) { throw new CompilerException( String.Format("Unable to find hardware specifier named: {0}", values[0])); } if (!property.CanWrite) { throw new CompilerException(String.Format( "Unable to set hardware specifier {0} it is read-only", values[0])); } object convertedValue; try { // parse if it's an enum, use built-in converters otherwise. if (property.PropertyType.IsEnum) { convertedValue = Enum.Parse(property.PropertyType, values[1], true); } else { convertedValue = Convert.ChangeType(values[1], property.PropertyType); } property.SetValue(f.hardware, convertedValue, null); } catch { throw new CompilerException(String.Format( "Unable to set hardware specifier {0}, was expecting a {1} received {2}", values[0], property.PropertyType.Name, values[1])); } } }
public static void read(RobotFile f, Stream s) { // Buffer into this memory stream System.IO.MemoryStream ms = new MemoryStream(BUFFER_SIZE); // read the stream byte[] buffer = new byte[BUFFER_SIZE]; int len; while ((len = s.Read(buffer, 0, BUFFER_SIZE)) > 0) { ms.Write(buffer, 0, len); } f.program = ms.GetBuffer(); // FIXME: where would one store hardware here? }
public static void read(RobotFile f, Stream s) { StringBuilder sb = new StringBuilder(); StreamReader sr = new StreamReader(s); string line; while ((line = sr.ReadLine()) != null) { // buffer sb.AppendLine(line); // lets check to see if this is a hardware specifier setHardware(f, line); } f.code = sb.ToString(); // Immediately compile for convenience f.compile(); }
// Convenience function to construct a RobotFile from a file public static RobotFile OpenFile(String filename) { RobotFile f = new RobotFile(); FileStream s = new FileStream(filename, FileMode.Open, FileAccess.Read); // Sane default in case the file does not contain the robot name f.name = Path.GetFileNameWithoutExtension(filename); // Determine which file format class to use based on extension switch (System.IO.Path.GetExtension(filename).ToLower()) { case ".bin": ClassicMBinRobot.read(f, s); break; case ".rwr": WinRoboWar5.read(f, s); break; case ".rtxt": SourceTestLoader.read(f, s); break; case ".rbin": BinaryTestLoader.read(f, s); break; default: throw new ArgumentException("Not a robot file."); } return f; }
/// <summary> /// Checks if the specified line is a hardware specifier. If so, it reflects the specifier onto the /// bot. /// </summary> /// <param name="f"></param> /// <param name="line"></param> private static void setHardware(RobotFile f, string line) { if (line.Trim().ToLower().StartsWith(HARDWARE_STRING)) { string hardwareSpecifier = line.Trim().Substring(HARDWARE_STRING.Length); // split off the values and look for string[] values = hardwareSpecifier.Split(':').Select(str => str.Trim()).ToArray(); if (values.Length != 2) throw new CompilerException(String.Format("MalFormed hardware specifier: {0}", line)); PropertyInfo property = f.hardware.GetType().GetProperty(values[0]); // basic checks and errors if (property == null) throw new CompilerException( String.Format("Unable to find hardware specifier named: {0}", values[0])); if (!property.CanWrite) throw new CompilerException(String.Format( "Unable to set hardware specifier {0} it is read-only", values[0])); object convertedValue; try { // parse if it's an enum, use built-in converters otherwise. if (property.PropertyType.IsEnum) convertedValue = Enum.Parse(property.PropertyType, values[1], true); else convertedValue = Convert.ChangeType(values[1], property.PropertyType); property.SetValue(f.hardware, convertedValue, null); } catch { throw new CompilerException(String.Format( "Unable to set hardware specifier {0}, was expecting a {1} received {2}", values[0], property.PropertyType.Name, values[1])); } } }
// Convenience function to construct a RobotFile from a file public static RobotFile OpenFile(String filename) { RobotFile f = new RobotFile(); FileStream s = new FileStream(filename, FileMode.Open, FileAccess.Read); // Sane default in case the file does not contain the robot name f.name = Path.GetFileNameWithoutExtension(filename); // Determine which file format class to use based on extension switch (System.IO.Path.GetExtension(filename).ToLower()) { case ".bin": ClassicMBinRobot.read(f, s); break; case ".rwr": WinRoboWar5.read(f, s); break; case ".rtxt": SourceTestLoader.read(f, s); break; case ".rbin": BinaryTestLoader.read(f, s); break; default: throw new ArgumentException("Not a robot file."); } return(f); }
public static void write(RobotFile f, Stream s) { // FIXME }
// Robot is the only ArenaObject with no OnSpawn. internal Robot(Arena P, double X, double Y, int number, RobotFile file) : base(P, X, Y) { this.number = number; this.file = file; interp = new Interpreter(new MemoryStream(file.program)); // Load all the default registers StockRegisters.inject(this); team = 0; alive = true; deathReason = DeathReason.Suicided; icon = 0; hardware = file.hardware; energy = hardware.energyMax; damage = hardware.damageMax; shield = 0; aim = 90; look = 0; scan = 0; collision = false; wall = false; friend = false; stunned = 0; hit = 0; kills = 0; survival = 0; killTime = new int[6]{ -1, -1, -1, -1, -1, -1 }; deathTime = -1; killer = null; // FIXME: actually implement the history history = new Int16[50]; // FIXME: actually implement signals signals = new Int16[10]; }
public static void read(RobotFile f, Stream s) { byte[] buf = new byte[141]; if (s.Read(buf, 0, 141) != 141) { throw new IOException("Could not read header."); } f.hardware.energyMax = WinUtil.read16(buf, 0); f.hardware.damageMax = WinUtil.read16(buf, 2); f.hardware.shieldMax = WinUtil.read16(buf, 4); f.hardware.processorSpeed = buf[6]; f.hardware.noNegEnergy = buf[7] > 0; switch (buf[8]) { case 1: f.turretType = TurretType.Line; break; case 2: f.turretType = TurretType.Dot; break; case 3: default: f.turretType = TurretType.None; break; } // FIXME: do I have to support case 20? switch (buf[9]) { case 0: f.hardware.gunType = BulletType.Rubber; break; case 2: f.hardware.gunType = BulletType.Explosive; break; case 1: default: f.hardware.gunType = BulletType.Normal; break; } f.hardware.hasMissiles = buf[10] > 0; f.hardware.hasTacNukes = buf[11] > 0; f.hardware.hasHellbores = buf[12] > 0; f.hardware.hasMines = buf[13] > 0; f.hardware.hasStunners = buf[14] > 0; f.hardware.hasDrones = buf[15] > 0; f.hardware.hasLasers = buf[16] > 0; f.hardware.probeFlag = buf[17] > 0; // 4 reserved bytes // FIXME: shieldicon (1 byte) // FIXME: deathicon (1 byte) // FIXME: hiticon (1 byte) // FIXME: blockicon (1 byte) // FIXME: collisionicon (1 byte) // FIXME: cursor position (4 bytes) // FIXME: 10 x 4 bytes, "Sound # Start" // FIXME: 10 x 4 bytes, "Icon # Start" int programstart = WinUtil.read32(buf, 111) - 1; int codestart = WinUtil.read32(buf, 115) - 1; // FIXME: 10 x 1 bytes, "Sound # Exists" // FIXME: 10 x 1 bytes, "Icon # Exists" f.locked = buf[139] > 0; // FIXME: language (1 byte) // Read the byte code int programlen = codestart - programstart; s.Seek(programstart, SeekOrigin.Begin); byte[] temp = new byte[programlen]; if (s.Read(temp, 0, programlen) != programlen) { throw new IOException("Could not read program."); } // Swap byte order f.program = new byte[programlen]; for (int i = 0; i < programlen; i += 2) { f.program[i] = temp[i + 1]; f.program[i + 1] = temp[i]; } // FIXME: read source code }
/// <summary> /// Adds a robot to the arena. /// </summary> /// <param name="file"></param> public void AddRobot(RobotFile file) { robots.Add(new RobotWrapper(arena.loadRobot(file))); }
/// <summary> /// Reads a robot from stdin /// </summary> /// <returns>False if the quit character was seen, true otherwise.</returns> private bool ReadRobot(string name) { StringBuilder roboFile = new StringBuilder(); string readLine; while ((readLine = Console.ReadLine()) != EOF_STR) { if (readLine == QUIT_STR) return false; roboFile.AppendLine(readLine); } MemoryStream ms = new MemoryStream(ASCIIEncoding.ASCII.GetBytes(roboFile.ToString())); RobotFile result = new RobotFile(); result.name = name; SourceTestLoader.read(result, ms); AddRobot(result); return true; }
public static void LoadStartHeader() { // Load the header and robots from the file byte[] buffer = new byte[258]; f.Read(buffer, 0, 8); Debug.Assert(MacUtil.readString(buffer, 0, 4) == "RDMP"); int seed = MacUtil.read16(buffer, 4); int numBots = MacUtil.read16(buffer, 6); Debug.Assert(numBots < 7); robotFiles = new RobotFile[numBots]; for (int i = 0; i < numBots; i++) { RobotFile nf = new RobotFile(); robotFiles[i] = nf; f.Read(buffer, 0, 258); Debug.Assert(buffer[0] > 0); nf.name = MacUtil.readString(buffer, 1, buffer[0]); int progLen = MacUtil.read16(buffer, 256); Debug.Assert(progLen <= (int)Bytecodes.NUM_MAX_CODE); nf.program = new byte[progLen * 2]; f.Read(nf.program, 0, progLen * 2); f.Read(buffer, 0, 40); nf.hardware.energyMax = MacUtil.read16(buffer, 0); nf.hardware.damageMax = MacUtil.read16(buffer, 2); nf.hardware.shieldMax = MacUtil.read16(buffer, 4); nf.hardware.processorSpeed = MacUtil.read16(buffer, 6); int gun = MacUtil.read16(buffer, 8); switch (gun) { case 1: nf.hardware.gunType = BulletType.Rubber; break; case 3: nf.hardware.gunType = BulletType.Explosive; break; case 2: default: nf.hardware.gunType = BulletType.Normal; break; } nf.hardware.hasMissiles = MacUtil.read16(buffer, 10) > 0; nf.hardware.hasTacNukes = MacUtil.read16(buffer, 12) > 0; nf.hardware.hasLasers = MacUtil.read16(buffer, 16) > 0; nf.hardware.hasHellbores = MacUtil.read16(buffer, 18) > 0; nf.hardware.hasDrones = MacUtil.read16(buffer, 20) > 0; nf.hardware.hasMines = MacUtil.read16(buffer, 22) > 0; nf.hardware.hasStunners = MacUtil.read16(buffer, 24) > 0; nf.hardware.noNegEnergy = MacUtil.read16(buffer, 26) > 0; nf.hardware.probeFlag = MacUtil.read16(buffer, 28) > 0; nf.hardware.deathIconFlag = MacUtil.read16(buffer, 30) > 0; nf.hardware.collisionIconFlag = MacUtil.read16(buffer, 32) > 0; nf.hardware.shieldHitIconFlag = MacUtil.read16(buffer, 34) > 0; nf.hardware.hitIconFlag = MacUtil.read16(buffer, 36) > 0; nf.hardware.shieldOnIconFlag = MacUtil.read16(buffer, 38) > 0; int advantages = MacUtil.read16(buffer, 14); Debug.Assert(advantages == nf.hardware.advantages); } // Print info header Console.WriteLine("Replaying match with mac seed {0} and {1} robot(s):", seed, numBots); string[] names = new string[numBots]; for (int i = 0; i < numBots; i++) names[i] = robotFiles[i].name; Console.WriteLine(String.Join(", ", names)); }
public static void read(RobotFile f, Stream s) { MacBinary mbin = new MacBinary(s); f.name = mbin.filename; if (mbin.res.Contains(resPasswordType) && mbin.res[resPasswordType].Contains(resPasswordID)) { byte[] passbytes = mbin.res[resPasswordType][resPasswordID].data; f.password = MacUtil.readString(passbytes, 0, passbytes.Length); f.locked = true; } else { f.locked = false; } if (mbin.res.Contains(resCodeLengthType) && mbin.res[resCodeLengthType].Contains(resCodeLengthID) && mbin.res.Contains(resRobotCodeType) && mbin.res[resRobotCodeType].Contains(resRobotCodeID)) { //int codelen = Util.read16(mbin.res[resCodeLengthType][resCodeLengthID].data, 0); f.program = mbin.res[resRobotCodeType][resRobotCodeID].data; } if (mbin.res.Contains(resColorIconType)) { MacResourceType t = mbin.res[resColorIconType]; for (int i = 0; i < 10; i++) { if (!t.Contains(resIconMinID + i)) { continue; } byte[] iconbytes = t[resIconMinID + i].data; // FIXME: set up icon } } if (mbin.res.Contains(resIconType)) { MacResourceType t = mbin.res[resIconType]; for (int i = 0; i < 10; i++) { if (f.icons[i] != null || !t.Contains(resIconMinID + i)) { continue; } byte[] iconbytes = t[resIconMinID + i].data; // FIXME: set up icon } } if (mbin.res.Contains(resSoundType)) { MacResourceType t = mbin.res[resSoundType]; for (int i = 0; i < 10; i++) { if (!t.Contains(resSoundMinID + i)) { continue; } byte[] soundbytes = t[resSoundMinID + i].data; // FIXME: set up sound } } if (mbin.res.Contains(resHardwareType) && mbin.res[resHardwareType].Contains(resHardwareID)) { byte[] hardbytes = mbin.res[resHardwareType][resHardwareID].data; if (hardbytes.Length >= 40) { f.hardware.energyMax = MacUtil.read16(hardbytes, 0); f.hardware.damageMax = MacUtil.read16(hardbytes, 2); f.hardware.shieldMax = MacUtil.read16(hardbytes, 4); f.hardware.processorSpeed = MacUtil.read16(hardbytes, 6); int gun = MacUtil.read16(hardbytes, 8); switch (gun) { case 1: f.hardware.gunType = BulletType.Rubber; break; case 3: f.hardware.gunType = BulletType.Explosive; break; case 2: default: f.hardware.gunType = BulletType.Normal; break; } f.hardware.hasMissiles = MacUtil.read16(hardbytes, 10) > 0; f.hardware.hasTacNukes = MacUtil.read16(hardbytes, 12) > 0; // ignore advantages f.hardware.hasLasers = MacUtil.read16(hardbytes, 16) > 0; f.hardware.hasHellbores = MacUtil.read16(hardbytes, 18) > 0; f.hardware.hasDrones = MacUtil.read16(hardbytes, 20) > 0; f.hardware.hasMines = MacUtil.read16(hardbytes, 22) > 0; f.hardware.hasStunners = MacUtil.read16(hardbytes, 24) > 0; f.hardware.noNegEnergy = MacUtil.read16(hardbytes, 26) > 0; f.hardware.probeFlag = MacUtil.read16(hardbytes, 28) > 0; f.hardware.deathIconFlag = MacUtil.read16(hardbytes, 30) > 0; f.hardware.collisionIconFlag = MacUtil.read16(hardbytes, 32) > 0; f.hardware.shieldHitIconFlag = MacUtil.read16(hardbytes, 34) > 0; f.hardware.hitIconFlag = MacUtil.read16(hardbytes, 36) > 0; f.hardware.shieldOnIconFlag = MacUtil.read16(hardbytes, 38) > 0; } } if (mbin.res.Contains(resTurretType) && mbin.res[resTurretType].Contains(resTurretID)) { byte[] turtbytes = mbin.res[resTurretType][resTurretID].data; if (turtbytes.Length >= 2) { int turt = MacUtil.read16(turtbytes, 0); switch (turt) { case 2: f.turretType = TurretType.Dot; break; case 3: f.turretType = TurretType.None; break; case 1: default: f.turretType = TurretType.Line; break; } } } }
public static void read(RobotFile f, Stream s) { byte[] buf = new byte[141]; if (s.Read(buf, 0, 141) != 141) throw new IOException("Could not read header."); f.hardware.energyMax = WinUtil.read16(buf, 0); f.hardware.damageMax = WinUtil.read16(buf, 2); f.hardware.shieldMax = WinUtil.read16(buf, 4); f.hardware.processorSpeed = buf[6]; f.hardware.noNegEnergy = buf[7] > 0; switch (buf[8]) { case 1: f.turretType = TurretType.Line; break; case 2: f.turretType = TurretType.Dot; break; case 3: default: f.turretType = TurretType.None; break; } // FIXME: do I have to support case 20? switch (buf[9]) { case 0: f.hardware.gunType = BulletType.Rubber; break; case 2: f.hardware.gunType = BulletType.Explosive; break; case 1: default: f.hardware.gunType = BulletType.Normal; break; } f.hardware.hasMissiles = buf[10] > 0; f.hardware.hasTacNukes = buf[11] > 0; f.hardware.hasHellbores = buf[12] > 0; f.hardware.hasMines = buf[13] > 0; f.hardware.hasStunners = buf[14] > 0; f.hardware.hasDrones = buf[15] > 0; f.hardware.hasLasers = buf[16] > 0; f.hardware.probeFlag = buf[17] > 0; // 4 reserved bytes // FIXME: shieldicon (1 byte) // FIXME: deathicon (1 byte) // FIXME: hiticon (1 byte) // FIXME: blockicon (1 byte) // FIXME: collisionicon (1 byte) // FIXME: cursor position (4 bytes) // FIXME: 10 x 4 bytes, "Sound # Start" // FIXME: 10 x 4 bytes, "Icon # Start" int programstart = WinUtil.read32(buf, 111) - 1; int codestart = WinUtil.read32(buf, 115) - 1; // FIXME: 10 x 1 bytes, "Sound # Exists" // FIXME: 10 x 1 bytes, "Icon # Exists" f.locked = buf[139] > 0; // FIXME: language (1 byte) // Read the byte code int programlen = codestart - programstart; s.Seek(programstart, SeekOrigin.Begin); byte[] temp = new byte[programlen]; if (s.Read(temp, 0, programlen) != programlen) throw new IOException("Could not read program."); // Swap byte order f.program = new byte[programlen]; for (int i = 0; i < programlen; i += 2) { f.program[i] = temp[i + 1]; f.program[i + 1] = temp[i]; } // FIXME: read source code }
public static void read(RobotFile f, Stream s) { MacBinary mbin = new MacBinary(s); f.name = mbin.filename; if (mbin.res.Contains(resPasswordType) && mbin.res[resPasswordType].Contains(resPasswordID)) { byte[] passbytes = mbin.res[resPasswordType][resPasswordID].data; f.password = MacUtil.readString(passbytes, 0, passbytes.Length); f.locked = true; } else f.locked = false; if (mbin.res.Contains(resCodeLengthType) && mbin.res[resCodeLengthType].Contains(resCodeLengthID) && mbin.res.Contains(resRobotCodeType) && mbin.res[resRobotCodeType].Contains(resRobotCodeID)) { //int codelen = Util.read16(mbin.res[resCodeLengthType][resCodeLengthID].data, 0); f.program = mbin.res[resRobotCodeType][resRobotCodeID].data; } if (mbin.res.Contains(resColorIconType)) { MacResourceType t = mbin.res[resColorIconType]; for (int i = 0; i < 10; i++) { if (!t.Contains(resIconMinID + i)) continue; byte[] iconbytes = t[resIconMinID + i].data; // FIXME: set up icon } } if (mbin.res.Contains(resIconType)) { MacResourceType t = mbin.res[resIconType]; for (int i = 0; i < 10; i++) { if (f.icons[i] != null || !t.Contains(resIconMinID + i)) continue; byte[] iconbytes = t[resIconMinID + i].data; // FIXME: set up icon } } if (mbin.res.Contains(resSoundType)) { MacResourceType t = mbin.res[resSoundType]; for (int i = 0; i < 10; i++) { if (!t.Contains(resSoundMinID + i)) continue; byte[] soundbytes = t[resSoundMinID + i].data; // FIXME: set up sound } } if (mbin.res.Contains(resHardwareType) && mbin.res[resHardwareType].Contains(resHardwareID)) { byte[] hardbytes = mbin.res[resHardwareType][resHardwareID].data; if (hardbytes.Length >= 40) { f.hardware.energyMax = MacUtil.read16(hardbytes, 0); f.hardware.damageMax = MacUtil.read16(hardbytes, 2); f.hardware.shieldMax = MacUtil.read16(hardbytes, 4); f.hardware.processorSpeed = MacUtil.read16(hardbytes, 6); int gun = MacUtil.read16(hardbytes, 8); switch (gun) { case 1: f.hardware.gunType = BulletType.Rubber; break; case 3: f.hardware.gunType = BulletType.Explosive; break; case 2: default: f.hardware.gunType = BulletType.Normal; break; } f.hardware.hasMissiles = MacUtil.read16(hardbytes, 10) > 0; f.hardware.hasTacNukes = MacUtil.read16(hardbytes, 12) > 0; // ignore advantages f.hardware.hasLasers = MacUtil.read16(hardbytes, 16) > 0; f.hardware.hasHellbores = MacUtil.read16(hardbytes, 18) > 0; f.hardware.hasDrones = MacUtil.read16(hardbytes, 20) > 0; f.hardware.hasMines = MacUtil.read16(hardbytes, 22) > 0; f.hardware.hasStunners = MacUtil.read16(hardbytes, 24) > 0; f.hardware.noNegEnergy = MacUtil.read16(hardbytes, 26) > 0; f.hardware.probeFlag = MacUtil.read16(hardbytes, 28) > 0; f.hardware.deathIconFlag = MacUtil.read16(hardbytes, 30) > 0; f.hardware.collisionIconFlag = MacUtil.read16(hardbytes, 32) > 0; f.hardware.shieldHitIconFlag = MacUtil.read16(hardbytes, 34) > 0; f.hardware.hitIconFlag = MacUtil.read16(hardbytes, 36) > 0; f.hardware.shieldOnIconFlag = MacUtil.read16(hardbytes, 38) > 0; } } if (mbin.res.Contains(resTurretType) && mbin.res[resTurretType].Contains(resTurretID)) { byte[] turtbytes = mbin.res[resTurretType][resTurretID].data; if (turtbytes.Length >= 2) { int turt = MacUtil.read16(turtbytes, 0); switch (turt) { case 2: f.turretType = TurretType.Dot; break; case 3: f.turretType = TurretType.None; break; case 1: default: f.turretType = TurretType.Line; break; } } } }
// Instantiate a Robot based on the loaded RobotFile public Robot loadRobot(RobotFile f) { // FIXME: Can this be done during a match? // Arena full? if (robots.Count == Constants.MAX_ROBOTS) return null; // Try to find a starting position not too close to the other robots. // FIXME: construct a list of starting positions in the constructor // so the outcome of prng.Next() is consistent. int x, y; double dist; do { x = prng.Next(Constants.ARENA_SIZE - 30) + 15; y = prng.Next(Constants.ARENA_SIZE - 30) + 15; dist = 1000; foreach (Robot other in robots) { double test = Math.Pow(x - other.x, 2) + Math.Pow(y - other.y, 2); if (test < dist) dist = test; } } while (dist < 625); // Instantiate Robot robot = new Robot(this, x, y, robots.Count, f); // Update state robots_.Add(robot); numAlive++; return robot; }