Netrek-dev, I’m pleased to announce that netrek.networkmom.net <http://netrek.networkmom.net/> now has 16 (pretty dumb) Netrek Robots ready to shoot in your general direction! As humans join the server, robots will logoff. As humans leave the server, robots will join. Only humans are counted in the metaserver submission. Since this is the netrek-dev list, below is the Swift code for the Robot Mark 1. I hope it is highly readable. Stability and feature improvements to the Swift Netrek server will continue (in particular, still no genocide logic). I also fixed a few bugs in the MacOS and iOS clients while developing the server and will push those next week. I’m also happy to accept pull requests for better robots. You can also suggest a “name” for your robot. Will your robot namesake go on to achieve honor and glory? If you login to the server, you’ll see that all four teams are active. That’s intentional. There’s a plan for that… Darrell https://github.com/darrellroot/netrek-server-swift/blob/master/Sources/netrek-server-swift/Robots/RobotModel1.swift <https://github.com/darrellroot/netrek-server-swift/blob/master/Sources/netrek-server-swift/Robots/RobotModel1.swift> // // RobotModel1.swift // netrek-server-swift // // Created by Darrell Root on 7/15/20. // import Foundation class RobotModel1: Robot { enum Strategy { case refuel case repair case dogfight } var strategy: Strategy = .dogfight weak var me: Player? public let userinfo = "RobotModel1" public let preferredShip = ShipType.cruiser required init(player: Player, universe: Universe) { self.me = player } public func secondTimerFired() { guard let me = me else { return } switch me.status { case .free, .observe: //should not get here break case .outfit: guard me.receivedCpOutfit(team: me.team, ship: self.preferredShip) else { debugPrint("\(#file) \(#function) Unable to outfit ship") return } return case .explode: break case .dead: guard me.receivedCpOutfit(team: me.team, ship: self.preferredShip) else { debugPrint("\(#file) \(#function) Unable to outfit ship") return } return case .alive: guard let nearestEnemy = self.nearestEnemy() else { return } adjustShields(nearestEnemy: nearestEnemy) shootLaser(nearestEnemy: nearestEnemy) shootTorpedo(nearestEnemy: nearestEnemy) switch self.strategy { case .refuel: strategyRefuel() case .repair: strategyRepair() case .dogfight: strategyDogfight(nearestEnemy: nearestEnemy) } } } private func adjustShields(nearestEnemy: Player) { guard let me = me else { return } let enemyDistance = NetrekMath.distance(me,nearestEnemy) if enemyDistance < Laser.baseRange * 2 { //shields should be up if !me.shieldsUp { me.receivedCpShield(up: true) } } else { if me.shieldsUp { me.receivedCpShield(up: false) } } } private func shootLaser(nearestEnemy: Player) { guard let me = me else { return } let enemyDistance = NetrekMath.distance(me,nearestEnemy) if enemyDistance < Laser.baseRange / 2 { let enemyDirectionRadian = NetrekMath.angle(origin: me, target: nearestEnemy) let enemyDirectionNetrek = NetrekMath.directionRadian2Netrek(enemyDirectionRadian) me.fireLaser(direction: enemyDirectionNetrek) } } private func shootTorpedo(nearestEnemy: Player) { guard let me = me else { return } let enemyDistance = NetrekMath.distance(me,nearestEnemy) //TODO adjust to torpedo range if enemyDistance < Laser.baseRange { let enemyDirectionRadian = NetrekMath.angle(origin: me, target: nearestEnemy) let variance = Double.random(in: -0.3 ..< 0.3) me.fireTorpedo(direction: enemyDirectionRadian + variance) } } private func strategyDogfight(nearestEnemy: Player) { guard let me = me else { return } //random course toward enemy var directionRadian = NetrekMath.angle(origin: me, target: nearestEnemy) //random evasive 120 degrees each way directionRadian += Double.random(in: Double.pi * -0.3 ..< Double.pi * 0.3) me.receivedDirection(direction: directionRadian) //random speed var speed = Int(me.ship.maxSpeed / 2 - 1) speed += Int.random(in: -2..<2) me.receivedCpSpeed(speed: speed) } private func strategyRepair() { guard let me = me else { return } if let planet = me.orbit, planet.repair { return } if let planet = me.orbit { me.receivedRepair(true) return } if let planet = self.nearestRepairPlanet() { me.receivedPlanetLock(planetID: planet.planetID) me.receivedCpSpeed(speed: Int(me.ship.maxSpeed / 2)) return } else { //no friendly fuel planet so we stop to repair me.receivedRepair(true) } } private func strategyRefuel() { guard let me = me else { return } if let planet = me.orbit, planet.fuel { return } if let planet = me.planetLock, planet.fuel { return } if let planet = self.nearestFuelPlanet() { me.receivedPlanetLock(planetID: planet.planetID) me.receivedCpSpeed(speed: Int(me.ship.maxSpeed / 2)) return } else { //no friendly fuel planet so we stop to refuel me.receivedCpSpeed(speed: 0) } } private func decideStrategy() { guard let me = self.me else { debugPrint("\(#file) \(#function) Unable to identify myself") return } if me.damage > me.ship.maxDamage / 2 { self.strategy = .repair return } if me.fuel < me.ship.maxFuel / 3 { self.strategy = .refuel return } if self.strategy == .repair && me.damage < 10 { self.strategy = .dogfight } if self.strategy == .refuel && me.fuel > (me.ship.maxFuel - 500) { self.strategy = .dogfight } } } -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mailman.us.netrek.org/pipermail/netrek-dev/attachments/20200715/1b35e71c/attachment-0001.htm>